Go Back   EQEmulator Home > EQEmulator Forums > Development > Development::Development

Development::Development Forum for development topics and for those interested in EQEMu development. (Not a support forum)

Reply
 
Thread Tools Display Modes
  #1  
Old 09-14-2008, 01:01 PM
James76
Sarnak
 
Join Date: Sep 2008
Location: Canada
Posts: 53
Default KEYRING by Jaystonian (aka James76)

Discussion: http://eqemulator.net/forums/showthread.php?t=26177

Please forgive the indent loss. This should be straight-forward. The last modification in Doors::HandleClick, the /*NEW*/ lines indicate what to add, just look for the start and don't miss the curly braces.

================================================== ========================
[in SQL]

Quote:
drop table if exists `keyring`;
create table `keyring`(
`char_id` integer not null,
`item_id` integer not null
) engine=MyISAM DEFAULT CHARSET=latin1;
================================================== ========================
[in ./common/database.cpp add to method Database:eleteCharacter(char *name)]:

Quote:
#if DEBUG >= 5
printf(" keyring");
#endif
RunQuery(query, MakeAnyLenString(&query, "DELETE FROM keyring WHERE char_id='%d'", charid), errbuf, NULL, &affected_rows);
if(query)
{
safe_delete_array(query);
query = NULL;
}
================================================== ========================
[in ./zone/client.h add to header:]
Quote:
#include <list>
================================================== ========================
[in ./zone/client.h add to private section of Client class definition:]
Quote:
std::list<int32> keyring;
================================================== ========================
[in ./zone/client.h add to public section of Client class definition:]
Quote:
void KeyRingLoad();
void KeyRingAdd(int32 item_id);
bool KeyRingCheck(int32 item_id);
void KeyRingList();
================================================== ========================
[in ./zone/client.cpp add to constructor:]
Quote:
keyring.clear();
================================================== ========================
[in ./zone/client.cpp add:]
Quote:
void Client::KeyRingLoad()
{
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
query = new char[256];

keyring.clear();
sprintf(query, "SELECT item_id FROM keyring WHERE char_id='%i' ORDER BY item_id",character_id);
if (database.RunQuery(query, strlen(query), errbuf, &result))
{
safe_delete_array(query);
while(0 != (row = mysql_fetch_row(result))){
keyring.push_back(atoi(row[0]));
}
mysql_free_result(result);
}else {
cerr << "Error in Client::KeyRingLoad query '" << query << "' " << errbuf << endl;
safe_delete_array(query);
return;
}
}

void Client::KeyRingAdd(int32 item_id)
{
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
int32 affected_rows = 0;
query = new char[256];
bool bFound = KeyRingCheck(item_id);
if(!bFound){
sprintf(query, "INSERT INTO keyring(char_id,item_id) VALUES(%i,%i)",character_id,item_id);
if(database.RunQuery(query, strlen(query), errbuf, 0, &affected_rows))
{
Message(4,"Added to keyring.");
safe_delete_array(query);
}
else
{
cerr << "Error in Doors::HandleClick query '" << query << "' " << errbuf << endl;
safe_delete_array(query);
return;
}
keyring.push_back(item_id);
}
}

bool Client::KeyRingCheck(int32 item_id)
{
for(std::list<int32>::iterator iter = keyring.begin();
iter != keyring.end();
++iter)
{
if(*iter == item_id)
return true;
}
return false;
}

