Log in

View Full Version : help with code


spider661
02-18-2009, 06:06 AM
im trying to get corpse summoning to work so im messing with SummonBurriedPlayerCorpse quest command i changed it to not read if there IsBurried (not changed here) but anyways it works great but the bodys are still there if the zone never reloads.. so if players are in the zone or whatever all the bodys you summoned get summoned to the npc running this command plus stay in the zone where you died meaning you can dupe items. is there a way to remove the body's from the zone there in before making the new body.

i know you can get the zone the old body was in by getting the zone id from the database. i just don't know how to remove it.

this is the code to summon them
playercorpse.cpp

Corpse* ZoneDatabase::SummonBurriedPlayerCorpse(int32 char_id, int32 dest_zoneid, float dest_x, float dest_y, float dest_z, float dest_heading) {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
Corpse* NewCorpse = 0;
unsigned long* lengths;

if (RunQuery(query, MakeAnyLenString(&query, "SELECT id, charname, data, timeofdeath, rezzed FROM player_corpses WHERE charid='%u' AND IsBurried=1 ORDER BY timeofdeath LIMIT 1", char_id), errbuf, &result)) {
row = mysql_fetch_row(result);
lengths = mysql_fetch_lengths(result);
if(row) {
NewCorpse = Corpse::LoadFromDBData(atoi(row[0]), char_id, row[1], (uchar*) row[2], lengths[2], dest_x, dest_y, dest_z, dest_heading, row[3],atoi(row[4])==1, false);
if(NewCorpse) {
entity_list.AddCorpse(NewCorpse);
if(!UnburyPlayerCorpse(NewCorpse->GetDBID(), dest_zoneid, dest_x, dest_y, dest_z, dest_heading))
LogFile->write(EQEMuLog::Error, "Unable to unbury a summoned player corpse for character id %u.", char_id);
}
else
LogFile->write(EQEMuLog::Error, "Unable to construct a player corpse from a burried player corpse for character id %u.", char_id);
}

mysql_free_result(result);
}
else {
cerr << "Error in SummonBurriedPlayerCorpse query '" << query << "' " << errbuf << endl;
}

safe_delete_array(query);

return NewCorpse;
}

spider661
02-18-2009, 08:32 PM
can this not be done? i have been looking at this code all day and i cant think of a way to do it.. there has got to be somethign a timer that checks a global or something? there has got to be a way to depop all the corpses in the game that belong to the player this command is used on. please any help is better then im doing on my own.

trevius
02-18-2009, 08:41 PM
Sorry, Spider, I would probably try to help, but I am buried up to my neck in stuff to do already. I am sure most of the other devs are as well right now, or they may just not have time to help with this issue. If it was something simple that I was already familiar with, I could probably give some pointers at least, but I don't really know anything about what you are needing and it would take a bit of research for me to even know where to start.

Basically, I am just saying that if you don't get much assistance on this issue, try not to get too upset about it :)

Hopefully someone will see it and know what needs to be done. Most times, I find that if I need help with code, it is hard to get it unless it is something that another coder is interested in. I have alot of code that I have spent quite a bit of time on only to put them aside because I couldn't get it working on my own. Since this code probably isn't something that someone else is currently already wanting to work on, it is probably unlikely that anyone else will. I am not trying to be negative in any way, just trying to let you know why it may be hard to get help with this. Sorry, I couldn't be of any real assistance this time.

BTW, I am sure what you are trying to do can be done. It is just a matter of how to actually do it.

Maybe the code in this post can be of some use to you:

http://www.eqemulator.net/forums/showthread.php?t=26610

spider661
02-18-2009, 09:14 PM
i would be surprised if no one was working on this already im actually surprised its not working already to tell you the truth what im doing s trying to get corpse summoners to work. just going about it thought the summon SummonBurriedPlayerCorpse command just though i would be easier i actually have it all working sept the fact the the body stays in zones that are not reloaded.. say you die in guild lobby then summon your corpse the code makes a new corpse but then it leaves the old one also.. i need o remove the old one so players cant dupe gear then this will be all working.. i wish it worked already but well as we all know it don't.

