Moved zonedatabase functions out of corpse.cpp

Conversion portion mostly complete
Some header readability cleanup
Some function renaming
Struct renaming
Many variable renaming
MySQL error log for all of QueryDatabase
Corpse table renaming
Corpse table field renaming
Most corpse database functions redone
This commit is contained in:
Akkadius 2014-11-22 17:55:48 -06:00
parent 79a70271d5
commit 111fb84041
24 changed files with 1380 additions and 1012 deletions

View File

@ -48,6 +48,7 @@
#include "guilds.h" #include "guilds.h"
#include "string_util.h" #include "string_util.h"
#include "extprofile.h" #include "extprofile.h"
extern Client client; extern Client client;
#ifdef _WINDOWS #ifdef _WINDOWS
@ -1349,7 +1350,6 @@ bool Database::CheckDatabaseConversions() {
printf("Starting conversion...\n\n"); printf("Starting conversion...\n\n");
} }
// Testing account = 11001
int char_iter_count = 0; int char_iter_count = 0;
rquery = StringFormat("SELECT `id` FROM `character_`"); rquery = StringFormat("SELECT `id` FROM `character_`");
results = QueryDatabase(rquery); results = QueryDatabase(rquery);
@ -2084,6 +2084,275 @@ bool Database::CheckDatabaseConversions() {
#endif #endif
DBPlayerCorpse_Struct_temp* dbpc;
classic_db_temp::DBPlayerCorpse_Struct_temp* dbpc_c;
uint32 in_datasize;
bool is_sof = false;
std::string c_type;
std::string scquery;
int8 first_entry = 0;
rquery = StringFormat("SHOW COLUMNS FROM `character_corpses` LIKE 'data'");
results = QueryDatabase(rquery);
if (results.RowCount() != 0){
rquery = StringFormat("SELECT DISTINCT charid FROM character_corpses");
results = QueryDatabase(rquery);
for (auto row = results.begin(); row != results.end(); ++row) {
squery = StringFormat("SELECT id, charname, data, time_of_death, is_rezzed FROM character_corpses WHERE `charid` = %i", atoi(row[0]));
auto results2 = QueryDatabase(squery);
for (auto row2 = results2.begin(); row2 != results2.end(); ++row2) {
in_datasize = results2.LengthOfColumn(2);
dbpc = (DBPlayerCorpse_Struct_temp*)row2[2];
dbpc_c = (classic_db_temp::DBPlayerCorpse_Struct_temp*)row2[2];
if (dbpc == nullptr)
continue;
if (dbpc_c == nullptr)
continue;
/* SoF+ */
uint32 esize1 = (sizeof(DBPlayerCorpse_Struct_temp)+(dbpc->itemcount * sizeof(player_lootitem_temp::ServerLootItem_Struct_temp)));
uint32 esize2 = (sizeof(classic_db_temp::DBPlayerCorpse_Struct_temp) + (dbpc_c->itemcount * sizeof(player_lootitem_temp::ServerLootItem_Struct_temp)));
/* SoF */
if (in_datasize == esize1) {
is_sof = true;
c_type = "SOF";
}
/* Classic */
if (in_datasize == esize2) {
is_sof = false;
c_type = "Legacy";
}
if (in_datasize != esize2 && in_datasize != esize1) {
std::cout << "[Error] in Corpse Size - OLD SIZE: " << esize1 << " SOF SIZE: " << esize2 << " db_blob_datasize: " << in_datasize << std::endl;
is_sof = false;
c_type = "NULL";
continue;
}
std::cout << "Corpse: OK [" << c_type << "]: " << "Corpse ID: " << atoi(row2[0]) << std::endl;
if (is_sof){
scquery = StringFormat("UPDATE `character_corpses` SET \n"
"`is_locked` = %d,\n"
"`exp` = %u,\n"
"`size` = %f,\n"
"`level` = %u,\n"
"`race` = %u,\n"
"`gender` = %u,\n"
"`class` = %u,\n"
"`deity` = %u,\n"
"`texture` = %u,\n"
"`helm_texture` = %u,\n"
"`copper` = %u,\n"
"`silver` = %u,\n"
"`gold` = %u,\n"
"`platinum` = %u,\n"
"`hair_color` = %u,\n"
"`beard_color` = %u,\n"
"`eye_color_1` = %u,\n"
"`eye_color_2` = %u,\n"
"`hair_style` = %u,\n"
"`face` = %u,\n"
"`beard` = %u,\n"
"`drakkin_heritage` = %u,\n"
"`drakkin_tattoo` = %u,\n"
"`drakkin_details` = %u,\n"
"`wc_1` = %u,\n"
"`wc_2` = %u,\n"
"`wc_3` = %u,\n"
"`wc_4` = %u,\n"
"`wc_5` = %u,\n"
"`wc_6` = %u,\n"
"`wc_7` = %u,\n"
"`wc_8` = %u,\n"
"`wc_9` = %u \n"
"WHERE `id` = %u \n",
dbpc->locked,
dbpc->exp,
dbpc->size,
dbpc->level,
dbpc->race,
dbpc->gender,
dbpc->class_,
dbpc->deity,
dbpc->texture,
dbpc->helmtexture,
dbpc->copper,
dbpc->silver,
dbpc->gold,
dbpc->plat,
dbpc->haircolor,
dbpc->beardcolor,
dbpc->eyecolor1,
dbpc->eyecolor2,
dbpc->hairstyle,
dbpc->face,
dbpc->beard,
dbpc->drakkin_heritage,
dbpc->drakkin_tattoo,
dbpc->drakkin_details,
dbpc->item_tint[0].color,
dbpc->item_tint[1].color,
dbpc->item_tint[2].color,
dbpc->item_tint[3].color,
dbpc->item_tint[4].color,
dbpc->item_tint[5].color,
dbpc->item_tint[6].color,
dbpc->item_tint[7].color,
dbpc->item_tint[8].color,
atoi(row2[0])
);
if (scquery != ""){ auto sc_results = QueryDatabase(scquery); ThrowDBError(sc_results.ErrorMessage(), "Corpse Convert: Base Data", scquery); }
first_entry = 0;
scquery = "";
/* Print Items */
for (unsigned int i = 0; i < dbpc->itemcount; i++) {
if (first_entry != 1){
scquery = StringFormat("REPLACE INTO `character_corpse_items` \n"
" (corpse_id, equip_slot, item_id, charges, aug_1, aug_2, aug_3, aug_4, aug_5, attuned) \n"
" VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, 0) \n",
atoi(row2[0]),
dbpc->items[i].equipSlot,
dbpc->items[i].item_id,
dbpc->items[i].charges,
dbpc->items[i].aug1,
dbpc->items[i].aug2,
dbpc->items[i].aug3,
dbpc->items[i].aug4,
dbpc->items[i].aug5
);
first_entry = 1;
}
else{
scquery = scquery + StringFormat(", (%u, %u, %u, %u, %u, %u, %u, %u, %u, 0) \n",
atoi(row2[0]),
dbpc->items[i].equipSlot,
dbpc->items[i].item_id,
dbpc->items[i].charges,
dbpc->items[i].aug1,
dbpc->items[i].aug2,
dbpc->items[i].aug3,
dbpc->items[i].aug4,
dbpc->items[i].aug5
);
}
}
if (scquery != ""){ auto sc_results = QueryDatabase(scquery); ThrowDBError(sc_results.ErrorMessage(), "Corpse Convert: SOF: Items", scquery); }
}
else{
/* Classic Converter */
scquery = StringFormat("UPDATE `character_corpses` SET \n"
"`is_locked` = %d,\n"
"`exp` = %u,\n"
"`size` = %f,\n"
"`level` = %u,\n"
"`race` = %u,\n"
"`gender` = %u,\n"
"`class` = %u,\n"
"`deity` = %u,\n"
"`texture` = %u,\n"
"`helm_texture` = %u,\n"
"`copper` = %u,\n"
"`silver` = %u,\n"
"`gold` = %u,\n"
"`platinum` = %u,\n"
"`hair_color` = %u,\n"
"`beard_color` = %u,\n"
"`eye_color_1` = %u,\n"
"`eye_color_2` = %u,\n"
"`hair_style` = %u,\n"
"`face` = %u,\n"
"`beard` = %u,\n"
"`wc_1` = %u,\n"
"`wc_2` = %u,\n"
"`wc_3` = %u,\n"
"`wc_4` = %u,\n"
"`wc_5` = %u,\n"
"`wc_6` = %u,\n"
"`wc_7` = %u,\n"
"`wc_8` = %u,\n"
"`wc_9` = %u \n"
"WHERE `id` = %u \n",
dbpc_c->locked,
dbpc_c->exp,
dbpc_c->size,
dbpc_c->level,
dbpc_c->race,
dbpc_c->gender,
dbpc_c->class_,
dbpc_c->deity,
dbpc_c->texture,
dbpc_c->helmtexture,
dbpc_c->copper,
dbpc_c->silver,
dbpc_c->gold,
dbpc_c->plat,
dbpc_c->haircolor,
dbpc_c->beardcolor,
dbpc_c->eyecolor1,
dbpc_c->eyecolor2,
dbpc_c->hairstyle,
dbpc_c->face,
dbpc_c->beard,
dbpc_c->item_tint[0].color,
dbpc_c->item_tint[1].color,
dbpc_c->item_tint[2].color,
dbpc_c->item_tint[3].color,
dbpc_c->item_tint[4].color,
dbpc_c->item_tint[5].color,
dbpc_c->item_tint[6].color,
dbpc_c->item_tint[7].color,
dbpc_c->item_tint[8].color,
atoi(row2[0])
);
if (scquery != ""){ auto sc_results = QueryDatabase(scquery); ThrowDBError(sc_results.ErrorMessage(), "Corpse Convert: Legacy :: Base Data", scquery); }
first_entry = 0;
scquery = "";
/* Print Items */
for (unsigned int i = 0; i < dbpc_c->itemcount; i++) {
if (first_entry != 1){
scquery = StringFormat("REPLACE INTO `character_corpse_items` \n"
" (corpse_id, equip_slot, item_id, charges, aug_1, aug_2, aug_3, aug_4, aug_5, attuned) \n"
" VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, 0) \n",
atoi(row2[0]),
dbpc_c->items[i].equipSlot,
dbpc_c->items[i].item_id,
dbpc_c->items[i].charges,
dbpc_c->items[i].aug1,
dbpc_c->items[i].aug2,
dbpc_c->items[i].aug3,
dbpc_c->items[i].aug4,
dbpc_c->items[i].aug5
);
first_entry = 1;
}
else{
scquery = scquery + StringFormat(", (%u, %u, %u, %u, %u, %u, %u, %u, %u, 0) \n",
atoi(row2[0]),
dbpc_c->items[i].equipSlot,
dbpc_c->items[i].item_id,
dbpc_c->items[i].charges,
dbpc_c->items[i].aug1,
dbpc_c->items[i].aug2,
dbpc_c->items[i].aug3,
dbpc_c->items[i].aug4,
dbpc_c->items[i].aug5
);
}
}
if (scquery != ""){ auto sc_results = QueryDatabase(scquery); ThrowDBError(sc_results.ErrorMessage(), "Corpse Convert: Legacy : Items", scquery); }
}
}
}
QueryDatabase(StringFormat("ALTER TABLE `character_corpses` DROP COLUMN `data`"));
}
/* Fetch Automatic Database Upgrade Script */ /* Fetch Automatic Database Upgrade Script */
if (!std::ifstream("db_update.pl")){ if (!std::ifstream("db_update.pl")){
std::cout << "Pulling down automatic database upgrade script...\n" << std::endl; std::cout << "Pulling down automatic database upgrade script...\n" << std::endl;
@ -2093,8 +2362,8 @@ bool Database::CheckDatabaseConversions() {
system("wget -O db_update.pl https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/db_update.pl"); system("wget -O db_update.pl https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/db_update.pl");
#endif #endif
} }
/* Run Automatic Database Upgrade Script */
/* Run Automatic Database Upgrade Script */
system("perl db_update.pl ran_from_world"); system("perl db_update.pl ran_from_world");
return true; return true;
@ -3659,7 +3928,7 @@ bool Database::CheckInstanceExists(uint16 instance_id)
void Database::BuryCorpsesInInstance(uint16 instance_id) void Database::BuryCorpsesInInstance(uint16 instance_id)
{ {
std::string query = StringFormat("UPDATE player_corpses SET IsBurried=1, instanceid=0 WHERE instanceid=%u", instance_id); std::string query = StringFormat("UPDATE character_corpses SET IsBurried=1, instanceid=0 WHERE instanceid=%u", instance_id);
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
} }

View File

@ -93,6 +93,87 @@ struct ExtendedProfile_Struct;
struct GuildMember_Struct; struct GuildMember_Struct;
class PTimerList; class PTimerList;
#pragma pack(1)
namespace player_lootitem_temp
{
struct ServerLootItem_Struct_temp {
uint32 item_id;
int16 equipSlot;
uint8 charges;
uint16 lootslot;
uint32 aug1;
uint32 aug2;
uint32 aug3;
uint32 aug4;
uint32 aug5;
};
}
struct DBPlayerCorpse_Struct_temp {
uint32 crc;
bool locked;
uint32 itemcount;
uint32 exp;
float size;
uint8 level;
uint8 race;
uint8 gender;
uint8 class_;
uint8 deity;
uint8 texture;
uint8 helmtexture;
uint32 copper;
uint32 silver;
uint32 gold;
uint32 plat;
Color_Struct item_tint[9];
uint8 haircolor;
uint8 beardcolor;
uint8 eyecolor1;
uint8 eyecolor2;
uint8 hairstyle;
uint8 face;
uint8 beard;
uint32 drakkin_heritage;
uint32 drakkin_tattoo;
uint32 drakkin_details;
player_lootitem_temp::ServerLootItem_Struct_temp items[0];
};
namespace classic_db_temp
{
struct DBPlayerCorpse_Struct_temp {
uint32 crc;
bool locked;
uint32 itemcount;
uint32 exp;
float size;
uint8 level;
uint8 race;
uint8 gender;
uint8 class_;
uint8 deity;
uint8 texture;
uint8 helmtexture;
uint32 copper;
uint32 silver;
uint32 gold;
uint32 plat;
Color_Struct item_tint[9];
uint8 haircolor;
uint8 beardcolor;
uint8 eyecolor1;
uint8 eyecolor2;
uint8 hairstyle;
uint8 face;
uint8 beard;
player_lootitem_temp::ServerLootItem_Struct_temp items[0];
};
}
#pragma pack()
class Database : public DBcore { class Database : public DBcore {
public: public:
Database(); Database();

View File

@ -4,6 +4,7 @@
#include <winsock2.h> #include <winsock2.h>
#endif #endif
#include <fstream>
#include <iostream> #include <iostream>
#include <errmsg.h> #include <errmsg.h>
#include <mysqld_error.h> #include <mysqld_error.h>
@ -126,6 +127,16 @@ MySQLRequestResult DBcore::QueryDatabase(const char* query, uint32 querylen, boo
MySQLRequestResult requestResult(res, (uint32)mysql_affected_rows(&mysql), rowCount, (uint32)mysql_field_count(&mysql), (uint32)mysql_insert_id(&mysql)); MySQLRequestResult requestResult(res, (uint32)mysql_affected_rows(&mysql), rowCount, (uint32)mysql_field_count(&mysql), (uint32)mysql_insert_id(&mysql));
/* Implement Logging at the Root*/
if (requestResult.ErrorMessage() != ""){
std::cout << "\n[MYSQL ERR] " << requestResult.ErrorMessage() << "\n\n" << query << "\n" << std::endl;
/* Write to log file */
std::ofstream log("eqemu_query_error_log.txt", std::ios_base::app | std::ios_base::out);
log << "[MYSQL ERR] " << requestResult.ErrorMessage() << "\n" << query << "\n";
log.close();
}
#if DEBUG_MYSQL_QUERIES >= 1 #if DEBUG_MYSQL_QUERIES >= 1
if (requestResult.Success()) if (requestResult.Success())

View File

@ -1217,8 +1217,8 @@ ItemInst* SharedDatabase::CreateBaseItem(const Item_Struct* item, int16 charges)
int32 SharedDatabase::DeleteStalePlayerCorpses() { int32 SharedDatabase::DeleteStalePlayerCorpses() {
if(RuleB(Zone, EnableShadowrest)) if(RuleB(Zone, EnableShadowrest))
{ {
std::string query = StringFormat("UPDATE player_corpses SET IsBurried = 1 WHERE IsBurried = 0 AND " std::string query = StringFormat("UPDATE character_corpses SET IsBurried = 1 WHERE IsBurried = 0 AND "
"(UNIX_TIMESTAMP() - UNIX_TIMESTAMP(timeofdeath)) > %d AND NOT timeofdeath = 0", "(UNIX_TIMESTAMP() - UNIX_TIMESTAMP(time_of_death)) > %d AND NOT time_of_death = 0",
(RuleI(Character, CorpseDecayTimeMS) / 1000)); (RuleI(Character, CorpseDecayTimeMS) / 1000));
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success()) if (!results.Success())
@ -1227,8 +1227,8 @@ int32 SharedDatabase::DeleteStalePlayerCorpses() {
return results.RowsAffected(); return results.RowsAffected();
} }
std::string query = StringFormat("DELETE FROM player_corpses WHERE (UNIX_TIMESTAMP() - UNIX_TIMESTAMP(timeofdeath)) > %d " std::string query = StringFormat("DELETE FROM character_corpses WHERE (UNIX_TIMESTAMP() - UNIX_TIMESTAMP(time_of_death)) > %d "
"AND NOT timeofdeath = 0", (RuleI(Character, CorpseDecayTimeMS) / 1000)); "AND NOT time_of_death = 0", (RuleI(Character, CorpseDecayTimeMS) / 1000));
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success()) if (!results.Success())
return -1; return -1;
@ -1238,7 +1238,7 @@ int32 SharedDatabase::DeleteStalePlayerCorpses() {
int32 SharedDatabase::DeleteStalePlayerBackups() { int32 SharedDatabase::DeleteStalePlayerBackups() {
// 1209600 seconds = 2 weeks // 1209600 seconds = 2 weeks
const std::string query = "DELETE FROM player_corpses_backup WHERE (UNIX_TIMESTAMP() - UNIX_TIMESTAMP(timeofdeath)) > 1209600"; const std::string query = "DELETE FROM player_corpses_backup WHERE (UNIX_TIMESTAMP() - UNIX_TIMESTAMP(time_of_death)) > 1209600";
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success()) if (!results.Success())
return -1; return -1;

View File

@ -376,7 +376,7 @@ void Adventure::MoveCorpsesToGraveyard()
std::list<uint32> dbid_list; std::list<uint32> dbid_list;
std::list<uint32> charid_list; std::list<uint32> charid_list;
std::string query = StringFormat("SELECT id, charid FROM player_corpses WHERE instanceid=%d", GetInstanceID()); std::string query = StringFormat("SELECT id, charid FROM character_corpses WHERE instanceid=%d", GetInstanceID());
auto results = database.QueryDatabase(query); auto results = database.QueryDatabase(query);
if(!results.Success()) if(!results.Success())
LogFile->write(EQEMuLog::Error, "Error in AdventureManager:::MoveCorpsesToGraveyard: %s (%s)", query.c_str(), results.ErrorMessage().c_str()); LogFile->write(EQEMuLog::Error, "Error in AdventureManager:::MoveCorpsesToGraveyard: %s (%s)", query.c_str(), results.ErrorMessage().c_str());
@ -392,7 +392,7 @@ void Adventure::MoveCorpsesToGraveyard()
float y = GetTemplate()->graveyard_y + MakeRandomFloat(-GetTemplate()->graveyard_radius, GetTemplate()->graveyard_radius); float y = GetTemplate()->graveyard_y + MakeRandomFloat(-GetTemplate()->graveyard_radius, GetTemplate()->graveyard_radius);
float z = GetTemplate()->graveyard_z; float z = GetTemplate()->graveyard_z;
query = StringFormat("UPDATE player_corpses " query = StringFormat("UPDATE character_corpses "
"SET zoneid = %d, instanceid = 0, " "SET zoneid = %d, instanceid = 0, "
"x = %f, y = %f, z = %f WHERE instanceid = %d", "x = %f, y = %f, z = %f WHERE instanceid = %d",
GetTemplate()->graveyard_zone_id, GetTemplate()->graveyard_zone_id,

View File

@ -4969,7 +4969,7 @@ void Client::SummonAndRezzAllCorpses()
entity_list.RemoveAllCorpsesByCharID(CharacterID()); entity_list.RemoveAllCorpsesByCharID(CharacterID());
int CorpseCount = database.SummonAllPlayerCorpses(CharacterID(), zone->GetZoneID(), zone->GetInstanceID(), int CorpseCount = database.SummonAllCharacterCorpses(CharacterID(), zone->GetZoneID(), zone->GetInstanceID(),
GetX(), GetY(), GetZ(), GetHeading()); GetX(), GetY(), GetZ(), GetHeading());
if(CorpseCount <= 0) if(CorpseCount <= 0)
{ {
@ -5007,7 +5007,7 @@ void Client::SummonAllCorpses(float dest_x, float dest_y, float dest_z, float de
entity_list.RemoveAllCorpsesByCharID(CharacterID()); entity_list.RemoveAllCorpsesByCharID(CharacterID());
int CorpseCount = database.SummonAllPlayerCorpses(CharacterID(), zone->GetZoneID(), zone->GetInstanceID(), int CorpseCount = database.SummonAllCharacterCorpses(CharacterID(), zone->GetZoneID(), zone->GetInstanceID(),
dest_x, dest_y, dest_z, dest_heading); dest_x, dest_y, dest_z, dest_heading);
if(CorpseCount <= 0) if(CorpseCount <= 0)
{ {
@ -5051,7 +5051,7 @@ void Client::DepopPlayerCorpse(uint32 dbid)
void Client::BuryPlayerCorpses() void Client::BuryPlayerCorpses()
{ {
database.BuryAllPlayerCorpses(CharacterID()); database.BuryAllCharacterCorpses(CharacterID());
} }
void Client::NotifyNewTitlesAvailable() void Client::NotifyNewTitlesAvailable()

View File

@ -1031,9 +1031,9 @@ void SetConsumption(int32 in_hunger, int32 in_thirst);
void DepopAllCorpses(); void DepopAllCorpses();
void DepopPlayerCorpse(uint32 dbid); void DepopPlayerCorpse(uint32 dbid);
void BuryPlayerCorpses(); void BuryPlayerCorpses();
uint32 GetCorpseCount() { return database.GetPlayerCorpseCount(CharacterID()); } uint32 GetCorpseCount() { return database.GetCharacterCorpseCount(CharacterID()); }
uint32 GetCorpseID(int corpse) { return database.GetPlayerCorpseID(CharacterID(), corpse); } uint32 GetCorpseID(int corpse) { return database.GetCharacterCorpseID(CharacterID(), corpse); }
uint32 GetCorpseItemAt(int corpse_id, int slot_id) { return database.GetPlayerCorpseItemAt(corpse_id, slot_id); } uint32 GetCorpseItemAt(int corpse_id, int slot_id) { return database.GetCharacterCorpseItemAt(corpse_id, slot_id); }
void SuspendMinion(); void SuspendMinion();
void Doppelganger(uint16 spell_id, Mob *target, const char *name_override, int pet_count, int pet_duration); void Doppelganger(uint16 spell_id, Mob *target, const char *name_override, int pet_count, int pet_duration);
void NotifyNewTitlesAvailable(); void NotifyNewTitlesAvailable();

View File

@ -4827,7 +4827,7 @@ void Client::Handle_OP_ConsiderCorpse(const EQApplicationPacket *app)
else else
Message(0, "This corpse will decay in %i minutes and %i seconds.", min, sec); Message(0, "This corpse will decay in %i minutes and %i seconds.", min, sec);
Message(0, "This corpse %s be resurrected.", tcorpse->Rezzed() ? "cannot" : "can"); Message(0, "This corpse %s be resurrected.", tcorpse->IsRezzed() ? "cannot" : "can");
/* /*
hour = 0; hour = 0;
@ -6175,8 +6175,8 @@ void Client::Handle_OP_GMSearchCorpse(const EQApplicationPacket *app)
char *escSearchString = new char[129]; char *escSearchString = new char[129];
database.DoEscapeString(escSearchString, gmscs->Name, strlen(gmscs->Name)); database.DoEscapeString(escSearchString, gmscs->Name, strlen(gmscs->Name));
std::string query = StringFormat("SELECT charname, zoneid, x, y, z, timeofdeath, rezzed, IsBurried " std::string query = StringFormat("SELECT charname, zoneid, x, y, z, time_of_death, rezzed, IsBurried "
"FROM player_corpses WheRE charname LIKE '%%%s%%' ORDER BY charname LIMIT %i", "FROM character_corpses WheRE charname LIKE '%%%s%%' ORDER BY charname LIMIT %i",
escSearchString, maxResults); escSearchString, maxResults);
safe_delete_array(escSearchString); safe_delete_array(escSearchString);
auto results = database.QueryDatabase(query); auto results = database.QueryDatabase(query);
@ -6193,7 +6193,7 @@ void Client::Handle_OP_GMSearchCorpse(const EQApplicationPacket *app)
else else
Message(clientMessageYellow, "There are %i corpse(s) that match the search string '%s'.", results.RowCount(), gmscs->Name); Message(clientMessageYellow, "There are %i corpse(s) that match the search string '%s'.", results.RowCount(), gmscs->Name);
char charName[64], timeOfDeath[20]; char charName[64], time_of_death[20];
std::string popupText = "<table><tr><td>Name</td><td>Zone</td><td>X</td><td>Y</td><td>Z</td><td>Date</td><td>" std::string popupText = "<table><tr><td>Name</td><td>Zone</td><td>X</td><td>Y</td><td>Z</td><td>Date</td><td>"
"Rezzed</td><td>Buried</td></tr><tr><td>&nbsp</td><td></td><td></td><td></td><td></td><td>" "Rezzed</td><td>Buried</td></tr><tr><td>&nbsp</td><td></td><td></td><td></td><td></td><td>"
@ -6208,13 +6208,13 @@ void Client::Handle_OP_GMSearchCorpse(const EQApplicationPacket *app)
float CorpseY = atof(row[3]); float CorpseY = atof(row[3]);
float CorpseZ = atof(row[4]); float CorpseZ = atof(row[4]);
strn0cpy(timeOfDeath, row[5], sizeof(timeOfDeath)); strn0cpy(time_of_death, row[5], sizeof(time_of_death));
bool corpseRezzed = atoi(row[6]); bool corpseRezzed = atoi(row[6]);
bool corpseBuried = atoi(row[7]); bool corpseBuried = atoi(row[7]);
popupText += StringFormat("<tr><td>%s</td><td>%s</td><td>%8.0f</td><td>%8.0f</td><td>%8.0f</td><td>%s</td><td>%s</td><td>%s</td></tr>", popupText += StringFormat("<tr><td>%s</td><td>%s</td><td>%8.0f</td><td>%8.0f</td><td>%8.0f</td><td>%s</td><td>%s</td><td>%s</td></tr>",
charName, StaticGetZoneName(ZoneID), CorpseX, CorpseY, CorpseZ, timeOfDeath, charName, StaticGetZoneName(ZoneID), CorpseX, CorpseY, CorpseZ, time_of_death,
corpseRezzed ? "Yes" : "No", corpseBuried ? "Yes" : "No"); corpseRezzed ? "Yes" : "No", corpseBuried ? "Yes" : "No");
if (popupText.size() > 4000) { if (popupText.size() > 4000) {

View File

@ -2173,7 +2173,7 @@ void Client::HandleRespawnFromHover(uint32 Option)
_log(SPELLS__REZ, "Found corpse. Marking corpse as rezzed."); _log(SPELLS__REZ, "Found corpse. Marking corpse as rezzed.");
corpse->Rezzed(true); corpse->IsRezzed(true);
corpse->CompleteRezz(); corpse->CompleteRezz();
} }
} }

View File

@ -8456,7 +8456,7 @@ void command_setgraveyard(Client *c, const Seperator *sep)
zoneid = database.GetZoneID(sep->arg[1]); zoneid = database.GetZoneID(sep->arg[1]);
if(zoneid > 0) { if(zoneid > 0) {
graveyard_id = database.NewGraveyardRecord(zoneid, t->GetX(), t->GetY(), t->GetZ(), t->GetHeading()); graveyard_id = database.CreateGraveyardRecord(zoneid, t->GetX(), t->GetY(), t->GetZ(), t->GetHeading());
if(graveyard_id > 0) { if(graveyard_id > 0) {
c->Message(0, "Successfuly added a new record for this graveyard!"); c->Message(0, "Successfuly added a new record for this graveyard!");
@ -8519,7 +8519,7 @@ void command_summonburriedplayercorpse(Client *c, const Seperator *sep)
return; return;
} }
Corpse* PlayerCorpse = database.SummonBurriedPlayerCorpse(t->CharacterID(), t->GetZoneID(), zone->GetInstanceID(), t->GetX(), t->GetY(), t->GetZ(), t->GetHeading()); Corpse* PlayerCorpse = database.SummonBuriedCharacterCorpses(t->CharacterID(), t->GetZoneID(), zone->GetInstanceID(), t->GetX(), t->GetY(), t->GetZ(), t->GetHeading());
if(!PlayerCorpse) if(!PlayerCorpse)
c->Message(0, "Your target doesn't have any burried corpses."); c->Message(0, "Your target doesn't have any burried corpses.");
@ -8538,7 +8538,7 @@ void command_getplayerburriedcorpsecount(Client *c, const Seperator *sep)
return; return;
} }
uint32 CorpseCount = database.GetPlayerBurriedCorpseCount(t->CharacterID()); uint32 CorpseCount = database.GetCharacterBuriedCorpseCount(t->CharacterID());
if(CorpseCount > 0) if(CorpseCount > 0)
c->Message(0, "Your target has a total of %u burried corpses.", CorpseCount); c->Message(0, "Your target has a total of %u burried corpses.", CorpseCount);

View File

@ -63,132 +63,41 @@ void Corpse::SendLootReqErrorPacket(Client* client, uint8 response) {
safe_delete(outapp); safe_delete(outapp);
} }
Corpse* Corpse::LoadFromDBData(uint32 in_dbid, uint32 in_charid, char* in_charname, uchar* in_data, uint32 in_datasize, float in_x, float in_y, float in_z, float in_heading, char* timeofdeath, bool rezzed, bool wasAtGraveyard) { Corpse* Corpse::LoadFromDBData(uint32 in_dbid, uint32 in_charid, char* in_charname, PlayerCorpse_Struct* pcs, float in_x, float in_y, float in_z, float in_heading, char* time_of_death, bool rezzed, bool was_at_graveyard) {
if (in_datasize < sizeof(classic_db::DBPlayerCorpse_Struct)) { /* Load Items */
LogFile->write(EQEMuLog::Error, "Corpse::LoadFromDBData: Corrupt data: in_datasize < sizeof(DBPlayerCorpse_Struct)");
return 0;
}
classic_db::DBPlayerCorpse_Struct* dbpc = (classic_db::DBPlayerCorpse_Struct*) in_data;
bool isSoF = true;
uint32 esize1 = (sizeof(DBPlayerCorpse_Struct) + (dbpc->itemcount * sizeof(player_lootitem::ServerLootItem_Struct)));
uint32 esize2 = (sizeof(classic_db::DBPlayerCorpse_Struct) + (dbpc->itemcount * sizeof(player_lootitem::ServerLootItem_Struct)));
if (in_datasize != esize1) {
LogFile->write(EQEMuLog::Error, "Corpse::LoadFromDBData: Corrupt data: in_datasize (%i) != expected size (%i) Continuing on...", in_datasize, esize1);
if (in_datasize != esize2) {
LogFile->write(EQEMuLog::Error, "Corpse::LoadFromDBData: Corrupt data: in_datasize (%i) != expected size (%i) Your corpse is done broke, sir.", in_datasize, esize2);
return 0;
}
else
{
isSoF = false;
}
}
if(isSoF)
{
DBPlayerCorpse_Struct* dbpcs = (DBPlayerCorpse_Struct*) in_data;
if (dbpcs->crc != CRC32::Generate(&((uchar*) dbpcs)[4], in_datasize - 4)) {
LogFile->write(EQEMuLog::Error, "Corpse::LoadFromDBData: Corrupt data: crc failure");
return 0;
}
ItemList itemlist; ItemList itemlist;
ServerLootItem_Struct* tmp = 0; ServerLootItem_Struct* tmp = 0;
for (unsigned int i=0; i < dbpcs->itemcount; i++) { for (unsigned int i = 0; i < pcs->itemcount; i++) {
tmp = new ServerLootItem_Struct; tmp = new ServerLootItem_Struct;
memcpy(tmp, &dbpcs->items[i], sizeof(player_lootitem::ServerLootItem_Struct)); memcpy(tmp, &pcs->items[i], sizeof(player_lootitem::ServerLootItem_Struct));
tmp->equipSlot = CorpseToServerSlot(tmp->equipSlot); // temp hack until corpse blobs are removed tmp->equipSlot = CorpseToServerSlot(tmp->equipSlot);
itemlist.push_back(tmp); itemlist.push_back(tmp);
} }
// Little hack to account for the fact the race in the corpse struct is a uint8 and Froglok/Drakkin race number > 255 /* Create Corpse Entity */
// and to maintain backwards compatability with existing corpses in the database. Corpse* pc = new Corpse(in_dbid, in_charid, in_charname, &itemlist, pcs->copper, pcs->silver, pcs->gold, pcs->plat, in_x, in_y, in_z, in_heading, pcs->size, pcs->gender, pcs->race, pcs->class_, pcs->deity, pcs->level, pcs->texture, pcs->helmtexture, pcs->exp, was_at_graveyard);
uint16 RealRace; if (pcs->locked)
switch(dbpcs->race) {
case 254:
RealRace = DRAKKIN;
break;
case 255:
RealRace = FROGLOK;
break;
default:
RealRace = dbpc->race;
}
Corpse* pc = new Corpse(in_dbid, in_charid, in_charname, &itemlist, dbpcs->copper, dbpcs->silver, dbpcs->gold, dbpcs->plat, in_x, in_y, in_z, in_heading, dbpcs->size, dbpcs->gender, RealRace, dbpcs->class_, dbpcs->deity, dbpcs->level, dbpcs->texture, dbpcs->helmtexture, dbpcs->exp, wasAtGraveyard);
if (dbpcs->locked)
pc->Lock(); pc->Lock();
// load tints /* Load Item Tints */
memcpy(pc->item_tint, dbpcs->item_tint, sizeof(pc->item_tint)); memcpy(pc->item_tint, pcs->item_tint, sizeof(pc->item_tint));
// appearance
pc->haircolor = dbpcs->haircolor; /* Load Physical Appearance */
pc->beardcolor = dbpcs->beardcolor; pc->haircolor = pcs->haircolor;
pc->eyecolor1 = dbpcs->eyecolor1; pc->beardcolor = pcs->beardcolor;
pc->eyecolor2 = dbpcs->eyecolor2; pc->eyecolor1 = pcs->eyecolor1;
pc->hairstyle = dbpcs->hairstyle; pc->eyecolor2 = pcs->eyecolor2;
pc->luclinface = dbpcs->face; pc->hairstyle = pcs->hairstyle;
pc->beard = dbpcs->beard; pc->luclinface = pcs->face;
pc->drakkin_heritage = dbpcs->drakkin_heritage; pc->beard = pcs->beard;
pc->drakkin_tattoo = dbpcs->drakkin_tattoo; pc->drakkin_heritage = pcs->drakkin_heritage;
pc->drakkin_details = dbpcs->drakkin_details; pc->drakkin_tattoo = pcs->drakkin_tattoo;
pc->Rezzed(rezzed); pc->drakkin_details = pcs->drakkin_details;
pc->IsRezzed(rezzed);
pc->become_npc = false; pc->become_npc = false;
return pc; return pc;
} }
else
{
if (dbpc->crc != CRC32::Generate(&((uchar*) dbpc)[4], in_datasize - 4)) {
LogFile->write(EQEMuLog::Error, "Corpse::LoadFromDBData: Corrupt data: crc failure");
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(player_lootitem::ServerLootItem_Struct));
tmp->equipSlot = CorpseToServerSlot(tmp->equipSlot); // temp hack until corpse blobs are removed
itemlist.push_back(tmp);
}
// Little hack to account for the fact the race in the corpse struct is a uint8 and Froglok/Drakkin race number > 255
// and to maintain backwards compatability with existing corpses in the database.
uint16 RealRace;
switch(dbpc->race) {
case 254:
RealRace = DRAKKIN;
break;
case 255:
RealRace = FROGLOK;
break;
default:
RealRace = dbpc->race;
}
Corpse* pc = new Corpse(in_dbid, 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, RealRace, dbpc->class_, dbpc->deity, dbpc->level, dbpc->texture, dbpc->helmtexture,dbpc->exp, wasAtGraveyard);
if (dbpc->locked)
pc->Lock();
// load tints
memcpy(pc->item_tint, dbpc->item_tint, sizeof(pc->item_tint));
// appearance
pc->haircolor = dbpc->haircolor;
pc->beardcolor = dbpc->beardcolor;
pc->eyecolor1 = dbpc->eyecolor1;
pc->eyecolor2 = dbpc->eyecolor2;
pc->hairstyle = dbpc->hairstyle;
pc->luclinface = dbpc->face;
pc->beard = dbpc->beard;
pc->drakkin_heritage = 0;
pc->drakkin_tattoo = 0;
pc->drakkin_details = 0;
pc->Rezzed(rezzed);
pc->become_npc = false;
return pc;
}
}
// To be used on NPC death and ZoneStateLoad // To be used on NPC death and ZoneStateLoad
// Mongrel: added see_invis and see_invis_undead // Mongrel: added see_invis and see_invis_undead
@ -222,7 +131,7 @@ Corpse::Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NP
npctype_id = in_npctypeid; npctype_id = in_npctypeid;
SetPKItem(0); SetPKItem(0);
charid = 0; charid = 0;
dbid = 0; corpse_db_id = 0;
p_depop = false; p_depop = false;
strcpy(orgname, in_npc->GetName()); strcpy(orgname, in_npc->GetName());
strcpy(name, in_npc->GetName()); strcpy(name, in_npc->GetName());
@ -331,7 +240,7 @@ Corpse::Corpse(Client* client, int32 in_rezexp)
pLocked = false; pLocked = false;
BeingLootedBy = 0xFFFFFFFF; BeingLootedBy = 0xFFFFFFFF;
charid = client->CharacterID(); charid = client->CharacterID();
dbid = 0; corpse_db_id = 0;
p_depop = false; p_depop = false;
copper = 0; copper = 0;
silver = 0; silver = 0;
@ -435,14 +344,14 @@ Corpse::Corpse(Client* client, int32 in_rezexp)
client->CalcBonuses(); // will only affect offline profile viewing of dead characters..unneeded overhead client->CalcBonuses(); // will only affect offline profile viewing of dead characters..unneeded overhead
client->Save(); client->Save();
Rezzed(false); IsRezzed(false);
Save(); Save();
database.TransactionCommit(); database.TransactionCommit();
return; return;
} //end "not leaving naked corpses" } //end "not leaving naked corpses"
Rezzed(false); IsRezzed(false);
Save(); Save();
} }
@ -503,7 +412,7 @@ Corpse::Corpse(uint32 in_dbid, uint32 in_charid, char* in_charname, ItemList* in
p_PlayerCorpse = true; p_PlayerCorpse = true;
pLocked = false; pLocked = false;
BeingLootedBy = 0xFFFFFFFF; BeingLootedBy = 0xFFFFFFFF;
dbid = in_dbid; corpse_db_id = in_dbid;
p_depop = false; p_depop = false;
charid = in_charid; charid = in_charid;
itemlist = *in_itemlist; itemlist = *in_itemlist;
@ -522,7 +431,7 @@ Corpse::Corpse(uint32 in_dbid, uint32 in_charid, char* in_charname, ItemList* in
} }
Corpse::~Corpse() { Corpse::~Corpse() {
if (p_PlayerCorpse && !(p_depop && dbid == 0)) { if (p_PlayerCorpse && !(p_depop && corpse_db_id == 0)) {
Save(); Save();
} }
ItemList::iterator cur,end; ItemList::iterator cur,end;
@ -557,8 +466,8 @@ bool Corpse::Save() {
return true; return true;
uint32 tmp = this->CountItems(); uint32 tmp = this->CountItems();
uint32 tmpsize = sizeof(DBPlayerCorpse_Struct) + (tmp * sizeof(player_lootitem::ServerLootItem_Struct)); uint32 tmpsize = sizeof(PlayerCorpse_Struct)+(tmp * sizeof(player_lootitem::ServerLootItem_Struct));
DBPlayerCorpse_Struct* dbpc = (DBPlayerCorpse_Struct*) new uchar[tmpsize]; PlayerCorpse_Struct* dbpc = (PlayerCorpse_Struct*) new uchar[tmpsize];
memset(dbpc, 0, tmpsize); memset(dbpc, 0, tmpsize);
dbpc->itemcount = tmp; dbpc->itemcount = tmp;
dbpc->size = this->size; dbpc->size = this->size;
@ -567,23 +476,7 @@ bool Corpse::Save() {
dbpc->silver = this->silver; dbpc->silver = this->silver;
dbpc->gold = this->gold; dbpc->gold = this->gold;
dbpc->plat = this->platinum; dbpc->plat = this->platinum;
dbpc->race = this->race;
// Little hack to account for the fact the race in the corpse struct is a uint8 and Froglok/Drakkin race number > 255
// and to maintain backwards compatability with existing corpses in the database.
uint16 CorpseRace;
switch(race) {
case DRAKKIN:
CorpseRace = 254;
break;
case FROGLOK:
CorpseRace = 255;
break;
default:
CorpseRace = race;
}
dbpc->race = CorpseRace;
dbpc->class_ = class_; dbpc->class_ = class_;
dbpc->gender = gender; dbpc->gender = gender;
dbpc->deity = deity; dbpc->deity = deity;
@ -613,36 +506,28 @@ bool Corpse::Save() {
memcpy((char*)&dbpc->items[x++], (char*)item, sizeof(player_lootitem::ServerLootItem_Struct)); memcpy((char*)&dbpc->items[x++], (char*)item, sizeof(player_lootitem::ServerLootItem_Struct));
} }
dbpc->crc = CRC32::Generate(&((uchar*) dbpc)[4], tmpsize - 4); if (corpse_db_id == 0) {
corpse_db_id = database.SaveCharacterCorpse(charid, orgname, zone->GetZoneID(), zone->GetInstanceID(), dbpc, x_pos, y_pos, z_pos, heading);
}
else{
corpse_db_id = database.UpdateCharacterCorpse(corpse_db_id, charid, orgname, zone->GetZoneID(), zone->GetInstanceID(), dbpc, x_pos, y_pos, z_pos, heading, IsRezzed());
}
if (dbid == 0)
{
dbid = database.CreatePlayerCorpse(charid, orgname, zone->GetZoneID(), zone->GetInstanceID(), (uchar*) dbpc, tmpsize, x_pos, y_pos, z_pos, heading);
if(RuleB(Zone, UsePlayerCorpseBackups) == true)
database.CreatePlayerCorpseBackup(dbid, charid, orgname, zone->GetZoneID(), zone->GetInstanceID(), (uchar*) dbpc, tmpsize, x_pos, y_pos, z_pos, heading);
}
else
dbid = database.UpdatePlayerCorpse(dbid, charid, orgname, zone->GetZoneID(), zone->GetInstanceID(), (uchar*) dbpc, tmpsize, x_pos, y_pos, z_pos, heading,Rezzed());
safe_delete_array(dbpc);
if (dbid == 0) {
std::cout << "Error: Failed to save player corpse '" << this->GetName() << "'" << std::endl;
return false;
}
return true; return true;
} }
void Corpse::Delete() { void Corpse::Delete() {
if (IsPlayerCorpse() && dbid != 0) if (IsPlayerCorpse() && corpse_db_id != 0)
database.DeletePlayerCorpse(dbid); database.DeleteCharacterCorpse(corpse_db_id);
dbid = 0;
corpse_db_id = 0;
p_depop = true; p_depop = true;
} }
void Corpse::Bury() { void Corpse::Bury() {
if (IsPlayerCorpse() && dbid != 0) if (IsPlayerCorpse() && corpse_db_id != 0)
database.BuryPlayerCorpse(dbid); database.BuryCharacterCorpse(corpse_db_id);
dbid = 0; corpse_db_id = 0;
p_depop = true; p_depop = true;
} }
@ -677,8 +562,7 @@ void Corpse::AddItem(uint32 itemnum, uint16 charges, int16 slot, uint32 aug1, ui
itemlist.push_back(item); itemlist.push_back(item);
} }
ServerLootItem_Struct* Corpse::GetItem(uint16 lootslot, ServerLootItem_Struct** bag_item_data) ServerLootItem_Struct* Corpse::GetItem(uint16 lootslot, ServerLootItem_Struct** bag_item_data) {
{
ServerLootItem_Struct *sitem = 0, *sitem2; ServerLootItem_Struct *sitem = 0, *sitem2;
// find the item // find the item
@ -726,9 +610,7 @@ uint32 Corpse::GetWornItem(int16 equipSlot) const {
return 0; return 0;
} }
void Corpse::RemoveItem(uint16 lootslot) void Corpse::RemoveItem(uint16 lootslot) {
{
if (lootslot == 0xFFFF) if (lootslot == 0xFFFF)
return; return;
@ -745,10 +627,8 @@ void Corpse::RemoveItem(uint16 lootslot)
} }
} }
void Corpse::RemoveItem(ServerLootItem_Struct* item_data) void Corpse::RemoveItem(ServerLootItem_Struct* item_data){
{
uint8 material; uint8 material;
ItemList::iterator cur,end; ItemList::iterator cur,end;
cur = itemlist.begin(); cur = itemlist.begin();
end = itemlist.end(); end = itemlist.end();
@ -808,18 +688,18 @@ bool Corpse::Process() {
if(zone->HasGraveyard()) { if(zone->HasGraveyard()) {
Save(); Save();
p_depop = true; p_depop = true;
database.GraveyardPlayerCorpse(dbid, zone->graveyard_zoneid(), database.SendCharacterCorpseToGraveyard(corpse_db_id, zone->graveyard_zoneid(),
(zone->GetZoneID() == zone->graveyard_zoneid()) ? zone->GetInstanceID() : 0, zone->graveyard_x(), (zone->GetZoneID() == zone->graveyard_zoneid()) ? zone->GetInstanceID() : 0, zone->graveyard_x(),
zone->graveyard_y(), zone->graveyard_z(), zone->graveyard_heading()); zone->graveyard_y(), zone->graveyard_z(), zone->graveyard_heading());
corpse_graveyard_timer.Disable(); corpse_graveyard_timer.Disable();
ServerPacket* pack = new ServerPacket(ServerOP_SpawnPlayerCorpse, sizeof(SpawnPlayerCorpse_Struct)); ServerPacket* pack = new ServerPacket(ServerOP_SpawnPlayerCorpse, sizeof(SpawnPlayerCorpse_Struct));
SpawnPlayerCorpse_Struct* spc = (SpawnPlayerCorpse_Struct*)pack->pBuffer; SpawnPlayerCorpse_Struct* spc = (SpawnPlayerCorpse_Struct*)pack->pBuffer;
spc->player_corpse_id = dbid; spc->player_corpse_id = corpse_db_id;
spc->zone_id = zone->graveyard_zoneid(); spc->zone_id = zone->graveyard_zoneid();
worldserver.SendPacket(pack); worldserver.SendPacket(pack);
safe_delete(pack); safe_delete(pack);
LogFile->write(EQEMuLog::Debug, "Moved %s player corpse to the designated graveyard in zone %s.", this->GetName(), database.GetZoneName(zone->graveyard_zoneid())); LogFile->write(EQEMuLog::Debug, "Moved %s player corpse to the designated graveyard in zone %s.", this->GetName(), database.GetZoneName(zone->graveyard_zoneid()));
dbid = 0; corpse_db_id = 0;
} }
corpse_graveyard_timer.Disable(); corpse_graveyard_timer.Disable();
@ -835,10 +715,10 @@ bool Corpse::Process() {
if(!RuleB(Zone, EnableShadowrest)) if(!RuleB(Zone, EnableShadowrest))
Delete(); Delete();
else { else {
if(database.BuryPlayerCorpse(dbid)) { if(database.BuryCharacterCorpse(corpse_db_id)) {
Save(); Save();
p_depop = true; p_depop = true;
dbid = 0; corpse_db_id = 0;
LogFile->write(EQEMuLog::Debug, "Tagged %s player corpse has burried.", this->GetName()); LogFile->write(EQEMuLog::Debug, "Tagged %s player corpse has burried.", this->GetName());
} }
else else
@ -895,7 +775,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
return; return;
} }
if(IsPlayerCorpse() && dbid == 0) { if(IsPlayerCorpse() && corpse_db_id == 0) {
// SendLootReqErrorPacket(client, 0); // SendLootReqErrorPacket(client, 0);
client->Message(13, "Warning: Corpse's dbid = 0! Corpse will not survive zone shutdown!"); client->Message(13, "Warning: Corpse's dbid = 0! Corpse will not survive zone shutdown!");
std::cout << "Error: PlayerCorpse::MakeLootRequestPackets: dbid = 0!" << std::endl; std::cout << "Error: PlayerCorpse::MakeLootRequestPackets: dbid = 0!" << std::endl;
@ -1458,534 +1338,6 @@ void Corpse::Spawn() {
safe_delete(app); safe_delete(app);
} }
bool ZoneDatabase::DeleteGraveyard(uint32 zone_id, uint32 graveyard_id) {
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = new char[256];
uint32 query_length = 0;
uint32 affected_rows = 0;
query_length = sprintf(query,"UPDATE zone SET graveyard_id=0 WHERE zoneidnumber=%u AND version=0", zone_id);
if (!RunQuery(query, query_length, errbuf, 0, &affected_rows)) {
safe_delete_array(query);
std::cerr << "Error1 in DeleteGraveyard query " << errbuf << std::endl;
return false;
}
if (affected_rows == 0) {
std::cerr << "Error2 in DeleteGraveyard query: affected_rows = 0" << std::endl;
return false;
}
query_length = sprintf(query,"DELETE FROM graveyard WHERE id=%u", graveyard_id);
if (!RunQuery(query, query_length, errbuf, 0, &affected_rows)) {
safe_delete_array(query);
std::cerr << "Error3 in DeleteGraveyard query " << errbuf << std::endl;
return false;
}
safe_delete_array(query);
if (affected_rows == 0) {
std::cerr << "Error4 in DeleteGraveyard query: affected_rows = 0" << std::endl;
return false;
}
return true;
}
uint32 ZoneDatabase::AddGraveyardIDToZone(uint32 zone_id, uint32 graveyard_id) {
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = new char[256];
char* end = query;
uint32 affected_rows = 0;
end += sprintf(end,"UPDATE zone SET graveyard_id=%u WHERE zoneidnumber=%u AND version=0", graveyard_id, zone_id);
if (!RunQuery(query, (uint32) (end - query), errbuf, 0, &affected_rows)) {
safe_delete_array(query);
std::cerr << "Error1 in AddGraveyardIDToZone query " << errbuf << std::endl;
return 0;
}
safe_delete_array(query);
if (affected_rows == 0) {
std::cerr << "Error2 in AddGraveyardIDToZone query: affected_rows = 0" << std::endl;
return 0;
}
return zone_id;
}
uint32 ZoneDatabase::NewGraveyardRecord(uint32 graveyard_zoneid, float graveyard_x, float graveyard_y, float graveyard_z, float graveyard_heading) {
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = new char[256];
char* end = query;
uint32 affected_rows = 0;
uint32 new_graveyard_id = 0;
end += sprintf(end,"INSERT INTO graveyard SET zone_id=%u, x=%1.1f, y=%1.1f, z=%1.1f, heading=%1.1f", graveyard_zoneid, graveyard_x, graveyard_y, graveyard_z, graveyard_heading);
if (!RunQuery(query, (uint32) (end - query), errbuf, 0, &affected_rows, &new_graveyard_id)) {
safe_delete_array(query);
std::cerr << "Error1 in NewGraveyardRecord query " << errbuf << std::endl;
return 0;
}
safe_delete_array(query);
if (affected_rows == 0) {
std::cerr << "Error2 in NewGraveyardRecord query: affected_rows = 0" << std::endl;
return 0;
}
if(new_graveyard_id <= 0) {
std::cerr << "Error3 in NewGraveyardRecord query: new_graveyard_id <= 0" << std::endl;
return 0;
}
return new_graveyard_id;
}
uint32 ZoneDatabase::GraveyardPlayerCorpse(uint32 dbid, uint32 zoneid, uint16 instanceid, float x, float y, float z, float heading) {
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = new char[256];
char* end = query;
uint32 affected_rows = 0;
// We probably don't want a graveyard located in an instance.
end += sprintf(end,"Update player_corpses SET zoneid=%u, instanceid=0, x=%1.1f, y=%1.1f, z=%1.1f, heading=%1.1f, WasAtGraveyard=1 WHERE id=%d", zoneid, x, y, z, heading, dbid);
if (!RunQuery(query, (uint32) (end - query), errbuf, 0, &affected_rows)) {
safe_delete_array(query);
std::cerr << "Error1 in GraveyardPlayerCorpse query " << errbuf << std::endl;
return 0;
}
safe_delete_array(query);
if (affected_rows == 0) {
std::cerr << "Error2 in GraveyardPlayerCorpse query: affected_rows = 0" << std::endl;
return 0;
}
return dbid;
}
uint32 ZoneDatabase::UpdatePlayerCorpse(uint32 dbid, uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, uchar* data, uint32 datasize, float x, float y, float z, float heading, bool rezzed) {
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = new char[256+(datasize*2)];
char* end = query;
uint32 affected_rows = 0;
end += sprintf(end, "Update player_corpses SET data=");
*end++ = '\'';
end += DoEscapeString(end, (char*)data, datasize);
*end++ = '\'';
end += sprintf(end,", charname='%s', zoneid=%u, instanceid=%u, charid=%d, x=%1.1f, y=%1.1f, z=%1.1f, heading=%1.1f WHERE id=%d", charname, zoneid, instanceid, charid, x, y, z, heading, dbid);
if (!RunQuery(query, (uint32) (end - query), errbuf, 0, &affected_rows)) {
safe_delete_array(query);
std::cerr << "Error1 in UpdatePlayerCorpse query " << errbuf << std::endl;
return 0;
}
safe_delete_array(query);
if (affected_rows == 0) {
std::cerr << "Error2 in UpdatePlayerCorpse query: affected_rows = 0" << std::endl;
return 0;
}
if(rezzed){
if (!RunQuery(query, MakeAnyLenString(&query, "update player_corpses set rezzed = 1 WHERE id=%d",dbid), errbuf)) {
std::cerr << "Error in UpdatePlayerCorpse/Rezzed query: " << errbuf << std::endl;
}
safe_delete_array(query);
}
return dbid;
}
void ZoneDatabase::MarkCorpseAsRezzed(uint32 dbid)
{
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
if(!database.RunQuery(query,MakeAnyLenString(&query, "UPDATE player_corpses SET rezzed = 1 WHERE id = %i", dbid), errbuf))
{
LogFile->write(EQEMuLog::Error, "MarkCorpseAsRezzed failed: %s, %s", query, errbuf);
}
safe_delete_array(query);
}
uint32 ZoneDatabase::CreatePlayerCorpse(uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, uchar* data, uint32 datasize, float x, float y, float z, float heading) {
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = new char[256+(datasize*2)];
char* end = query;
//MYSQL_RES *result;
//MYSQL_ROW row;
uint32 affected_rows = 0;
uint32 last_insert_id = 0;
end += sprintf(end, "Insert into player_corpses SET data=");
*end++ = '\'';
end += DoEscapeString(end, (char*)data, datasize);
*end++ = '\'';
end += sprintf(end,", charname='%s', zoneid=%u, instanceid=%u, charid=%d, x=%1.1f, y=%1.1f, z=%1.1f, heading=%1.1f, timeofdeath=Now(), IsBurried=0", charname, zoneid, instanceid, charid, x, y, z, heading);
if (!RunQuery(query, (uint32) (end - query), errbuf, 0, &affected_rows, &last_insert_id)) {
safe_delete_array(query);
std::cerr << "Error1 in CreatePlayerCorpse query " << errbuf << std::endl;
return 0;
}
safe_delete_array(query);
if (affected_rows == 0) {
std::cerr << "Error2 in CreatePlayerCorpse query: affected_rows = 0" << std::endl;
return 0;
}
if (last_insert_id == 0) {
std::cerr << "Error3 in CreatePlayerCorpse query: last_insert_id = 0" << std::endl;
return 0;
}
return last_insert_id;
}
bool ZoneDatabase::CreatePlayerCorpseBackup(uint32 dbid, uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, uchar* data, uint32 datasize, float x, float y, float z, float heading) {
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = new char[256+(datasize*2)];
char* end = query;
uint32 affected_rows = 0;
uint32 last_insert_id = 0;
bool result = false;
DBPlayerCorpse_Struct* dbpcs = (DBPlayerCorpse_Struct*) data;
if (dbid != 0) {
if(RuleB(Character, LeaveCorpses) == true && dbpcs->level >= RuleI(Character, DeathItemLossLevel)){
end += sprintf(end, "Insert into player_corpses_backup SET data=");
*end++ = '\'';
end += DoEscapeString(end, (char*)data, datasize);
*end++ = '\'';
end += sprintf(end,", charname='%s', zoneid=%u, instanceid=%u, charid=%d, x=%1.1f, y=%1.1f, z=%1.1f, heading=%1.1f, timeofdeath=Now(), IsBurried=0, id=%u", charname, zoneid, instanceid, charid, x, y, z, heading, dbid);
if (RunQuery(query, (uint32) (end - query), errbuf, 0, &affected_rows)) {
if (affected_rows == 1)
result = true;
else
std::cerr << "Error in CreatePlayerCorpseBackup query: affected_rows != 1" << std::endl;
}
else
std::cerr << "Error in CreatePlayerCorpseBackup query " << errbuf << std::endl;
}
safe_delete_array(query);
}
else {
std::cerr << "Error in CreatePlayerCorpseBackup: dbid = 0" << std::endl;
}
return result;
}
uint32 ZoneDatabase::GetPlayerBurriedCorpseCount(uint32 char_id) {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
uint32 CorpseCount = 0;
if (RunQuery(query, MakeAnyLenString(&query, "select count(*) from player_corpses where charid = '%u' and IsBurried = 1", char_id), errbuf, &result)) {
row = mysql_fetch_row(result);
CorpseCount = atoi(row[0]);
mysql_free_result(result);
}
else {
std::cerr << "Error in GetPlayerBurriedCorpseCount query '" << query << "' " << errbuf << std::endl;
}
safe_delete_array(query);
return CorpseCount;
}
uint32 ZoneDatabase::GetPlayerCorpseCount(uint32 char_id) {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
uint32 CorpseCount = 0;
if (RunQuery(query, MakeAnyLenString(&query, "select count(*) from player_corpses where charid = '%u'", char_id), errbuf, &result)) {
row = mysql_fetch_row(result);
CorpseCount = atoi(row[0]);
mysql_free_result(result);
}
else {
std::cerr << "Error in GetPlayerCorpseCount query '" << query << "' " << errbuf << std::endl;
}
safe_delete_array(query);
return CorpseCount;
}
uint32 ZoneDatabase::GetPlayerCorpseID(uint32 char_id, uint8 corpse) {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
uint32 id = 0;
if (RunQuery(query, MakeAnyLenString(&query, "select id from player_corpses where charid = '%u'", char_id), errbuf, &result)) {
for (int i=0; i<corpse;i++) {
row = mysql_fetch_row(result);
id = (uint32)atoi(row[0]);
}
mysql_free_result(result);
}
else {
std::cerr << "Error in GetPlayerCorpseID query '" << query << "' " << errbuf << std::endl;
}
safe_delete_array(query);
return id;
}
uint32 ZoneDatabase::GetPlayerCorpseItemAt(uint32 corpse_id, uint16 slotid) {
Corpse* tmp = LoadPlayerCorpse(corpse_id);
uint32 itemid = 0;
if (tmp) {
itemid = tmp->GetWornItem(slotid);
tmp->DepopCorpse();
}
return itemid;
}
Corpse* ZoneDatabase::SummonBurriedPlayerCorpse(uint32 char_id, uint32 dest_zoneid, uint16 dest_instanceid, 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);
NewCorpse->SetDecayTimer(RuleI(Character, CorpseDecayTimeMS));
NewCorpse->Spawn();
if(!UnburyPlayerCorpse(NewCorpse->GetDBID(), dest_zoneid, dest_instanceid, 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 {
std::cerr << "Error in SummonBurriedPlayerCorpse query '" << query << "' " << errbuf << std::endl;
}
safe_delete_array(query);
return NewCorpse;
}
bool ZoneDatabase::SummonAllPlayerCorpses(uint32 char_id, uint32 dest_zoneid, uint16 dest_instanceid,
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;
int CorpseCount = 0;
unsigned long* lengths;
if(!RunQuery(query, MakeAnyLenString(&query, "UPDATE player_corpses SET zoneid = %i, instanceid = %i, x = %f, y = %f, z = %f, "
"heading = %f, IsBurried = 0, WasAtGraveyard = 0 WHERE charid = %i",
dest_zoneid, dest_instanceid, dest_x, dest_y, dest_z, dest_heading, char_id), errbuf))
LogFile->write(EQEMuLog::Error, "Error moving corpses, Query = %s, Error = %s\n", query, errbuf);
safe_delete_array(query);
if (RunQuery(query, MakeAnyLenString(&query, "SELECT id, charname, data, timeofdeath, rezzed FROM player_corpses WHERE charid='%u'"
"ORDER BY timeofdeath", char_id), errbuf, &result))
{
while((row = mysql_fetch_row(result)))
{
lengths = mysql_fetch_lengths(result);
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);
NewCorpse->SetDecayTimer(RuleI(Character, CorpseDecayTimeMS));
NewCorpse->Spawn();
++CorpseCount;
}
else
LogFile->write(EQEMuLog::Error, "Unable to construct a player corpse for character id %u.", char_id);
}
mysql_free_result(result);
}
else
LogFile->write(EQEMuLog::Error, "Error in SummonAllPlayerCorpses Query = %s, Error = %s\n", query, errbuf);
safe_delete_array(query);
return (CorpseCount > 0);
}
bool ZoneDatabase::UnburyPlayerCorpse(uint32 dbid, uint32 new_zoneid, uint16 new_instanceid, float new_x, float new_y, float new_z, float new_heading) {
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = new char[256];
char* end = query;
uint32 affected_rows = 0;
bool Result = false;
end += sprintf(end, "UPDATE player_corpses SET IsBurried=0, zoneid=%u, instanceid=%u, x=%f, y=%f, z=%f, heading=%f, timeofdeath=Now(), WasAtGraveyard=0 WHERE id=%u", new_zoneid, new_instanceid, new_x, new_y, new_z, new_heading, dbid);
if (RunQuery(query, (uint32) (end - query), errbuf, 0, &affected_rows)) {
if (affected_rows == 1)
Result = true;
else
std::cerr << "Error2 in UnburyPlayerCorpse query: affected_rows NOT EQUAL to 1, as expected." << std::endl;
}
else
std::cerr << "Error1 in UnburyPlayerCorpse query " << errbuf << std::endl;
safe_delete_array(query);
return Result;
}
Corpse* ZoneDatabase::LoadPlayerCorpse(uint32 player_corpse_id) {
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, charid, charname, x, y, z, heading, data, timeofdeath, rezzed, WasAtGraveyard FROM player_corpses WHERE id='%u'", player_corpse_id), errbuf, &result)) {
row = mysql_fetch_row(result);
lengths = mysql_fetch_lengths(result);
if(row && lengths)
{
NewCorpse = Corpse::LoadFromDBData(atoi(row[0]), atoi(row[1]), row[2], (uchar*) row[7], lengths[7], atof(row[3]), atoi(row[4]), atoi(row[5]), atoi(row[6]), row[8],atoi(row[9])==1, atoi(row[10]));
entity_list.AddCorpse(NewCorpse);
}
mysql_free_result(result);
}
else {
std::cerr << "Error in LoadPlayerCorpse query '" << query << "' " << errbuf << std::endl;
std::cerr << "Note that if your missing the 'rezzed' field you can add it with:\nALTER TABLE `player_corpses` ADD `rezzed` TINYINT UNSIGNED DEFAULT \"0\";\n";
}
safe_delete_array(query);
return NewCorpse;
}
bool ZoneDatabase::LoadPlayerCorpses(uint32 iZoneID, uint16 iInstanceID) {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
uint32 query_length = 0;
unsigned long* lengths;
if(!RuleB(Zone, EnableShadowrest))
query_length = MakeAnyLenString(&query, "SELECT id, charid, charname, x, y, z, heading, data, timeofdeath, rezzed, WasAtGraveyard FROM player_corpses WHERE zoneid='%u' AND instanceid='%u'", iZoneID, iInstanceID);
else
query_length = MakeAnyLenString(&query, "SELECT id, charid, charname, x, y, z, heading, data, timeofdeath, rezzed, 0 FROM player_corpses WHERE zoneid='%u' AND instanceid='%u' AND IsBurried=0", iZoneID, iInstanceID);
if (RunQuery(query, query_length, errbuf, &result)) {
safe_delete_array(query);
while ((row = mysql_fetch_row(result))) {
lengths = mysql_fetch_lengths(result);
entity_list.AddCorpse(Corpse::LoadFromDBData(atoi(row[0]), atoi(row[1]), row[2], (uchar*) row[7], lengths[7], atof(row[3]), atoi(row[4]), atoi(row[5]), atoi(row[6]), row[8],atoi(row[9])==1, atoi(row[10])));
}
mysql_free_result(result);
}
else {
std::cerr << "Error in LoadPlayerCorpses query '" << query << "' " << errbuf << std::endl;
std::cerr << "Note that if your missing the 'rezzed' field you can add it with:\nALTER TABLE `player_corpses` ADD `rezzed` TINYINT UNSIGNED DEFAULT \"0\";\n";
safe_delete_array(query);
return false;
}
return true;
}
uint32 ZoneDatabase::GetFirstCorpseID(uint32 char_id) {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
uint32 CorpseID = 0;
MakeAnyLenString(&query, "SELECT id FROM player_corpses WHERE charid='%u' AND IsBurried=0 ORDER BY timeofdeath LIMIT 1", char_id);
if (RunQuery(query, strlen(query), errbuf, &result)) {
if (mysql_num_rows(result)!= 0){
row = mysql_fetch_row(result);
CorpseID = atoi(row[0]);
mysql_free_result(result);
}
}
else {
std::cerr << "Error in GetFirstCorpseID query '" << query << "' " << errbuf << std::endl;
safe_delete_array(query);
return 0;
}
safe_delete_array(query);
return CorpseID;
}
bool ZoneDatabase::BuryPlayerCorpse(uint32 dbid) {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE player_corpses SET IsBurried = 1 WHERE id=%d", dbid), errbuf)) {
std::cerr << "Error in BuryPlayerCorpse query '" << query << "' " << errbuf << std::endl;
safe_delete_array(query);
return false;
}
safe_delete_array(query);
return true;
}
bool ZoneDatabase::BuryAllPlayerCorpses(uint32 charid) {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE player_corpses SET IsBurried = 1 WHERE charid=%d", charid), errbuf)) {
std::cerr << "Error in BuryPlayerCorpse query '" << query << "' " << errbuf << std::endl;
safe_delete_array(query);
return false;
}
safe_delete_array(query);
return true;
}
bool ZoneDatabase::DeletePlayerCorpse(uint32 dbid) {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
if (!RunQuery(query, MakeAnyLenString(&query, "Delete from player_corpses where id=%d", dbid), errbuf)) {
std::cerr << "Error in DeletePlayerCorpse query '" << query << "' " << errbuf << std::endl;
safe_delete_array(query);
return false;
}
safe_delete_array(query);
return true;
}
// these functions operate with a material slot, which is from 0 to 8
uint32 Corpse::GetEquipment(uint8 material_slot) const { uint32 Corpse::GetEquipment(uint8 material_slot) const {
int invslot; int invslot;
@ -2039,7 +1391,7 @@ void Corpse::LoadPlayerCorpseDecayTime(uint32 dbid){
char *query = 0; char *query = 0;
MYSQL_RES *result; MYSQL_RES *result;
MYSQL_ROW row; MYSQL_ROW row;
if (database.RunQuery(query, MakeAnyLenString(&query, "SELECT (UNIX_TIMESTAMP() - UNIX_TIMESTAMP(timeofdeath)) FROM player_corpses WHERE id=%d and not timeofdeath=0", dbid), errbuf, &result)) { if (database.RunQuery(query, MakeAnyLenString(&query, "SELECT (UNIX_TIMESTAMP() - UNIX_TIMESTAMP(time_of_death)) FROM character_corpses WHERE id=%d and not time_of_death=0", dbid), errbuf, &result)) {
safe_delete_array(query); safe_delete_array(query);
while ((row = mysql_fetch_row(result))) { while ((row = mysql_fetch_row(result))) {
if(atoi(row[0]) > 0 && RuleI(Character, CorpseDecayTimeMS) > (atoi(row[0]) * 1000)) { if(atoi(row[0]) > 0 && RuleI(Character, CorpseDecayTimeMS) > (atoi(row[0]) * 1000)) {
@ -2178,27 +1530,3 @@ int16 Corpse::CorpseToServerSlot(int16 corpse_slot)
} }
*/ */
} }
/*
void Corpse::CastRezz(uint16 spellid, Mob* Caster){
if(Rezzed()){
if(Caster && Caster->IsClient())
Caster->Message(13,"This character has already been resurrected.");
return;
}
APPLAYER* outapp = new APPLAYER(OP_RezzRequest, sizeof(Resurrect_Struct));
Resurrect_Struct* rezz = (Resurrect_Struct*) outapp->pBuffer;
memcpy(rezz->your_name,this->orgname,30);
memcpy(rezz->corpse_name,this->name,30);
memcpy(rezz->rezzer_name,Caster->GetName(),30);
memcpy(rezz->zone,zone->GetShortName(),15);
rezz->spellid = spellid;
rezz->x = this->x_pos;
rezz->y = this->y_pos;
rezz->z = (float)this->z_pos;
worldserver.RezzPlayer(outapp, rezzexp, OP_RezzRequest);
//DumpPacket(outapp);
safe_delete(outapp);
}
*/

View File

@ -31,7 +31,7 @@ class Corpse : public Mob
public: public:
static void SendEndLootErrorPacket(Client* client); static void SendEndLootErrorPacket(Client* client);
static void SendLootReqErrorPacket(Client* client, uint8 response = 2); static void SendLootReqErrorPacket(Client* client, uint8 response = 2);
static Corpse* LoadFromDBData(uint32 in_corpseid, uint32 in_charid, char* in_charname, uchar* in_data, uint32 in_datasize, float in_x, float in_y, float in_z, float in_heading, char* timeofdeath, bool rezzed = false, bool wasAtGraveyard = false); static Corpse* LoadFromDBData(uint32 in_corpseid, uint32 in_charid, char* in_charname, PlayerCorpse_Struct* pcs, float in_x, float in_y, float in_z, float in_heading, char* time_of_death, bool rezzed = false, bool wasAtGraveyard = false);
Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NPCType** in_npctypedata, uint32 in_decaytime = 600000); Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NPCType** in_npctypedata, uint32 in_decaytime = 600000);
Corpse(Client* client, int32 in_rezexp); Corpse(Client* client, int32 in_rezexp);
@ -41,8 +41,8 @@ public:
//abstract virtual function implementations requird by base abstract class //abstract virtual function implementations requird by base abstract class
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) { return true; } virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) { return true; }
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false) { return; } virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false) { return; }
virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = true, bool IsFromSpell = false, virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false,
ExtraAttackOptions *opts = nullptr) { return false; } bool IsStrikethrough = true, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) { return false; }
virtual bool HasRaid() { return false; } virtual bool HasRaid() { return false; }
virtual bool HasGroup() { return false; } virtual bool HasGroup() { return false; }
virtual Raid* GetRaid() { return 0; } virtual Raid* GetRaid() { return 0; }
@ -66,7 +66,7 @@ public:
inline bool IsLocked() { return pLocked; } inline bool IsLocked() { return pLocked; }
inline void ResetLooter() { BeingLootedBy = 0xFFFFFFFF; } inline void ResetLooter() { BeingLootedBy = 0xFFFFFFFF; }
inline bool IsBeingLooted() { return (BeingLootedBy != 0xFFFFFFFF); } inline bool IsBeingLooted() { return (BeingLootedBy != 0xFFFFFFFF); }
inline uint32 GetDBID() { return dbid; } inline uint32 GetDBID() { return corpse_db_id; }
inline char* GetOwnerName() { return orgname;} inline char* GetOwnerName() { return orgname;}
void SetDecayTimer(uint32 decaytime); void SetDecayTimer(uint32 decaytime);
@ -102,8 +102,8 @@ public:
bool CanMobLoot(int charid); bool CanMobLoot(int charid);
void AllowMobLoot(Mob *them, uint8 slot); void AllowMobLoot(Mob *them, uint8 slot);
void AddLooter(Mob *who); void AddLooter(Mob *who);
bool Rezzed() { return rez; } bool IsRezzed() { return rez; }
void Rezzed(bool in_rez) { rez = in_rez; } void IsRezzed(bool in_rez) { rez = in_rez; }
void Spawn(); void Spawn();
char orgname[64]; char orgname[64];
@ -122,7 +122,7 @@ private:
bool p_PlayerCorpse; bool pIsChanged; bool p_PlayerCorpse; bool pIsChanged;
bool pLocked; bool pLocked;
int32 pkitem; int32 pkitem;
uint32 dbid; uint32 corpse_db_id;
uint32 charid; uint32 charid;
ItemList itemlist; ItemList itemlist;
uint32 copper; uint32 copper;

View File

@ -50,7 +50,7 @@ Doors::Doors(const Door* door)
incline = door->incline; incline = door->incline;
opentype = door->opentype; opentype = door->opentype;
guild_id = door->guild_id; guild_id = door->guild_id;
lockpick = door->lockpick; lockpick = door->lock_pick;
keyitem = door->keyitem; keyitem = door->keyitem;
nokeyring = door->nokeyring; nokeyring = door->nokeyring;
trigger_door = door->trigger_door; trigger_door = door->trigger_door;
@ -678,7 +678,7 @@ bool ZoneDatabase::LoadDoors(int32 iDoorCount, Door *into, const char *zone_name
into[rowIndex].heading = (float)atof(row[7]); into[rowIndex].heading = (float)atof(row[7]);
into[rowIndex].opentype = atoi(row[8]); into[rowIndex].opentype = atoi(row[8]);
into[rowIndex].guild_id = atoi(row[9]); into[rowIndex].guild_id = atoi(row[9]);
into[rowIndex].lockpick = atoi(row[10]); into[rowIndex].lock_pick = atoi(row[10]);
into[rowIndex].keyitem = atoi(row[11]); into[rowIndex].keyitem = atoi(row[11]);
into[rowIndex].nokeyring = atoi(row[12]); into[rowIndex].nokeyring = atoi(row[12]);
into[rowIndex].trigger_door = atoi(row[13]); into[rowIndex].trigger_door = atoi(row[13]);

View File

@ -1678,7 +1678,7 @@ int EntityList::RezzAllCorpsesByCharID(uint32 charid)
while (it != corpse_list.end()) { while (it != corpse_list.end()) {
if (it->second->GetCharID() == charid) { if (it->second->GetCharID() == charid) {
RezzExp += it->second->GetRezzExp(); RezzExp += it->second->GetRezzExp();
it->second->Rezzed(true); it->second->IsRezzed(true);
it->second->CompleteRezz(); it->second->CompleteRezz();
} }
++it; ++it;

View File

@ -44,7 +44,7 @@ uint32 Lua_Corpse::GetDBID() {
bool Lua_Corpse::IsRezzed() { bool Lua_Corpse::IsRezzed() {
Lua_Safe_Call_Bool(); Lua_Safe_Call_Bool();
return self->Rezzed(); return self->IsRezzed();
} }
const char* Lua_Corpse::GetOwnerName() { const char* Lua_Corpse::GetOwnerName() {

View File

@ -4338,7 +4338,7 @@ Corpse* Merc::GetGroupMemberCorpse() {
if(g->members[i] && g->members[i]->IsClient()) { if(g->members[i] && g->members[i]->IsClient()) {
corpse = entity_list.GetCorpseByOwnerWithinRange(g->members[i]->CastToClient(), this, RuleI(Mercs, ResurrectRadius)); corpse = entity_list.GetCorpseByOwnerWithinRange(g->members[i]->CastToClient(), this, RuleI(Mercs, ResurrectRadius));
if(corpse && !corpse->Rezzed()) { if(corpse && !corpse->IsRezzed()) {
return corpse; return corpse;
} }
} }

View File

@ -780,7 +780,7 @@ XS(XS_Corpse_IsRezzed)
if(THIS == nullptr) if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->Rezzed(); RETVAL = THIS->IsRezzed();
ST(0) = boolSV(RETVAL); ST(0) = boolSV(RETVAL);
sv_2mortal(ST(0)); sv_2mortal(ST(0));
} }

View File

@ -1744,7 +1744,7 @@ bool QuestManager::summonburriedplayercorpse(uint32 char_id, float dest_x, float
bool Result = false; bool Result = false;
if(char_id > 0) { if(char_id > 0) {
Corpse* PlayerCorpse = database.SummonBurriedPlayerCorpse(char_id, zone->GetZoneID(), zone->GetInstanceID(), dest_x, dest_y, dest_z, dest_heading); Corpse* PlayerCorpse = database.SummonBuriedCharacterCorpses(char_id, zone->GetZoneID(), zone->GetInstanceID(), dest_x, dest_y, dest_z, dest_heading);
if(PlayerCorpse) { if(PlayerCorpse) {
Result = true; Result = true;
} }
@ -1767,7 +1767,7 @@ uint32 QuestManager::getplayerburriedcorpsecount(uint32 char_id) {
uint32 Result = 0; uint32 Result = 0;
if(char_id > 0) { if(char_id > 0) {
Result = database.GetPlayerBurriedCorpseCount(char_id); Result = database.GetCharacterBuriedCorpseCount(char_id);
} }
return Result; return Result;
} }
@ -1781,7 +1781,7 @@ bool QuestManager::buryplayercorpse(uint32 char_id)
uint32 PlayerCorpse = database.GetFirstCorpseID(char_id); uint32 PlayerCorpse = database.GetFirstCorpseID(char_id);
if(PlayerCorpse > 0) if(PlayerCorpse > 0)
{ {
database.BuryPlayerCorpse(PlayerCorpse); database.BuryCharacterCorpse(PlayerCorpse);
Corpse* corpse = entity_list.GetCorpseByDBID(PlayerCorpse); Corpse* corpse = entity_list.GetCorpseByDBID(PlayerCorpse);
if(corpse) if(corpse)
{ {

View File

@ -3806,9 +3806,9 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r
void Corpse::CastRezz(uint16 spellid, Mob* Caster) void Corpse::CastRezz(uint16 spellid, Mob* Caster)
{ {
_log(SPELLS__REZ, "Corpse::CastRezz spellid %i, Rezzed() is %i, rezzexp is %i", spellid,Rezzed(),rezzexp); _log(SPELLS__REZ, "Corpse::CastRezz spellid %i, Rezzed() is %i, rezzexp is %i", spellid,IsRezzed(),rezzexp);
if(Rezzed()){ if(IsRezzed()){
if(Caster && Caster->IsClient()) if(Caster && Caster->IsClient())
Caster->Message(13,"This character has already been resurrected."); Caster->Message(13,"This character has already been resurrected.");
@ -3838,7 +3838,7 @@ void Corpse::CastRezz(uint16 spellid, Mob* Caster)
rezz->unknown020 = 0x00000000; rezz->unknown020 = 0x00000000;
rezz->unknown088 = 0x00000000; rezz->unknown088 = 0x00000000;
// We send this to world, because it needs to go to the player who may not be in this zone. // We send this to world, because it needs to go to the player who may not be in this zone.
worldserver.RezzPlayer(outapp, rezzexp, dbid, OP_RezzRequest); worldserver.RezzPlayer(outapp, rezzexp, corpse_db_id, OP_RezzRequest);
_pkt(SPELLS__REZ, outapp); _pkt(SPELLS__REZ, outapp);
safe_delete(outapp); safe_delete(outapp);
} }

View File

@ -704,7 +704,7 @@ void WorldServer::Process() {
_log(SPELLS__REZ, "Found corpse. Marking corpse as rezzed."); _log(SPELLS__REZ, "Found corpse. Marking corpse as rezzed.");
// I don't know why Rezzed is not set to true in CompleteRezz(). // I don't know why Rezzed is not set to true in CompleteRezz().
corpse->Rezzed(true); corpse->IsRezzed(true);
corpse->CompleteRezz(); corpse->CompleteRezz();
} }
} }
@ -1382,7 +1382,7 @@ void WorldServer::Process() {
case ServerOP_SpawnPlayerCorpse: { case ServerOP_SpawnPlayerCorpse: {
SpawnPlayerCorpse_Struct* s = (SpawnPlayerCorpse_Struct*)pack->pBuffer; SpawnPlayerCorpse_Struct* s = (SpawnPlayerCorpse_Struct*)pack->pBuffer;
Corpse* NewCorpse = database.LoadPlayerCorpse(s->player_corpse_id); Corpse* NewCorpse = database.LoadCharacterCorpse(s->player_corpse_id);
if(NewCorpse) if(NewCorpse)
NewCorpse->Spawn(); NewCorpse->Spawn();
else else

View File

@ -917,7 +917,7 @@ bool Zone::Init(bool iStaticZone) {
} }
LogFile->write(EQEMuLog::Status, "Loading player corpses..."); LogFile->write(EQEMuLog::Status, "Loading player corpses...");
if (!database.LoadPlayerCorpses(zoneid, instanceid)) { if (!database.LoadCharacterCorpses(zoneid, instanceid)) {
LogFile->write(EQEMuLog::Error, "Loading player corpses failed."); LogFile->write(EQEMuLog::Error, "Loading player corpses failed.");
return false; return false;
} }

View File

@ -7,6 +7,7 @@
#include "../common/rulesys.h" #include "../common/rulesys.h"
#include "../common/rdtsc.h" #include "../common/rdtsc.h"
#include "zone.h" #include "zone.h"
#include "corpse.h"
#include "client.h" #include "client.h"
#include "merc.h" #include "merc.h"
#include "groups.h" #include "groups.h"
@ -3328,3 +3329,723 @@ bool ZoneDatabase::GetFactionIdsForNPC(uint32 nfl_id, std::list<struct NPCFactio
} }
return true; return true;
} }
/*
Corpse Queries
*/
bool ZoneDatabase::DeleteGraveyard(uint32 zone_id, uint32 graveyard_id) {
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = new char[256];
uint32 query_length = 0;
uint32 affected_rows = 0;
query_length = sprintf(query, "UPDATE zone SET graveyard_id=0 WHERE zone_idnumber=%u AND version=0", zone_id);
if (!RunQuery(query, query_length, errbuf, 0, &affected_rows)) {
safe_delete_array(query);
std::cerr << "Error1 in DeleteGraveyard query " << errbuf << std::endl;
return false;
}
if (affected_rows == 0) {
std::cerr << "Error2 in DeleteGraveyard query: affected_rows = 0" << std::endl;
return false;
}
query_length = sprintf(query, "DELETE FROM graveyard WHERE id=%u", graveyard_id);
if (!RunQuery(query, query_length, errbuf, 0, &affected_rows)) {
safe_delete_array(query);
std::cerr << "Error3 in DeleteGraveyard query " << errbuf << std::endl;
return false;
}
safe_delete_array(query);
if (affected_rows == 0) {
std::cerr << "Error4 in DeleteGraveyard query: affected_rows = 0" << std::endl;
return false;
}
return true;
}
uint32 ZoneDatabase::AddGraveyardIDToZone(uint32 zone_id, uint32 graveyard_id) {
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = new char[256];
char* end = query;
uint32 affected_rows = 0;
end += sprintf(end, "UPDATE zone SET graveyard_id=%u WHERE zone_idnumber=%u AND version=0", graveyard_id, zone_id);
if (!RunQuery(query, (uint32)(end - query), errbuf, 0, &affected_rows)) {
safe_delete_array(query);
std::cerr << "Error1 in AddGraveyardIDToZone query " << errbuf << std::endl;
return 0;
}
safe_delete_array(query);
if (affected_rows == 0) {
std::cerr << "Error2 in AddGraveyardIDToZone query: affected_rows = 0" << std::endl;
return 0;
}
return zone_id;
}
uint32 ZoneDatabase::CreateGraveyardRecord(uint32 graveyard_zone_id, float graveyard_x, float graveyard_y, float graveyard_z, float graveyard_heading) {
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = new char[256];
char* end = query;
uint32 affected_rows = 0;
uint32 new_graveyard_id = 0;
end += sprintf(end, "INSERT INTO graveyard SET zone_id=%u, x=%1.1f, y=%1.1f, z=%1.1f, heading=%1.1f", graveyard_zone_id, graveyard_x, graveyard_y, graveyard_z, graveyard_heading);
if (!RunQuery(query, (uint32)(end - query), errbuf, 0, &affected_rows, &new_graveyard_id)) {
safe_delete_array(query);
std::cerr << "Error1 in NewGraveyardRecord query " << errbuf << std::endl;
return 0;
}
safe_delete_array(query);
if (affected_rows == 0) {
std::cerr << "Error2 in NewGraveyardRecord query: affected_rows = 0" << std::endl;
return 0;
}
if (new_graveyard_id <= 0) {
std::cerr << "Error3 in NewGraveyardRecord query: new_graveyard_id <= 0" << std::endl;
return 0;
}
return new_graveyard_id;
}
uint32 ZoneDatabase::SendCharacterCorpseToGraveyard(uint32 dbid, uint32 zone_id, uint16 instance_id, float x, float y, float z, float heading) {
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = new char[256];
char* end = query;
uint32 affected_rows = 0;
// We probably don't want a graveyard located in an instance.
end += sprintf(end, "Update character_corpses SET zone_id=%u, instance_id=0, x=%1.1f, y=%1.1f, z=%1.1f, heading=%1.1f, was_at_graveyard=1 WHERE id=%d", zone_id, x, y, z, heading, dbid);
if (!RunQuery(query, (uint32)(end - query), errbuf, 0, &affected_rows)) {
safe_delete_array(query);
std::cerr << "Error1 in GraveyardPlayerCorpse query " << errbuf << std::endl;
return 0;
}
safe_delete_array(query);
if (affected_rows == 0) {
std::cerr << "Error2 in GraveyardPlayerCorpse query: affected_rows = 0" << std::endl;
return 0;
}
return dbid;
}
uint32 ZoneDatabase::UpdateCharacterCorpse(uint32 db_id, uint32 char_id, const char* char_name, uint32 zone_id, uint16 instance_id, PlayerCorpse_Struct* dbpc, float x, float y, float z, float heading, bool is_rezzed) {
std::string query = StringFormat("UPDATE `character_corpses` SET \n"
"`charname` = '%s',\n"
"`zone_id` = %u,\n"
"`instance_id` = %u,\n"
"`charid` = %d,\n"
"`x` = %1.1f,\n"
"`y` = %1.1f,\n"
"`z` = %1.1f,\n"
"`heading` = %1.1f,\n"
"`is_locked` = %d,\n"
"`exp` = %u,\n"
"`size` = %f,\n"
"`level` = %u,\n"
"`race` = %u,\n"
"`gender` = %u,\n"
"`class` = %u,\n"
"`deity` = %u,\n"
"`texture` = %u,\n"
"`helm_texture` = %u,\n"
"`copper` = %u,\n"
"`silver` = %u,\n"
"`gold` = %u,\n"
"`platinum` = %u,\n"
"`hair_color` = %u,\n"
"`beard_color` = %u,\n"
"`eye_color_1` = %u,\n"
"`eye_color_2` = %u,\n"
"`hair_style` = %u,\n"
"`face` = %u,\n"
"`beard` = %u,\n"
"`drakkin_heritage` = %u,\n"
"`drakkin_tattoo` = %u,\n"
"`drakkin_details` = %u,\n"
"`wc_1` = %u,\n"
"`wc_2` = %u,\n"
"`wc_3` = %u,\n"
"`wc_4` = %u,\n"
"`wc_5` = %u,\n"
"`wc_6` = %u,\n"
"`wc_7` = %u,\n"
"`wc_8` = %u,\n"
"`wc_9` = %u \n"
"WHERE `id` = %u",
EscapeString(char_name).c_str(),
zone_id,
instance_id,
char_id,
x,
y,
z,
heading,
dbpc->locked,
dbpc->exp,
dbpc->size,
dbpc->level,
dbpc->race,
dbpc->gender,
dbpc->class_,
dbpc->deity,
dbpc->texture,
dbpc->helmtexture,
dbpc->copper,
dbpc->silver,
dbpc->gold,
dbpc->plat,
dbpc->haircolor,
dbpc->beardcolor,
dbpc->eyecolor1,
dbpc->eyecolor2,
dbpc->hairstyle,
dbpc->face,
dbpc->beard,
dbpc->drakkin_heritage,
dbpc->drakkin_tattoo,
dbpc->drakkin_details,
dbpc->item_tint[0].color,
dbpc->item_tint[1].color,
dbpc->item_tint[2].color,
dbpc->item_tint[3].color,
dbpc->item_tint[4].color,
dbpc->item_tint[5].color,
dbpc->item_tint[6].color,
dbpc->item_tint[7].color,
dbpc->item_tint[8].color,
db_id
);
auto results = QueryDatabase(query);
query = StringFormat("DELETE FROM `character_corpse_items` WHERE `corpse_id` = %u");
results = QueryDatabase(query);
/* Dump Items from Inventory */
uint8 first_entry = 0;
for (unsigned int i = 0; i < dbpc->itemcount; i++) {
if (first_entry != 1){
query = StringFormat("REPLACE INTO `character_corpse_items` \n"
" (corpse_id, equip_slot, item_id, charges, aug_1, aug_2, aug_3, aug_4, aug_5, attuned) \n"
" VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, 0) \n",
db_id,
dbpc->items[i].equip_slot,
dbpc->items[i].item_id,
dbpc->items[i].charges,
dbpc->items[i].aug_1,
dbpc->items[i].aug_2,
dbpc->items[i].aug_3,
dbpc->items[i].aug_4,
dbpc->items[i].aug_5
);
first_entry = 1;
}
else{
query = query + StringFormat(", (%u, %u, %u, %u, %u, %u, %u, %u, %u, 0) \n",
db_id,
dbpc->items[i].equip_slot,
dbpc->items[i].item_id,
dbpc->items[i].charges,
dbpc->items[i].aug_1,
dbpc->items[i].aug_2,
dbpc->items[i].aug_3,
dbpc->items[i].aug_4,
dbpc->items[i].aug_5
);
}
}
results = QueryDatabase(query);
return db_id;
}
void ZoneDatabase::MarkCorpseAsRezzed(uint32 db_id) {
std::string query = StringFormat("UPDATE `character_corpses` SET `is_rezzed` = 1 WHERE `id` = %i", db_id);
auto results = QueryDatabase(query);
}
uint32 ZoneDatabase::SaveCharacterCorpse(uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, PlayerCorpse_Struct* dbpc, float x, float y, float z, float heading) {
/* Dump Basic Corpse Data */
std::string query = StringFormat("INSERT INTO `character_corpses` SET \n"
"`charname` = '%s',\n"
"`zone_id` = %u,\n"
"`instance_id` = %u,\n"
"`charid` = %d,\n"
"`x` = %1.1f,\n"
"`y` = %1.1f,\n"
"`z` = %1.1f,\n"
"`heading` = %1.1f,\n"
"`time_of_death` = NOW(),\n"
"`is_buried` = 0,"
"`is_locked` = %d,\n"
"`exp` = %u,\n"
"`size` = %f,\n"
"`level` = %u,\n"
"`race` = %u,\n"
"`gender` = %u,\n"
"`class` = %u,\n"
"`deity` = %u,\n"
"`texture` = %u,\n"
"`helm_texture` = %u,\n"
"`copper` = %u,\n"
"`silver` = %u,\n"
"`gold` = %u,\n"
"`platinum` = %u,\n"
"`hair_color` = %u,\n"
"`beard_color` = %u,\n"
"`eye_color_1` = %u,\n"
"`eye_color_2` = %u,\n"
"`hair_style` = %u,\n"
"`face` = %u,\n"
"`beard` = %u,\n"
"`drakkin_heritage` = %u,\n"
"`drakkin_tattoo` = %u,\n"
"`drakkin_details` = %u,\n"
"`wc_1` = %u,\n"
"`wc_2` = %u,\n"
"`wc_3` = %u,\n"
"`wc_4` = %u,\n"
"`wc_5` = %u,\n"
"`wc_6` = %u,\n"
"`wc_7` = %u,\n"
"`wc_8` = %u,\n"
"`wc_9` = %u \n",
EscapeString(charname).c_str(),
zoneid,
instanceid,
charid,
x,
y,
z,
heading,
dbpc->locked,
dbpc->exp,
dbpc->size,
dbpc->level,
dbpc->race,
dbpc->gender,
dbpc->class_,
dbpc->deity,
dbpc->texture,
dbpc->helmtexture,
dbpc->copper,
dbpc->silver,
dbpc->gold,
dbpc->plat,
dbpc->haircolor,
dbpc->beardcolor,
dbpc->eyecolor1,
dbpc->eyecolor2,
dbpc->hairstyle,
dbpc->face,
dbpc->beard,
dbpc->drakkin_heritage,
dbpc->drakkin_tattoo,
dbpc->drakkin_details,
dbpc->item_tint[0].color,
dbpc->item_tint[1].color,
dbpc->item_tint[2].color,
dbpc->item_tint[3].color,
dbpc->item_tint[4].color,
dbpc->item_tint[5].color,
dbpc->item_tint[6].color,
dbpc->item_tint[7].color,
dbpc->item_tint[8].color
);
auto results = QueryDatabase(query);
uint32 last_insert_id = results.LastInsertedID();
/* Dump Items from Inventory */
uint8 first_entry = 0;
for (unsigned int i = 0; i < dbpc->itemcount; i++) {
if (first_entry != 1){
query = StringFormat("REPLACE INTO `character_corpse_items` \n"
" (corpse_id, equip_slot, item_id, charges, aug_1, aug_2, aug_3, aug_4, aug_5, attuned) \n"
" VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, 0) \n",
last_insert_id,
dbpc->items[i].equip_slot,
dbpc->items[i].item_id,
dbpc->items[i].charges,
dbpc->items[i].aug_1,
dbpc->items[i].aug_2,
dbpc->items[i].aug_3,
dbpc->items[i].aug_4,
dbpc->items[i].aug_5
);
first_entry = 1;
}
else{
query = query + StringFormat(", (%u, %u, %u, %u, %u, %u, %u, %u, %u, 0) \n",
last_insert_id,
dbpc->items[i].equip_slot,
dbpc->items[i].item_id,
dbpc->items[i].charges,
dbpc->items[i].aug_1,
dbpc->items[i].aug_2,
dbpc->items[i].aug_3,
dbpc->items[i].aug_4,
dbpc->items[i].aug_5
);
}
}
auto sc_results = QueryDatabase(query);
return last_insert_id;
}
uint32 ZoneDatabase::GetCharacterBuriedCorpseCount(uint32 char_id) {
std::string query = StringFormat("SELECT COUNT(*) FROM `character_corpses` WHERE `charid` = '%u' AND `is_buried` = 1", char_id);
auto results = QueryDatabase(query);
for (auto row = results.begin(); row != results.end(); ++row) {
return atoi(row[0]);
}
return 0;
}
uint32 ZoneDatabase::GetCharacterCorpseCount(uint32 char_id) {
std::string query = StringFormat("SELECT COUNT(*) FROM `character_corpses` WHERE `charid` = '%u'", char_id);
auto results = QueryDatabase(query);
for (auto row = results.begin(); row != results.end(); ++row) {
return atoi(row[0]);
}
return 0;
}
uint32 ZoneDatabase::GetCharacterCorpseID(uint32 char_id, uint8 corpse) {
std::string query = StringFormat("SELECT `id` FROM `character_corpses` WHERE `charid` = '%u'", char_id);
auto results = QueryDatabase(query);
for (auto row = results.begin(); row != results.end(); ++row) {
for (int i = 0; i < corpse; i++) {
return atoi(row[0]);
}
}
return 0;
}
uint32 ZoneDatabase::GetCharacterCorpseItemAt(uint32 corpse_id, uint16 slotid) {
Corpse* tmp = LoadCharacterCorpse(corpse_id);
uint32 itemid = 0;
if (tmp) {
itemid = tmp->GetWornItem(slotid);
tmp->DepopCorpse();
}
return itemid;
}
bool ZoneDatabase::LoadCharacterCorpseData(uint32 corpse_id, PlayerCorpse_Struct* pcs){
std::string query = StringFormat(
"SELECT \n"
"id, \n"
"charid, \n"
"charname, \n"
"zone_id, \n"
"instance_id, \n"
"x, \n"
"y, \n"
"z, \n"
"heading, \n"
"`data`, \n"
"time_of_death, \n"
"is_rezzed, \n"
"is_buried, \n"
"was_at_graveyard, \n"
"is_locked, \n"
"exp, \n"
"size, \n"
"`level`, \n"
"race, \n"
"gender, \n"
"class, \n"
"deity, \n"
"texture, \n"
"helm_texture, \n"
"copper, \n"
"silver, \n"
"gold, \n"
"platinum, \n"
"hair_color, \n"
"beard_color, \n"
"eye_color_1, \n"
"eye_color_2, \n"
"hair_style, \n"
"face, \n"
"beard, \n"
"drakkin_heritage,\n"
"drakkin_tattoo, \n"
"drakkin_details, \n"
"wc_1, \n"
"wc_2, \n"
"wc_3, \n"
"wc_4, \n"
"wc_5, \n"
"wc_6, \n"
"wc_7, \n"
"wc_8, \n"
"wc_9 \n"
"FROM \n"
"character_corpses\n"
"WHERE `id` = %u LIMIT 1\n",
corpse_id
);
auto results = QueryDatabase(query);
uint16 i = 0;
for (auto row = results.begin(); row != results.end(); ++row) {
pcs->locked = atoi(row[i]); i++; // is_locked,
pcs->exp = atoi(row[i]); i++; // exp,
pcs->size = atoi(row[i]); i++; // size,
pcs->level = atoi(row[i]); i++; // `level`,
pcs->race = atoi(row[i]); i++; // race,
pcs->gender = atoi(row[i]); i++; // gender,
pcs->class_ = atoi(row[i]); i++; // class,
pcs->deity = atoi(row[i]); i++; // deity,
pcs->texture = atoi(row[i]); i++; // texture,
pcs->helmtexture = atoi(row[i]); i++; // helm_texture,
pcs->copper = atoi(row[i]); i++; // copper,
pcs->silver = atoi(row[i]); i++; // silver,
pcs->gold = atoi(row[i]); i++; // gold,
pcs->plat = atoi(row[i]); i++; // platinum,
pcs->haircolor = atoi(row[i]); i++; // hair_color,
pcs->beardcolor = atoi(row[i]); i++; // beard_color,
pcs->eyecolor1 = atoi(row[i]); i++; // eye_color_1,
pcs->eyecolor2 = atoi(row[i]); i++; // eye_color_2,
pcs->hairstyle = atoi(row[i]); i++; // hair_style,
pcs->face = atoi(row[i]); i++; // face,
pcs->beard = atoi(row[i]); i++; // beard,
pcs->drakkin_heritage = atoi(row[i]); i++; // drakkin_heritage,
pcs->drakkin_tattoo = atoi(row[i]); i++; // drakkin_tattoo,
pcs->drakkin_details = atoi(row[i]); i++; // drakkin_details,
pcs->item_tint[0].color = atoi(row[i]); i++; // wc_1,
pcs->item_tint[1].color = atoi(row[i]); i++; // wc_2,
pcs->item_tint[2].color = atoi(row[i]); i++; // wc_3,
pcs->item_tint[3].color = atoi(row[i]); i++; // wc_4,
pcs->item_tint[4].color = atoi(row[i]); i++; // wc_5,
pcs->item_tint[5].color = atoi(row[i]); i++; // wc_6,
pcs->item_tint[6].color = atoi(row[i]); i++; // wc_7,
pcs->item_tint[7].color = atoi(row[i]); i++; // wc_8,
pcs->item_tint[8].color = atoi(row[i]); i++; // wc_9
}
query = StringFormat(
"SELECT \n"
"equip_slot, \n"
"item_id, \n"
"charges, \n"
"aug_1, \n"
"aug_2, \n"
"aug_3, \n"
"aug_4, \n"
"aug_5, \n"
"attuned \n"
"FROM \n"
"character_corpse_items \n"
"WHERE `corpse_id` = %u\n"
"ORDER BY `equip_slot`",
corpse_id
);
results = QueryDatabase(query);
i = 0;
uint16 r = 0;
for (auto row = results.begin(); row != results.end(); ++row) {
pcs->items[i].equip_slot = atoi(row[r]); r++; // equip_slot,
pcs->items[i].item_id = atoi(row[r]); r++; // item_id,
pcs->items[i].charges = atoi(row[r]); r++; // charges,
pcs->items[i].aug_1 = atoi(row[r]); r++; // aug_1,
pcs->items[i].aug_2 = atoi(row[r]); r++; // aug_2,
pcs->items[i].aug_3 = atoi(row[r]); r++; // aug_3,
pcs->items[i].aug_4 = atoi(row[r]); r++; // aug_4,
pcs->items[i].aug_5 = atoi(row[r]); r++; // aug_5,
r = 0;
i++;
}
pcs->itemcount = i;
return true;
}
Corpse* ZoneDatabase::SummonBuriedCharacterCorpses(uint32 char_id, uint32 dest_zone_id, uint16 dest_instance_id, float dest_x, float dest_y, float dest_z, float dest_heading) {
Corpse* NewCorpse = 0;
std::string query = StringFormat(
"SELECT `id`, `charname`, `time_of_death`, `is_rezzed` FROM `character_corpses` WHERE `charid` = '%u' AND `is_buried` = 1 ORDER BY `time_of_death` LIMIT 1",
char_id
);
auto results = QueryDatabase(query);
for (auto row = results.begin(); row != results.end(); ++row) {
PlayerCorpse_Struct pcs;
database.LoadCharacterCorpseData(atoi(row[0]), &pcs);
NewCorpse = Corpse::LoadFromDBData(atoi(row[0]), char_id, row[1], &pcs, dest_x, dest_y, dest_z, dest_heading, row[2], atoi(row[3]) == 1, false);
if (NewCorpse) {
entity_list.AddCorpse(NewCorpse);
NewCorpse->SetDecayTimer(RuleI(Character, CorpseDecayTimeMS));
NewCorpse->Spawn();
if (!UnburyCharacterCorpse(NewCorpse->GetDBID(), dest_zone_id, dest_instance_id, 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);
}
}
return NewCorpse;
}
bool ZoneDatabase::SummonAllCharacterCorpses(uint32 char_id, uint32 dest_zone_id, uint16 dest_instance_id, float dest_x, float dest_y, float dest_z, float dest_heading) {
Corpse* NewCorpse = 0;
int CorpseCount = 0;
std::string query = StringFormat(
"UPDATE character_corpses SET zone_id = %i, instance_id = %i, x = %f, y = %f, z = %f, heading = %f, is_buried = 0, was_at_graveyard = 0 WHERE charid = %i",
dest_zone_id, dest_instance_id, dest_x, dest_y, dest_z, dest_heading, char_id
);
auto results = QueryDatabase(query);
query = StringFormat(
"SELECT `id`, `charname`, `time_of_death`, `is_rezzed` FROM `character_corpses` WHERE `charid` = '%u'"
"ORDER BY time_of_death",
char_id
);
results = QueryDatabase(query);
for (auto row = results.begin(); row != results.end(); ++row) {
PlayerCorpse_Struct pcs;
database.LoadCharacterCorpseData(atoi(row[0]), &pcs);
NewCorpse = Corpse::LoadFromDBData(atoi(row[0]),
char_id,
row[1],
&pcs,
dest_x,
dest_y,
dest_z,
dest_heading,
row[2],
atoi(row[3]) == 1, false);
if (NewCorpse) {
entity_list.AddCorpse(NewCorpse);
NewCorpse->SetDecayTimer(RuleI(Character, CorpseDecayTimeMS));
NewCorpse->Spawn();
++CorpseCount;
}
else{
LogFile->write(EQEMuLog::Error, "Unable to construct a player corpse for character id %u.", char_id);
}
}
return (CorpseCount > 0);
}
bool ZoneDatabase::UnburyCharacterCorpse(uint32 db_id, uint32 new_zone_id, uint16 new_instance_id, float new_x, float new_y, float new_z, float new_heading) {
std::string query = StringFormat(
"UPDATE `character_corpses` SET `is_buried` = 0, `zone_id` = %u, `instance_id` = %u, `x` = %f, `y` = %f, `z` = %f, `heading` = %f, `time_of_death` = Now(), `was_at_graveyard` = 0 WHERE `id` = %u",
new_zone_id, new_instance_id, new_x, new_y, new_z, new_heading, db_id
);
auto results = QueryDatabase(query);
if (results.Success() && results.RowsAffected() != 0){
return true;
}
return false;
}
Corpse* ZoneDatabase::LoadCharacterCorpse(uint32 player_corpse_id) {
Corpse* NewCorpse = 0;
std::string query = StringFormat(
"SELECT `id`, `charid`, `charname`, `x`, `y`, `z`, `heading`, `time_of_death`, `is_rezzed`, `was_at_graveyard` FROM `character_corpses` WHERE `id` = '%u' LIMIT 1",
player_corpse_id
);
auto results = QueryDatabase(query);
for (auto row = results.begin(); row != results.end(); ++row) {
PlayerCorpse_Struct pcs;
database.LoadCharacterCorpseData(atoi(row[0]), &pcs);
NewCorpse = Corpse::LoadFromDBData(
atoi(row[0]), // id uint32 in_dbid
atoi(row[1]), // charid uint32 in_charid
row[2], // charname char* in_charname
&pcs, // PlayerCorpse_Struct* pcs
atof(row[3]), // x float in_x
atof(row[4]), // y float in_y
atof(row[5]), // z float in_z
atof(row[6]), // heading float in_heading
row[7], // time_of_death char* time_of_death
atoi(row[8]) == 1, // is_rezzed bool rezzed
atoi(row[9]) // was_at_graveyard bool was_at_graveyard
);
entity_list.AddCorpse(NewCorpse);
}
return NewCorpse;
}
bool ZoneDatabase::LoadCharacterCorpses(uint32 zone_id, uint16 instance_id) {
std::string query;
if (!RuleB(Zone, EnableShadowrest))
query = StringFormat( "SELECT id, charid, charname, x, y, z, heading, time_of_death, is_rezzed, was_at_graveyard FROM character_corpses WHERE zone_id='%u' AND instance_id='%u'", zone_id, instance_id);
else
query = StringFormat("SELECT id, charid, charname, x, y, z, heading, time_of_death, is_rezzed, 0 as was_at_graveyard FROM character_corpses WHERE zone_id='%u' AND instance_id='%u' AND is_buried=0", zone_id, instance_id);
auto results = QueryDatabase(query);
for (auto row = results.begin(); row != results.end(); ++row) {
PlayerCorpse_Struct pcs;
database.LoadCharacterCorpseData(atoi(row[0]), &pcs);
entity_list.AddCorpse(
Corpse::LoadFromDBData(
atoi(row[0]), // id uint32 in_dbid
atoi(row[1]), // charid uint32 in_charid
row[2], // charname char* in_charname
&pcs, // PlayerCorpse_tSruct* pcs
atof(row[3]), // x float in_x
atof(row[4]), // y float in_y
atof(row[5]), // z float in_z
atof(row[6]), // heading float in_heading
row[7], // time_of_death char* time_of_death
atoi(row[8]) == 1, // is_rezzed bool rezzed
atoi(row[9])
)
);
}
return true;
}
uint32 ZoneDatabase::GetFirstCorpseID(uint32 char_id) {
std::string query = StringFormat("SELECT `id` FROM `character_corpses` WHERE `charid` = '%u' AND `is_buried` = 0 ORDER BY `time_of_death` LIMIT 1", char_id);
auto results = QueryDatabase(query);
for (auto row = results.begin(); row != results.end(); ++row) {
return atoi(row[0]);
}
return 0;
}
bool ZoneDatabase::BuryCharacterCorpse(uint32 db_id) {
std::string query = StringFormat("UPDATE `character_corpses` SET `is_buried` = 1 WHERE `id` = %d", db_id);
auto results = QueryDatabase(query);
if (results.Success() && results.RowsAffected() != 0){
return true;
}
return false;
}
bool ZoneDatabase::BuryAllCharacterCorpses(uint32 char_id) {
std::string query = StringFormat("UPDATE `character_corpses` SET `is_buried` = 1 WHERE `charid` = %d", char_id);
auto results = QueryDatabase(query);
if (results.Success() && results.RowsAffected() != 0){
return true;
}
return false;
}
bool ZoneDatabase::DeleteCharacterCorpse(uint32 db_id) {
std::string query = StringFormat("DELETE FROM `character_corpses` WHERE `id` = %d", db_id);
auto results = QueryDatabase(query);
if (results.Success() && results.RowsAffected() != 0){
return true;
}
return false;
}

View File

@ -227,9 +227,10 @@ public:
void SaveTraderItem(uint32 char_id,uint32 itemid,uint32 uniqueid, int32 charges,uint32 itemcost,uint8 slot); void SaveTraderItem(uint32 char_id,uint32 itemid,uint32 uniqueid, int32 charges,uint32 itemcost,uint8 slot);
void UpdateTraderItemCharges(int char_id, uint32 ItemInstID, int32 charges); void UpdateTraderItemCharges(int char_id, uint32 ItemInstID, int32 charges);
void UpdateTraderItemPrice(int CharID, uint32 ItemID, uint32 Charges, uint32 NewPrice); void UpdateTraderItemPrice(int CharID, uint32 ItemID, uint32 Charges, uint32 NewPrice);
ItemInst* LoadSingleTraderItem(uint32 char_id, int uniqueid);
void DeleteTraderItem(uint32 char_id); void DeleteTraderItem(uint32 char_id);
void DeleteTraderItem(uint32 char_id,uint16 slot_id); void DeleteTraderItem(uint32 char_id,uint16 slot_id);
ItemInst* LoadSingleTraderItem(uint32 char_id, int uniqueid);
Trader_Struct* LoadTraderItem(uint32 char_id); Trader_Struct* LoadTraderItem(uint32 char_id);
TraderCharges_Struct* LoadTraderItemWithCharges(uint32 char_id); TraderCharges_Struct* LoadTraderItemWithCharges(uint32 char_id);
@ -294,29 +295,30 @@ public:
bool NoRentExpired(const char* name); bool NoRentExpired(const char* name);
/* Corpses */ /* Corpses */
bool GetDecayTimes(npcDecayTimes_Struct* npcCorpseDecayTimes);
uint32 CreatePlayerCorpse(uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, uchar* data, uint32 datasize, float x, float y, float z, float heading); bool LoadCharacterCorpseData(uint32 corpse_id, PlayerCorpse_Struct* pcs);
bool CreatePlayerCorpseBackup(uint32 dbid, uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, uchar* data, uint32 datasize, float x, float y, float z, float heading); Corpse* LoadCharacterCorpse(uint32 player_corpse_id);
uint32 UpdatePlayerCorpse(uint32 dbid, uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, uchar* data, uint32 datasize, float x, float y, float z, float heading, bool rezzed = false); Corpse* SummonBuriedCharacterCorpses(uint32 char_id, uint32 dest_zoneid, uint16 dest_instanceid, float dest_x, float dest_y, float dest_z, float dest_heading);
void MarkCorpseAsRezzed(uint32 dbid); void MarkCorpseAsRezzed(uint32 dbid);
bool BuryPlayerCorpse(uint32 dbid); bool GetDecayTimes(npcDecayTimes_Struct* npcCorpseDecayTimes);
bool BuryAllPlayerCorpses(uint32 charid); bool BuryCharacterCorpse(uint32 dbid);
bool DeletePlayerCorpse(uint32 dbid); bool BuryAllCharacterCorpses(uint32 charid);
uint32 GetPlayerBurriedCorpseCount(uint32 char_id); bool DeleteCharacterCorpse(uint32 dbid);
Corpse* SummonBurriedPlayerCorpse(uint32 char_id, uint32 dest_zoneid, uint16 dest_instanceid, float dest_x, float dest_y, float dest_z, float dest_heading); bool SummonAllCharacterCorpses(uint32 char_id, uint32 dest_zoneid, uint16 dest_instanceid, float dest_x, float dest_y, float dest_z, float dest_heading);
bool SummonAllPlayerCorpses(uint32 char_id, uint32 dest_zoneid, uint16 dest_instanceid, float dest_x, float dest_y, float dest_z, float dest_heading);
bool SummonAllGraveyardCorpses(uint32 cur_zoneid, uint32 dest_zoneid, uint16 dest_instanceid, float dest_x, float dest_y, float dest_z, float dest_heading); bool SummonAllGraveyardCorpses(uint32 cur_zoneid, uint32 dest_zoneid, uint16 dest_instanceid, float dest_x, float dest_y, float dest_z, float dest_heading);
Corpse* LoadPlayerCorpse(uint32 player_corpse_id); bool UnburyCharacterCorpse(uint32 dbid, uint32 new_zoneid, uint16 dest_instanceid, float new_x, float new_y, float new_z, float new_heading);
bool UnburyPlayerCorpse(uint32 dbid, uint32 new_zoneid, uint16 dest_instanceid, float new_x, float new_y, float new_z, float new_heading); bool LoadCharacterCorpses(uint32 iZoneID, uint16 iInstanceID);
bool LoadPlayerCorpses(uint32 iZoneID, uint16 iInstanceID);
uint32 GraveyardPlayerCorpse(uint32 dbid, uint32 zoneid, uint16 instanceid, float x, float y, float z, float heading);
uint32 NewGraveyardRecord(uint32 graveyard_zoneid, float graveyard_x, float graveyard_y, float graveyard_z, float graveyard_heading);
uint32 AddGraveyardIDToZone(uint32 zone_id, uint32 graveyard_id);
bool DeleteGraveyard(uint32 zone_id, uint32 graveyard_id); bool DeleteGraveyard(uint32 zone_id, uint32 graveyard_id);
uint32 GetCharacterBuriedCorpseCount(uint32 char_id);
uint32 SendCharacterCorpseToGraveyard(uint32 dbid, uint32 zoneid, uint16 instanceid, float x, float y, float z, float heading);
uint32 CreateGraveyardRecord(uint32 graveyard_zoneid, float graveyard_x, float graveyard_y, float graveyard_z, float graveyard_heading);
uint32 AddGraveyardIDToZone(uint32 zone_id, uint32 graveyard_id);
uint32 SaveCharacterCorpse(uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, PlayerCorpse_Struct* dbpc, float x, float y, float z, float heading);
uint32 UpdateCharacterCorpse(uint32 dbid, uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, PlayerCorpse_Struct* dbpc, float x, float y, float z, float heading, bool rezzed = false);
uint32 GetFirstCorpseID(uint32 char_id); uint32 GetFirstCorpseID(uint32 char_id);
uint32 GetPlayerCorpseCount(uint32 char_id); uint32 GetCharacterCorpseCount(uint32 char_id);
uint32 GetPlayerCorpseID(uint32 char_id, uint8 corpse); uint32 GetCharacterCorpseID(uint32 char_id, uint8 corpse);
uint32 GetPlayerCorpseItemAt(uint32 corpse_id, uint16 slotid); uint32 GetCharacterCorpseItemAt(uint32 corpse_id, uint16 slotid);
uint32 GetPlayerCorpseTimeLeft(uint8 corpse, uint8 type); uint32 GetPlayerCorpseTimeLeft(uint8 corpse, uint8 type);
/* Faction */ /* Faction */
@ -361,7 +363,6 @@ public:
uint32 GetFreeGrid(uint16 zoneid); uint32 GetFreeGrid(uint16 zoneid);
void DeleteGrid(Client *c, uint32 sg2, uint32 grid_num, bool grid_too, uint16 zoneid); void DeleteGrid(Client *c, uint32 sg2, uint32 grid_num, bool grid_too, uint16 zoneid);
void DeleteWaypoint(Client *c, uint32 grid_num, uint32 wp_num, uint16 zoneid); void DeleteWaypoint(Client *c, uint32 grid_num, uint32 wp_num, uint16 zoneid);
// uint32 AddWP(Client *c, uint32 sg2, uint16 grid_num, uint8 wp_num, float xpos, float ypos, float zpos, uint32 pause, float xpos1, float ypos1, float zpos1, int type1, int type2,uint16 zoneid);
void AddWP(Client *c, uint32 gridid, uint32 wpnum, float xpos, float ypos, float zpos, uint32 pause, uint16 zoneid, float heading); void AddWP(Client *c, uint32 gridid, uint32 wpnum, float xpos, float ypos, float zpos, uint32 pause, uint16 zoneid, float heading);
uint32 AddWPForSpawn(Client *c, uint32 spawn2id, float xpos, float ypos, float zpos, uint32 pause, int type1, int type2, uint16 zoneid, float heading); uint32 AddWPForSpawn(Client *c, uint32 spawn2id, float xpos, float ypos, float zpos, uint32 pause, int type1, int type2, uint16 zoneid, float heading);
void ModifyGrid(Client *c, bool remove, uint32 id, uint8 type = 0, uint8 type2 = 0, uint16 zoneid = 0); void ModifyGrid(Client *c, bool remove, uint32 id, uint8 type = 0, uint8 type2 = 0, uint16 zoneid = 0);
@ -374,7 +375,7 @@ public:
int GetHighestWaypoint(uint32 zoneid, uint32 gridid); int GetHighestWaypoint(uint32 zoneid, uint32 gridid);
/* NPCs */ /* NPCs */
const NPCType* GetNPCType(uint32 id);
uint32 NPCSpawnDB(uint8 command, const char* zone, uint32 zone_version, Client *c, NPC* spawn = 0, uint32 extra = 0); // 0 = Create 1 = Add; 2 = Update; 3 = Remove; 4 = Delete uint32 NPCSpawnDB(uint8 command, const char* zone, uint32 zone_version, Client *c, NPC* spawn = 0, uint32 extra = 0); // 0 = Create 1 = Add; 2 = Update; 3 = Remove; 4 = Delete
uint32 CreateNewNPCCommand(const char* zone, uint32 zone_version, Client *client, NPC* spawn, uint32 extra); uint32 CreateNewNPCCommand(const char* zone, uint32 zone_version, Client *client, NPC* spawn, uint32 extra);
uint32 AddNewNPCSpawnGroupCommand(const char* zone, uint32 zone_version, Client *client, NPC* spawn, uint32 respawnTime); uint32 AddNewNPCSpawnGroupCommand(const char* zone, uint32 zone_version, Client *client, NPC* spawn, uint32 respawnTime);
@ -391,8 +392,10 @@ public:
void AddLootDropToNPC(NPC* npc, uint32 lootdrop_id, ItemList* itemlist, uint8 droplimit, uint8 mindrop); void AddLootDropToNPC(NPC* npc, uint32 lootdrop_id, ItemList* itemlist, uint8 droplimit, uint8 mindrop);
uint32 GetMaxNPCSpellsID(); uint32 GetMaxNPCSpellsID();
uint32 GetMaxNPCSpellsEffectsID(); uint32 GetMaxNPCSpellsEffectsID();
DBnpcspells_Struct* GetNPCSpells(uint32 iDBSpellsID); DBnpcspells_Struct* GetNPCSpells(uint32 iDBSpellsID);
DBnpcspellseffects_Struct* GetNPCSpellsEffects(uint32 iDBSpellsEffectsID); DBnpcspellseffects_Struct* GetNPCSpellsEffects(uint32 iDBSpellsEffectsID);
const NPCType* GetNPCType(uint32 id);
/* Mercs */ /* Mercs */
const NPCType* GetMercType(uint32 id, uint16 raceid, uint32 clientlevel); const NPCType* GetMercType(uint32 id, uint16 raceid, uint32 clientlevel);
@ -403,8 +406,6 @@ public:
bool LoadCurrentMerc(Client *c); bool LoadCurrentMerc(Client *c);
bool SaveMerc(Merc *merc); bool SaveMerc(Merc *merc);
bool DeleteMerc(uint32 merc_id); bool DeleteMerc(uint32 merc_id);
//void LoadMercTypesForMercMerchant(NPC *merchant);
//void LoadMercsForMercMerchant(NPC *merchant);
/* Petitions */ /* Petitions */
void UpdateBug(BugStruct* bug); void UpdateBug(BugStruct* bug);

View File

@ -36,10 +36,8 @@ struct NPCType
{ {
char name[64]; char name[64];
char lastname[70]; char lastname[70];
int32 cur_hp; int32 cur_hp;
int32 max_hp; int32 max_hp;
float size; float size;
float runspeed; float runspeed;
uint8 gender; uint8 gender;
@ -130,38 +128,28 @@ struct NPCType
uint8 probability; uint8 probability;
}; };
/* namespace player_lootitem {
Below are the blob structures for saving player corpses to the database
-Quagmire
create table player_corpses (id int(11) unsigned not null auto_increment primary key, charid int(11) unsigned not null,
charname varchar(30) not null, zonename varchar(16)not null, x float not null, y float not null, z float not null,
heading float not null, data blob not null, time timestamp(14), index zonename (zonename));
*/
namespace player_lootitem
{
struct ServerLootItem_Struct { struct ServerLootItem_Struct {
uint32 item_id; uint32 item_id;
int16 equipSlot; int16 equip_slot;
uint8 charges; uint8 charges;
uint16 lootslot; uint16 lootslot;
uint32 aug1; uint32 aug_1;
uint32 aug2; uint32 aug_2;
uint32 aug3; uint32 aug_3;
uint32 aug4; uint32 aug_4;
uint32 aug5; uint32 aug_5;
}; };
} }
struct DBPlayerCorpse_Struct { struct PlayerCorpse_Struct {
uint32 crc; uint32 crc;
bool locked; bool locked;
uint32 itemcount; uint32 itemcount;
uint32 exp; uint32 exp;
float size; float size;
uint8 level; uint8 level;
uint8 race; uint32 race;
uint8 gender; uint8 gender;
uint8 class_; uint8 class_;
uint8 deity; uint8 deity;
@ -185,37 +173,6 @@ struct DBPlayerCorpse_Struct {
player_lootitem::ServerLootItem_Struct items[0]; player_lootitem::ServerLootItem_Struct items[0];
}; };
namespace classic_db
{
struct DBPlayerCorpse_Struct {
uint32 crc;
bool locked;
uint32 itemcount;
uint32 exp;
float size;
uint8 level;
uint8 race;
uint8 gender;
uint8 class_;
uint8 deity;
uint8 texture;
uint8 helmtexture;
uint32 copper;
uint32 silver;
uint32 gold;
uint32 plat;
Color_Struct item_tint[9];
uint8 haircolor;
uint8 beardcolor;
uint8 eyecolor1;
uint8 eyecolor2;
uint8 hairstyle;
uint8 face;
uint8 beard;
player_lootitem::ServerLootItem_Struct items[0];
};
}
struct Door { struct Door {
uint32 db_id; uint32 db_id;
uint8 door_id; uint8 door_id;
@ -228,7 +185,7 @@ struct Door {
int incline; int incline;
uint8 opentype; uint8 opentype;
uint32 guild_id; uint32 guild_id;
uint16 lockpick; uint16 lock_pick;
uint32 keyitem; uint32 keyitem;
uint8 nokeyring; uint8 nokeyring;
uint8 trigger_door; uint8 trigger_door;