EQEmulator Forums

EQEmulator Forums (https://www.eqemulator.org/forums/index.php)
-   Development::Development (https://www.eqemulator.org/forums/forumdisplay.php?f=590)
-   -   KEYRING by Jaystonian (aka James76) (https://www.eqemulator.org/forums/showthread.php?t=26177)

James76 09-14-2008 01:01 PM

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::DeleteCharacter(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::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
/*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*/ }
}
================================================== ========================

James76 09-14-2008 01:09 PM

final note:
 
This is only for door keys.

trevius 09-14-2008 07:10 PM

Quote:

Originally Posted by James76 (Post 155836)
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 :)

James76 09-14-2008 07:59 PM

Yes, flawless victory.

cavedude 09-14-2008 08:47 PM

Great work! Would you mind posting a diff, or at the least approximate line numbers?

James76 09-14-2008 09:03 PM

Quote:

Originally Posted by cavedude (Post 155866)
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.

joligario 09-15-2008 02:11 AM

Quote:

Originally Posted by trevius (Post 155858)
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.

trevius 09-15-2008 04:16 AM

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.

James76 09-15-2008 08:51 PM

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.

cavedude 09-15-2008 08:58 PM

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.

James76 09-16-2008 01:09 AM

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.

trevius 09-16-2008 04:39 AM

I think you missed Cavedude's post :P

KLS 09-16-2008 05:59 AM

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

Angelox 09-16-2008 08:56 AM

Quote:

Originally Posted by KLS (Post 156017)
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.

trevius 09-16-2008 09:28 AM

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


All times are GMT -4. The time now is 07:25 PM.

Powered by vBulletin®, Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.