cavedude
02-18-2009, 09:20 PM
They won't be able to dupe gear. It's two physical bodies, but still only one corpse in the database. As each item/coin is looted, the database is updated meaning it will be updated on each physical body.

However, take a look at the code that depops the corpse entity when its timer expires. You can probably use that to do what you need to.

spider661
02-18-2009, 09:24 PM
cavedude im not understanding what your saying i see the bodys i loot them the loot is on both of them so i dont get y you say it will not dupe the gear grated its not a dupe but its still 2 sets of the same gear.

as for the depop code it works on a timer tied to the corpse so im no sure how that would help with removing the corpse from a diff zone when i cant find the corpse its self. if you could give a small example even if its jsut bull that gives me an idea of what your saying maybe i can work off that but other then that im lost on how it would work?

spider661
02-24-2009, 03:07 PM
ok i got this mostly working but having some probs with body's still laying around that peeps can loot and get the gear off of.. so scene you guys are so busy with other things understandable i figure ill post what i got working and see if someone can find the prob or a fix with what i got.. in all my testing on a server by my self this works perfectly but when i put it on the server with everyone else i breaks so her goes..

client_packet.cpp


void Client::Handle_OP_LootRequest(const EQApplicationPacket *app)
{
if (app->size != sizeof(int32)) {
cout << "Wrong size: OP_LootRequest, size=" << app->size << ", expected " << sizeof(int32) << endl;
return;
}

Entity* ent = entity_list.GetID(*((int32*)app->pBuffer));
////////////////////////ADDED////////////////////////////////
if(ent->IsPlayerCorpse())
{
ent->CastToCorpse()->EndFasleLoot(this, app);
}
///////////////////////END ADDED///////////////////////////////
if (ent == 0) {
Message(13, "Error: OP_LootRequest: Corpse not found (ent = 0)");
Corpse::SendLootReqErrorPacket(this);
return;
}
if (ent->IsCorpse()) {
if(invisible) {
BuffFadeByEffect(SE_Invisibility);
BuffFadeByEffect(SE_Invisibility2);
invisible = false;
}
if(invisible_undead) {
BuffFadeByEffect(SE_InvisVsUndead);
BuffFadeByEffect(SE_InvisVsUndead2);
invisible_undead = false;
}
if(invisible_animals){
BuffFadeByEffect(SE_InvisVsAnimals);
invisible_animals = false;
}
if(hidden || improved_hidden){
hidden = false;
improved_hidden = false;
EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct));
SpawnAppearance_Struct* sa_out = (SpawnAppearance_Struct*)outapp->pBuffer;
sa_out->spawn_id = GetID();
sa_out->type = 0x03;
sa_out->parameter = 0;
entity_list.QueueClients(this, outapp, true);
safe_delete(outapp);
}
ent->CastToCorpse()->MakeLootRequestPackets(this, app);
return;
}
else {
cout << "npc == 0 LOOTING FOOKED3" << endl;
Message(13, "Error: OP_LootRequest: Corpse not a corpse?");
Corpse::SendLootReqErrorPacket(this);
}
return;
}


playercorpse.cpp