void Client::KeyRingList()
{
Message(4,"Keys on Keyring:");
const Item_Struct *item = 0;
for(std::list<int32>::iterator iter = keyring.begin();
iter != keyring.end();
++iter)
{
if ((item = database.GetItem(*iter))!=NULL) {
Message(4,item->Name);
}
}
}
================================================== ========================
[in ./common/emu_oplist.h add]
Quote:
N(OP_KeyRing),
================================================== ========================
[in patch_Titanium.conf add]
Quote:
OP_KeyRing=0x68c4
================================================== ========================
[in ./zone/client_packet.h add]
Quote:
void Handle_OP_KeyRing(const EQApplicationPacket *app);
================================================== ========================
[in ./zone/client_packet.cpp in function MapOpcodes() add]
Quote:
ConnectedOpcodes[OP_KeyRing] = &Client::Handle_OP_KeyRing;
================================================== ========================
[in ./zone/client_packet.cpp add]
Quote:
void Client::Handle_OP_KeyRing(const EQApplicationPacket *app)
{
KeyRingList();
}
================================================== ========================
[in ./zone/client_packet.cpp, insert in Client::FinishConnState2() just after SetEndurance():]
Quote:
KeyRingLoad();
================================================== ========================
[in ./zone/doors.cpp in method Doors::HandleClick(...) add code on lines]
Quote:
if (sender->GetGM()) // GM can always open locks - should probably be changed to require a key
{
sender->Message_StringID(4,DOORS_GM);
if( !IsDoorOpen() || opentype == 58 )
{
md->action = OPEN_DOOR;
}
else
{
md->action = CLOSE_DOOR;
}
}
else if (playerkey)
{ // they have something they are trying to open it with
if (keyneeded && keyneeded == playerkey)
{ // key required and client is using the right key
/*NEW*/ sender->KeyRingAdd(playerkey);
sender->Message(4,"You got it open!"); // more debug spam
if( !IsDoorOpen() || opentype == 58 )
{
md->action = OPEN_DOOR;
}
else
{
md->action = CLOSE_DOOR;
}
}
}
else if(lockpicks != NULL)
{
if(sender->GetSkill(PICK_LOCK))
{
if(lockpicks->GetItem()->ItemType == ItemTypeLockPick)
{
float modskill=sender->GetSkill(PICK_LOCK);
sender->CheckIncreaseSkill(PICK_LOCK, 1);
#if EQDEBUG>=5
LogFile->write(EQEMuLog:ebug,"Client has lockpicks: skill=%f", modskill);
#endif

if(GetLockpick() <= modskill)
{
if(!IsDoorOpen())
{
md->action = OPEN_DOOR;
}
else
{
md->action = CLOSE_DOOR;
}
sender->Message_StringID(4,DOORS_SUCCESSFUL_PICK);
}
else
{
sender->Message_StringID(4,DOORS_INSUFFICIENT_SKILL);
return;
}
}
else
{
sender->Message_StringID(4,DOORS_NO_PICK);
return;
}
}
else
{
sender->Message_StringID(4,DOORS_CANT_PICK);
return;
}
}
else
{ // locked door and nothing to open it with
/*NEW*/ if(keyneeded != 0){
/*NEW*/ //search for key on keyring
/*NEW*/ if(sender->KeyRingCheck(keyneeded)){
/*NEW*/ sender->Message(4,"You got it open!"); // more debug spam
/*NEW*/ if( !IsDoorOpen() || opentype == 58 )
/*NEW*/ {
/*NEW*/ md->action = OPEN_DOOR;
/*NEW*/ }
/*NEW*/ else
/*NEW*/ {
/*NEW*/ md->action = CLOSE_DOOR;
/*NEW*/ }
/*NEW*/ }
/*NEW*/ }
/*NEW*/ else
/*NEW*/ {
sender->Message_StringID(4,DOORS_LOCKED);
return;
/*NEW*/ }
}
================================================== ========================
Reply With Quote
  #2  
Old 09-14-2008, 01:09 PM
James76
Sarnak
 
Join Date: Sep 2008
Location: Canada
Posts: 53
Default final note:

This is only for door keys.
Reply With Quote
  #3  
Old 09-14-2008, 07:10 PM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

Quote:
Originally Posted by James76 View Post
This is only for door keys.
As apposed to what? Are there other things that would go on the keyring?

Thanks for the code submission! Have you tested this and verified that it all works? I can't wait to get this on my server and try it out
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!
Reply With Quote
  #4  
Old 09-14-2008, 07:59 PM
James76
Sarnak
 
Join Date: Sep 2008
Location: Canada
Posts: 53
Default

Yes, flawless victory.
Reply With Quote
  #5  
Old 09-14-2008, 08:47 PM
cavedude's Avatar
cavedude
The PEQ Dude
 
Join Date: Apr 2003
Location: -
Posts: 1,988
Default

Great work! Would you mind posting a diff, or at the least approximate line numbers?
Reply With Quote
  #6  
Old 09-14-2008, 09:03 PM
James76
Sarnak
 
Join Date: Sep 2008
Location: Canada
Posts: 53
Default

Quote:
Originally Posted by cavedude View Post
Great work! Would you mind posting a diff, or at the least approximate line numbers?
Sure, for the larger files, np. The rest is simple, just add your methods anywhere to the file (usually at bottom) or modify near the top..

Working down my list of mods,

line 493 ./common/database.cpp

line 46 ./zone/client.h (header section)
line 877 ./zone/client.h (private section)
line 190 ./zone/client.h (public section)

line 3281 ./zone/client.cpp (4 methods to insert)

line 318 ./zone/client_packet.cpp
line 7000 ./zone/client_packet.cpp (add Client::Handle_OP_KeyRing())
line 6436 ./zone/client_packet.cpp (mod FinishConnState2())

line 165 ./zone/doors.cpp (this is start of section)



You may find it easier to open some sort of text editor, copy my entire post over, and delete each section as you add it in.
Reply With Quote
  #7  
Old 09-15-2008, 02:11 AM
joligario's Avatar
joligario
Developer
 
Join Date: Mar 2003
Posts: 1,490
Default

Quote:
Originally Posted by trevius View Post
As apposed to what? Are there other things that would go on the keyring?

Thanks for the code submission! Have you tested this and verified that it all works? I can't wait to get this on my server and try it out
One thing that comes to mind, Trakanon's Idol goes on keyring and it is not a door.
Reply With Quote
  #8  
Old 09-15-2008, 04:16 AM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

I think the port into Seb is an object in the doors table. So even though it isn't a door in the way you would normally think of one, I imagine it would be treated the same as far as the emulator and this code is concerned. Unless it is a zone point that requires a key or something. Don't really feel like searching the DB to check which one hehe.
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!
Reply With Quote
  #9  
Old 09-15-2008, 08:51 PM
James76
Sarnak
 
Join Date: Sep 2008
Location: Canada
Posts: 53
Default bug found

Somehow it breaks the code for clicking on the factory door in Plane of Innovation after killing Xanamech. I get:

You got the door open.
This is locked...

Hold tight, I'll figure it out.
Reply With Quote
  #10  
Old 09-15-2008, 08:58 PM
cavedude's Avatar
cavedude
The PEQ Dude
 
Join Date: Apr 2003
Location: -
Posts: 1,988
Default

The factory door is handled by a Perl script, because it requires a character flag, and not a key. The door is permalocked using keyitem 1, and it's up to the script to determine if the player can open the door or not, and if so to do it. There are also doors in a similar situation, but the door can accept two keys. In that case, the script would be the same except for looking for a global, it would look for one of the keys in the player's inventory. Here is the script:

Code:
sub EVENT_CLICKDOOR {
   
   if($doorid == 7 || $doorid == 263){
      if($qglobals{pop_poi_dragon} == 1) {
            $client->Message(0,"You got the door open.");
            quest::forcedooropen(7);
      }
   }
   $qglobals{pop_poi_dragon}=undef;
  }
In other news, I must be a complete idiot, because I can't get this code to work at all. Even if I manually insert the keyitem into my database, it doesn't show up on /key, and I can't open the door without the item. (I've been trying the Paineel door.) Of course, it may be a compatibility issue as PEQ's code is significantly different than EQEmu's. Though, I think doors are the same, it could very well be my error. Also, I admit I only tried one keyitem/door so it just may be that one that is broken.
Reply With Quote
  #11  
Old 09-16-2008, 01:09 AM
James76
Sarnak
 
Join Date: Sep 2008
Location: Canada
Posts: 53
Default

ok I had some time to look at this... i disabled my code and I found I could click on the door for a while and it still wouldn't open. It looks like Client::Message_StringID(4,DOORS_LOCKED) has been hijacked with a flags check to unlock the door....

So one fix and one change.

In ./zone/doors.cpp it should look like:

Code:
		// a key is required or the door is locked but can be picked or both
		sender->Message(4,"This is locked...");		// debug spam - should probably go
		if (sender->GetGM())		// GM can always open locks - should probably be changed to require a key
		{
			sender->Message_StringID(4,DOORS_GM);
			if( !IsDoorOpen() || opentype == 58 )
			{ 
				md->action = OPEN_DOOR; 
			} 
			else
			{ 
				md->action = CLOSE_DOOR; 
			} 
		}
		else if (playerkey)
		{	// they have something they are trying to open it with
			if (keyneeded && keyneeded == playerkey)
			{	// key required and client is using the right key 
/*NEW*/				sender->KeyRingAdd(playerkey);
				sender->Message(4,"You got it open!");		// more debug spam
				if( !IsDoorOpen() || opentype == 58 )
				{ 
					md->action = OPEN_DOOR; 
				} 
				else
				{ 
					md->action = CLOSE_DOOR; 
				} 
			}
		}
		else if(lockpicks != NULL)
		{
			if(sender->GetSkill(PICK_LOCK))
			{
				if(lockpicks->GetItem()->ItemType == ItemTypeLockPick)
				{
					float modskill=sender->GetSkill(PICK_LOCK);
					sender->CheckIncreaseSkill(PICK_LOCK, 1);
#if EQDEBUG>=5
					LogFile->write(EQEMuLog::Debug,"Client has lockpicks: skill=%f", modskill);
#endif

					if(GetLockpick() <= modskill)
					{
						if(!IsDoorOpen())
						{ 
							md->action = OPEN_DOOR; 
						} 
						else
						{ 
							md->action = CLOSE_DOOR; 
						}
						sender->Message_StringID(4,DOORS_SUCCESSFUL_PICK);
					}
					else
					{
						sender->Message_StringID(4,DOORS_INSUFFICIENT_SKILL);
						return;
					}
				}
				else
				{
					sender->Message_StringID(4,DOORS_NO_PICK);
					return;
				}
			}
			else
			{
				sender->Message_StringID(4,DOORS_CANT_PICK);
				return;
			}
		}
		else
		{	// locked door and nothing to open it with
			//search for key on keyring
/*NEW*/			if(sender->KeyRingCheck(keyneeded)){
/*NEW*/				sender->Message(4,"You got it open!");		// more debug spam
/*NEW*/				if( !IsDoorOpen() || opentype == 58 )
/*NEW*/				{ 
/*NEW*/					md->action = OPEN_DOOR; 
/*NEW*/				} 
/*NEW*/				else
/*NEW*/				{ 
/*NEW*/					md->action = CLOSE_DOOR; 
/*NEW*/				} 
/*NEW*/			}
/*NEW*/			else 
/*NEW*/			{
				sender->Message_StringID(4,DOORS_LOCKED);
				return;
/*NEW*/			}
		}
	}