Corpse* Corpse::LoadCorpseDBData(int32 in_dbid, int32 in_charid, char* in_charname, uchar* in_data, int32 in_datasize, float in_x, float in_y, float in_z, float in_heading, char* timeofdeath, bool rezzed, bool wasAtGraveyard) {
if (in_datasize < sizeof(DBPlayerCorpse_Struct)) {
cout << "Corpse::LoadFromDBData: Corrupt data: in_datasize < sizeof(DBPlayerCorpse_Struct)" << endl;
return 0;
}
DBPlayerCorpse_Struct* dbpc = (DBPlayerCorpse_Struct*) in_data;
if (in_datasize != (sizeof(DBPlayerCorpse_Struct) + (dbpc->itemcount * sizeof(ServerLootItem_Struct)))) {
cout << "Corpse::LoadFromDBData: Corrupt data: in_datasize != expected size" << endl;
return 0;
}
if (dbpc->crc != CRC32::Generate(&((uchar*) dbpc)[4], in_datasize - 4)) {
cout << "Corpse::LoadFromDBData: Corrupt data: crc failure" << endl;
return 0;
}
ItemList itemlist;
ServerLootItem_Struct* tmp = 0;
for (unsigned int i=0; i < dbpc->itemcount; i++) {
tmp = new ServerLootItem_Struct;
memcpy(tmp, &dbpc->items[i], sizeof(ServerLootItem_Struct));
itemlist.push_back(tmp);
}
Corpse* pc1 = new Corpse(database.GetNextCorpseCount(), in_charid, in_charname, &itemlist, dbpc->copper, dbpc->silver, dbpc->gold, dbpc->plat, in_x, in_y, in_z, in_heading, dbpc->size, dbpc->gender, dbpc->race, dbpc->class_, dbpc->deity, dbpc->level, dbpc->texture, dbpc->helmtexture,dbpc->exp, wasAtGraveyard);
if (dbpc->locked)
pc1->Lock();

// load tints
memcpy(pc1->item_tint, dbpc->item_tint, sizeof(pc1->item_tint));
// appearance
pc1->haircolor = dbpc->haircolor;
pc1->beardcolor = dbpc->beardcolor;
pc1->eyecolor1 = dbpc->eyecolor1;
pc1->eyecolor2 = dbpc->eyecolor2;
pc1->hairstyle = dbpc->hairstyle;
pc1->luclinface = dbpc->face;
pc1->beard = dbpc->beard;
pc1->Rezzed(rezzed);
pc1->become_npc = false;
return pc1;
}

bool Corpse::NotValidCorpse() {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
unsigned long* lengths;
if (database.RunQuery(query, MakeAnyLenString(&query, "SELECT * FROM player_corpses WHERE id='%u' ORDER BY timeofdeath LIMIT 1", dbid), errbuf, &result)) {
row = mysql_fetch_row(result);
lengths = mysql_fetch_lengths(result);
if(row)
return false;
else
return true;
}
}

void Corpse::EndFasleLoot(Client* client, const EQApplicationPacket* app) {
if (this->NotValidCorpse()) {
client->Message(13,"This corpse has already been summoned and is invalid");
EQApplicationPacket* outapp = new EQApplicationPacket;
outapp->SetOpcode(OP_LootComplete);
outapp->size = 0;
client->QueuePacket(outapp);
safe_delete(outapp);

//client->Save(); //inventory operations auto-commit
this->BeingLootedBy = 0xFFFFFFFF;
Delete();
}
}


sint32 ZoneDatabase::GetNextCorpseCount() {
char errbuf[MYSQL_ERRMSG_SIZE];
MYSQL_RES *result;
MYSQL_ROW row;
sint32 ret = -1;

char query[] = "SELECT MAX(id),count(*) FROM player_corpses";
if (RunQuery(query, strlen(query), errbuf, &result)) {
row = mysql_fetch_row(result);
if (row != NULL && row[1] != 0) {
ret = atoi(row[1]);
}
}
mysql_free_result(result);

return ret+1;
}

int32 ZoneDatabase::GetPlayerBurriedCorpseCount(int32 char_id) {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
int32 CorpseCount = 0;
/////////////EDITED/////////////////////////////////////
if (RunQuery(query, MakeAnyLenString(&query, "select count(*) from player_corpses where charid = '%u'", char_id), errbuf, &result)) {
////////////END EDIT///////////////////////////////////
/////////////REMOVED////////////////////////////////////
//if (RunQuery(query, MakeAnyLenString(&query, "select count(*) from player_corpses where charid = '%u' and IsBurried = 1", char_id), errbuf, &result)) {
//////////////END REMOVED/////////////////////////////////
row = mysql_fetch_row(result);
CorpseCount = atoi(row[0]);
mysql_free_result(result);
}
else {
cerr << "Error in GetPlayerBurriedCorpseCount query '" << query << "' " << errbuf << endl;
}

safe_delete_array(query);

return CorpseCount;
}