Then in ./zone/client.cpp add to very start of Client::KeyRingAdd()

Code:
if(0==item_id)return;
Now the PoI factory door works. The message is still FUNKY but whatever.
Reply With Quote
  #12  
Old 09-16-2008, 04:39 AM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

I think you missed Cavedude's post :P
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!
Reply With Quote
  #13  
Old 09-16-2008, 05:59 AM
KLS
Administrator
 
Join Date: Sep 2006
Posts: 1,348
Default

I'll be a few days at least (probably more) before I can get this and everything else posted in this section looked at. R.I.P free time =p
Reply With Quote
  #14  
Old 09-16-2008, 08:56 AM
Angelox
AX Classic Developer
 
Join Date: May 2006
Location: filler
Posts: 2,049
Default

Quote:
Originally Posted by KLS View Post
I'll be a few days at least (probably more) before I can get this and everything else posted in this section looked at. R.I.P free time =p
Well, You got plenty of people I'm sure would help; people that have been around, and we all know, like trevius, Derision - those are just the first two that come to my head out of a whole bunch. And what about Scorpious2k? what happened to him? he was helping and now hes gone.
I have yet to understand what the idea is behind all this 'closed doors' operation.
Reply With Quote
  #15  
Old 09-16-2008, 09:28 AM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

LOL, well I can certainly build a working source and test it for bugs, but I am no where near good enough to read code and see if something is horribly wrong with it somewhere. I am sure that most of the time it would be just fine, but I am also sure that it would be done much sloppier than how KLS would add it. I know she sometimes edits the code some before actually adding it.

I feel like Derision would do a good job at it, but he isn't a developer yet. Not exactly sure where S2K is, but I know he was having some PC problems for a while. He may have just popped out as quickly as he popped back in :P

No rush, KLS. I still haven't tested alot of the new code updates yet. I have been super busy with finalizing a zone I have been working on for about 4 months. It should be done in a day or 2 and I will try to get all of the new code submissions in and test them as best I can. I will let you all know what I find So far I know that my scribespells and traindiscs code works well.

Though, I have been seeing a considerably large amount of "world zone disconnects". Where it will send a message like that and then say it reconnected to all zones in use by each zone name. It doesn't actually cause a crash as long as you stay in the zone, but if you try to zone out, you get booted back to login. Then, if you login again you are fine, at least until it happens again. Currently it seems to happen every couple of hours.

I have seen this happen before, but never this bad. The only time in the past that I ever saw it was when I was using the emulator admin tool and doing database searches for accounts/characters.

The only thing I can think of that is causing it now is the 1129 source, or custom code I have added in. Or, it could be that I gave 2 of my GMs remote database access recently. But, the problem happens even when neither of them are doing any changes/queries. I will look into this issue more later, but if anyone else is having this problem too, I would be glad to know that it isn't just me. Plus, that helps narrow down what is causing it.

I guess I should have made a whole new support post about that issue lol. Got carried away =P
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!
Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

   

All times are GMT -4. The time now is 06:05 PM.


 

Everquest is a registered trademark of Daybreak Game Company LLC.
EQEmulator is not associated or affiliated in any way with Daybreak Game Company LLC.
Except where otherwise noted, this site is licensed under a Creative Commons License.
       
Powered by vBulletin®, Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3