Corpse* ZoneDatabase::SummonBurriedPlayerCorpse(int32 char_id, int32 dest_zoneid, float dest_x, float dest_y, float dest_z, float dest_heading) {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
Corpse* NewCorpse = 0;
unsigned long* lengths;
/////////////EDITED/////////////////////////////////////
if (RunQuery(query, MakeAnyLenString(&query, "SELECT id, charname, data, timeofdeath, rezzed FROM player_corpses WHERE charid='%u' ORDER BY timeofdeath LIMIT 1", char_id), errbuf, &result)) {
////////////END EDIT///////////////////////////////////
/////////////REMOVED////////////////////////////////////
//if (RunQuery(query, MakeAnyLenString(&query, "SELECT id, charname, data, timeofdeath, rezzed FROM player_corpses WHERE charid='%u' AND IsBurried=1 ORDER BY timeofdeath LIMIT 1", char_id), errbuf, &result)) {
//////////////END REMOVED/////////////////////////////////
row = mysql_fetch_row(result);
lengths = mysql_fetch_lengths(result);
if(row) {
int32 oldid = atoi(row[0]);
NewCorpse = Corpse::LoadCorpseDBData(oldid, char_id, row[1], (uchar*) row[2], lengths[2], dest_x, dest_y, dest_z, dest_heading, row[3],atoi(row[4])==1, false);
if(NewCorpse) {
entity_list.AddCorpse(NewCorpse);
if(!UnburyPlayerCorpse(oldid, dest_zoneid, dest_x, dest_y, dest_z, dest_heading, NewCorpse->GetDBID()))
LogFile->write(EQEMuLog::Error, "Unable to unbury a summoned player corpse for character id %u.", char_id);
}
else
LogFile->write(EQEMuLog::Error, "Unable to construct a player corpse from a burried player corpse for character id %u.", char_id);
}

mysql_free_result(result);
}
else {
cerr << "Error in SummonBurriedPlayerCorpse query '" << query << "' " << errbuf << endl;
}

safe_delete_array(query);

return NewCorpse;
}

/////////ADDED//////////////
bool ZoneDatabase::UnburyPlayerCorpse(int32 dbid, int32 new_zoneid, float new_x, float new_y, float new_z, float new_heading, int32 newid) {
/////////END ADDED/////////
/////////REMOVED///////////
//bool ZoneDatabase::UnburyPlayerCorpse(int32 dbid, int32 new_zoneid, float new_x, float new_y, float new_z, float new_heading) {
/////////END REMOVED///////
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = new char[256];
char* end = query;
int32 affected_rows = 0;
bool Result = false;
end += sprintf(end, "UPDATE player_corpses SET IsBurried=0, id=%u, zoneid=%u, x=%f, y=%f, z=%f, heading=%f, WasAtGraveyard=0 WHERE id=%u", newid, new_zoneid, new_x, new_y, new_z, new_heading, dbid);

if (RunQuery(query, (int32) (end - query), errbuf, 0, &affected_rows)) {
if (affected_rows == 1)
Result = true;
else
cerr << "Error2 in UnburyPlayerCorpse query: affected_rows NOT EQUAL to 1, as expected." << endl;
}
else
cerr << "Error1 in UnburyPlayerCorpse query " << errbuf << endl;

safe_delete_array(query);

return Result;
}


i also put the isvalid check in the rezz code it works when the code works that wil not let you loot it..

so basically what this does is summons a corpse using the SummonBurriedPlayerCorpse quest command.. then it changes the corpse id and then changes the record in the database to the new id hen when you try to loot or rezz a corpse it looks in the database for that corpse id if its there lets you continue if its not there stops and fads the corpse.

something is breaking after you summon the body the id changes the new corpse is lootable.. but sometimes (not all the time) when you go back to a zone where your old body was if the corpse is there it lets you loot it again and get all your gear and money all over again.. that's not supposed to happen it should be invalid at that time and not let you loot it.