From f1bb019933fa8e4010905a3d082c1854e40f3e3b Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 16:46:17 -0700 Subject: [PATCH 001/127] SaveZoneCFG converted to QueryDatabase --- zone/zonedb.cpp | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 0d1653453..d2fd1f8e5 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -69,23 +69,26 @@ ZoneDatabase::~ZoneDatabase() { } } -bool ZoneDatabase::SaveZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct* zd){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - if (!RunQuery(query, MakeAnyLenString(&query, "update zone set underworld=%f,minclip=%f," - "maxclip=%f,fog_minclip=%f,fog_maxclip=%f,fog_blue=%i,fog_red=%i,fog_green=%i,sky=%i," - "ztype=%i,zone_exp_multiplier=%f,safe_x=%f,safe_y=%f,safe_z=%f " - "where zoneidnumber=%i and version=%i", - zd->underworld,zd->minclip, - zd->maxclip,zd->fog_minclip[0],zd->fog_maxclip[0],zd->fog_blue[0],zd->fog_red[0],zd->fog_green[0],zd->sky, - zd->ztype,zd->zone_exp_multiplier, - zd->safe_x,zd->safe_y,zd->safe_z, - zoneid, instance_id),errbuf)) { - LogFile->write(EQEMuLog::Error, "Error in SaveZoneCFG query %s: %s", query, errbuf); - safe_delete_array(query); - return false; +bool ZoneDatabase::SaveZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct* zd) { + + std::string query = StringFormat("UPDATE zone SET underworld = %f, minclip = %f, " + "maxclip = %f, fog_minclip = %f, fog_maxclip = %f, " + "fog_blue = %i, fog_red = %i, fog_green = %i, " + "sky = %i, ztype = %i, zone_exp_multiplier = %f, " + "safe_x = %f, safe_y = %f, safe_z = %f " + "WHERE zoneidnumber = %i AND version = %i", + zd->underworld, zd->minclip, + zd->maxclip, zd->fog_minclip[0], zd->fog_maxclip[0], + zd->fog_blue[0], zd->fog_red[0], zd->fog_green[0], + zd->sky, zd->ztype, zd->zone_exp_multiplier, + zd->safe_x, zd->safe_y, zd->safe_z, + zoneid, instance_id); + auto results = QueryDatabase(query); + if (!results.Success()) { + LogFile->write(EQEMuLog::Error, "Error in SaveZoneCFG query %s: %s", query.c_str(), results.ErrorMessage().c_str()); + return false; } - safe_delete_array(query); + return true; } @@ -1211,7 +1214,7 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { tmpNPCType->armor_tint[0] |= (atoi(row[r++]) & 0xFF) << 8; tmpNPCType->armor_tint[0] |= (atoi(row[r++]) & 0xFF); tmpNPCType->armor_tint[0] |= (tmpNPCType->armor_tint[0]) ? (0xFF << 24) : 0; - + int i; if (armor_tint_id > 0) { @@ -1304,7 +1307,7 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { tmpNPCType->healscale = atoi(row[r++]); tmpNPCType->no_target_hotkey = atoi(row[r++]) == 1 ? true : false; tmpNPCType->raid_target = atoi(row[r++]) == 0 ? false : true; - + // If NPC with duplicate NPC id already in table, // free item we attempted to add. if (zone->npctable.find(tmpNPCType->npc_id) != zone->npctable.end()) @@ -1849,9 +1852,9 @@ void ZoneDatabase::SaveMercBuffs(Merc *merc) { CalculateCorruptionCounters(buffs[BuffCount].spellid) > 0 ? buffs[BuffCount].counters : 0, buffs[BuffCount].numhits, buffs[BuffCount].melee_rune, buffs[BuffCount].magic_rune, buffs[BuffCount].dot_rune, - buffs[BuffCount].caston_x, - IsPersistent, - buffs[BuffCount].caston_y, + buffs[BuffCount].caston_x, + IsPersistent, + buffs[BuffCount].caston_y, buffs[BuffCount].caston_z, buffs[BuffCount].ExtraDIChance), TempErrorMessageBuffer)) { errorMessage = std::string(TempErrorMessageBuffer); @@ -2931,7 +2934,7 @@ void ZoneDatabase::LoadPetInfo(Client *c) { pi = suspended; else continue; - + int slot = atoi(row[1]); if (slot < EmuConstants::EQUIPMENT_BEGIN || slot > EmuConstants::EQUIPMENT_END) continue; From 693dde04e34a9c415802a056e6e6ff93fbd836df Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 17:16:30 -0700 Subject: [PATCH 002/127] GetZoneCFG converted to QueryDatabase --- zone/zonedb.cpp | 182 +++++++++++++++++++++++------------------------- 1 file changed, 88 insertions(+), 94 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index d2fd1f8e5..cba20fdcc 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -93,103 +93,97 @@ bool ZoneDatabase::SaveZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct } bool ZoneDatabase::GetZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct *zone_data, bool &can_bind, bool &can_combat, bool &can_levitate, bool &can_castoutdoor, bool &is_city, bool &is_hotzone, bool &allow_mercs, uint8 &zone_type, int &ruleset, char **map_filename) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - int i=0; - int b=0; - bool good = false; + *map_filename = new char[100]; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT ztype," - "fog_red,fog_green,fog_blue,fog_minclip,fog_maxclip," - "fog_red2,fog_green2,fog_blue2,fog_minclip2,fog_maxclip2," - "fog_red3,fog_green3,fog_blue3,fog_minclip3,fog_maxclip3," - "fog_red4,fog_green4,fog_blue4,fog_minclip4,fog_maxclip4,fog_density," - "sky,zone_exp_multiplier,safe_x,safe_y,safe_z,underworld," - "minclip,maxclip,time_type,canbind,cancombat,canlevitate," - "castoutdoor,hotzone,ruleset,suspendbuffs,map_file_name,short_name," - "rain_chance1,rain_chance2,rain_chance3,rain_chance4," - "rain_duration1,rain_duration2,rain_duration3,rain_duration4," - "snow_chance1,snow_chance2,snow_chance3,snow_chance4," - "snow_duration1,snow_duration2,snow_duration3,snow_duration4" - " from zone where zoneidnumber=%i and version=%i",zoneid, instance_id), errbuf, &result)) { - safe_delete_array(query); - row = mysql_fetch_row(result); - if(row) - { - int r = 0; - memset(zone_data,0,sizeof(NewZone_Struct)); - zone_data->ztype=atoi(row[r++]); - - for(i=0;i<4;i++){ - zone_data->fog_red[i]=atoi(row[r++]); - zone_data->fog_green[i]=atoi(row[r++]); - zone_data->fog_blue[i]=atoi(row[r++]); - zone_data->fog_minclip[i]=atof(row[r++]); - zone_data->fog_maxclip[i]=atof(row[r++]); - } - - zone_data->fog_density = atof(row[r++]);; - zone_data->sky=atoi(row[r++]); - zone_data->zone_exp_multiplier=atof(row[r++]); - zone_data->safe_x=atof(row[r++]); - zone_data->safe_y=atof(row[r++]); - zone_data->safe_z=atof(row[r++]); - zone_data->underworld=atof(row[r++]); - zone_data->minclip=atof(row[r++]); - zone_data->maxclip=atof(row[r++]); - - zone_data->time_type=atoi(row[r++]); -//not in the DB yet: - zone_data->gravity = 0.4; - - b = atoi(row[r++]); - can_bind = b==0?false:true; - is_city = b==2?true:false; - can_combat = atoi(row[r++])==0?false:true; - can_levitate = atoi(row[r++])==0?false:true; - can_castoutdoor = atoi(row[r++])==0?false:true; - is_hotzone = atoi(row[r++])==0?false:true; - allow_mercs = true; - zone_type = zone_data->ztype; - ruleset = atoi(row[r++]); - zone_data->SuspendBuffs = atoi(row[r++]); - char *file = row[r++]; - if(file) - { - strcpy(*map_filename, file); - } - else - { - strcpy(*map_filename, row[r++]); - } - for(i=0;i<4;i++){ - zone_data->rain_chance[i]=atoi(row[r++]); - } - for(i=0;i<4;i++){ - zone_data->rain_duration[i]=atoi(row[r++]); - } - for(i=0;i<4;i++){ - zone_data->snow_chance[i]=atoi(row[r++]); - } - for(i=0;i<4;i++){ - zone_data->snow_duration[i]=atof(row[r++]); - } - good = true; - } - mysql_free_result(result); - } - else - { - LogFile->write(EQEMuLog::Error, "Error in GetZoneCFG query %s: %s", query, errbuf); - strcpy(*map_filename, "default"); - } - safe_delete_array(query); - zone_data->zone_id = zoneid; - return(good); + std::string query = StringFormat("SELECT ztype, fog_red, fog_green, fog_blue, fog_minclip, fog_maxclip, " // 5 + "fog_red2, fog_green2, fog_blue2, fog_minclip2, fog_maxclip2, " // 5 + "fog_red3, fog_green3, fog_blue3, fog_minclip3, fog_maxclip3, " // 5 + "fog_red4, fog_green4, fog_blue4, fog_minclip4, fog_maxclip4, " // 5 + "fog_density, sky, zone_exp_multiplier, safe_x, safe_y, safe_z, underworld, " // 7 + "minclip, maxclip, time_type, canbind, cancombat, canlevitate, " // 6 + "castoutdoor, hotzone, ruleset, suspendbuffs, map_file_name, short_name, " // 6 + "rain_chance1, rain_chance2, rain_chance3, rain_chance4, " // 4 + "rain_duration1, rain_duration2, rain_duration3, rain_duration4, " // 4 + "snow_chance1, snow_chance2, snow_chance3, snow_chance4, " // 4 + "snow_duration1, snow_duration2, snow_duration3, snow_duration4 " // 4 + "FROM zone WHERE zoneidnumber = %i AND version = %i", zoneid, instance_id); + auto results = QueryDatabase(query); + if (!results.Success()) { + LogFile->write(EQEMuLog::Error, "Error in GetZoneCFG query %s: %s", query.c_str(), results.ErrorMessage().c_str()); + strcpy(*map_filename, "default"); + return false; + } + + if (results.RowCount() == 0) { + strcpy(*map_filename, "default"); + return false; + } + + auto row = results.begin(); + + memset(zone_data, 0, sizeof(NewZone_Struct)); + zone_data->ztype = atoi(row[0]); + zone_type = zone_data->ztype; + + int index; + for(index = 0; index < 4; index++) { + zone_data->fog_red[index]=atoi(row[1 + index * 5]); + zone_data->fog_green[index]=atoi(row[2 + index * 5]); + zone_data->fog_blue[index]=atoi(row[3 + index * 5]); + zone_data->fog_minclip[index]=atof(row[4 + index * 5]); + zone_data->fog_maxclip[index]=atof(row[5 + index * 5]); + } + + zone_data->fog_density = atof(row[22]); + zone_data->sky=atoi(row[23]); + zone_data->zone_exp_multiplier=atof(row[24]); + zone_data->safe_x=atof(row[25]); + zone_data->safe_y=atof(row[26]); + zone_data->safe_z=atof(row[27]); + zone_data->underworld=atof(row[28]); + zone_data->minclip=atof(row[29]); + zone_data->maxclip=atof(row[30]); + zone_data->time_type=atoi(row[31]); + + //not in the DB yet: + zone_data->gravity = 0.4; + allow_mercs = true; + + int bindable = 0; + bindable = atoi(row[32]); + + can_bind = bindable == 0? false: true; + is_city = bindable == 2? true: false; + can_combat = atoi(row[33]) == 0? false: true; + can_levitate = atoi(row[34]) == 0? false: true; + can_castoutdoor = atoi(row[35]) == 0? false: true; + is_hotzone = atoi(row[36]) == 0? false: true; + + + ruleset = atoi(row[36]); + zone_data->SuspendBuffs = atoi(row[37]); + + char *file = row[38]; + if(file) + strcpy(*map_filename, file); + else + strcpy(*map_filename, row[39]); + + for(index = 0; index < 4; index++) + zone_data->rain_chance[index]=atoi(row[40 + index]); + + for(index = 0; index < 4; index++) + zone_data->rain_duration[index]=atoi(row[44 + index]); + + for(index = 0; index < 4; index++) + zone_data->snow_chance[index]=atoi(row[49 + index]); + + for(index = 0; index < 4; index++) + zone_data->snow_duration[index]=atof(row[53 + index]); + + return true; } //updates or clears the respawn time in the database for the current spawn id From bcdfd32bc07e011c50efff02ab51cd464930224b Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 17:21:07 -0700 Subject: [PATCH 003/127] UpdateSpawn2Timeleft converted to QueryDatabase --- zone/zonedb.cpp | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index cba20fdcc..ae3ecdfe6 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -193,29 +193,26 @@ void ZoneDatabase::UpdateSpawn2Timeleft(uint32 id, uint16 instance_id, uint32 ti gettimeofday(&tv, nullptr); uint32 cur = tv.tv_sec; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - //if we pass timeleft as 0 that means we clear from respawn time //otherwise we update with a REPLACE INTO - if(timeleft == 0) - { - if (!RunQuery(query, MakeAnyLenString(&query, "DELETE FROM respawn_times WHERE id=%lu " - "AND instance_id=%lu",(unsigned long)id, (unsigned long)instance_id),errbuf)) - { - LogFile->write(EQEMuLog::Error, "Error in UpdateTimeLeft query %s: %s", query, errbuf); - } - safe_delete_array(query); - } - else - { - if (!RunQuery(query, MakeAnyLenString(&query, "REPLACE INTO respawn_times (id,start,duration,instance_id) " - "VALUES(%lu,%lu,%lu,%lu)",(unsigned long)id, (unsigned long)cur, (unsigned long)timeleft, (unsigned long)instance_id),errbuf)) - { - LogFile->write(EQEMuLog::Error, "Error in UpdateTimeLeft query %s: %s", query, errbuf); - } - safe_delete_array(query); + if(timeleft == 0) { + std::string query = StringFormat("DELETE FROM respawn_times WHERE id=%lu " + "AND instance_id = %lu",(unsigned long)id, (unsigned long)instance_id); + auto results = QueryDatabase(query); + if (!results.Success()) + LogFile->write(EQEMuLog::Error, "Error in UpdateTimeLeft query %s: %s", query.c_str(), results.ErrorMessage().c_str()); + + return; } + + std::string query = StringFormat("REPLACE INTO respawn_times (id, start, duration, instance_id) " + "VALUES (%lu, %lu, %lu, %lu)", + (unsigned long)id, (unsigned long)cur, + (unsigned long)timeleft, (unsigned long)instance_id); + auto results = QueryDatabase(query); + if (!results.Success()) + LogFile->write(EQEMuLog::Error, "Error in UpdateTimeLeft query %s: %s", query.c_str(), results.ErrorMessage().c_str()); + return; } From 4f9d4b00238b3bd8781a7b5a95724ba709f7410e Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 17:25:27 -0700 Subject: [PATCH 004/127] GetSpawnTimeLeft converted to QueryDatabase --- zone/zonedb.cpp | 72 +++++++++++++++++++------------------------------ 1 file changed, 27 insertions(+), 45 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index ae3ecdfe6..63d6f83eb 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -219,52 +219,34 @@ void ZoneDatabase::UpdateSpawn2Timeleft(uint32 id, uint16 instance_id, uint32 ti //Gets the respawn time left in the database for the current spawn id uint32 ZoneDatabase::GetSpawnTimeLeft(uint32 id, uint16 instance_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - - MakeAnyLenString(&query, "SELECT start, duration FROM respawn_times WHERE id=%lu AND instance_id=%lu", - (unsigned long)id, (unsigned long)zone->GetInstanceID()); - - if (RunQuery(query, strlen(query), errbuf, &result)) - { - safe_delete_array(query); - row = mysql_fetch_row(result); - if(row) - { - timeval tv; - gettimeofday(&tv, nullptr); - uint32 resStart = atoi(row[0]); - uint32 resDuration = atoi(row[1]); - - //compare our values to current time - if((resStart + resDuration) <= tv.tv_sec) - { - //our current time was expired - mysql_free_result(result); - return 0; - } - else - { - //we still have time left on this timer - mysql_free_result(result); - return ((resStart + resDuration) - tv.tv_sec); - } - } - else - { - mysql_free_result(result); - return 0; - } - } - else - { - LogFile->write(EQEMuLog::Error, "Error in GetSpawnTimeLeft query '%s': %s", query, errbuf); - safe_delete_array(query); + std::string query = StringFormat("SELECT start, duration FROM respawn_times " + "WHERE id = %lu AND instance_id = %lu", + (unsigned long)id, (unsigned long)zone->GetInstanceID()); + auto results = QueryDatabase(query); + if (!results.Success()) { + LogFile->write(EQEMuLog::Error, "Error in GetSpawnTimeLeft query '%s': %s", query.c_str(), results.ErrorMessage().c_str()); return 0; - } - return 0; + } + + if (results.RowCount() != 1) + return 0; + + auto row = results.begin(); + + timeval tv; + gettimeofday(&tv, nullptr); + uint32 resStart = atoi(row[0]); + uint32 resDuration = atoi(row[1]); + + //compare our values to current time + if((resStart + resDuration) <= tv.tv_sec) { + //our current time was expired + return 0; + } + + //we still have time left on this timer + return ((resStart + resDuration) - tv.tv_sec); + } void ZoneDatabase::UpdateSpawn2Status(uint32 id, uint8 new_status) From 3479525f391ba4f8bb6d51fc8d8d48ba689b65f5 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 17:27:19 -0700 Subject: [PATCH 005/127] UpdateSpawn2Status converted to QueryDatabase --- zone/zonedb.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 63d6f83eb..bcf67b5f5 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -251,15 +251,11 @@ uint32 ZoneDatabase::GetSpawnTimeLeft(uint32 id, uint16 instance_id) void ZoneDatabase::UpdateSpawn2Status(uint32 id, uint8 new_status) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; + std::string query = StringFormat("UPDATE spawn2 SET enabled = %i WHERE id = %lu", new_status, (unsigned long)id); + auto results = QueryDatabase(query); + if(!results.Success()) + LogFile->write(EQEMuLog::Error, "Error in UpdateSpawn2Status query %s: %s", query.c_str(), results.ErrorMessage().c_str()); - if(!RunQuery(query, MakeAnyLenString(&query, "UPDATE spawn2 SET enabled=%i WHERE id=%lu", new_status, (unsigned long)id),errbuf)) - { - LogFile->write(EQEMuLog::Error, "Error in UpdateSpawn2Status query %s: %s", query, errbuf); - } - safe_delete_array(query); - return; } bool ZoneDatabase::logevents(const char* accountname,uint32 accountid,uint8 status,const char* charname, const char* target,const char* descriptiontype, const char* description,int event_nid){ From 96f122f9018beb78d08037f83e07dee16cc96416 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 17:31:16 -0700 Subject: [PATCH 006/127] logevents converted to QueryDatabase --- zone/zonedb.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index bcf67b5f5..2b15560b1 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -259,8 +259,7 @@ void ZoneDatabase::UpdateSpawn2Status(uint32 id, uint8 new_status) } bool ZoneDatabase::logevents(const char* accountname,uint32 accountid,uint8 status,const char* charname, const char* target,const char* descriptiontype, const char* description,int event_nid){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; + uint32 len = strlen(description); uint32 len2 = strlen(target); char* descriptiontext = new char[2*len+1]; @@ -269,14 +268,20 @@ bool ZoneDatabase::logevents(const char* accountname,uint32 accountid,uint8 stat memset(targetarr, 0, 2*len2+1); DoEscapeString(descriptiontext, description, len); DoEscapeString(targetarr, target, len2); - if (!RunQuery(query, MakeAnyLenString(&query, "Insert into eventlog (accountname,accountid,status,charname,target,descriptiontype,description,event_nid) values('%s',%i,%i,'%s','%s','%s','%s','%i')", accountname,accountid,status,charname,targetarr,descriptiontype,descriptiontext,event_nid), errbuf)) { - std::cerr << "Error in logevents" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + + std::string query = StringFormat("INSERT INTO eventlog (accountname, accountid, status, " + "charname, target, descriptiontype, description, event_nid) " + "VALUES('%s', %i, %i, '%s', '%s', '%s', '%s', '%i')", + accountname, accountid, status, charname, targetarr, + descriptiontype, descriptiontext, event_nid); + safe_delete_array(descriptiontext); + safe_delete_array(targetarr); + auto results = QueryDatabase(query); + if (!results.Success()) { + std::cerr << "Error in logevents" << query << "' " << results.ErrorMessage() << std::endl; return false; } - safe_delete_array(query); - safe_delete_array(descriptiontext); - safe_delete_array(targetarr); + return true; } From ce507d891a9d056e3f87356c3278bd8014e05095 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 17:39:25 -0700 Subject: [PATCH 007/127] UpdateBug converted to QueryDatabase --- zone/zonedb.cpp | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 2b15560b1..aa444e9db 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -286,10 +286,7 @@ bool ZoneDatabase::logevents(const char* accountname,uint32 accountid,uint8 stat } -void ZoneDatabase::UpdateBug(BugStruct* bug){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - +void ZoneDatabase::UpdateBug(BugStruct* bug) { uint32 len = strlen(bug->bug); char* bugtext = nullptr; @@ -319,16 +316,18 @@ void ZoneDatabase::UpdateBug(BugStruct* bug){ } //x and y are intentionally swapped because eq is inversexy coords - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO bugs (zone, name, ui, x, y, z, type, flag, target, bug, date) " - "values('%s', '%s', '%s', '%.2f', '%.2f', '%.2f', '%s', %d, '%s', '%s', CURDATE())", zone->GetShortName(), bug->name, - uitext==nullptr?"":uitext, bug->y, bug->x, bug->z, bug->chartype, bug->type, targettext==nullptr?"Unknown Target":targettext, - bugtext==nullptr?"":bugtext), errbuf)) { - std::cerr << "Error in UpdateBug" << query << "' " << errbuf << std::endl; - } - safe_delete_array(query); - safe_delete_array(bugtext); + std::string query = StringFormat("INSERT INTO bugs (zone, name, ui, x, y, z, type, flag, target, bug, date) " + "VALUES('%s', '%s', '%s', '%.2f', '%.2f', '%.2f', '%s', %d, '%s', '%s', CURDATE())", + zone->GetShortName(), bug->name, uitext == nullptr ? "": uitext, + bug->x, bug->y, bug->z, bug->chartype, bug->type, targettext == nullptr? "Unknown Target": targettext, + bugtext==nullptr?"":bugtext); + safe_delete_array(bugtext); safe_delete_array(uitext); safe_delete_array(targettext); + auto results = QueryDatabase(query); + if (!results.Success()) + std::cerr << "Error in UpdateBug '" << query << "' " << results.ErrorMessage() << std::endl; + } void ZoneDatabase::UpdateBug(PetitionBug_Struct* bug){ From 09332f6c2678ad796fb647da23c6ce116fe01e84 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 17:42:13 -0700 Subject: [PATCH 008/127] UpdateBug converted to QueryDatabase --- zone/zonedb.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index aa444e9db..ec5f8b251 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -331,17 +331,20 @@ void ZoneDatabase::UpdateBug(BugStruct* bug) { } void ZoneDatabase::UpdateBug(PetitionBug_Struct* bug){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; + uint32 len = strlen(bug->text); char* bugtext = new char[2*len+1]; memset(bugtext, 0, 2*len+1); DoEscapeString(bugtext, bug->text, len); - if (!RunQuery(query, MakeAnyLenString(&query, "Insert into bugs (type,name,bugtext,flag) values('%s','%s','%s',%i)","Petition",bug->name,bugtext,25), errbuf)) { - std::cerr << "Error in UpdateBug" << query << "' " << errbuf << std::endl; - } - safe_delete_array(query); - safe_delete_array(bugtext); + + std::string query = StringFormat("INSERT INTO bugs (type, name, bugtext, flag) " + "VALUES('%s', '%s', '%s', %i)", + "Petition", bug->name, bugtext, 25); + safe_delete_array(bugtext); + auto results = QueryDatabase(query); + if (!results.Success()) + std::cerr << "Error in UpdateBug '" << query << "' " << results.ErrorMessage() << std::endl; + } From 046da9efae78fb6de2c4e05012c43ad0a9cb532b Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 17:46:12 -0700 Subject: [PATCH 009/127] SetSpecialAttkFlag converted to QueryDatabase --- zone/zonedb.cpp | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index ec5f8b251..8ac38b712 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -383,21 +383,13 @@ bool ZoneDatabase::GetAccountInfoForLogin_result(MYSQL_RES* result, int16* admin bool ZoneDatabase::SetSpecialAttkFlag(uint8 id, const char* flag) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE npc_types SET npcspecialattks='%s' WHERE id=%i;",flag,id), errbuf, 0, &affected_rows)) { - safe_delete_array(query); + std::string query = StringFormat("UPDATE npc_types SET npcspecialattks='%s' WHERE id = %i;", flag, id); + auto results = QueryDatabase(query); + if (!results.Success()) return false; - } - safe_delete_array(query); - if (affected_rows == 0) { - return false; - } - - return true; + return results.RowsAffected() != 0; } bool ZoneDatabase::DoorIsOpen(uint8 door_id,const char* zone_name) From e60658c684f8c3af3f126f1ddaeba13addfa28e2 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 17:51:52 -0700 Subject: [PATCH 010/127] GetEventLogs converted to QueryDatabase --- zone/zonedb.cpp | 64 +++++++++++++++++++++---------------------------- 1 file changed, 27 insertions(+), 37 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 8ac38b712..892cafcc6 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -411,12 +411,6 @@ void ZoneDatabase::SetDoorPlace(uint8 value,uint8 door_id,const char* zone_name) void ZoneDatabase::GetEventLogs(const char* name,char* target,uint32 account_id,uint8 eventid,char* detail,char* timestamp, CharacterEventLog_Struct* cel) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - query = new char[256]; - uint32 count = 0; char modifications[200]; if(strlen(name) != 0) sprintf(modifications,"charname=\'%s\'",name); @@ -424,46 +418,42 @@ void ZoneDatabase::GetEventLogs(const char* name,char* target,uint32 account_id, sprintf(modifications,"accountid=%i",account_id); if(strlen(target) != 0) - sprintf(modifications,"%s AND target like \'%%%s%%\'",modifications,target); + sprintf(modifications,"%s AND target LIKE \'%%%s%%\'",modifications,target); if(strlen(detail) != 0) - sprintf(modifications,"%s AND description like \'%%%s%%\'",modifications,detail); + sprintf(modifications,"%s AND description LIKE \'%%%s%%\'",modifications,detail); if(strlen(timestamp) != 0) - sprintf(modifications,"%s AND time like \'%%%s%%\'",modifications,timestamp); + sprintf(modifications,"%s AND time LIKE \'%%%s%%\'",modifications,timestamp); if(eventid == 0) eventid =1; sprintf(modifications,"%s AND event_nid=%i",modifications,eventid); - MakeAnyLenString(&query, "SELECT id,accountname,accountid,status,charname,target,time,descriptiontype,description FROM eventlog where %s",modifications); - if (RunQuery(query, strlen(query), errbuf, &result)) - { - safe_delete_array(query); - while((row = mysql_fetch_row(result))) - { - if(count > 255) - break; - cel->eld[count].id = atoi(row[0]); - strn0cpy(cel->eld[count].accountname,row[1],64); - cel->eld[count].account_id = atoi(row[2]); - cel->eld[count].status = atoi(row[3]); - strn0cpy(cel->eld[count].charactername,row[4],64); - strn0cpy(cel->eld[count].targetname,row[5],64); - sprintf(cel->eld[count].timestamp,"%s",row[6]); - strn0cpy(cel->eld[count].descriptiontype,row[7],64); - strn0cpy(cel->eld[count].details,row[8],128); - cel->eventid = eventid; - count++; - cel->count = count; - } - mysql_free_result(result); - } - else - { - // TODO: Invalid item length in database - safe_delete_array(query); - } + std::string query = StringFormat("SELECT id, accountname, accountid, status, charname, target, " + "time, descriptiontype, description FROM eventlog WHERE %s", modifications); + auto results = QueryDatabase(query); + if (!results.Success()) + return; + + int index = 0; + for (auto row = results.begin(); row != results.end(); ++row, ++index) { + if(index == 255) + break; + + cel->eld[index].id = atoi(row[0]); + strn0cpy(cel->eld[index].accountname,row[1],64); + cel->eld[index].account_id = atoi(row[2]); + cel->eld[index].status = atoi(row[3]); + strn0cpy(cel->eld[index].charactername,row[4],64); + strn0cpy(cel->eld[index].targetname,row[5],64); + sprintf(cel->eld[index].timestamp,"%s",row[6]); + strn0cpy(cel->eld[index].descriptiontype,row[7],64); + strn0cpy(cel->eld[index].details,row[8],128); + cel->eventid = eventid; + cel->count = index + 1; + } + } // Load child objects for a world container (i.e., forge, bag dropped to ground, etc) From 3777e8d1ce9922d53b9e93e017583ab392e78442 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 17:57:44 -0700 Subject: [PATCH 011/127] LoadWorldContainer converted to QueryDatabase --- zone/zonedb.cpp | 67 ++++++++++++++++++++----------------------------- 1 file changed, 27 insertions(+), 40 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 892cafcc6..e428c0fb9 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -464,49 +464,36 @@ void ZoneDatabase::LoadWorldContainer(uint32 parentid, ItemInst* container) return; } - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - //const Item_Struct* item = nullptr; - //ItemInst* inst = nullptr; + std::string query = StringFormat("SELECT bagidx, itemid, charges, augslot1, augslot2, augslot3, augslot4, augslot5 " + "FROM object_contents WHERE parentid = %i", parentid); + auto results = QueryDatabase(query); + if (!results.Success()) { + LogFile->write(EQEMuLog::Error, "Error in DB::LoadWorldContainer: %s", results.ErrorMessage().c_str()); + return; + } - uint32 len_query = MakeAnyLenString(&query, "select " - "bagidx,itemid,charges,augslot1,augslot2,augslot3,augslot4,augslot5 from object_contents where parentid=%i", parentid); + for (auto row = results.begin(); row != results.end(); ++row) { + uint8 index = (uint8)atoi(row[0]); + uint32 item_id = (uint32)atoi(row[1]); + int8 charges = (int8)atoi(row[2]); + uint32 aug[EmuConstants::ITEM_COMMON_SIZE]; + aug[0] = (uint32)atoi(row[3]); + aug[1] = (uint32)atoi(row[4]); + aug[2] = (uint32)atoi(row[5]); + aug[3] = (uint32)atoi(row[6]); + aug[4] = (uint32)atoi(row[7]); - if (RunQuery(query, len_query, errbuf, &result)) { - while ((row = mysql_fetch_row(result))) { - uint8 index = (uint8)atoi(row[0]); - uint32 item_id = (uint32)atoi(row[1]); - int8 charges = (int8)atoi(row[2]); - uint32 aug[EmuConstants::ITEM_COMMON_SIZE]; - aug[0] = (uint32)atoi(row[3]); - aug[1] = (uint32)atoi(row[4]); - aug[2] = (uint32)atoi(row[5]); - aug[3] = (uint32)atoi(row[6]); - aug[4] = (uint32)atoi(row[7]); + ItemInst* inst = database.CreateItem(item_id, charges); + if (inst && inst->GetItem()->ItemClass == ItemClassCommon) { + for(int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) + if (aug[i]) + inst->PutAugment(&database, i, aug[i]); + // Put item inside world container + container->PutItem(index, *inst); + safe_delete(inst); + } + } - ItemInst* inst = database.CreateItem(item_id, charges); - if (inst) { - if (inst->GetItem()->ItemClass == ItemClassCommon) { - for(int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) { - if (aug[i]) { - inst->PutAugment(&database, i, aug[i]); - } - } - } - // Put item inside world container - container->PutItem(index, *inst); - safe_delete(inst); - } - } - mysql_free_result(result); - } - else { - LogFile->write(EQEMuLog::Error, "Error in DB::LoadWorldContainer: %s", errbuf); - } - - safe_delete_array(query); } // Save child objects for a world container (i.e., forge, bag dropped to ground, etc) From c666d9c553146d2706979b5a8e1770659020033b Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 18:03:02 -0700 Subject: [PATCH 012/127] SaveWorldContainer converted to QueryDatabase --- zone/zonedb.cpp | 51 +++++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index e428c0fb9..ac2bb1705 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -499,42 +499,43 @@ void ZoneDatabase::LoadWorldContainer(uint32 parentid, ItemInst* container) // Save child objects for a world container (i.e., forge, bag dropped to ground, etc) void ZoneDatabase::SaveWorldContainer(uint32 zone_id, uint32 parent_id, const ItemInst* container) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - // Since state is not saved for each world container action, we'll just delete // all and save from scratch .. we may come back later to optimize - //DeleteWorldContainer(parent_id); - - if (!container) { + if (!container) return; - } + //Delete all items from container DeleteWorldContainer(parent_id,zone_id); + // Save all 10 items, if they exist for (uint8 index = SUB_BEGIN; index < EmuConstants::ITEM_CONTAINER_SIZE; index++) { + ItemInst* inst = container->GetItem(index); - if (inst) { - uint32 item_id = inst->GetItem()->ID; - uint32 augslot[EmuConstants::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM }; - if (inst->IsType(ItemClassCommon)) { - for(int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) { - ItemInst *auginst=inst->GetAugment(i); - augslot[i]=(auginst && auginst->GetItem()) ? auginst->GetItem()->ID : 0; - } - } - uint32 len_query = MakeAnyLenString(&query, + if (!inst) + continue; - "replace into object_contents (zoneid,parentid,bagidx,itemid,charges,augslot1,augslot2,augslot3,augslot4,augslot5,droptime) values (%i,%i,%i,%i,%i,%i,%i,%i,%i,%i,now())", - zone_id, parent_id, index, item_id, inst->GetCharges(),augslot[0],augslot[1],augslot[2],augslot[3],augslot[4]); + uint32 item_id = inst->GetItem()->ID; + uint32 augslot[EmuConstants::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM }; - if (!RunQuery(query, len_query, errbuf)) { - LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::SaveWorldContainer: %s", errbuf); - } - safe_delete_array(query); - } + if (inst->IsType(ItemClassCommon)) { + for(int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) { + ItemInst *auginst=inst->GetAugment(i); + augslot[i]=(auginst && auginst->GetItem()) ? auginst->GetItem()->ID : 0; + } + } + + std::string query = StringFormat("REPLACE INTO object_contents " + "(zoneid, parentid, bagidx, itemid, charges, " + "augslot1, augslot2, augslot3, augslot4, augslot5, droptime) " + "VALUES (%i, %i, %i, %i, %i, %i, %i, %i, %i, %i, now())", + zone_id, parent_id, index, item_id, inst->GetCharges(), + augslot[0], augslot[1], augslot[2], augslot[3], augslot[4]); + auto results = QueryDatabase(query); + if (!results.Success()) + LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::SaveWorldContainer: %s", results.ErrorMessage().c_str()); + + } - } } // Remove all child objects inside a world container (i.e., forge, bag dropped to ground, etc) From 09713311f6172872c37c79d8610c2d42789069e9 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 18:06:03 -0700 Subject: [PATCH 013/127] DeleteWorldContainer converted to QueryDatabase --- zone/zonedb.cpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index ac2bb1705..0c62c273b 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -539,18 +539,13 @@ void ZoneDatabase::SaveWorldContainer(uint32 zone_id, uint32 parent_id, const It } // Remove all child objects inside a world container (i.e., forge, bag dropped to ground, etc) -void ZoneDatabase::DeleteWorldContainer(uint32 parent_id,uint32 zone_id) +void ZoneDatabase::DeleteWorldContainer(uint32 parent_id, uint32 zone_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; + std::string query = StringFormat("DELETE FROM object_contents WHERE parentid = %i AND zoneid = %i", parent_id, zone_id); + auto results = QueryDatabase(query); + if (!results.Success()) + LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::DeleteWorldContainer: %s", results.ErrorMessage().c_str()); - uint32 len_query = MakeAnyLenString(&query, - "delete from object_contents where parentid=%i and zoneid=%i", parent_id,zone_id); - if (!RunQuery(query, len_query, errbuf)) { - LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::DeleteWorldContainer: %s", errbuf); - } - - safe_delete_array(query); } Trader_Struct* ZoneDatabase::LoadTraderItem(uint32 char_id){ From e9c6e96452a513df29542c98cf05c287bd7660d6 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 18:16:05 -0700 Subject: [PATCH 014/127] LoadTraderItem converted to QueryDatabase --- zone/zonedb.cpp | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 0c62c273b..47d03e851 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -549,30 +549,27 @@ void ZoneDatabase::DeleteWorldContainer(uint32 parent_id, uint32 zone_id) } Trader_Struct* ZoneDatabase::LoadTraderItem(uint32 char_id){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + Trader_Struct* loadti = new Trader_Struct; memset(loadti,0,sizeof(Trader_Struct)); - if (RunQuery(query,MakeAnyLenString(&query, "select * from trader where char_id=%i order by slot_id limit 80",char_id),errbuf,&result)){ - safe_delete_array(query); - loadti->Code = BazaarTrader_ShowItems; - while ((row = mysql_fetch_row(result))) { - if(atoi(row[5])>=80 || atoi(row[4])<0) - _log(TRADING__CLIENT, "Bad Slot number when trying to load trader information!\n"); - else{ - loadti->Items[atoi(row[5])] = atoi(row[1]); - loadti->ItemCost[atoi(row[5])] = atoi(row[4]); - } - } - mysql_free_result(result); + + std::string query = StringFormat("SELECT * FROM trader WHERE char_id = %i ORDER BY slot_id LIMIT 80", char_id); + auto results = QueryDatabase(query); + if (!results.Success()) { + _log(TRADING__CLIENT, "Failed to load trader information!\n"); + return loadti; } - else{ - safe_delete_array(query); - _log(TRADING__CLIENT, "Failed to load trader information!\n"); - } - return loadti; + + loadti->Code = BazaarTrader_ShowItems; + for (auto row = results.begin(); row != results.end(); ++row) { + if(atoi(row[5])>=80 || atoi(row[4])<0) { + _log(TRADING__CLIENT, "Bad Slot number when trying to load trader information!\n"); + continue; + } + + loadti->Items[atoi(row[5])] = atoi(row[1]); + loadti->ItemCost[atoi(row[5])] = atoi(row[4]); + } } TraderCharges_Struct* ZoneDatabase::LoadTraderItemWithCharges(uint32 char_id){ From 0f47b73a64f2b0e9f160ae34e6c62560ab12ea8c Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 18:21:50 -0700 Subject: [PATCH 015/127] LoadTraderItemWithCharges converted to QueryDatabase --- zone/zonedb.cpp | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 47d03e851..3a34c40ae 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -573,30 +573,29 @@ Trader_Struct* ZoneDatabase::LoadTraderItem(uint32 char_id){ } TraderCharges_Struct* ZoneDatabase::LoadTraderItemWithCharges(uint32 char_id){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + TraderCharges_Struct* loadti = new TraderCharges_Struct; memset(loadti,0,sizeof(TraderCharges_Struct)); - if (RunQuery(query,MakeAnyLenString(&query, "select * from trader where char_id=%i order by slot_id limit 80",char_id),errbuf,&result)){ - safe_delete_array(query); - while ((row = mysql_fetch_row(result))) { - if(atoi(row[5])>=80 || atoi(row[5])<0) - _log(TRADING__CLIENT, "Bad Slot number when trying to load trader information!\n"); - else{ - loadti->ItemID[atoi(row[5])] = atoi(row[1]); - loadti->SerialNumber[atoi(row[5])] = atoi(row[2]); - loadti->Charges[atoi(row[5])] = atoi(row[3]); - loadti->ItemCost[atoi(row[5])] = atoi(row[4]); - } - } - mysql_free_result(result); - } - else{ - safe_delete_array(query); - _log(TRADING__CLIENT, "Failed to load trader information!\n"); - } + + std::string query = StringFormat("SELECT * FROM trader WHERE char_id=%i ORDER BY slot_id LIMIT 80", char_id); + auto results = QueryDatabase(query); + if (!results.Success()) { + _log(TRADING__CLIENT, "Failed to load trader information!\n"); + return loadti; + } + + for (auto row = results.begin(); row != results.end(); ++row) { + if(atoi(row[5])>=80 || atoi(row[5])<0) { + _log(TRADING__CLIENT, "Bad Slot number when trying to load trader information!\n"); + continue; + } + + loadti->ItemID[atoi(row[5])] = atoi(row[1]); + loadti->SerialNumber[atoi(row[5])] = atoi(row[2]); + loadti->Charges[atoi(row[5])] = atoi(row[3]); + loadti->ItemCost[atoi(row[5])] = atoi(row[4]); + } + return loadti; } From bc884f5daf7680b201b690fea7a9be399c95e769 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 18:35:54 -0700 Subject: [PATCH 016/127] LoadSingleTraderItem converted to QueryDatabase --- zone/zonedb.cpp | 72 ++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 3a34c40ae..5b014d188 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -601,52 +601,50 @@ TraderCharges_Struct* ZoneDatabase::LoadTraderItemWithCharges(uint32 char_id){ ItemInst* ZoneDatabase::LoadSingleTraderItem(uint32 CharID, int SerialNumber) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + std::string query = StringFormat("SELECT * FROM trader WHERE char_id = %i AND serialnumber = %i " + "ORDER BY slot_id LIMIT 80", CharID, SerialNumber); + auto results = QueryDatabase(query); + if (!results.Success()) + return nullptr; - if (RunQuery(query,MakeAnyLenString(&query, "select * from trader where char_id=%i and serialnumber=%i order by slot_id limit 80", - CharID, SerialNumber),errbuf,&result)){ - safe_delete_array(query); + if (results.RowCount() == 0) { + _log(TRADING__CLIENT, "Bad result from query\n"); fflush(stdout); + return nullptr; + } - if (mysql_num_rows(result) != 1) { - _log(TRADING__CLIENT, "Bad result from query\n"); fflush(stdout); - return nullptr; - } - row = mysql_fetch_row(result); - int ItemID = atoi(row[1]); - int Charges = atoi(row[3]); - int Cost = atoi(row[4]); + auto row = results.begin(); - const Item_Struct *item=database.GetItem(ItemID); + int ItemID = atoi(row[1]); + int Charges = atoi(row[3]); + int Cost = atoi(row[4]); - if(!item) { - _log(TRADING__CLIENT, "Unable to create item\n"); fflush(stdout); - return nullptr; - } + const Item_Struct *item = database.GetItem(ItemID); - if (item && (item->NoDrop!=0)) { - ItemInst* inst = database.CreateItem(item); - if(!inst) { - _log(TRADING__CLIENT, "Unable to create item instance\n"); fflush(stdout); - return nullptr; - } - - inst->SetCharges(Charges); - inst->SetSerialNumber(SerialNumber); - inst->SetMerchantSlot(SerialNumber); - inst->SetPrice(Cost); - if(inst->IsStackable()) - inst->SetMerchantCount(Charges); - - return inst; - } + if(!item) { + _log(TRADING__CLIENT, "Unable to create item\n"); + fflush(stdout); + return nullptr; } - return nullptr; + if (item->NoDrop == 0) + return nullptr; + ItemInst* inst = database.CreateItem(item); + if(!inst) { + _log(TRADING__CLIENT, "Unable to create item instance\n"); + fflush(stdout); + return nullptr; + } + inst->SetCharges(Charges); + inst->SetSerialNumber(SerialNumber); + inst->SetMerchantSlot(SerialNumber); + inst->SetPrice(Cost); + + if(inst->IsStackable()) + inst->SetMerchantCount(Charges); + + return inst; } void ZoneDatabase::SaveTraderItem(uint32 CharID, uint32 ItemID, uint32 SerialNumber, int32 Charges, uint32 ItemCost, uint8 Slot){ From efd97bad1476aa4485e08b6472a84b66d057cb22 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 18:38:57 -0700 Subject: [PATCH 017/127] SaveTraderItem converted to QueryDatabase --- zone/zonedb.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 5b014d188..1bd17ee35 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -649,13 +649,12 @@ ItemInst* ZoneDatabase::LoadSingleTraderItem(uint32 CharID, int SerialNumber) { void ZoneDatabase::SaveTraderItem(uint32 CharID, uint32 ItemID, uint32 SerialNumber, int32 Charges, uint32 ItemCost, uint8 Slot){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - if (!(RunQuery(query,MakeAnyLenString(&query, "replace INTO trader VALUES(%i,%i,%i,%i,%i,%i)", - CharID, ItemID, SerialNumber, Charges, ItemCost, Slot),errbuf))) - _log(TRADING__CLIENT, "Failed to save trader item: %i for char_id: %i, the error was: %s\n", ItemID, CharID, errbuf); + std::string query = StringFormat("REPLACE INTO trader VALUES(%i, %i, %i, %i, %i, %i)", + CharID, ItemID, SerialNumber, Charges, ItemCost, Slot); + auto results = QueryDatabase(query); + if (!results.Success()) + _log(TRADING__CLIENT, "Failed to save trader item: %i for char_id: %i, the error was: %s\n", ItemID, CharID, results.ErrorMessage().c_str()); - safe_delete_array(query); } void ZoneDatabase::UpdateTraderItemCharges(int CharID, uint32 SerialNumber, int32 Charges) { From d44d7c6bbde1b64e7e6d6ae4fa22eaf6970124d7 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 18:42:25 -0700 Subject: [PATCH 018/127] UpdateTraderItemCharges converted to QueryDatabase --- zone/zonedb.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 1bd17ee35..3e8eb5b1f 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -660,14 +660,13 @@ void ZoneDatabase::SaveTraderItem(uint32 CharID, uint32 ItemID, uint32 SerialNum void ZoneDatabase::UpdateTraderItemCharges(int CharID, uint32 SerialNumber, int32 Charges) { _log(TRADING__CLIENT, "ZoneDatabase::UpdateTraderItemCharges(%i, %i, %i)", CharID, SerialNumber, Charges); - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - if (!(RunQuery(query,MakeAnyLenString(&query, "update trader set charges=%i where char_id=%i and serialnumber=%i", - Charges, CharID, SerialNumber),errbuf))) - _log(TRADING__CLIENT, "Failed to update charges for trader item: %i for char_id: %i, the error was: %s\n", - SerialNumber, CharID, errbuf); - safe_delete_array(query); + std::string query = StringFormat("UPDATE trader SET charges = %i WHERE char_id = %i AND serialnumber = %i", + Charges, CharID, SerialNumber); + auto results = QueryDatabase(query); + if (!results.Success()) + _log(TRADING__CLIENT, "Failed to update charges for trader item: %i for char_id: %i, the error was: %s\n", + SerialNumber, CharID, results.ErrorMessage().c_str()); } From 62ad60b4ad76ab20a5d830c4827cb0f331e62a48 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 18:50:10 -0700 Subject: [PATCH 019/127] UpdateTraderItemPrice converted to QueryDatabase --- zone/zonedb.cpp | 46 +++++++++++++++++++--------------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 3e8eb5b1f..dbed63f9c 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -679,42 +679,34 @@ void ZoneDatabase::UpdateTraderItemPrice(int CharID, uint32 ItemID, uint32 Charg if(!item) return; - char errbuf[MYSQL_ERRMSG_SIZE]; - - char* Query = 0; - if(NewPrice == 0) { _log(TRADING__CLIENT, "Removing Trader items from the DB for CharID %i, ItemID %i", CharID, ItemID); - if (!(RunQuery(Query,MakeAnyLenString(&Query, "delete from trader where char_id=%i and item_id=%i", - CharID, ItemID),errbuf))) - - _log(TRADING__CLIENT, "Failed to remove trader item(s): %i for char_id: %i, the error was: %s\n", - ItemID, CharID, errbuf); - - safe_delete_array(Query); + std::string query = StringFormat("DELETE FROM trader WHERE char_id = %i AND item_id = %i",CharID, ItemID); + auto results = QueryDatabase(query); + if (!results.Success()) + _log(TRADING__CLIENT, "Failed to remove trader item(s): %i for char_id: %i, the error was: %s\n", ItemID, CharID, results.ErrorMessage().c_str()); return; } - else { - if(!item->Stackable) { - if (!(RunQuery(Query,MakeAnyLenString(&Query, "update trader set item_cost=%i where char_id=%i and item_id=%i" - " and charges=%i", NewPrice, CharID, ItemID, Charges),errbuf))) - _log(TRADING__CLIENT, "Failed to update price for trader item: %i for char_id: %i, the error was: %s\n", - ItemID, CharID, errbuf); - } - else { - if (!(RunQuery(Query,MakeAnyLenString(&Query, "update trader set item_cost=%i where char_id=%i and item_id=%i", - NewPrice, CharID, ItemID),errbuf))) + if(!item->Stackable) { + std::string query = StringFormat("UPDATE trader SET item_cost = %i " + "WHERE char_id = %i AND item_id = %i AND charges=%i", + NewPrice, CharID, ItemID, Charges); + auto results = QueryDatabase(query); + if (!results.Success()) + _log(TRADING__CLIENT, "Failed to update price for trader item: %i for char_id: %i, the error was: %s\n", ItemID, CharID, results.ErrorMessage().c_str()); - _log(TRADING__CLIENT, "Failed to update price for trader item: %i for char_id: %i, the error was: %s\n", - ItemID, CharID, errbuf); - } - - safe_delete_array(Query); - } + return; + } + std::string query = StringFormat("UPDATE trader SET item_cost = %i " + "WHERE char_id = %i AND item_id = %i", + NewPrice, CharID, ItemID); + auto results = QueryDatabase(query); + if (!results.Success()) + _log(TRADING__CLIENT, "Failed to update price for trader item: %i for char_id: %i, the error was: %s\n", ItemID, CharID, results.ErrorMessage().c_str()); } void ZoneDatabase::DeleteTraderItem(uint32 char_id){ From c160d6d929cd181d16c593c2aa02276dbdfc1934 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 18:53:05 -0700 Subject: [PATCH 020/127] DeleteTraderItem converted to QueryDatabase --- zone/zonedb.cpp | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index dbed63f9c..187af5e09 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -710,17 +710,21 @@ void ZoneDatabase::UpdateTraderItemPrice(int CharID, uint32 ItemID, uint32 Charg } void ZoneDatabase::DeleteTraderItem(uint32 char_id){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - if(char_id==0){ - if (!(RunQuery(query,MakeAnyLenString(&query, "delete from trader"),errbuf))) - _log(TRADING__CLIENT, "Failed to delete all trader items data, the error was: %s\n",errbuf); + + if(char_id==0) { + const std::string query = "DELETE FROM trader"; + auto results = QueryDatabase(query); + if (!results.Success()) + _log(TRADING__CLIENT, "Failed to delete all trader items data, the error was: %s\n", results.ErrorMessage().c_str()); + + return; } - else{ - if (!(RunQuery(query,MakeAnyLenString(&query, "delete from trader where char_id=%i",char_id),errbuf))) - _log(TRADING__CLIENT, "Failed to delete trader item data for char_id: %i, the error was: %s\n",char_id,errbuf); - } - safe_delete_array(query); + + std::string query = StringFormat("DELETE FROM trader WHERE char_id = %i", char_id); + auto results = QueryDatabase(query); + if (!results.Success()) + _log(TRADING__CLIENT, "Failed to delete trader item data for char_id: %i, the error was: %s\n", char_id, results.ErrorMessage().c_str()); + } void ZoneDatabase::DeleteTraderItem(uint32 CharID,uint16 SlotID){ char errbuf[MYSQL_ERRMSG_SIZE]; From d234016224f83f8705ae5468aa52a2b1544485fd Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 18:55:42 -0700 Subject: [PATCH 021/127] DeleteTraderItem converted to QueryDatabase --- zone/zonedb.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 187af5e09..5521a7255 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -726,12 +726,12 @@ void ZoneDatabase::DeleteTraderItem(uint32 char_id){ _log(TRADING__CLIENT, "Failed to delete trader item data for char_id: %i, the error was: %s\n", char_id, results.ErrorMessage().c_str()); } -void ZoneDatabase::DeleteTraderItem(uint32 CharID,uint16 SlotID){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - if (!(RunQuery(query,MakeAnyLenString(&query, "delete from trader where char_id=%i and slot_id=%i",CharID, SlotID),errbuf))) - _log(TRADING__CLIENT, "Failed to delete trader item data for char_id: %i, the error was: %s\n",CharID, errbuf); - safe_delete_array(query); +void ZoneDatabase::DeleteTraderItem(uint32 CharID,uint16 SlotID) { + + std::string query = StringFormat("DELETE FROM trader WHERE char_id = %i And slot_id = %i", CharID, SlotID); + auto results = QueryDatabase(query); + if (!results.Success()) + _log(TRADING__CLIENT, "Failed to delete trader item data for char_id: %i, the error was: %s\n",CharID, results.ErrorMessage().c_str()); } void ZoneDatabase::DeleteBuyLines(uint32 CharID){ From e19a59b2691317440af29cb3954e72726005c329 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 18:59:17 -0700 Subject: [PATCH 022/127] DeleteBuyLines converted to QueryDatabase --- zone/zonedb.cpp | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 5521a7255..c1240810f 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -734,19 +734,22 @@ void ZoneDatabase::DeleteTraderItem(uint32 CharID,uint16 SlotID) { _log(TRADING__CLIENT, "Failed to delete trader item data for char_id: %i, the error was: %s\n",CharID, results.ErrorMessage().c_str()); } -void ZoneDatabase::DeleteBuyLines(uint32 CharID){ +void ZoneDatabase::DeleteBuyLines(uint32 CharID) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - if(CharID==0){ - if (!(RunQuery(query,MakeAnyLenString(&query, "delete from buyer"),errbuf))) - _log(TRADING__CLIENT, "Failed to delete all buyer items data, the error was: %s\n",errbuf); + if(CharID==0) { + const std::string query = "DELETE FROM buyer"; + auto results = QueryDatabase(query); + if (!results.Success()) + _log(TRADING__CLIENT, "Failed to delete all buyer items data, the error was: %s\n",results.ErrorMessage().c_str()); + + return; } - else{ - if (!(RunQuery(query,MakeAnyLenString(&query, "delete from buyer where charid=%i",CharID),errbuf))) - _log(TRADING__CLIENT, "Failed to delete buyer item data for charid: %i, the error was: %s\n",CharID,errbuf); - } - safe_delete_array(query); + + std::string query = StringFormat("DELETE FROM buyer WHERE charid = %i", CharID); + auto results = QueryDatabase(query); + if (!results.Success()) + _log(TRADING__CLIENT, "Failed to delete buyer item data for charid: %i, the error was: %s\n",CharID,results.ErrorMessage().c_str()); + } void ZoneDatabase::AddBuyLine(uint32 CharID, uint32 BuySlot, uint32 ItemID, const char* ItemName, uint32 Quantity, uint32 Price) { From 9ed69999a5e5af2d8bd7d89a7fcc345803846446 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 19:02:28 -0700 Subject: [PATCH 023/127] AddBuyLine converted to QueryDatabase --- zone/zonedb.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index c1240810f..30b3db079 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -754,13 +754,12 @@ void ZoneDatabase::DeleteBuyLines(uint32 CharID) { void ZoneDatabase::AddBuyLine(uint32 CharID, uint32 BuySlot, uint32 ItemID, const char* ItemName, uint32 Quantity, uint32 Price) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - if (!(RunQuery(query,MakeAnyLenString(&query, "replace INTO buyer VALUES(%i,%i, %i,\"%s\",%i,%i)", - CharID, BuySlot, ItemID, ItemName, Quantity, Price),errbuf))) - _log(TRADING__CLIENT, "Failed to save buline item: %i for char_id: %i, the error was: %s\n", ItemID, CharID, errbuf); + std::string query = StringFormat("REPLACE INTO buyer VALUES(%i, %i, %i, \"%s\", %i, %i)", + CharID, BuySlot, ItemID, ItemName, Quantity, Price); + auto results = QueryDatabase(query); + if (!results.Success()) + _log(TRADING__CLIENT, "Failed to save buline item: %i for char_id: %i, the error was: %s\n", ItemID, CharID, results.ErrorMessage().c_str()); - safe_delete_array(query); } void ZoneDatabase::RemoveBuyLine(uint32 CharID, uint32 BuySlot) { From a7efa9d4e43cc97d04bfdd21bb263e6caf59cbcc Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 19:20:32 -0700 Subject: [PATCH 024/127] RemoveBuyLine converted to QueryDatabase --- zone/zonedb.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 30b3db079..726ad4b16 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -764,13 +764,11 @@ void ZoneDatabase::AddBuyLine(uint32 CharID, uint32 BuySlot, uint32 ItemID, cons void ZoneDatabase::RemoveBuyLine(uint32 CharID, uint32 BuySlot) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; + std::string query = StringFormat("DELETE FROM buyer WHERE charid = %i AND buyslot = %i", CharID, BuySlot); + auto results = QueryDatabase(query); + if (!results.Success()) + _log(TRADING__CLIENT, "Failed to delete buyslot %i for charid: %i, the error was: %s\n", BuySlot, CharID, results.ErrorMessage().c_str()); - if (!(RunQuery(query,MakeAnyLenString(&query, "delete from buyer where charid=%i and buyslot=%i", CharID, BuySlot), errbuf))) - _log(TRADING__CLIENT, "Failed to delete buyslot %i for charid: %i, the error was: %s\n", BuySlot, CharID, errbuf); - - safe_delete_array(query); } void ZoneDatabase::UpdateBuyLine(uint32 CharID, uint32 BuySlot, uint32 Quantity) { From 41769a3fa8a4598591e0bc3dc00cfc82f3529eac Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 19:28:53 -0700 Subject: [PATCH 025/127] UpdateBuyLine converted to QueryDatabase --- zone/zonedb.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 726ad4b16..cf60969ea 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -778,14 +778,10 @@ void ZoneDatabase::UpdateBuyLine(uint32 CharID, uint32 BuySlot, uint32 Quantity) return; } - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - - if (!(RunQuery(query,MakeAnyLenString(&query, "update buyer set quantity=%i where charid=%i and buyslot=%i", - Quantity, CharID, BuySlot), errbuf))) - _log(TRADING__CLIENT, "Failed to update quantity in buyslot %i for charid: %i, the error was: %s\n", BuySlot, CharID, errbuf); - - safe_delete_array(query); + std::string query = StringFormat("UPDATE buyer SET quantity = %i WHERE charid = %i AND buyslot = %i", Quantity, CharID, BuySlot); + auto results = QueryDatabase(query); + if (!results.Success()) + _log(TRADING__CLIENT, "Failed to update quantity in buyslot %i for charid: %i, the error was: %s\n", BuySlot, CharID, results.ErrorMessage().c_str()); } From 74d3192c2e8c9b8023a3fd7612c687be16be1fc5 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 19:46:23 -0700 Subject: [PATCH 026/127] NoRentExpired converted to QueryDatabase --- zone/zonedb.cpp | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index cf60969ea..f51074396 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -918,20 +918,19 @@ bool ZoneDatabase::GetCharacterInfoForLogin_result(MYSQL_RES* result, } bool ZoneDatabase::NoRentExpired(const char* name){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, "Select (UNIX_TIMESTAMP(NOW())-timelaston) from character_ where name='%s'", name), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - uint32 seconds = atoi(row[0]); - mysql_free_result(result); - return (seconds>1800); - } - } - return false; + std::string query = StringFormat("SELECT (UNIX_TIMESTAMP(NOW())-timelaston) " + "FROM character_ WHERE name = '%s'", name); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + + if (results.RowCount() != 1) + return false; + + auto row = results.begin(); + uint32 seconds = atoi(row[0]); + + return (seconds>1800); } /* Searches npctable for matching id, and returns the item if found, From 9769a96ebdbc4ced444cc4227f35dfeb1753d83d Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 20:21:39 -0700 Subject: [PATCH 027/127] GetNPCType converted to QueryDatabase --- zone/zonedb.cpp | 469 +++++++++++++++++++----------------------------- 1 file changed, 180 insertions(+), 289 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index f51074396..837878720 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -939,320 +939,211 @@ bool ZoneDatabase::NoRentExpired(const char* name){ */ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { const NPCType *npc=nullptr; - std::map::iterator itr; // If NPC is already in tree, return it. - if((itr = zone->npctable.find(id)) != zone->npctable.end()) + auto itr = zone->npctable.find(id); + if(itr != zone->npctable.end()) return itr->second; - // Otherwise, get NPCs from database. - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + // Otherwise, get NPCs from database. - // If id is 0, load all npc_types for the current zone, - // according to spawn2. - const char *basic_query = "SELECT " - "npc_types.id," - "npc_types.name," - "npc_types.level," - "npc_types.race," - "npc_types.class," - "npc_types.hp," - "npc_types.mana," - "npc_types.gender," - "npc_types.texture," - "npc_types.helmtexture," - "npc_types.size," - "npc_types.loottable_id," - "npc_types.merchant_id," - "npc_types.alt_currency_id," - "npc_types.adventure_template_id," - "npc_types.trap_template," - "npc_types.attack_speed," - "npc_types.STR," - "npc_types.STA," - "npc_types.DEX," - "npc_types.AGI," - "npc_types._INT," - "npc_types.WIS," - "npc_types.CHA," - "npc_types.MR," - "npc_types.CR," - "npc_types.DR," - "npc_types.FR," - "npc_types.PR," - "npc_types.Corrup," - "npc_types.PhR," - "npc_types.mindmg," - "npc_types.maxdmg," - "npc_types.attack_count," - "npc_types.special_abilities," - "npc_types.npc_spells_id," - "npc_types.npc_spells_effects_id," - "npc_types.d_meele_texture1," - "npc_types.d_meele_texture2," - "npc_types.ammo_idfile," - "npc_types.prim_melee_type," - "npc_types.sec_melee_type," - "npc_types.ranged_type," - "npc_types.runspeed," - "npc_types.findable," - "npc_types.trackable," - "npc_types.hp_regen_rate," - "npc_types.mana_regen_rate," - "npc_types.aggroradius," - "npc_types.assistradius," - "npc_types.bodytype," - "npc_types.npc_faction_id," - "npc_types.face," - "npc_types.luclin_hairstyle," - "npc_types.luclin_haircolor," - "npc_types.luclin_eyecolor," - "npc_types.luclin_eyecolor2," - "npc_types.luclin_beardcolor," - "npc_types.luclin_beard," - "npc_types.drakkin_heritage," - "npc_types.drakkin_tattoo," - "npc_types.drakkin_details," - "npc_types.armortint_id," - "npc_types.armortint_red," - "npc_types.armortint_green," - "npc_types.armortint_blue," - "npc_types.see_invis," - "npc_types.see_invis_undead," - "npc_types.lastname," - "npc_types.qglobal," - "npc_types.AC," - "npc_types.npc_aggro," - "npc_types.spawn_limit," - "npc_types.see_hide," - "npc_types.see_improved_hide," - "npc_types.ATK," - "npc_types.Accuracy," - "npc_types.Avoidance," - "npc_types.slow_mitigation," - "npc_types.maxlevel," - "npc_types.scalerate," - "npc_types.private_corpse," - "npc_types.unique_spawn_by_name," - "npc_types.underwater," - "npc_types.emoteid," - "npc_types.spellscale," - "npc_types.healscale," - "npc_types.no_target_hotkey," - "npc_types.raid_target"; + // If id is 0, load all npc_types for the current zone, + // according to spawn2. + std::string query = StringFormat("SELECT npc_types.id, npc_types.name, npc_types.level, npc_types.race, " + "npc_types.class, npc_types.hp, npc_types.mana, npc_types.gender, " + "npc_types.texture, npc_types.helmtexture, npc_types.size, " + "npc_types.loottable_id, npc_types.merchant_id, npc_types.alt_currency_id, " + "npc_types.adventure_template_id, npc_types.trap_template, npc_types.attack_speed, " + "npc_types.STR, npc_types.STA, npc_types.DEX, npc_types.AGI, npc_types._INT, " + "npc_types.WIS, npc_types.CHA, npc_types.MR, npc_types.CR, npc_types.DR, " + "npc_types.FR, npc_types.PR, npc_types.Corrup, npc_types.PhR," + "npc_types.mindmg, npc_types.maxdmg, npc_types.attack_count, npc_types.special_abilities," + "npc_types.npc_spells_id, npc_types.npc_spells_effects_id, npc_types.d_meele_texture1," + "npc_types.d_meele_texture2, npc_types.ammo_idfile, npc_types.prim_melee_type," + "npc_types.sec_melee_type, npc_types.ranged_type, npc_types.runspeed, npc_types.findable," + "npc_types.trackable, npc_types.hp_regen_rate, npc_types.mana_regen_rate, " + "npc_types.aggroradius, npc_types.assistradius, npc_types.bodytype, npc_types.npc_faction_id, " + "npc_types.face, npc_types.luclin_hairstyle, npc_types.luclin_haircolor, " + "npc_types.luclin_eyecolor, npc_types.luclin_eyecolor2, npc_types.luclin_beardcolor," + "npc_types.luclin_beard, npc_types.drakkin_heritage, npc_types.drakkin_tattoo, " + "npc_types.drakkin_details, npc_types.armortint_id, " + "npc_types.armortint_red, npc_types.armortint_green, npc_types.armortint_blue, " + "npc_types.see_invis, npc_types.see_invis_undead, npc_types.lastname, " + "npc_types.qglobal, npc_types.AC, npc_types.npc_aggro, npc_types.spawn_limit, " + "npc_types.see_hide, npc_types.see_improved_hide, npc_types.ATK, npc_types.Accuracy, " + "npc_types.Avoidance, npc_types.slow_mitigation, npc_types.maxlevel, npc_types.scalerate, " + "npc_types.private_corpse, npc_types.unique_spawn_by_name, npc_types.underwater, " + "npc_types.emoteid, npc_types.spellscale, npc_types.healscale, npc_types.no_target_hotkey," + "npc_types.raid_target FROM npc_types WHERE id = %d", id); - MakeAnyLenString(&query, "%s FROM npc_types WHERE id=%d", basic_query, id); + auto results = QueryDatabase(query); + if (!results.Success()) { + std::cerr << "Error loading NPCs from database. Bad query: " << results.ErrorMessage() << std::endl; + return nullptr; + } - if (RunQuery(query, strlen(query), errbuf, &result)) { - // Process each row returned. - while((row = mysql_fetch_row(result))) { - NPCType *tmpNPCType; - tmpNPCType = new NPCType; - memset (tmpNPCType, 0, sizeof *tmpNPCType); - int r = 0; - tmpNPCType->npc_id = atoi(row[r++]); + for (auto row = results.begin(); row != results.end(); ++row) { + NPCType *tmpNPCType; + tmpNPCType = new NPCType; + memset (tmpNPCType, 0, sizeof *tmpNPCType); - strn0cpy(tmpNPCType->name, row[r++], 50); + tmpNPCType->npc_id = atoi(row[0]); - tmpNPCType->level = atoi(row[r++]); - tmpNPCType->race = atoi(row[r++]); - tmpNPCType->class_ = atoi(row[r++]); - tmpNPCType->max_hp = atoi(row[r++]); - tmpNPCType->cur_hp = tmpNPCType->max_hp; - tmpNPCType->Mana = atoi(row[r++]); - tmpNPCType->gender = atoi(row[r++]); - tmpNPCType->texture = atoi(row[r++]); - tmpNPCType->helmtexture = atoi(row[r++]); - tmpNPCType->size = atof(row[r++]); - tmpNPCType->loottable_id = atoi(row[r++]); - tmpNPCType->merchanttype = atoi(row[r++]); - tmpNPCType->alt_currency_type = atoi(row[r++]); - tmpNPCType->adventure_template = atoi(row[r++]); - tmpNPCType->trap_template = atoi(row[r++]); - tmpNPCType->attack_speed = atof(row[r++]); - tmpNPCType->STR = atoi(row[r++]); - tmpNPCType->STA = atoi(row[r++]); - tmpNPCType->DEX = atoi(row[r++]); - tmpNPCType->AGI = atoi(row[r++]); - tmpNPCType->INT = atoi(row[r++]); - tmpNPCType->WIS = atoi(row[r++]); - tmpNPCType->CHA = atoi(row[r++]); - tmpNPCType->MR = atoi(row[r++]); - tmpNPCType->CR = atoi(row[r++]); - tmpNPCType->DR = atoi(row[r++]); - tmpNPCType->FR = atoi(row[r++]); - tmpNPCType->PR = atoi(row[r++]); - tmpNPCType->Corrup = atoi(row[r++]); - tmpNPCType->PhR = atoi(row[r++]); - tmpNPCType->min_dmg = atoi(row[r++]); - tmpNPCType->max_dmg = atoi(row[r++]); - tmpNPCType->attack_count = atoi(row[r++]); - strn0cpy(tmpNPCType->special_abilities, row[r++], 512); - tmpNPCType->npc_spells_id = atoi(row[r++]); - tmpNPCType->npc_spells_effects_id = atoi(row[r++]); - tmpNPCType->d_meele_texture1 = atoi(row[r++]); - tmpNPCType->d_meele_texture2 = atoi(row[r++]); - strn0cpy(tmpNPCType->ammo_idfile, row[r++], 30); - tmpNPCType->prim_melee_type = atoi(row[r++]); - tmpNPCType->sec_melee_type = atoi(row[r++]); - tmpNPCType->ranged_type = atoi(row[r++]); - tmpNPCType->runspeed= atof(row[r++]); - tmpNPCType->findable = atoi(row[r++]) == 0? false : true; - tmpNPCType->trackable = atoi(row[r++]) == 0? false : true; - tmpNPCType->hp_regen = atoi(row[r++]); - tmpNPCType->mana_regen = atoi(row[r++]); + strn0cpy(tmpNPCType->name, row[1], 50); - tmpNPCType->aggroradius = (int32)atoi(row[r++]); - // set defaultvalue for aggroradius - if (tmpNPCType->aggroradius <= 0) - tmpNPCType->aggroradius = 70; - tmpNPCType->assistradius = (int32)atoi(row[r++]); - if (tmpNPCType->assistradius <= 0) - tmpNPCType->assistradius = tmpNPCType->aggroradius; + tmpNPCType->level = atoi(row[2]); + tmpNPCType->race = atoi(row[3]); + tmpNPCType->class_ = atoi(row[4]); + tmpNPCType->max_hp = atoi(row[5]); + tmpNPCType->cur_hp = tmpNPCType->max_hp; + tmpNPCType->Mana = atoi(row[6]); + tmpNPCType->gender = atoi(row[7]); + tmpNPCType->texture = atoi(row[8]); + tmpNPCType->helmtexture = atoi(row[9]); + tmpNPCType->size = atof(row[10]); + tmpNPCType->loottable_id = atoi(row[11]); + tmpNPCType->merchanttype = atoi(row[12]); + tmpNPCType->alt_currency_type = atoi(row[13]); + tmpNPCType->adventure_template = atoi(row[14]); + tmpNPCType->trap_template = atoi(row[15]); + tmpNPCType->attack_speed = atof(row[16]); + tmpNPCType->STR = atoi(row[17]); + tmpNPCType->STA = atoi(row[18]); + tmpNPCType->DEX = atoi(row[19]); + tmpNPCType->AGI = atoi(row[20]); + tmpNPCType->INT = atoi(row[21]); + tmpNPCType->WIS = atoi(row[22]); + tmpNPCType->CHA = atoi(row[23]); + tmpNPCType->MR = atoi(row[24]); + tmpNPCType->CR = atoi(row[25]); + tmpNPCType->DR = atoi(row[26]); + tmpNPCType->FR = atoi(row[27]); + tmpNPCType->PR = atoi(row[28]); + tmpNPCType->Corrup = atoi(row[29]); + tmpNPCType->PhR = atoi(row[30]); + tmpNPCType->min_dmg = atoi(row[31]); + tmpNPCType->max_dmg = atoi(row[32]); + tmpNPCType->attack_count = atoi(row[33]); + strn0cpy(tmpNPCType->special_abilities, row[34], 512); + tmpNPCType->npc_spells_id = atoi(row[35]); + tmpNPCType->npc_spells_effects_id = atoi(row[36]); + tmpNPCType->d_meele_texture1 = atoi(row[37]); + tmpNPCType->d_meele_texture2 = atoi(row[38]); + strn0cpy(tmpNPCType->ammo_idfile, row[39], 30); + tmpNPCType->prim_melee_type = atoi(row[40]); + tmpNPCType->sec_melee_type = atoi(row[41]); + tmpNPCType->ranged_type = atoi(row[42]); + tmpNPCType->runspeed= atof(row[43]); + tmpNPCType->findable = atoi(row[44]) == 0? false : true; + tmpNPCType->trackable = atoi(row[45]) == 0? false : true; + tmpNPCType->hp_regen = atoi(row[46]); + tmpNPCType->mana_regen = atoi(row[47]); - if (row[r] && strlen(row[r])) - tmpNPCType->bodytype = (uint8)atoi(row[r]); - else - tmpNPCType->bodytype = 0; - r++; + // set defaultvalue for aggroradius + tmpNPCType->aggroradius = (int32)atoi(row[48]); + if (tmpNPCType->aggroradius <= 0) + tmpNPCType->aggroradius = 70; - tmpNPCType->npc_faction_id = atoi(row[r++]); + tmpNPCType->assistradius = (int32)atoi(row[49]); + if (tmpNPCType->assistradius <= 0) + tmpNPCType->assistradius = tmpNPCType->aggroradius; - tmpNPCType->luclinface = atoi(row[r++]); - tmpNPCType->hairstyle = atoi(row[r++]); - tmpNPCType->haircolor = atoi(row[r++]); - tmpNPCType->eyecolor1 = atoi(row[r++]); - tmpNPCType->eyecolor2 = atoi(row[r++]); - tmpNPCType->beardcolor = atoi(row[r++]); - tmpNPCType->beard = atoi(row[r++]); - tmpNPCType->drakkin_heritage = atoi(row[r++]); - tmpNPCType->drakkin_tattoo = atoi(row[r++]); - tmpNPCType->drakkin_details = atoi(row[r++]); - uint32 armor_tint_id = atoi(row[r++]); - tmpNPCType->armor_tint[0] = (atoi(row[r++]) & 0xFF) << 16; - tmpNPCType->armor_tint[0] |= (atoi(row[r++]) & 0xFF) << 8; - tmpNPCType->armor_tint[0] |= (atoi(row[r++]) & 0xFF); - tmpNPCType->armor_tint[0] |= (tmpNPCType->armor_tint[0]) ? (0xFF << 24) : 0; + if (row[50] && strlen(row[50])) + tmpNPCType->bodytype = (uint8)atoi(row[50]); + else + tmpNPCType->bodytype = 0; - int i; - if (armor_tint_id > 0) - { - if (tmpNPCType->armor_tint[0] == 0) - { - char at_errbuf[MYSQL_ERRMSG_SIZE]; - char *at_query = nullptr; - MYSQL_RES *at_result = nullptr; - MYSQL_ROW at_row; + tmpNPCType->npc_faction_id = atoi(row[51]); - MakeAnyLenString(&at_query, - "SELECT " - "red1h,grn1h,blu1h," - "red2c,grn2c,blu2c," - "red3a,grn3a,blu3a," - "red4b,grn4b,blu4b," - "red5g,grn5g,blu5g," - "red6l,grn6l,blu6l," - "red7f,grn7f,blu7f," - "red8x,grn8x,blu8x," - "red9x,grn9x,blu9x " - "FROM npc_types_tint WHERE id=%d", armor_tint_id); + tmpNPCType->luclinface = atoi(row[52]); + tmpNPCType->hairstyle = atoi(row[53]); + tmpNPCType->haircolor = atoi(row[54]); + tmpNPCType->eyecolor1 = atoi(row[55]); + tmpNPCType->eyecolor2 = atoi(row[56]); + tmpNPCType->beardcolor = atoi(row[57]); + tmpNPCType->beard = atoi(row[58]); + tmpNPCType->drakkin_heritage = atoi(row[59]); + tmpNPCType->drakkin_tattoo = atoi(row[60]); + tmpNPCType->drakkin_details = atoi(row[61]); - if (RunQuery(at_query, strlen(at_query), at_errbuf, &at_result)) - { - if ((at_row = mysql_fetch_row(at_result))) - { - for (i = EmuConstants::MATERIAL_BEGIN; i <= EmuConstants::MATERIAL_END; i++) - { - tmpNPCType->armor_tint[i] = atoi(at_row[i * 3]) << 16; - tmpNPCType->armor_tint[i] |= atoi(at_row[i * 3 + 1]) << 8; - tmpNPCType->armor_tint[i] |= atoi(at_row[i * 3 + 2]); - tmpNPCType->armor_tint[i] |= (tmpNPCType->armor_tint[i]) ? (0xFF << 24) : 0; - } - } - else - { - armor_tint_id = 0; - } - } - else - { - armor_tint_id = 0; - } + uint32 armor_tint_id = atoi(row[62]); - if (at_result) - { - mysql_free_result(at_result); - } + tmpNPCType->armor_tint[0] = (atoi(row[63]) & 0xFF) << 16; + tmpNPCType->armor_tint[0] |= (atoi(row[64]) & 0xFF) << 8; + tmpNPCType->armor_tint[0] |= (atoi(row[65]) & 0xFF); + tmpNPCType->armor_tint[0] |= (tmpNPCType->armor_tint[0]) ? (0xFF << 24) : 0; - safe_delete_array(at_query); - } - else - { - armor_tint_id = 0; - } - } + if (armor_tint_id == 0) + for (int index = MaterialChest; index <= EmuConstants::MATERIAL_END; index++) + tmpNPCType->armor_tint[index] = tmpNPCType->armor_tint[0]; + else if (tmpNPCType->armor_tint[0] == 0) + { + std::string armortint_query = StringFormat("SELECT red1h, grn1h, blu1h, " + "red2c, grn2c, blu2c, " + "red3a, grn3a, blu3a, " + "red4b, grn4b, blu4b, " + "red5g, grn5g, blu5g, " + "red6l, grn6l, blu6l, " + "red7f, grn7f, blu7f, " + "red8x, grn8x, blu8x, " + "red9x, grn9x, blu9x " + "FROM npc_types_tint WHERE id = %d", + armor_tint_id); + auto armortint_results = QueryDatabase(armortint_query); + if (!armortint_results.Success() || armortint_results.RowCount() == 0) + armor_tint_id = 0; + else { + auto armorTint_row = results.begin(); - if (armor_tint_id == 0) - { - for (i = MaterialChest; i <= EmuConstants::MATERIAL_END; i++) - { - tmpNPCType->armor_tint[i] = tmpNPCType->armor_tint[0]; - } - } + for (int index = EmuConstants::MATERIAL_BEGIN; index <= EmuConstants::MATERIAL_END; index++) { + tmpNPCType->armor_tint[index] = atoi(armorTint_row[index * 3]) << 16; + tmpNPCType->armor_tint[index] |= atoi(armorTint_row[index * 3 + 1]) << 8; + tmpNPCType->armor_tint[index] |= atoi(armorTint_row[index * 3 + 2]); + tmpNPCType->armor_tint[index] |= (tmpNPCType->armor_tint[index]) ? (0xFF << 24) : 0; + } + } + } else + armor_tint_id = 0; - tmpNPCType->see_invis = atoi(row[r++]); - tmpNPCType->see_invis_undead = atoi(row[r++])==0?false:true; // Set see_invis_undead flag - if (row[r] != nullptr) - strn0cpy(tmpNPCType->lastname, row[r], 32); - r++; + tmpNPCType->see_invis = atoi(row[66]); + tmpNPCType->see_invis_undead = atoi(row[67]) == 0? false: true; // Set see_invis_undead flag + if (row[68] != nullptr) + strn0cpy(tmpNPCType->lastname, row[68], 32); - tmpNPCType->qglobal = atoi(row[r++])==0?false:true; // qglobal - tmpNPCType->AC = atoi(row[r++]); - tmpNPCType->npc_aggro = atoi(row[r++])==0?false:true; - tmpNPCType->spawn_limit = atoi(row[r++]); - tmpNPCType->see_hide = atoi(row[r++])==0?false:true; - tmpNPCType->see_improved_hide = atoi(row[r++])==0?false:true; - tmpNPCType->ATK = atoi(row[r++]); - tmpNPCType->accuracy_rating = atoi(row[r++]); - tmpNPCType->avoidance_rating = atoi(row[r++]); - tmpNPCType->slow_mitigation = atoi(row[r++]); - tmpNPCType->maxlevel = atoi(row[r++]); - tmpNPCType->scalerate = atoi(row[r++]); - tmpNPCType->private_corpse = atoi(row[r++]) == 1 ? true : false; - tmpNPCType->unique_spawn_by_name = atoi(row[r++]) == 1 ? true : false; - tmpNPCType->underwater = atoi(row[r++]) == 1 ? true : false; - tmpNPCType->emoteid = atoi(row[r++]); - tmpNPCType->spellscale = atoi(row[r++]); - tmpNPCType->healscale = atoi(row[r++]); - tmpNPCType->no_target_hotkey = atoi(row[r++]) == 1 ? true : false; - tmpNPCType->raid_target = atoi(row[r++]) == 0 ? false : true; + tmpNPCType->qglobal = atoi(row[69]) == 0? false: true; // qglobal + tmpNPCType->AC = atoi(row[70]); + tmpNPCType->npc_aggro = atoi(row[71]) == 0? false: true; + tmpNPCType->spawn_limit = atoi(row[72]); + tmpNPCType->see_hide = atoi(row[73]) == 0? false: true; + tmpNPCType->see_improved_hide = atoi(row[74]) == 0? false: true; + tmpNPCType->ATK = atoi(row[75]); + tmpNPCType->accuracy_rating = atoi(row[76]); + tmpNPCType->avoidance_rating = atoi(row[77]); + tmpNPCType->slow_mitigation = atoi(row[78]); + tmpNPCType->maxlevel = atoi(row[79]); + tmpNPCType->scalerate = atoi(row[80]); + tmpNPCType->private_corpse = atoi(row[81]) == 1 ? true: false; + tmpNPCType->unique_spawn_by_name = atoi(row[82]) == 1 ? true: false; + tmpNPCType->underwater = atoi(row[83]) == 1 ? true: false; + tmpNPCType->emoteid = atoi(row[84]); + tmpNPCType->spellscale = atoi(row[85]); + tmpNPCType->healscale = atoi(row[86]); + tmpNPCType->no_target_hotkey = atoi(row[87]) == 1 ? true: false; + tmpNPCType->raid_target = atoi(row[88]) == 0 ? false: true; - // If NPC with duplicate NPC id already in table, - // free item we attempted to add. - if (zone->npctable.find(tmpNPCType->npc_id) != zone->npctable.end()) - { - std::cerr << "Error loading duplicate NPC " << tmpNPCType->npc_id << std::endl; - delete tmpNPCType; - npc = nullptr; - } else { - zone->npctable[tmpNPCType->npc_id]=tmpNPCType; - npc = tmpNPCType; - } + // If NPC with duplicate NPC id already in table, + // free item we attempted to add. + if (zone->npctable.find(tmpNPCType->npc_id) != zone->npctable.end()) { + std::cerr << "Error loading duplicate NPC " << tmpNPCType->npc_id << std::endl; + delete tmpNPCType; + return nullptr; + } -// Sleep(0); - } - - if (result) { - mysql_free_result(result); - } - } else - std::cerr << "Error loading NPCs from database. Bad query: " << errbuf << std::endl; - safe_delete_array(query); + zone->npctable[tmpNPCType->npc_id]=tmpNPCType; + npc = tmpNPCType; + } return npc; } From 205e1d404e86fffe66dafdd2c6e261d00b0b9501 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 20:50:36 -0700 Subject: [PATCH 028/127] GetMercType converted to QueryDatabase --- zone/zonedb.cpp | 405 +++++++++++++++--------------------------------- 1 file changed, 125 insertions(+), 280 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 837878720..a43295ce9 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1148,312 +1148,157 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { return npc; } - const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 clientlevel) { - const NPCType *npc=nullptr; - std::map::iterator itr; //need to save based on merc_npc_type & client level uint32 merc_type_id = id * 100 + clientlevel; // If NPC is already in tree, return it. - if((itr = zone->merctable.find(merc_type_id)) != zone->merctable.end()) + auto itr = zone->merctable.find(merc_type_id); + if(itr != zone->merctable.end()) return itr->second; + //If the NPC type is 0, return nullptr. (sanity check) if(id == 0) - return nullptr; + return nullptr; // Otherwise, get NPCs from database. - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + // If id is 0, load all npc_types for the current zone, + // according to spawn2. + std::string query = StringFormat("SELECT vwMercNpcTypes.merc_npc_type_id, vwMercNpcTypes.name, " + "vwMercNpcTypes.level, vwMercNpcTypes.race_id, vwMercNpcTypes.class_id, " + "vwMercNpcTypes.hp, vwMercNpcTypes.mana, vwMercNpcTypes.gender, " + "vwMercNpcTypes.texture, vwMercNpcTypes.helmtexture, vwMercNpcTypes.attack_speed, " + "vwMercNpcTypes.STR, vwMercNpcTypes.STA, vwMercNpcTypes.DEX, vwMercNpcTypes.AGI, " + "vwMercNpcTypes._INT, vwMercNpcTypes.WIS, vwMercNpcTypes.CHA, vwMercNpcTypes.MR, " + "vwMercNpcTypes.CR, vwMercNpcTypes.DR, vwMercNpcTypes.FR, vwMercNpcTypes.PR, " + "vwMercNpcTypes.Corrup, vwMercNpcTypes.mindmg, vwMercNpcTypes.maxdmg, " + "vwMercNpcTypes.attack_count, vwMercNpcTypes.special_abilities, " + "vwMercNpcTypes.d_meele_texture1, vwMercNpcTypes.d_meele_texture2, " + "vwMercNpcTypes.prim_melee_type, vwMercNpcTypes.sec_melee_type, " + "vwMercNpcTypes.runspeed, vwMercNpcTypes.hp_regen_rate, vwMercNpcTypes.mana_regen_rate, " + "vwMercNpcTypes.bodytype, vwMercNpcTypes.armortint_id, " + "vwMercNpcTypes.armortint_red, vwMercNpcTypes.armortint_green, vwMercNpcTypes.armortint_blue, " + "vwMercNpcTypes.AC, vwMercNpcTypes.ATK, vwMercNpcTypes.Accuracy, vwMercNpcTypes.spellscale, " + "vwMercNpcTypes.healscale FROM vwMercNpcTypes " + "WHERE merc_npc_type_id = %d AND clientlevel = %d AND race_id = %d", + id, clientlevel, raceid); //dual primary keys. one is ID, one is level. + auto results = QueryDatabase(query); + if (!results.Success()) { + std::cerr << "Error loading NPCs from database. Bad query: " << results.ErrorMessage() << std::endl; + return nullptr; + } + const NPCType *npc; - // If id is 0, load all npc_types for the current zone, - // according to spawn2. - const char *basic_query = "SELECT " - "vwMercNpcTypes.merc_npc_type_id," - "vwMercNpcTypes.name," - //"vwMercNpcTypes.clientlevel," - "vwMercNpcTypes.level," - "vwMercNpcTypes.race_id," - "vwMercNpcTypes.class_id," - "vwMercNpcTypes.hp," - "vwMercNpcTypes.mana," - "vwMercNpcTypes.gender," - "vwMercNpcTypes.texture," - "vwMercNpcTypes.helmtexture," - //"vwMercNpcTypes.size," - // "vwMercNpcTypes.loottable_id," - // "vwMercNpcTypes.merchant_id," - // "vwMercNpcTypes.alt_currency_id," - // "vwMercNpcTypes.adventure_template_id," - // "vwMercNpcTypes.trap_template," - "vwMercNpcTypes.attack_speed," - "vwMercNpcTypes.STR," - "vwMercNpcTypes.STA," - "vwMercNpcTypes.DEX," - "vwMercNpcTypes.AGI," - "vwMercNpcTypes._INT," - "vwMercNpcTypes.WIS," - "vwMercNpcTypes.CHA," - "vwMercNpcTypes.MR," - "vwMercNpcTypes.CR," - "vwMercNpcTypes.DR," - "vwMercNpcTypes.FR," - "vwMercNpcTypes.PR," - "vwMercNpcTypes.Corrup," - "vwMercNpcTypes.mindmg," - "vwMercNpcTypes.maxdmg," - "vwMercNpcTypes.attack_count," - "vwMercNpcTypes.special_abilities," - // "vwMercNpcTypes.npc_spells_id," - "vwMercNpcTypes.d_meele_texture1," - "vwMercNpcTypes.d_meele_texture2," - "vwMercNpcTypes.prim_melee_type," - "vwMercNpcTypes.sec_melee_type," - "vwMercNpcTypes.runspeed," - // "vwMercNpcTypes.findable," - // "vwMercNpcTypes.trackable," - "vwMercNpcTypes.hp_regen_rate," - "vwMercNpcTypes.mana_regen_rate," - // "vwMercNpcTypes.aggroradius," - "vwMercNpcTypes.bodytype," - // "vwMercNpcTypes.npc_faction_id," - //"vwMercNpcTypes.face," - //"vwMercNpcTypes.luclin_hairstyle," - //"vwMercNpcTypes.luclin_haircolor," - //"vwMercNpcTypes.luclin_eyecolor," - //"vwMercNpcTypes.luclin_eyecolor2," - //"vwMercNpcTypes.luclin_beardcolor," - //"vwMercNpcTypes.luclin_beard," - //"vwMercNpcTypes.drakkin_heritage," - //"vwMercNpcTypes.drakkin_tattoo," - //"vwMercNpcTypes.drakkin_details," - "vwMercNpcTypes.armortint_id," - "vwMercNpcTypes.armortint_red," - "vwMercNpcTypes.armortint_green," - "vwMercNpcTypes.armortint_blue," - // "vwMercNpcTypes.see_invis," - // "vwMercNpcTypes.see_invis_undead," - // "vwMercNpcTypes.lastname," - // "vwMercNpcTypes.qglobal," - "vwMercNpcTypes.AC," - // "vwMercNpcTypes.npc_aggro," - // "vwMercNpcTypes.spawn_limit," - // "vwMercNpcTypes.see_hide," - // "vwMercNpcTypes.see_improved_hide," - "vwMercNpcTypes.ATK," - "vwMercNpcTypes.Accuracy," - "vwMercNpcTypes.spellscale," - "vwMercNpcTypes.healscale"; - // "vwMercNpcTypes.slow_mitigation," - // "vwMercNpcTypes.maxlevel," - // "vwMercNpcTypes.scalerate," - // "vwMercNpcTypes.private_corpse," - // "vwMercNpcTypes.unique_spawn_by_name," - // "vwMercNpcTypes.underwater," - // "vwMercNpcTypes.emoteid"; + // Process each row returned. + for (auto row = results.begin(); row != results.end(); ++row) { + NPCType *tmpNPCType; + tmpNPCType = new NPCType; + memset (tmpNPCType, 0, sizeof *tmpNPCType); - MakeAnyLenString(&query, "%s FROM vwMercNpcTypes WHERE merc_npc_type_id=%d AND clientlevel=%d AND race_id = %d", basic_query, id, clientlevel, raceid); //dual primary keys. one is ID, one is level. + tmpNPCType->npc_id = atoi(row[0]); - if (RunQuery(query, strlen(query), errbuf, &result)) { - // Process each row returned. - while((row = mysql_fetch_row(result))) { - NPCType *tmpNPCType; - tmpNPCType = new NPCType; - memset (tmpNPCType, 0, sizeof *tmpNPCType); + strn0cpy(tmpNPCType->name, row[1], 50); - int r = 0; - tmpNPCType->npc_id = atoi(row[r++]); + tmpNPCType->level = atoi(row[2]); + tmpNPCType->race = atoi(row[3]); + tmpNPCType->class_ = atoi(row[4]); + tmpNPCType->max_hp = atoi(row[5]); + tmpNPCType->cur_hp = tmpNPCType->max_hp; + tmpNPCType->Mana = atoi(row[6]); + tmpNPCType->gender = atoi(row[7]); + tmpNPCType->texture = atoi(row[8]); + tmpNPCType->helmtexture = atoi(row[9]); + tmpNPCType->attack_speed = atof(row[10]); + tmpNPCType->STR = atoi(row[11]); + tmpNPCType->STA = atoi(row[12]); + tmpNPCType->DEX = atoi(row[13]); + tmpNPCType->AGI = atoi(row[14]); + tmpNPCType->INT = atoi(row[15]); + tmpNPCType->WIS = atoi(row[16]); + tmpNPCType->CHA = atoi(row[17]); + tmpNPCType->MR = atoi(row[18]); + tmpNPCType->CR = atoi(row[19]); + tmpNPCType->DR = atoi(row[20]); + tmpNPCType->FR = atoi(row[21]); + tmpNPCType->PR = atoi(row[22]); + tmpNPCType->Corrup = atoi(row[23]); + tmpNPCType->min_dmg = atoi(row[24]); + tmpNPCType->max_dmg = atoi(row[25]); + tmpNPCType->attack_count = atoi(row[26]); + strn0cpy(tmpNPCType->special_abilities, row[27], 512); - strn0cpy(tmpNPCType->name, row[r++], 50); + tmpNPCType->d_meele_texture1 = atoi(row[28]); + tmpNPCType->d_meele_texture2 = atoi(row[29]); + tmpNPCType->prim_melee_type = atoi(row[30]); + tmpNPCType->sec_melee_type = atoi(row[31]); + tmpNPCType->runspeed= atof(row[32]); - tmpNPCType->level = atoi(row[r++]); - tmpNPCType->race = atoi(row[r++]); - tmpNPCType->class_ = atoi(row[r++]); - tmpNPCType->max_hp = atoi(row[r++]); - tmpNPCType->cur_hp = tmpNPCType->max_hp; - tmpNPCType->Mana = atoi(row[r++]); - tmpNPCType->gender = atoi(row[r++]); - tmpNPCType->texture = atoi(row[r++]); - tmpNPCType->helmtexture = atoi(row[r++]); - //tmpNPCType->size = atof(row[r++]); - //tmpNPCType->loottable_id = atoi(row[r++]); - //tmpNPCType->merchanttype = atoi(row[r++]); - //tmpNPCType->alt_currency_type = atoi(row[r++]); - //tmpNPCType->adventure_template = atoi(row[r++]); - //tmpNPCType->trap_template = atoi(row[r++]); - tmpNPCType->attack_speed = atof(row[r++]); - tmpNPCType->STR = atoi(row[r++]); - tmpNPCType->STA = atoi(row[r++]); - tmpNPCType->DEX = atoi(row[r++]); - tmpNPCType->AGI = atoi(row[r++]); - tmpNPCType->INT = atoi(row[r++]); - tmpNPCType->WIS = atoi(row[r++]); - tmpNPCType->CHA = atoi(row[r++]); - tmpNPCType->MR = atoi(row[r++]); - tmpNPCType->CR = atoi(row[r++]); - tmpNPCType->DR = atoi(row[r++]); - tmpNPCType->FR = atoi(row[r++]); - tmpNPCType->PR = atoi(row[r++]); - tmpNPCType->Corrup = atoi(row[r++]); - tmpNPCType->min_dmg = atoi(row[r++]); - tmpNPCType->max_dmg = atoi(row[r++]); - tmpNPCType->attack_count = atoi(row[r++]); - strn0cpy(tmpNPCType->special_abilities, row[r++], 512); - //tmpNPCType->npc_spells_id = atoi(row[r++]); - tmpNPCType->d_meele_texture1 = atoi(row[r++]); - tmpNPCType->d_meele_texture2 = atoi(row[r++]); - tmpNPCType->prim_melee_type = atoi(row[r++]); - tmpNPCType->sec_melee_type = atoi(row[r++]); - tmpNPCType->runspeed= atof(row[r++]); - //tmpNPCType->findable = atoi(row[r++]) == 0? false : true; - //tmpNPCType->trackable = atoi(row[r++]) == 0? false : true; - tmpNPCType->hp_regen = atoi(row[r++]); - tmpNPCType->mana_regen = atoi(row[r++]); + tmpNPCType->hp_regen = atoi(row[33]); + tmpNPCType->mana_regen = atoi(row[34]); - //tmpNPCType->aggroradius = (int32)atoi(row[r++]); - tmpNPCType->aggroradius = RuleI(Mercs, AggroRadius); - // set defaultvalue for aggroradius - //if (tmpNPCType->aggroradius <= 0) - // tmpNPCType->aggroradius = 70; + tmpNPCType->aggroradius = RuleI(Mercs, AggroRadius); - if (row[r] && strlen(row[r])) - tmpNPCType->bodytype = (uint8)atoi(row[r]); - else - tmpNPCType->bodytype = 1; - r++; + if (row[35] && strlen(row[35])) + tmpNPCType->bodytype = (uint8)atoi(row[35]); + else + tmpNPCType->bodytype = 1; - //tmpNPCType->npc_faction_id = atoi(row[r++]); + uint32 armor_tint_id = atoi(row[36]); + tmpNPCType->armor_tint[0] = (atoi(row[37]) & 0xFF) << 16; + tmpNPCType->armor_tint[0] |= (atoi(row[38]) & 0xFF) << 8; + tmpNPCType->armor_tint[0] |= (atoi(row[39]) & 0xFF); + tmpNPCType->armor_tint[0] |= (tmpNPCType->armor_tint[0]) ? (0xFF << 24) : 0; - //tmpNPCType->luclinface = atoi(row[r++]); - //tmpNPCType->hairstyle = atoi(row[r++]); - //tmpNPCType->haircolor = atoi(row[r++]); - //tmpNPCType->eyecolor1 = atoi(row[r++]); - //tmpNPCType->eyecolor2 = atoi(row[r++]); - //tmpNPCType->beardcolor = atoi(row[r++]); - //tmpNPCType->beard = atoi(row[r++]); - //tmpNPCType->drakkin_heritage = atoi(row[r++]); - //tmpNPCType->drakkin_tattoo = atoi(row[r++]); - //tmpNPCType->drakkin_details = atoi(row[r++]); - uint32 armor_tint_id = atoi(row[r++]); - tmpNPCType->armor_tint[0] = (atoi(row[r++]) & 0xFF) << 16; - tmpNPCType->armor_tint[0] |= (atoi(row[r++]) & 0xFF) << 8; - tmpNPCType->armor_tint[0] |= (atoi(row[r++]) & 0xFF); - tmpNPCType->armor_tint[0] |= (tmpNPCType->armor_tint[0]) ? (0xFF << 24) : 0; + if (armor_tint_id == 0) + for (int index = MaterialChest; index <= EmuConstants::MATERIAL_END; index++) + tmpNPCType->armor_tint[index] = tmpNPCType->armor_tint[0]; + else if (tmpNPCType->armor_tint[0] == 0) { + std::string armorTint_query = StringFormat("SELECT red1h, grn1h, blu1h, " + "red2c, grn2c, blu2c, " + "red3a, grn3a, blu3a, " + "red4b, grn4b, blu4b, " + "red5g, grn5g, blu5g, " + "red6l, grn6l, blu6l, " + "red7f, grn7f, blu7f, " + "red8x, grn8x, blu8x, " + "red9x, grn9x, blu9x " + "FROM npc_types_tint WHERE id = %d", + armor_tint_id); + auto armorTint_results = QueryDatabase(armorTint_query); + if (!results.Success() || results.RowCount() == 0) + armor_tint_id = 0; + else { + auto armorTint_row = results.begin(); - int i; - if (armor_tint_id > 0) - { - if (tmpNPCType->armor_tint[0] == 0) - { - char at_errbuf[MYSQL_ERRMSG_SIZE]; - char *at_query = nullptr; - MYSQL_RES *at_result = nullptr; - MYSQL_ROW at_row; + for (int index = EmuConstants::MATERIAL_BEGIN; index <= EmuConstants::MATERIAL_END; index++) { + tmpNPCType->armor_tint[index] = atoi(armorTint_row[index * 3]) << 16; + tmpNPCType->armor_tint[index] |= atoi(armorTint_row[index * 3 + 1]) << 8; + tmpNPCType->armor_tint[index] |= atoi(armorTint_row[index * 3 + 2]); + tmpNPCType->armor_tint[index] |= (tmpNPCType->armor_tint[index]) ? (0xFF << 24) : 0; + } + } + } else + armor_tint_id = 0; - MakeAnyLenString(&at_query, - "SELECT " - "red1h,grn1h,blu1h," - "red2c,grn2c,blu2c," - "red3a,grn3a,blu3a," - "red4b,grn4b,blu4b," - "red5g,grn5g,blu5g," - "red6l,grn6l,blu6l," - "red7f,grn7f,blu7f," - "red8x,grn8x,blu8x," - "red9x,grn9x,blu9x " - "FROM npc_types_tint WHERE id=%d", armor_tint_id); + tmpNPCType->AC = atoi(row[40]); + tmpNPCType->ATK = atoi(row[41]); + tmpNPCType->accuracy_rating = atoi(row[42]); + tmpNPCType->scalerate = RuleI(Mercs, ScaleRate); + tmpNPCType->spellscale = atoi(row[43]); + tmpNPCType->healscale = atoi(row[4]); - if (RunQuery(at_query, strlen(at_query), at_errbuf, &at_result)) - { - if ((at_row = mysql_fetch_row(at_result))) - { - for (i = EmuConstants::MATERIAL_BEGIN; i <= EmuConstants::MATERIAL_END; i++) - { - tmpNPCType->armor_tint[i] = atoi(at_row[i * 3]) << 16; - tmpNPCType->armor_tint[i] |= atoi(at_row[i * 3 + 1]) << 8; - tmpNPCType->armor_tint[i] |= atoi(at_row[i * 3 + 2]); - tmpNPCType->armor_tint[i] |= (tmpNPCType->armor_tint[i]) ? (0xFF << 24) : 0; - } - } - else - { - armor_tint_id = 0; - } - } - else - { - armor_tint_id = 0; - } + // If NPC with duplicate NPC id already in table, + // free item we attempted to add. + if (zone->merctable.find(tmpNPCType->npc_id * 100 + clientlevel) != zone->merctable.end()) { + delete tmpNPCType; + return nullptr; + } - if (at_result) - { - mysql_free_result(at_result); - } - - safe_delete_array(at_query); - } - else - { - armor_tint_id = 0; - } - } - - if (armor_tint_id == 0) - { - for (i = MaterialChest; i <= EmuConstants::MATERIAL_END; i++) - { - tmpNPCType->armor_tint[i] = tmpNPCType->armor_tint[0]; - } - } - - //tmpNPCType->see_invis = atoi(row[r++]); - //tmpNPCType->see_invis_undead = atoi(row[r++])==0?false:true; // Set see_invis_undead flag - //if (row[r] != nullptr) - // strn0cpy(tmpNPCType->lastname, row[r], 32); - //r++; - - //tmpNPCType->qglobal = atoi(row[r++])==0?false:true; // qglobal - tmpNPCType->AC = atoi(row[r++]); - //tmpNPCType->npc_aggro = atoi(row[r++])==0?false:true; - //tmpNPCType->spawn_limit = atoi(row[r++]); - //tmpNPCType->see_hide = atoi(row[r++])==0?false:true; - //tmpNPCType->see_improved_hide = atoi(row[r++])==0?false:true; - tmpNPCType->ATK = atoi(row[r++]); - tmpNPCType->accuracy_rating = atoi(row[r++]); - //tmpNPCType->slow_mitigation = atof(row[r++]); - //tmpNPCType->maxlevel = atoi(row[r++]); - tmpNPCType->scalerate = RuleI(Mercs, ScaleRate); - //tmpNPCType->private_corpse = atoi(row[r++]) == 1 ? true : false; - //tmpNPCType->unique_spawn_by_name = atoi(row[r++]) == 1 ? true : false; - //tmpNPCType->underwater = atoi(row[r++]) == 1 ? true : false; - //tmpNPCType->emoteid = atoi(row[r++]); - tmpNPCType->spellscale = atoi(row[r++]); - tmpNPCType->healscale = atoi(row[r++]); - - // If NPC with duplicate NPC id already in table, - // free item we attempted to add. - if (zone->merctable.find(tmpNPCType->npc_id * 100 + clientlevel) != zone->merctable.end()) - { - delete tmpNPCType; - npc = nullptr; - } else { - zone->merctable[tmpNPCType->npc_id * 100 + clientlevel]=tmpNPCType; - npc = tmpNPCType; - } - -// Sleep(0); - } - - if (result) { - mysql_free_result(result); - } - } else - std::cerr << "Error loading NPCs from database. Bad query: " << errbuf << std::endl; - safe_delete_array(query); + zone->merctable[tmpNPCType->npc_id * 100 + clientlevel]=tmpNPCType; + npc = tmpNPCType; + } return npc; } From 322cea73427c36e2d5f6dd3a4e48a603aef61453 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 20:58:11 -0700 Subject: [PATCH 029/127] LoadMercInfo converted to QueryDatabase --- zone/zonedb.cpp | 92 ++++++++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 51 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index a43295ce9..7084d8e81 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1303,63 +1303,53 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client return npc; } -bool ZoneDatabase::LoadMercInfo(Client *c) { - bool loaded = false; +bool ZoneDatabase::LoadMercInfo(Client *client) { - if(c->GetEPP().merc_name[0] != 0) { - std::string errorMessage; - char* Query = 0; - char TempErrorMessageBuffer[MYSQL_ERRMSG_SIZE]; - MYSQL_RES* DatasetResult; - MYSQL_ROW DataRow; - //char name[64]; + if(client->GetEPP().merc_name[0] == 0) + return false; - //CleanMobName(c->GetEPP().merc_name, name); + std::string query = StringFormat("SELECT MercID, Slot, Name, TemplateID, SuspendedTime, " + "IsSuspended, TimerRemaining, Gender, StanceID, HP, Mana, " + "Endurance, Face, LuclinHairStyle, LuclinHairColor, " + "LuclinEyeColor, LuclinEyeColor2, LuclinBeardColor, LuclinBeard, " + "DrakkinHeritage, DrakkinTattoo, DrakkinDetails " + "FROM mercs WHERE OwnerCharacterID = '%i' ORDER BY Slot", client->CharacterID()); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; - if(!database.RunQuery(Query, MakeAnyLenString(&Query, "SELECT MercID, Slot, Name, TemplateID, SuspendedTime, IsSuspended, TimerRemaining, Gender, StanceID, HP, Mana, Endurance, Face, LuclinHairStyle, LuclinHairColor, LuclinEyeColor, LuclinEyeColor2, LuclinBeardColor, LuclinBeard, DrakkinHeritage, DrakkinTattoo, DrakkinDetails FROM mercs WHERE OwnerCharacterID = '%i' ORDER BY Slot", c->CharacterID()), TempErrorMessageBuffer, &DatasetResult)) { - errorMessage = std::string(TempErrorMessageBuffer); - } - else { - while(DataRow = mysql_fetch_row(DatasetResult)) { - uint8 slot = atoi(DataRow[1]); + for (auto row = results.begin(); row != results.end(); ++row) { + uint8 slot = atoi(row[1]); - if(slot >= MAXMERCS) { - continue; - } + if(slot >= MAXMERCS) + continue; - c->GetMercInfo(slot).mercid = atoi(DataRow[0]); - c->GetMercInfo(slot).slot = slot; - snprintf(c->GetMercInfo(slot).merc_name, 64, "%s", std::string(DataRow[2]).c_str()); - c->GetMercInfo(slot).MercTemplateID = atoi(DataRow[3]); - c->GetMercInfo(slot).SuspendedTime = atoi(DataRow[4]); - c->GetMercInfo(slot).IsSuspended = atoi(DataRow[5]) == 1 ? true : false; - c->GetMercInfo(slot).MercTimerRemaining = atoi(DataRow[6]); - c->GetMercInfo(slot).Gender = atoi(DataRow[7]); - c->GetMercInfo(slot).State = 5; - c->GetMercInfo(slot).Stance = atoi(DataRow[8]); - c->GetMercInfo(slot).hp = atoi(DataRow[9]); - c->GetMercInfo(slot).mana = atoi(DataRow[10]); - c->GetMercInfo(slot).endurance = atoi(DataRow[11]); - c->GetMercInfo(slot).face = atoi(DataRow[12]); - c->GetMercInfo(slot).luclinHairStyle = atoi(DataRow[13]); - c->GetMercInfo(slot).luclinHairColor = atoi(DataRow[14]); - c->GetMercInfo(slot).luclinEyeColor = atoi(DataRow[15]); - c->GetMercInfo(slot).luclinEyeColor2 = atoi(DataRow[16]); - c->GetMercInfo(slot).luclinBeardColor = atoi(DataRow[17]); - c->GetMercInfo(slot).luclinBeard = atoi(DataRow[18]); - c->GetMercInfo(slot).drakkinHeritage = atoi(DataRow[19]); - c->GetMercInfo(slot).drakkinTattoo = atoi(DataRow[20]); - c->GetMercInfo(slot).drakkinDetails = atoi(DataRow[21]); - loaded = true; - } + client->GetMercInfo(slot).mercid = atoi(row[0]); + client->GetMercInfo(slot).slot = slot; + snprintf(client->GetMercInfo(slot).merc_name, 64, "%s", row[2]); + client->GetMercInfo(slot).MercTemplateID = atoi(row[3]); + client->GetMercInfo(slot).SuspendedTime = atoi(row[4]); + client->GetMercInfo(slot).IsSuspended = atoi(row[5]) == 1 ? true : false; + client->GetMercInfo(slot).MercTimerRemaining = atoi(row[6]); + client->GetMercInfo(slot).Gender = atoi(row[7]); + client->GetMercInfo(slot).State = 5; + client->GetMercInfo(slot).Stance = atoi(row[8]); + client->GetMercInfo(slot).hp = atoi(row[9]); + client->GetMercInfo(slot).mana = atoi(row[10]); + client->GetMercInfo(slot).endurance = atoi(row[11]); + client->GetMercInfo(slot).face = atoi(row[12]); + client->GetMercInfo(slot).luclinHairStyle = atoi(row[13]); + client->GetMercInfo(slot).luclinHairColor = atoi(row[14]); + client->GetMercInfo(slot).luclinEyeColor = atoi(row[15]); + client->GetMercInfo(slot).luclinEyeColor2 = atoi(row[16]); + client->GetMercInfo(slot).luclinBeardColor = atoi(row[17]); + client->GetMercInfo(slot).luclinBeard = atoi(row[18]); + client->GetMercInfo(slot).drakkinHeritage = atoi(row[19]); + client->GetMercInfo(slot).drakkinTattoo = atoi(row[20]); + client->GetMercInfo(slot).drakkinDetails = atoi(row[21]); + } - mysql_free_result(DatasetResult); - } - - safe_delete_array(Query); - } - - return loaded; + return true; } bool ZoneDatabase::LoadCurrentMerc(Client *c) { From b846d89b5dde5385018cfe8e1ebb24f9c6fc1dac Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 21:04:00 -0700 Subject: [PATCH 030/127] LoadCurrentMerc converted to QueryDatabase --- zone/zonedb.cpp | 87 +++++++++++++++++++++++-------------------------- 1 file changed, 41 insertions(+), 46 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 7084d8e81..47381d5af 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1352,60 +1352,55 @@ bool ZoneDatabase::LoadMercInfo(Client *client) { return true; } -bool ZoneDatabase::LoadCurrentMerc(Client *c) { - bool loaded = false; +bool ZoneDatabase::LoadCurrentMerc(Client *client) { - if(c->GetEPP().merc_name[0] != 0) { - std::string errorMessage; - char* Query = 0; - char TempErrorMessageBuffer[MYSQL_ERRMSG_SIZE]; - MYSQL_RES* DatasetResult; - MYSQL_ROW DataRow; - //char name[64]; + if(client->GetEPP().merc_name[0] == 0) + return false; - uint8 slot = c->GetMercSlot(); + uint8 slot = client->GetMercSlot(); - if(slot > MAXMERCS) { - return false; - } + if(slot > MAXMERCS) + return false; - if(!database.RunQuery(Query, MakeAnyLenString(&Query, "SELECT MercID, Name, TemplateID, SuspendedTime, IsSuspended, TimerRemaining, Gender, StanceID, HP, Mana, Endurance, Face, LuclinHairStyle, LuclinHairColor, LuclinEyeColor, LuclinEyeColor2, LuclinBeardColor, LuclinBeard, DrakkinHeritage, DrakkinTattoo, DrakkinDetails FROM mercs WHERE OwnerCharacterID = '%i' AND Slot = '%u'", c->CharacterID(), slot), TempErrorMessageBuffer, &DatasetResult)) { - errorMessage = std::string(TempErrorMessageBuffer); - } - else { - while(DataRow = mysql_fetch_row(DatasetResult)) { - c->GetMercInfo(slot).mercid = atoi(DataRow[0]); - c->GetMercInfo(slot).slot = slot; - snprintf(c->GetMercInfo(slot).merc_name, 64, "%s", std::string(DataRow[1]).c_str()); - c->GetMercInfo(slot).MercTemplateID = atoi(DataRow[2]); - c->GetMercInfo(slot).SuspendedTime = atoi(DataRow[3]); - c->GetMercInfo(slot).IsSuspended = atoi(DataRow[4]) == 1 ? true : false; - c->GetMercInfo(slot).MercTimerRemaining = atoi(DataRow[5]); - c->GetMercInfo(slot).Gender = atoi(DataRow[6]); - c->GetMercInfo(slot).State = atoi(DataRow[7]); - c->GetMercInfo(slot).hp = atoi(DataRow[8]); - c->GetMercInfo(slot).mana = atoi(DataRow[9]); - c->GetMercInfo(slot).endurance = atoi(DataRow[10]); - c->GetMercInfo(slot).face = atoi(DataRow[11]); - c->GetMercInfo(slot).luclinHairStyle = atoi(DataRow[12]); - c->GetMercInfo(slot).luclinHairColor = atoi(DataRow[13]); - c->GetMercInfo(slot).luclinEyeColor = atoi(DataRow[14]); - c->GetMercInfo(slot).luclinEyeColor2 = atoi(DataRow[15]); - c->GetMercInfo(slot).luclinBeardColor = atoi(DataRow[16]); - c->GetMercInfo(slot).luclinBeard = atoi(DataRow[17]); - c->GetMercInfo(slot).drakkinHeritage = atoi(DataRow[18]); - c->GetMercInfo(slot).drakkinTattoo = atoi(DataRow[19]); - c->GetMercInfo(slot).drakkinDetails = atoi(DataRow[20]); - loaded = true; - } + std::string query = StringFormat("SELECT MercID, Name, TemplateID, SuspendedTime, " + "IsSuspended, TimerRemaining, Gender, StanceID, HP, " + "Mana, Endurance, Face, LuclinHairStyle, LuclinHairColor, " + "LuclinEyeColor, LuclinEyeColor2, LuclinBeardColor, " + "LuclinBeard, DrakkinHeritage, DrakkinTattoo, DrakkinDetails " + "FROM mercs WHERE OwnerCharacterID = '%i' AND Slot = '%u'", + client->CharacterID(), slot); + auto results = database.QueryDatabase(query); - mysql_free_result(DatasetResult); - } + if(!results.Success()) + return false; - safe_delete_array(Query); + + for (auto row = results.begin(); row != results.end(); ++row) { + client->GetMercInfo(slot).mercid = atoi(row[0]); + client->GetMercInfo(slot).slot = slot; + snprintf(client->GetMercInfo(slot).merc_name, 64, "%s", row[1]); + client->GetMercInfo(slot).MercTemplateID = atoi(row[2]); + client->GetMercInfo(slot).SuspendedTime = atoi(row[3]); + client->GetMercInfo(slot).IsSuspended = atoi(row[4]) == 1? true: false; + client->GetMercInfo(slot).MercTimerRemaining = atoi(row[5]); + client->GetMercInfo(slot).Gender = atoi(row[6]); + client->GetMercInfo(slot).State = atoi(row[7]); + client->GetMercInfo(slot).hp = atoi(row[8]); + client->GetMercInfo(slot).mana = atoi(row[9]); + client->GetMercInfo(slot).endurance = atoi(row[10]); + client->GetMercInfo(slot).face = atoi(row[11]); + client->GetMercInfo(slot).luclinHairStyle = atoi(row[12]); + client->GetMercInfo(slot).luclinHairColor = atoi(row[13]); + client->GetMercInfo(slot).luclinEyeColor = atoi(row[14]); + client->GetMercInfo(slot).luclinEyeColor2 = atoi(row[15]); + client->GetMercInfo(slot).luclinBeardColor = atoi(row[16]); + client->GetMercInfo(slot).luclinBeard = atoi(row[17]); + client->GetMercInfo(slot).drakkinHeritage = atoi(row[18]); + client->GetMercInfo(slot).drakkinTattoo = atoi(row[19]); + client->GetMercInfo(slot).drakkinDetails = atoi(row[20]); } - return loaded; + return true; } bool ZoneDatabase::SaveMerc(Merc *merc) { From c6e82448b6454488c81505dcd69a20706f6e90b8 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 21:17:17 -0700 Subject: [PATCH 031/127] SaveMerc converted to QueryDatabase --- zone/zonedb.cpp | 101 +++++++++++++++++++++++++++++------------------- 1 file changed, 61 insertions(+), 40 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 47381d5af..9e3c97ee5 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1405,57 +1405,78 @@ bool ZoneDatabase::LoadCurrentMerc(Client *client) { bool ZoneDatabase::SaveMerc(Merc *merc) { Client *owner = merc->GetMercOwner(); - bool Result = false; - std::string errorMessage; - if(!owner) { + if(!owner) return false; - } - - char* Query = 0; - char TempErrorMessageBuffer[MYSQL_ERRMSG_SIZE]; - uint32 affectedRows = 0; if(merc->GetMercID() == 0) { // New merc record uint32 TempNewMercID = 0; - if(!database.RunQuery(Query, MakeAnyLenString(&Query, "INSERT INTO mercs (OwnerCharacterID, Slot, Name, TemplateID, SuspendedTime, IsSuspended, TimerRemaining, Gender, StanceID, HP, Mana, Endurance, Face, LuclinHairStyle, LuclinHairColor, LuclinEyeColor, LuclinEyeColor2, LuclinBeardColor, LuclinBeard, DrakkinHeritage, DrakkinTattoo, DrakkinDetails) VALUES('%u', '%u', '%s', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%i', '%i', '%i', '%i', '%i', '%i', '%i', '%i', '%i', '%i')", merc->GetMercCharacterID(), owner->GetNumMercs(), merc->GetCleanName(), merc->GetMercTemplateID(), owner->GetMercInfo().SuspendedTime, merc->IsSuspended(), owner->GetMercInfo().MercTimerRemaining, merc->GetGender(), merc->GetStance(), merc->GetHP(), merc->GetMana(), merc->GetEndurance(), merc->GetLuclinFace(), merc->GetHairStyle(), merc->GetHairColor(), merc->GetEyeColor1(), merc->GetEyeColor2(), merc->GetBeardColor(), merc->GetBeard(), merc->GetDrakkinHeritage(), merc->GetDrakkinTattoo(), merc->GetDrakkinDetails() ), TempErrorMessageBuffer, 0, &affectedRows, &TempNewMercID)) { - errorMessage = std::string(TempErrorMessageBuffer); + std::string query = StringFormat("INSERT INTO mercs " + "(OwnerCharacterID, Slot, Name, TemplateID, " + "SuspendedTime, IsSuspended, TimerRemaining, " + "Gender, StanceID, HP, Mana, Endurance, Face, " + "LuclinHairStyle, LuclinHairColor, LuclinEyeColor, " + "LuclinEyeColor2, LuclinBeardColor, LuclinBeard, " + "DrakkinHeritage, DrakkinTattoo, DrakkinDetails) " + "VALUES('%u', '%u', '%s', '%u', '%u', '%u', '%u', " + "'%u', '%u', '%u', '%u', '%u', '%i', '%i', '%i', " + "'%i', '%i', '%i', '%i', '%i', '%i', '%i')", + merc->GetMercCharacterID(), owner->GetNumMercs(), + merc->GetCleanName(), merc->GetMercTemplateID(), + owner->GetMercInfo().SuspendedTime, merc->IsSuspended(), + owner->GetMercInfo().MercTimerRemaining, merc->GetGender(), + merc->GetStance(), merc->GetHP(), merc->GetMana(), + merc->GetEndurance(), merc->GetLuclinFace(), + merc->GetHairStyle(), merc->GetHairColor(), merc->GetEyeColor1(), + merc->GetEyeColor2(), merc->GetBeardColor(), + merc->GetBeard(), merc->GetDrakkinHeritage(), + merc->GetDrakkinTattoo(), merc->GetDrakkinDetails()); + auto results = database.QueryDatabase(query); + if(!results.Success()) { + owner->Message(13, results.ErrorMessage().c_str()); + return false; + } else if (results.RowsAffected() != 1) { + owner->Message(13, "Unable to save merc to the database."); + return false; } - else { - merc->SetMercID(TempNewMercID); - Result = true; - } - } - else { - // Update existing merc record - if(!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE mercs SET OwnerCharacterID = '%u', Slot = '%u', Name = '%s', TemplateID = '%u', SuspendedTime = '%u', IsSuspended = '%u', TimerRemaining = '%u', Gender = '%u', StanceID = '%u', HP = '%u', Mana = '%u', Endurance = '%u', Face = '%i', LuclinHairStyle = '%i', LuclinHairColor = '%i', LuclinEyeColor = '%i', LuclinEyeColor2 = '%i', LuclinBeardColor = '%i', LuclinBeard = '%i', DrakkinHeritage = '%i', DrakkinTattoo = '%i', DrakkinDetails = '%i' WHERE MercID = '%u'", merc->GetMercCharacterID(), owner->GetMercSlot(), merc->GetCleanName(), merc->GetMercTemplateID(), owner->GetMercInfo().SuspendedTime, merc->IsSuspended(), owner->GetMercInfo().MercTimerRemaining, merc->GetGender(), merc->GetStance(), merc->GetHP(), merc->GetMana(), merc->GetEndurance(), merc->GetLuclinFace(), merc->GetHairStyle(), merc->GetHairColor(), merc->GetEyeColor1(), merc->GetEyeColor2(), merc->GetBeardColor(), merc->GetBeard(), merc->GetDrakkinHeritage(), merc->GetDrakkinTattoo(), merc->GetDrakkinDetails(), merc->GetMercID()), TempErrorMessageBuffer, 0, &affectedRows)) { - errorMessage = std::string(TempErrorMessageBuffer); - } - else { - Result = true; - //time(&_startTotalPlayTime); - } - } - safe_delete_array(Query); - - if(!errorMessage.empty() || (Result && affectedRows != 1)) { - if(owner && !errorMessage.empty()) - owner->Message(13, errorMessage.c_str()); - else if(owner) - owner->Message(13, std::string("Unable to save merc to the database.").c_str()); - - Result = false; - } - else { - merc->UpdateMercInfo(owner); + merc->SetMercID(TempNewMercID); + merc->UpdateMercInfo(owner); database.SaveMercBuffs(merc); - //database.SaveMercStance(this); - //database.SaveMercTimers(this); + return true; } - return Result; + // Update existing merc record + std::string query = StringFormat("UPDATE mercs SET OwnerCharacterID = '%u', Slot = '%u', " + "Name = '%s', TemplateID = '%u', SuspendedTime = '%u', " + "IsSuspended = '%u', TimerRemaining = '%u', Gender = '%u', " + "StanceID = '%u', HP = '%u', Mana = '%u', Endurance = '%u', " + "Face = '%i', LuclinHairStyle = '%i', LuclinHairColor = '%i', " + "LuclinEyeColor = '%i', LuclinEyeColor2 = '%i', LuclinBeardColor = '%i', " + "LuclinBeard = '%i', DrakkinHeritage = '%i', DrakkinTattoo = '%i', " + "DrakkinDetails = '%i' WHERE MercID = '%u'", + merc->GetMercCharacterID(), owner->GetMercSlot(), merc->GetCleanName(), + merc->GetMercTemplateID(), owner->GetMercInfo().SuspendedTime, + merc->IsSuspended(), owner->GetMercInfo().MercTimerRemaining, + merc->GetGender(), merc->GetStance(), merc->GetHP(), merc->GetMana(), + merc->GetEndurance(), merc->GetLuclinFace(), merc->GetHairStyle(), + merc->GetHairColor(), merc->GetEyeColor1(), merc->GetEyeColor2(), + merc->GetBeardColor(), merc->GetBeard(), merc->GetDrakkinHeritage(), + merc->GetDrakkinTattoo(), merc->GetDrakkinDetails(), merc->GetMercID()); + auto results = database.QueryDatabase(query); + if (!results.Success()) { + owner->Message(13, results.ErrorMessage().c_str()); + return false; + } else if (results.RowsAffected() != 1) { + owner->Message(13, "Unable to save merc to the database."); + return false; + } + + merc->UpdateMercInfo(owner); + database.SaveMercBuffs(merc); + + return true; } void ZoneDatabase::SaveMercBuffs(Merc *merc) { From 5cabe109da6f2472140efc8ce13d452125d05de7 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 21:30:51 -0700 Subject: [PATCH 032/127] SaveMercBuffs converted to QueryDatabase --- zone/zonedb.cpp | 86 ++++++++++++++++++------------------------------- 1 file changed, 31 insertions(+), 55 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 9e3c97ee5..fc92c1254 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1480,66 +1480,42 @@ bool ZoneDatabase::SaveMerc(Merc *merc) { } void ZoneDatabase::SaveMercBuffs(Merc *merc) { + Buffs_Struct *buffs = merc->GetBuffs(); - std::string errorMessage; - char* Query = 0; - char TempErrorMessageBuffer[MYSQL_ERRMSG_SIZE]; - int BuffCount = 0; - int InsertCount = 0; - uint32 buff_count = merc->GetMaxBuffSlots(); - while(BuffCount < BUFF_COUNT) { - if(buffs[BuffCount].spellid > 0 && buffs[BuffCount].spellid != SPELL_UNKNOWN) { - if(InsertCount == 0) { - // Remove any existing buff saves - if(!database.RunQuery(Query, MakeAnyLenString(&Query, "DELETE FROM merc_buffs WHERE MercId = %u", merc->GetMercID()), TempErrorMessageBuffer)) { - errorMessage = std::string(TempErrorMessageBuffer); - safe_delete(Query); - Query = 0; - break; - } - } + // Remove any existing buff saves + std::string query = StringFormat("DELETE FROM merc_buffs WHERE MercId = %u", merc->GetMercID()); + auto results = database.QueryDatabase(query); + if(!results.Success()) { + LogFile->write(EQEMuLog::Error, "Error While Deleting Merc Buffs before save: %s", results.ErrorMessage().c_str()); + return; + } - int IsPersistent = 0; + for (int buffCount = 0; buffCount <= BUFF_COUNT; buffCount++) { + if(buffs[buffCount].spellid == 0 || buffs[buffCount].spellid == SPELL_UNKNOWN) + continue; - if(buffs[BuffCount].persistant_buff) - IsPersistent = 1; - else - IsPersistent = 0; + int IsPersistent = buffs[buffCount].persistant_buff? 1: 0; - if(!database.RunQuery(Query, MakeAnyLenString(&Query, "INSERT INTO merc_buffs (MercId, SpellId, CasterLevel, DurationFormula, " - "TicsRemaining, PoisonCounters, DiseaseCounters, CurseCounters, CorruptionCounters, HitCount, MeleeRune, MagicRune, " - "dot_rune, caston_x, Persistent, caston_y, caston_z, ExtraDIChance) VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %i, %u, %i, %i, %i);", - merc->GetMercID(), buffs[BuffCount].spellid, buffs[BuffCount].casterlevel, spells[buffs[BuffCount].spellid].buffdurationformula, - buffs[BuffCount].ticsremaining, - CalculatePoisonCounters(buffs[BuffCount].spellid) > 0 ? buffs[BuffCount].counters : 0, - CalculateDiseaseCounters(buffs[BuffCount].spellid) > 0 ? buffs[BuffCount].counters : 0, - CalculateCurseCounters(buffs[BuffCount].spellid) > 0 ? buffs[BuffCount].counters : 0, - CalculateCorruptionCounters(buffs[BuffCount].spellid) > 0 ? buffs[BuffCount].counters : 0, - buffs[BuffCount].numhits, buffs[BuffCount].melee_rune, buffs[BuffCount].magic_rune, - buffs[BuffCount].dot_rune, - buffs[BuffCount].caston_x, - IsPersistent, - buffs[BuffCount].caston_y, - buffs[BuffCount].caston_z, - buffs[BuffCount].ExtraDIChance), TempErrorMessageBuffer)) { - errorMessage = std::string(TempErrorMessageBuffer); - safe_delete(Query); - Query = 0; - break; - } - else { - safe_delete(Query); - Query = 0; - InsertCount++; - } - } - - BuffCount++; - } - - if(!errorMessage.empty()) { - LogFile->write(EQEMuLog::Error, "Error Saving Merc Buffs: %s", errorMessage.c_str()); + query = StringFormat("INSERT INTO merc_buffs (MercId, SpellId, CasterLevel, DurationFormula, " + "TicsRemaining, PoisonCounters, DiseaseCounters, CurseCounters, " + "CorruptionCounters, HitCount, MeleeRune, MagicRune, dot_rune, " + "caston_x, Persistent, caston_y, caston_z, ExtraDIChance) " + "VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %i, %u, %i, %i, %i);", + merc->GetMercID(), buffs[buffCount].spellid, buffs[buffCount].casterlevel, + spells[buffs[buffCount].spellid].buffdurationformula, buffs[buffCount].ticsremaining, + CalculatePoisonCounters(buffs[buffCount].spellid) > 0 ? buffs[buffCount].counters : 0, + CalculateDiseaseCounters(buffs[buffCount].spellid) > 0 ? buffs[buffCount].counters : 0, + CalculateCurseCounters(buffs[buffCount].spellid) > 0 ? buffs[buffCount].counters : 0, + CalculateCorruptionCounters(buffs[buffCount].spellid) > 0 ? buffs[buffCount].counters : 0, + buffs[buffCount].numhits, buffs[buffCount].melee_rune, buffs[buffCount].magic_rune, + buffs[buffCount].dot_rune, buffs[buffCount].caston_x, IsPersistent, buffs[buffCount].caston_y, + buffs[buffCount].caston_z, buffs[buffCount].ExtraDIChance); + results = database.QueryDatabase(query); + if(!results.Success()) { + LogFile->write(EQEMuLog::Error, "Error Saving Merc Buffs: %s", results.ErrorMessage().c_str()); + break; + } } } From 17b175daa4e42d4911b0088405a4e9b2109e8386 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 21:46:23 -0700 Subject: [PATCH 033/127] LoadMercBuffs converted to QueryDatabase --- zone/zonedb.cpp | 114 ++++++++++++++++++++++-------------------------- 1 file changed, 51 insertions(+), 63 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index fc92c1254..ff5c4e772 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1522,75 +1522,63 @@ void ZoneDatabase::SaveMercBuffs(Merc *merc) { void ZoneDatabase::LoadMercBuffs(Merc *merc) { Buffs_Struct *buffs = merc->GetBuffs(); uint32 max_slots = merc->GetMaxBuffSlots(); - std::string errorMessage; - char* Query = 0; - char TempErrorMessageBuffer[MYSQL_ERRMSG_SIZE]; - MYSQL_RES* DatasetResult; - MYSQL_ROW DataRow; + bool BuffsLoaded = false; - - if(!database.RunQuery(Query, MakeAnyLenString(&Query, "SELECT SpellId, CasterLevel, DurationFormula, TicsRemaining, PoisonCounters, DiseaseCounters, CurseCounters, CorruptionCounters, HitCount, MeleeRune, MagicRune, dot_rune, caston_x, Persistent, caston_y, caston_z, ExtraDIChance FROM merc_buffs WHERE MercId = %u", merc->GetMercID()), TempErrorMessageBuffer, &DatasetResult)) { - errorMessage = std::string(TempErrorMessageBuffer); - } - else { - int BuffCount = 0; - - while(DataRow = mysql_fetch_row(DatasetResult)) { - if(BuffCount == BUFF_COUNT) - break; - - buffs[BuffCount].spellid = atoi(DataRow[0]); - buffs[BuffCount].casterlevel = atoi(DataRow[1]); - buffs[BuffCount].ticsremaining = atoi(DataRow[3]); - - if(CalculatePoisonCounters(buffs[BuffCount].spellid) > 0) { - buffs[BuffCount].counters = atoi(DataRow[4]); - } else if(CalculateDiseaseCounters(buffs[BuffCount].spellid) > 0) { - buffs[BuffCount].counters = atoi(DataRow[5]); - } else if(CalculateCurseCounters(buffs[BuffCount].spellid) > 0) { - buffs[BuffCount].counters = atoi(DataRow[6]); - } else if(CalculateCorruptionCounters(buffs[BuffCount].spellid) > 0) { - buffs[BuffCount].counters = atoi(DataRow[7]); - } - buffs[BuffCount].numhits = atoi(DataRow[8]); - buffs[BuffCount].melee_rune = atoi(DataRow[9]); - buffs[BuffCount].magic_rune = atoi(DataRow[10]); - buffs[BuffCount].dot_rune = atoi(DataRow[11]); - buffs[BuffCount].caston_x = atoi(DataRow[12]); - buffs[BuffCount].casterid = 0; - - bool IsPersistent = false; - - if(atoi(DataRow[13])) - IsPersistent = true; - - buffs[BuffCount].caston_y = atoi(DataRow[13]); - buffs[BuffCount].caston_z = atoi(DataRow[14]); - buffs[BuffCount].ExtraDIChance = atoi(DataRow[15]); - - buffs[BuffCount].persistant_buff = IsPersistent; - - BuffCount++; - } - - mysql_free_result(DatasetResult); - - BuffsLoaded = true; + std::string query = StringFormat("SELECT SpellId, CasterLevel, DurationFormula, TicsRemaining, " + "PoisonCounters, DiseaseCounters, CurseCounters, CorruptionCounters, " + "HitCount, MeleeRune, MagicRune, dot_rune, caston_x, Persistent, " + "caston_y, caston_z, ExtraDIChance FROM merc_buffs WHERE MercId = %u", + merc->GetMercID()); + auto results = database.QueryDatabase(query); + if(!results.Success()) { + LogFile->write(EQEMuLog::Error, "Error Loading Merc Buffs: %s", results.ErrorMessage().c_str()); + return; } - safe_delete_array(Query); + int buffCount = 0; + for (auto row = results.begin(); row != results.end(); ++row, ++buffCount) { + if(buffCount == BUFF_COUNT) + break; - if(errorMessage.empty() && BuffsLoaded) { - if(!database.RunQuery(Query, MakeAnyLenString(&Query, "DELETE FROM merc_buffs WHERE MercId = %u", merc->GetMercID()), TempErrorMessageBuffer)) { - errorMessage = std::string(TempErrorMessageBuffer); - } - safe_delete_array(Query); - } + buffs[buffCount].spellid = atoi(row[0]); + buffs[buffCount].casterlevel = atoi(row[1]); + buffs[buffCount].ticsremaining = atoi(row[3]); + + if(CalculatePoisonCounters(buffs[buffCount].spellid) > 0) + buffs[buffCount].counters = atoi(row[4]); + + if(CalculateDiseaseCounters(buffs[buffCount].spellid) > 0) + buffs[buffCount].counters = atoi(row[5]); + + if(CalculateCurseCounters(buffs[buffCount].spellid) > 0) + buffs[buffCount].counters = atoi(row[6]); + + if(CalculateCorruptionCounters(buffs[buffCount].spellid) > 0) + buffs[buffCount].counters = atoi(row[7]); + + buffs[buffCount].numhits = atoi(row[8]); + buffs[buffCount].melee_rune = atoi(row[9]); + buffs[buffCount].magic_rune = atoi(row[10]); + buffs[buffCount].dot_rune = atoi(row[11]); + buffs[buffCount].caston_x = atoi(row[12]); + buffs[buffCount].casterid = 0; + + bool IsPersistent = atoi(row[13])? true: false; + + buffs[buffCount].caston_y = atoi(row[13]); + buffs[buffCount].caston_z = atoi(row[14]); + buffs[buffCount].ExtraDIChance = atoi(row[15]); + + buffs[buffCount].persistant_buff = IsPersistent; + + } + + query = StringFormat("DELETE FROM merc_buffs WHERE MercId = %u", merc->GetMercID()); + results = database.QueryDatabase(query); + if(!results.Success()) + LogFile->write(EQEMuLog::Error, "Error Loading Merc Buffs: %s", results.ErrorMessage().c_str()); - if(!errorMessage.empty()) { - LogFile->write(EQEMuLog::Error, "Error Loading Merc Buffs: %s", errorMessage.c_str()); - } } bool ZoneDatabase::DeleteMerc(uint32 merc_id) { From 2fd2cd4cece5f0df370278f716b3aab3539a9b39 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 21:54:28 -0700 Subject: [PATCH 034/127] DeleteMerc converted to QueryDatabase --- zone/zonedb.cpp | 48 +++++++++++++++++------------------------------- 1 file changed, 17 insertions(+), 31 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index ff5c4e772..2bbc3f840 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1582,41 +1582,27 @@ void ZoneDatabase::LoadMercBuffs(Merc *merc) { } bool ZoneDatabase::DeleteMerc(uint32 merc_id) { - std::string errorMessage; - bool Result = false; - int TempCounter = 0; - if(merc_id > 0) { - char* Query = 0; - char TempErrorMessageBuffer[MYSQL_ERRMSG_SIZE]; + if(merc_id == 0) + return false; - // TODO: These queries need to be ran together as a transaction.. ie, if one or more fail then they all will fail to commit to the database. + bool firstQueryWorked = false; + // TODO: These queries need to be ran together as a transaction.. ie, + // if one or more fail then they all will fail to commit to the database. + std::string query = StringFormat("DELETE FROM merc_buffs WHERE MercID = '%u'", merc_id); + auto results = database.QueryDatabase(query); + if(!results.Success()) + LogFile->write(EQEMuLog::Error, "Error Deleting Merc: %s", results.ErrorMessage().c_str()); + else + firstQueryWorked = true; - if(!database.RunQuery(Query, MakeAnyLenString(&Query, "DELETE FROM merc_buffs WHERE MercID = '%u'", merc_id), TempErrorMessageBuffer)) { - errorMessage = std::string(TempErrorMessageBuffer); - } - else - TempCounter++; + query = StringFormat("DELETE FROM mercs WHERE MercID = '%u'", merc_id); + if(!results.Success()) { + LogFile->write(EQEMuLog::Error, "Error Deleting Merc: %s", results.ErrorMessage().c_str()); + return false; + } - safe_delete_array(Query); - - if(!database.RunQuery(Query, MakeAnyLenString(&Query, "DELETE FROM mercs WHERE MercID = '%u'", merc_id), TempErrorMessageBuffer)) { - errorMessage = std::string(TempErrorMessageBuffer); - } - else - TempCounter++; - - safe_delete_array(Query); - - if(TempCounter == 2) - Result = true; - } - - if(!errorMessage.empty()) { - LogFile->write(EQEMuLog::Error, "Error Deleting Merc: %s", errorMessage.c_str()); - } - - return Result; + return firstQueryWorked; } void ZoneDatabase::LoadMercEquipment(Merc *merc) { From 2028a5846ce3ddada170a7cef93544cad1e47af7 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 22:00:00 -0700 Subject: [PATCH 035/127] LoadMercEquipment converted to QueryDatabase --- zone/zonedb.cpp | 49 +++++++++++++++++++++---------------------------- 1 file changed, 21 insertions(+), 28 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 2bbc3f840..25dc8f15c 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1606,38 +1606,31 @@ bool ZoneDatabase::DeleteMerc(uint32 merc_id) { } void ZoneDatabase::LoadMercEquipment(Merc *merc) { - std::string errorMessage; - char* Query = 0; - char TempErrorMessageBuffer[MYSQL_ERRMSG_SIZE]; - MYSQL_RES* DatasetResult; - MYSQL_ROW DataRow; - if(!database.RunQuery(Query, MakeAnyLenString(&Query, "SELECT item_id FROM merc_inventory WHERE merc_subtype_id = (SELECT merc_subtype_id FROM merc_subtypes WHERE class_id = '%u' AND tier_id = '%u') AND min_level <= %u AND max_level >= %u", merc->GetClass(), merc->GetTierID(), merc->GetLevel(), merc->GetLevel()), TempErrorMessageBuffer, &DatasetResult)) { - errorMessage = std::string(TempErrorMessageBuffer); - } - else { - int itemCount = 0; - - while(DataRow = mysql_fetch_row(DatasetResult)) { - if (itemCount == EmuConstants::EQUIPMENT_SIZE) - break; - - if(atoi(DataRow[0]) > 0) { - merc->AddItem(itemCount, atoi(DataRow[0])); - - itemCount++; - } - } - - mysql_free_result(DatasetResult); + std::string query = StringFormat("SELECT item_id FROM merc_inventory " + "WHERE merc_subtype_id = (" + "SELECT merc_subtype_id FROM merc_subtypes " + "WHERE class_id = '%u' AND tier_id = '%u') " + "AND min_level <= %u AND max_level >= %u", + merc->GetClass(), merc->GetTierID(), + merc->GetLevel(), merc->GetLevel()); + auto results = database.QueryDatabase(query); + if(!results.Success()) { + LogFile->write(EQEMuLog::Error, "Error Loading Merc Inventory: %s", results.ErrorMessage().c_str()); + return; } - safe_delete_array(Query); - Query = 0; + int itemCount = 0; + for(auto row = results.begin(); row != results.end(); ++row) { + if (itemCount == EmuConstants::EQUIPMENT_SIZE) + break; - if(!errorMessage.empty()) { - LogFile->write(EQEMuLog::Error, "Error Loading Merc Inventory: %s", errorMessage.c_str()); - } + if(atoi(row[0]) == 0) + continue; + + merc->AddItem(itemCount, atoi(row[0])); + itemCount++; + } } uint8 ZoneDatabase::GetGridType(uint32 grid, uint32 zoneid ) { From 2df66bd625c7a563559c84b0bb0d963df35ad804 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 22:04:40 -0700 Subject: [PATCH 036/127] GetGridType converted to QueryDatabase --- zone/zonedb.cpp | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 25dc8f15c..d28719134 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1634,23 +1634,20 @@ void ZoneDatabase::LoadMercEquipment(Merc *merc) { } uint8 ZoneDatabase::GetGridType(uint32 grid, uint32 zoneid ) { - char *query = 0; - char errbuf[MYSQL_ERRMSG_SIZE]; - MYSQL_RES *result; - MYSQL_ROW row; - int type = 0; - if (RunQuery(query, MakeAnyLenString(&query,"SELECT type from grid where id = %i and zoneid = %i",grid,zoneid),errbuf,&result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - type = atoi( row[0] ); - } - mysql_free_result(result); - } else { - std::cerr << "Error in GetGridType query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + + std::string query = StringFormat("SELECT type FROM grid WHERE id = %i AND zoneid = %i", grid, zoneid); + auto results = QueryDatabase(query); + if (!results.Success()) { + std::cerr << "Error in GetGridType query '" << query << "' " << results.ErrorMessage() << std::endl; + return 0; } - return type; + + if (results.RowCount() != 1) + return 0; + + auto row = results.begin(); + + return atoi(row[0]); } From e25f64d03b6ed9a27762e94cc4566d927c2a42e2 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 22:06:56 -0700 Subject: [PATCH 037/127] SaveMerchantTemp converted to QueryDatabase --- zone/zonedb.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index d28719134..6c291bc00 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1650,17 +1650,15 @@ uint8 ZoneDatabase::GetGridType(uint32 grid, uint32 zoneid ) { return atoi(row[0]); } - - void ZoneDatabase::SaveMerchantTemp(uint32 npcid, uint32 slot, uint32 item, uint32 charges){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - if (!RunQuery(query, MakeAnyLenString(&query, "replace into merchantlist_temp (npcid,slot,itemid,charges) values(%d,%d,%d,%d)", npcid, slot, item, charges), errbuf)) { - std::cerr << "Error in SaveMerchantTemp query '" << query << "' " << errbuf << std::endl; - } - safe_delete_array(query); + std::string query = StringFormat("REPLACE INTO merchantlist_temp (npcid, slot, itemid, charges) " + "VALUES(%d, %d, %d, %d)", npcid, slot, item, charges); + auto results = QueryDatabase(query); + if (!results.Success()) + std::cerr << "Error in SaveMerchantTemp query '" << query << "' " << results.ErrorMessage() << std::endl; } + void ZoneDatabase::DeleteMerchantTemp(uint32 npcid, uint32 slot){ char errbuf[MYSQL_ERRMSG_SIZE]; char *query = 0; From 909ca5440dd149b3cd1449be534ef0c52d230ef5 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 22:11:14 -0700 Subject: [PATCH 038/127] UpdateZoneSafeCoords converted to QueryDatabase --- zone/zonedb.cpp | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 6c291bc00..fd1b1649c 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1660,31 +1660,21 @@ void ZoneDatabase::SaveMerchantTemp(uint32 npcid, uint32 slot, uint32 item, uint } void ZoneDatabase::DeleteMerchantTemp(uint32 npcid, uint32 slot){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - if (!RunQuery(query, MakeAnyLenString(&query, "delete from merchantlist_temp where npcid=%d and slot=%d", npcid, slot), errbuf)) { - std::cerr << "Error in DeleteMerchantTemp query '" << query << "' " << errbuf << std::endl; - } - safe_delete_array(query); + std::string query = StringFormat("DELETE FROM merchantlist_temp WHERE npcid=%d AND slot=%d", npcid, slot); + auto results = QueryDatabase(query); + if (!results.Success()) + std::cerr << "Error in DeleteMerchantTemp query '" << query << "' " << results.ErrorMessage() << std::endl; + } - bool ZoneDatabase::UpdateZoneSafeCoords(const char* zonename, float x=0, float y=0, float z=0) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE zone SET safe_x='%f', safe_y='%f', safe_z='%f' WHERE short_name='%s';", x, y, z, zonename), errbuf, 0, &affected_rows)) { - safe_delete_array(query); + std::string query = StringFormat("UPDATE zone SET safe_x='%f', safe_y='%f', safe_z='%f' " + "WHERE short_name='%s';", x, y, z, zonename); + auto results = QueryDatabase(query); + if (!results.Success() || results.RowsAffected() == 0) return false; - } - safe_delete_array(query); - - if (affected_rows == 0) - { - return false; - } return true; } From babaff1985d45444c2e71d68efbe5bb09592fa67 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 22:14:40 -0700 Subject: [PATCH 039/127] GetUseCFGSafeCoords converted to QueryDatabase --- zone/zonedb.cpp | 39 ++++++++++----------------------------- 1 file changed, 10 insertions(+), 29 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index fd1b1649c..ea709b3c9 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1679,40 +1679,21 @@ bool ZoneDatabase::UpdateZoneSafeCoords(const char* zonename, float x=0, float y return true; } - uint8 ZoneDatabase::GetUseCFGSafeCoords() { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT value FROM variables WHERE varname='UseCFGSafeCoords'"), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) - { - row = mysql_fetch_row(result); - - uint8 usecoords = atoi(row[0]); - mysql_free_result(result); - return usecoords; - } - else - { - mysql_free_result(result); - return 0; - } - mysql_free_result(result); - } - else - { - - std::cerr << "Error in GetUseCFGSafeCoords query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return false; + const std::string query = "SELECT value FROM variables WHERE varname='UseCFGSafeCoords'"; + auto results = QueryDatabase(query); + if (!results.Success()) { + std::cerr << "Error in GetUseCFGSafeCoords query '" << query << "' " << results.ErrorMessage() << std::endl; + return 0; } - return 0; + if (results.RowCount() != 1) + return 0; + auto row = results.begin(); + + return atoi(row[0]); } From fe600bb0844448e6baa50b98963c6b8c89a61e49 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 23:07:19 -0700 Subject: [PATCH 040/127] Removed Get/SetServerFilters, unused and unsupported --- zone/zonedb.cpp | 80 ------------------------------------------------- zone/zonedb.h | 2 -- 2 files changed, 82 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index ea709b3c9..0a10e1401 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1696,86 +1696,6 @@ uint8 ZoneDatabase::GetUseCFGSafeCoords() return atoi(row[0]); } - -uint32 ZoneDatabase::GetServerFilters(char* name, ServerSideFilters_Struct *ssfs) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - - MYSQL_ROW row; - - - unsigned long* lengths; - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT serverfilters FROM account WHERE name='%s'", name), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - lengths = mysql_fetch_lengths(result); - if (lengths[0] == sizeof(ServerSideFilters_Struct)) { - memcpy(ssfs, row[0], sizeof(ServerSideFilters_Struct)); - } - else { - std::cerr << "Player profile length mismatch in ServerSideFilters" << std::endl; - mysql_free_result(result); - return 0; - } - } - else { - mysql_free_result(result); - return 0; - - } - uint32 len = lengths[0]; - mysql_free_result(result); - return len; - } - else { - std::cerr << "Error in ServerSideFilters query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return 0; - } - - return 0; -} - -bool ZoneDatabase::SetServerFilters(char* name, ServerSideFilters_Struct *ssfs) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char query[256+sizeof(ServerSideFilters_Struct)*2+1]; - char* end = query; - - //if (strlen(name) > 15) - // return false; - - /*for (int i=0; i 'z') && - (name[i] < 'A' || name[i] > 'Z') && - (name[i] < '0' || name[i] > '9')) - return 0; -}*/ - - - end += sprintf(end, "UPDATE account SET serverfilters="); - *end++ = '\''; - end += DoEscapeString(end, (char*)ssfs, sizeof(ServerSideFilters_Struct)); - *end++ = '\''; - end += sprintf(end," WHERE name='%s'", name); - - uint32 affected_rows = 0; - if (!RunQuery(query, (uint32) (end - query), errbuf, 0, &affected_rows)) { - std::cerr << "Error in SetServerSideFilters query " << errbuf << std::endl; - return false; - } - - if (affected_rows == 0) { - return false; - } - - return true; -} - - //New functions for timezone uint32 ZoneDatabase::GetZoneTZ(uint32 zoneid, uint32 version) { char errbuf[MYSQL_ERRMSG_SIZE]; diff --git a/zone/zonedb.h b/zone/zonedb.h index 22aa0eba4..3a7881d44 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -246,8 +246,6 @@ public: /* * General Character Related Stuff */ - bool SetServerFilters(char* name, ServerSideFilters_Struct *ssfs); - uint32 GetServerFilters(char* name, ServerSideFilters_Struct *ssfs); bool GetAccountInfoForLogin(uint32 account_id, int16* admin = 0, char* account_name = 0, uint32* lsaccountid = 0, uint8* gmspeed = 0, bool* revoked = 0, bool* gmhideme = 0); bool GetAccountInfoForLogin_result(MYSQL_RES* result, int16* admin = 0, char* account_name = 0, From 8525d819c1e9c81dad2933b6c1f97fcd13cb775f Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 23:13:59 -0700 Subject: [PATCH 041/127] GetZoneTZ converted to QueryDatabase --- zone/zonedb.cpp | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 0a10e1401..7718dbda4 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1698,27 +1698,21 @@ uint8 ZoneDatabase::GetUseCFGSafeCoords() //New functions for timezone uint32 ZoneDatabase::GetZoneTZ(uint32 zoneid, uint32 version) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT timezone FROM zone WHERE zoneidnumber=%i AND (version=%i OR version=0) ORDER BY version DESC", zoneid, version), errbuf, &result)) - { - safe_delete_array(query); - if (mysql_num_rows(result) > 0) { - row = mysql_fetch_row(result); - uint32 tmp = atoi(row[0]); - mysql_free_result(result); - return tmp; - } - mysql_free_result(result); - } - else { - std::cerr << "Error in GetZoneTZ query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - } - return 0; + std::string query = StringFormat("SELECT timezone FROM zone WHERE zoneidnumber = %i " + "AND (version = %i OR version = 0) ORDER BY version DESC", + zoneid, version); + auto results = QueryDatabase(query); + if (!results.Success()) { + std::cerr << "Error in GetZoneTZ query '" << query << "' " << results.ErrorMessage() << std::endl; + return 0; + } + + if (results.RowCount() == 0) + return 0; + + auto row = results.begin(); + return atoi(row[0]); } bool ZoneDatabase::SetZoneTZ(uint32 zoneid, uint32 version, uint32 tz) { From e79747c91995511a5872dae49930846857b984aa Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 20 Aug 2014 23:26:41 -0700 Subject: [PATCH 042/127] SetZoneTZ converted to QueryDatabase --- zone/zonedb.cpp | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 7718dbda4..b76fd6c5f 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1716,27 +1716,18 @@ uint32 ZoneDatabase::GetZoneTZ(uint32 zoneid, uint32 version) { } bool ZoneDatabase::SetZoneTZ(uint32 zoneid, uint32 version, uint32 tz) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; - if (RunQuery(query, MakeAnyLenString(&query, "UPDATE zone SET timezone=%i WHERE zoneidnumber=%i AND version=%i", tz, zoneid, version), errbuf, 0, &affected_rows)) { - safe_delete_array(query); - - if (affected_rows == 1) - return true; - else - return false; - } - else { - std::cerr << "Error in SetZoneTZ query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + std::string query = StringFormat("UPDATE zone SET timezone = %i " + "WHERE zoneidnumber = %i AND version = %i", + tz, zoneid, version); + auto results = QueryDatabase(query); + if (!results.Success()) { + std::cerr << "Error in SetZoneTZ query '" << query << "' " << results.ErrorMessage() << std::endl; return false; - } + } - return false; + return results.RowsAffected() == 1; } -//End new timezone functions. /* solar: this is never actually called, client_process starts an async query From 8441ffda3130e90ce073037b6b5e88044677335c Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 21 Aug 2014 11:52:15 -0700 Subject: [PATCH 043/127] GetAccountInfoForLogin removed, unused, unsupported --- zone/zonedb.cpp | 25 ------------------------- zone/zonedb.h | 2 -- 2 files changed, 27 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index b76fd6c5f..b7e4c5339 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1729,31 +1729,6 @@ bool ZoneDatabase::SetZoneTZ(uint32 zoneid, uint32 version, uint32 tz) { return results.RowsAffected() == 1; } -/* - solar: this is never actually called, client_process starts an async query - instead and uses GetAccountInfoForLogin_result to process it.. - */ -bool ZoneDatabase::GetAccountInfoForLogin(uint32 account_id, int16* admin, char* account_name, uint32* lsaccountid, uint8* gmspeed, bool* revoked,bool* gmhideme) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT status, name, lsaccount_id, gmspeed, revoked, hideme FROM account WHERE id=%i", account_id), errbuf, &result)) { - safe_delete_array(query); - bool ret = GetAccountInfoForLogin_result(result, admin, account_name, lsaccountid, gmspeed, revoked,gmhideme); - mysql_free_result(result); - return ret; - } - else - { - std::cerr << "Error in GetAccountInfoForLogin query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return false; - } - - return false; -} - void ZoneDatabase::RefreshGroupFromDB(Client *c){ if(!c){ return; diff --git a/zone/zonedb.h b/zone/zonedb.h index 3a7881d44..ae58bb596 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -246,8 +246,6 @@ public: /* * General Character Related Stuff */ - bool GetAccountInfoForLogin(uint32 account_id, int16* admin = 0, char* account_name = 0, - uint32* lsaccountid = 0, uint8* gmspeed = 0, bool* revoked = 0, bool* gmhideme = 0); bool GetAccountInfoForLogin_result(MYSQL_RES* result, int16* admin = 0, char* account_name = 0, uint32* lsaccountid = 0, uint8* gmspeed = 0, bool* revoked = 0, bool* gmhideme = nullptr, uint32* account_creation = 0); From 351a7a52fe50badf8d20e28aad160c8d865803bc Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 21 Aug 2014 12:01:22 -0700 Subject: [PATCH 044/127] GetCharacterInfoForLogin removed, unused, unsupported --- zone/zonedb.cpp | 33 --------------------------------- zone/zonedb.h | 4 ---- 2 files changed, 37 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index b7e4c5339..ee7d3a62f 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -785,39 +785,6 @@ void ZoneDatabase::UpdateBuyLine(uint32 CharID, uint32 BuySlot, uint32 Quantity) } -bool ZoneDatabase::GetCharacterInfoForLogin(const char* name, uint32* character_id, -char* current_zone, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, -uint32* pplen, uint32* guilddbid, uint8* guildrank, -uint8 *class_, uint8 *level, bool *LFP, bool *LFG, uint8 *NumXTargets, uint8 *firstlogon) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 querylen; - MYSQL_RES *result; - - bool ret = false; - - //DO NOT FORGET TO EDIT Client::Handle_Connect_OP_ZoneEntry if you change this. - - if (character_id && *character_id) { - // searching by ID should be a lil bit faster - querylen = MakeAnyLenString(&query, "SELECT id,profile,zonename,x,y,z,guild_id,rank,extprofile,class,level,lfp,lfg,instanceid,xtargets,firstlogon FROM character_ LEFT JOIN guild_members ON id=char_id WHERE id=%i", *character_id); - } - else { - querylen = MakeAnyLenString(&query, "SELECT id,profile,zonename,x,y,z,guild_id,rank,extprofile,class,level,lfp,lfg,instanceid,xtargets,firstlogon FROM character_ LEFT JOIN guild_members ON id=char_id WHERE name='%s'", name); - } - - if (RunQuery(query, querylen, errbuf, &result)) { - ret = GetCharacterInfoForLogin_result(result, character_id, current_zone, pp, inv, ext, pplen, guilddbid, guildrank, class_, level, LFP, LFG, NumXTargets, firstlogon); - mysql_free_result(result); - } - else { - LogFile->write(EQEMuLog::Error, "GetCharacterInfoForLogin query '%s' %s", query, errbuf); - } - - safe_delete_array(query); - return ret; -} - #define StructDist(in, f1, f2) (uint32(&in->f2)-uint32(&in->f1)) // Process results of GetCharacterInfoForLogin() diff --git a/zone/zonedb.h b/zone/zonedb.h index ae58bb596..cab3e84a9 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -253,10 +253,6 @@ public: PlayerProfile_Struct* pp = 0, Inventory* inv = 0, ExtendedProfile_Struct *ext = 0, uint32* pplen = 0, uint32* guilddbid = 0, uint8* guildrank = 0, uint8 *class_= 0, uint8 *level = 0, bool *LFP = 0, bool *LFG = 0, uint8 *NumXTargets = 0, uint8* firstlogon = 0); - bool GetCharacterInfoForLogin(const char* name, uint32* character_id = 0, char* current_zone = 0, - PlayerProfile_Struct* pp = 0, Inventory* inv = 0, ExtendedProfile_Struct *ext = 0, uint32* pplen = 0, - uint32* guilddbid = 0, uint8* guildrank = 0, uint8 *class_ = 0, uint8 *level = 0, bool *LFP = 0, - bool *LFG = 0, uint8 *NumXTargets = 0, uint8* firstlogon = 0); void SaveBuffs(Client *c); void LoadBuffs(Client *c); void LoadPetInfo(Client *c); From fbefad9eafbb17cfe88f8ce9b204c0cd1c43db66 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 21 Aug 2014 12:25:32 -0700 Subject: [PATCH 045/127] RefreshGroupFromDB converted to QueryDatabase --- zone/zonedb.cpp | 73 ++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 40 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index ee7d3a62f..6a4633dc9 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1696,62 +1696,55 @@ bool ZoneDatabase::SetZoneTZ(uint32 zoneid, uint32 version, uint32 tz) { return results.RowsAffected() == 1; } -void ZoneDatabase::RefreshGroupFromDB(Client *c){ - if(!c){ +void ZoneDatabase::RefreshGroupFromDB(Client *client){ + if(!client) return; - } - Group *g = c->GetGroup(); + Group *group = client->GetGroup(); - if(!g){ + if(!group) return; - } EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupUpdate2_Struct)); GroupUpdate2_Struct* gu = (GroupUpdate2_Struct*)outapp->pBuffer; gu->action = groupActUpdate; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - strcpy(gu->yourname, c->GetName()); - GetGroupLeadershipInfo(g->GetID(), gu->leadersname, nullptr, nullptr, nullptr, nullptr, &gu->leader_aas); - gu->NPCMarkerID = g->GetNPCMarkerID(); + strcpy(gu->yourname, client->GetName()); + GetGroupLeadershipInfo(group->GetID(), gu->leadersname, nullptr, nullptr, nullptr, nullptr, &gu->leader_aas); + gu->NPCMarkerID = group->GetNPCMarkerID(); int index = 0; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT name from group_id where groupid=%d", g->GetID()), errbuf, &result)) { - while((row = mysql_fetch_row(result))){ - if(index < 6){ - if(strcmp(c->GetName(), row[0]) != 0){ - strcpy(gu->membername[index], row[0]); - index++; - } - } - } - mysql_free_result(result); - } - else - { - printf("Error in group update query: %s\n", errbuf); - } - safe_delete_array(query); - c->QueuePacket(outapp); + std::string query = StringFormat("SELECT name FROM group_id WHERE groupid = %d", group->GetID()); + auto results = QueryDatabase(query); + if (!results.Success()) + printf("Error in group update query: %s\n", results.ErrorMessage().c_str()); + else + for (auto row = results.begin(); row != results.end(); ++row) { + if(index >= 6) + continue; + + if(strcmp(client->GetName(), row[0]) == 0) + continue; + + strcpy(gu->membername[index], row[0]); + index++; + } + + client->QueuePacket(outapp); safe_delete(outapp); - if(c->GetClientVersion() >= EQClientSoD) { - g->NotifyMainTank(c, 1); - g->NotifyPuller(c, 1); + if(client->GetClientVersion() >= EQClientSoD) { + group->NotifyMainTank(client, 1); + group->NotifyPuller(client, 1); } - g->NotifyMainAssist(c, 1); - - g->NotifyMarkNPC(c); - g->NotifyAssistTarget(c); - g->NotifyTankTarget(c); - g->NotifyPullerTarget(c); - g->SendMarkedNPCsToMember(c); + group->NotifyMainAssist(client, 1); + group->NotifyMarkNPC(client); + group->NotifyAssistTarget(client); + group->NotifyTankTarget(client); + group->NotifyPullerTarget(client); + group->SendMarkedNPCsToMember(client); } From 0ece5bf178d554023f7a948293d1dd84fff38541 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 21 Aug 2014 12:30:06 -0700 Subject: [PATCH 046/127] GroupCount converted to QueryDatabase --- zone/zonedb.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 6a4633dc9..3bfec9adf 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1748,21 +1748,21 @@ void ZoneDatabase::RefreshGroupFromDB(Client *client){ } -uint8 ZoneDatabase::GroupCount(uint32 groupid){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - uint8 count=0; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT count(charid) FROM group_id WHERE groupid=%d", groupid), errbuf, &result)) { - if((row = mysql_fetch_row(result))!=nullptr) - count = atoi(row[0]); - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::GroupCount query '%s': %s", query, errbuf); - } - safe_delete_array(query); - return count; +uint8 ZoneDatabase::GroupCount(uint32 groupid) { + + std::string query = StringFormat("SELECT count(charid) FROM group_id WHERE groupid = %d", groupid); + auto results = QueryDatabase(query); + if (!results.Success()) { + LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::GroupCount query '%s': %s", query.c_str(), results.ErrorMessage().c_str()); + return 0; + } + + if (results.RowCount() == 0) + return 0; + + auto row = results.begin(); + + return atoi(row[0]); } uint8 ZoneDatabase::RaidGroupCount(uint32 raidid, uint32 groupid) From a3bde6e1f183c10aa310b9830d1826c8c27cbd22 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 21 Aug 2014 12:35:33 -0700 Subject: [PATCH 047/127] RaidGroupCount converted to QueryDatabase --- zone/zonedb.cpp | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 3bfec9adf..447d1f94e 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1765,22 +1765,23 @@ uint8 ZoneDatabase::GroupCount(uint32 groupid) { return atoi(row[0]); } - uint8 ZoneDatabase::RaidGroupCount(uint32 raidid, uint32 groupid) - { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - uint8 count=0; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT count(charid) FROM raid_members WHERE raidid=%d AND groupid=%d;", raidid, groupid), errbuf, &result)) { - if((row = mysql_fetch_row(result))!=nullptr) - count = atoi(row[0]); - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::RaidGroupCount query '%s': %s", query, errbuf); - } - safe_delete_array(query); - return count; +uint8 ZoneDatabase::RaidGroupCount(uint32 raidid, uint32 groupid) { + + std::string query = StringFormat("SELECT count(charid) FROM raid_members " + "WHERE raidid = %d AND groupid = %d;", raidid, groupid); + auto results = QueryDatabase(query); + + if (!results.Success()) { + LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::RaidGroupCount query '%s': %s", query.c_str(), results.ErrorMessage().c_str()); + return 0; + } + + if (results.RowCount() == 0) + return 0; + + auto row = results.begin(); + + return atoi(row[0]); } int32 ZoneDatabase::GetBlockedSpellsCount(uint32 zoneid) From 5839921e08fea6334794b29092491b5aa1e37f3a Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 21 Aug 2014 12:39:38 -0700 Subject: [PATCH 048/127] GetBlockedSpellsCount converted to QueryDatabase --- zone/zonedb.cpp | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 447d1f94e..e0abc51c5 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1786,30 +1786,19 @@ uint8 ZoneDatabase::RaidGroupCount(uint32 raidid, uint32 groupid) { int32 ZoneDatabase::GetBlockedSpellsCount(uint32 zoneid) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - - MYSQL_RES *result; - MYSQL_ROW row; - query = new char[256]; - sprintf(query, "SELECT count(*) FROM blocked_spells WHERE zoneid=%d", zoneid); - if (RunQuery(query, strlen(query), errbuf, &result)) { - safe_delete_array(query); - row = mysql_fetch_row(result); - if (row != nullptr && row[0] != 0) { - int32 ret = atoi(row[0]); - mysql_free_result(result); - return ret; - } - mysql_free_result(result); - } - else { - std::cerr << "Error in GetBlockedSpellsCount query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + std::string query = StringFormat("SELECT count(*) FROM blocked_spells WHERE zoneid = %d", zoneid); + auto results = QueryDatabase(query); + if (!results.Success()) { + std::cerr << "Error in GetBlockedSpellsCount query '" << query << "' " << results.ErrorMessage() << std::endl; return -1; } - return -1; + if (results.RowCount() == 0) + return -1; + + auto row = results.begin(); + + return atoi(row[0]); } bool ZoneDatabase::LoadBlockedSpells(int32 blockedSpellsCount, ZoneSpellsBlocked* into, uint32 zoneid) From 699c8cc1eba5b230f03668e52262be85aecd30da Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 21 Aug 2014 12:46:52 -0700 Subject: [PATCH 049/127] LoadBlockedSpells converted to QueryDatabase --- zone/zonedb.cpp | 64 ++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 35 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index e0abc51c5..0cd0aae9b 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1805,42 +1805,36 @@ bool ZoneDatabase::LoadBlockedSpells(int32 blockedSpellsCount, ZoneSpellsBlocked { LogFile->write(EQEMuLog::Status, "Loading Blocked Spells from database..."); - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - - MakeAnyLenString(&query, "SELECT id, spellid, type, x, y, z, x_diff, y_diff, z_diff, message " - "FROM blocked_spells WHERE zoneid=%d ORDER BY id asc", zoneid); - if (RunQuery(query, strlen(query), errbuf, &result)) { - safe_delete_array(query); - int32 r; - for(r = 0; (row = mysql_fetch_row(result)); r++) { - if(r >= blockedSpellsCount) { - std::cerr << "Error, Blocked Spells Count of " << blockedSpellsCount << " exceeded." << std::endl; - break; - } - memset(&into[r], 0, sizeof(ZoneSpellsBlocked)); - if(row){ - into[r].spellid = atoi(row[1]); - into[r].type = atoi(row[2]); - into[r].x = atof(row[3]); - into[r].y = atof(row[4]); - into[r].z = atof(row[5]); - into[r].xdiff = atof(row[6]); - into[r].ydiff = atof(row[7]); - into[r].zdiff = atof(row[8]); - strn0cpy(into[r].message, row[9], 255); - } - } - mysql_free_result(result); - } - else - { - std::cerr << "Error in LoadBlockedSpells query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + std::string query = StringFormat("SELECT id, spellid, type, x, y, z, x_diff, y_diff, z_diff, message " + "FROM blocked_spells WHERE zoneid = %d ORDER BY id ASC", zoneid); + auto results = QueryDatabase(query); + if (!results.Success()) { + std::cerr << "Error in LoadBlockedSpells query '" << query << "' " << results.ErrorMessage() << std::endl; return false; - } + } + + if (results.RowCount() == 0) + return true; + + int32 index = 0; + for(auto row = results.begin(); row != results.end(); ++row, ++index) { + if(index >= blockedSpellsCount) { + std::cerr << "Error, Blocked Spells Count of " << blockedSpellsCount << " exceeded." << std::endl; + break; + } + + memset(&into[index], 0, sizeof(ZoneSpellsBlocked)); + into[index].spellid = atoi(row[1]); + into[index].type = atoi(row[2]); + into[index].x = atof(row[3]); + into[index].y = atof(row[4]); + into[index].z = atof(row[5]); + into[index].xdiff = atof(row[6]); + into[index].ydiff = atof(row[7]); + into[index].zdiff = atof(row[8]); + strn0cpy(into[index].message, row[9], 255); + } + return true; } From 765eaf7f4f69107b4b6a5a52ceab87298305fcff Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 21 Aug 2014 12:51:09 -0700 Subject: [PATCH 050/127] getZoneShutDownDelay converted to QueryDatabase --- zone/zonedb.cpp | 40 +++++++++++++++------------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 0cd0aae9b..815e0fa04 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1840,33 +1840,23 @@ bool ZoneDatabase::LoadBlockedSpells(int32 blockedSpellsCount, ZoneSpellsBlocked int ZoneDatabase::getZoneShutDownDelay(uint32 zoneID, uint32 version) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + std::string query = StringFormat("SELECT shutdowndelay FROM zone " + "WHERE zoneidnumber = %i AND (version=%i OR version=0) " + "ORDER BY version DESC", zoneID, version); + auto results = QueryDatabase(query); + if (!results.Success()) { + std::cerr << "Error in getZoneShutDownDelay query '" << query << "' " << results.ErrorMessage().c_str() << std::endl; + return (RuleI(Zone, AutoShutdownDelay)); + } - if (RunQuery(query, MakeAnyLenString(&query, "SELECT shutdowndelay FROM zone WHERE zoneidnumber=%i AND (version=%i OR version=0) ORDER BY version DESC", zoneID, version), errbuf, &result)) - { - if (mysql_num_rows(result) > 0) { - row = mysql_fetch_row(result); - int retVal = atoi(row[0]); + if (results.RowCount() == 0) { + std::cerr << "Error in getZoneShutDownDelay no result '" << query << "' " << std::endl; + return (RuleI(Zone, AutoShutdownDelay)); + } - mysql_free_result(result); - safe_delete_array(query); - return (retVal); - } - else { - std::cerr << "Error in getZoneShutDownDelay no result '" << query << "' " << errbuf << std::endl; - mysql_free_result(result); - safe_delete_array(query); - return (RuleI(Zone, AutoShutdownDelay)); - } - } - else { - std::cerr << "Error in getZoneShutDownDelay query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - } - return (RuleI(Zone, AutoShutdownDelay)); + auto row = results.begin(); + + return atoi(row[0]); } uint32 ZoneDatabase::GetKarma(uint32 acct_id) From e8c92c6fcc1f29be38b97726243173ef07d7641a Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 21 Aug 2014 13:06:33 -0700 Subject: [PATCH 051/127] GetKarma converted to QueryDatabase --- zone/zonedb.cpp | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 815e0fa04..dd4960f60 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1861,27 +1861,14 @@ int ZoneDatabase::getZoneShutDownDelay(uint32 zoneID, uint32 version) uint32 ZoneDatabase::GetKarma(uint32 acct_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - uint32 ret_val = 0; - - if (!RunQuery(query,MakeAnyLenString(&query, "select `karma` from `account` where `id`='%i' limit 1", - acct_id),errbuf,&result)) - { - safe_delete_array(query); + std::string query = StringFormat("SELECT `karma` FROM `account` WHERE `id` = '%i' LIMIT 1", acct_id); + auto results = QueryDatabase(query); + if (!results.Success()) return 0; - } - safe_delete_array(query); - row = mysql_fetch_row(result); + auto row = results.begin(); - ret_val = atoi(row[0]); - - mysql_free_result(result); - - return ret_val; + return atoi(row[0]); } void ZoneDatabase::UpdateKarma(uint32 acct_id, uint32 amount) From 46c9fe46e946018183dafc6826a0ed989fc39c9b Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 21 Aug 2014 13:08:57 -0700 Subject: [PATCH 052/127] UpdateKarma converted to QueryDatabase --- zone/zonedb.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index dd4960f60..80ec01038 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1873,16 +1873,11 @@ uint32 ZoneDatabase::GetKarma(uint32 acct_id) void ZoneDatabase::UpdateKarma(uint32 acct_id, uint32 amount) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; + std::string query = StringFormat("UPDATE account SET karma = %i WHERE id = %i", amount, acct_id); + auto results = QueryDatabase(query); + if (!results.Success()) + std::cerr << "Error in UpdateKarma query '" << query << "' " << results.ErrorMessage().c_str() << std::endl; - if (RunQuery(query, MakeAnyLenString(&query, "UPDATE account set karma=%i where id=%i", amount, acct_id), errbuf, 0, &affected_rows)){ - safe_delete_array(query);} - else { - std::cerr << "Error in UpdateKarma query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - } } void ZoneDatabase::ListAllInstances(Client* c, uint32 charid) From aab5ed226762f7639815b4aa0a3d81536f9aa93b Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 21 Aug 2014 13:19:37 -0700 Subject: [PATCH 053/127] ListAllInstances converted to QueryDatabase --- zone/zonedb.cpp | 42 ++++++++++++++++-------------------------- 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 80ec01038..5f2a746f5 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1880,38 +1880,28 @@ void ZoneDatabase::UpdateKarma(uint32 acct_id, uint32 amount) } -void ZoneDatabase::ListAllInstances(Client* c, uint32 charid) +void ZoneDatabase::ListAllInstances(Client* client, uint32 charid) { - if(!c) + if(!client) return; - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + std::string query = StringFormat("SELECT instance_list.id, zone, version " + "FROM instance_list JOIN instance_list_player " + "ON instance_list.id = instance_list_player.id " + "WHERE instance_list_player.charid = %lu", + (unsigned long)charid); + auto results = QueryDatabase(query); + if (!results.Success()) + return; + char name[64]; + database.GetCharName(charid, name); + client->Message(0, "%s is part of the following instances:", name); - if (RunQuery(query,MakeAnyLenString(&query, "SELECT instance_list.id, zone, version FROM instance_list JOIN" - " instance_list_player ON instance_list.id = instance_list_player.id" - " WHERE instance_list_player.charid=%lu", (unsigned long)charid),errbuf,&result)) - { - safe_delete_array(query); - - char name[64]; - database.GetCharName(charid, name); - c->Message(0, "%s is part of the following instances:", name); - while(row = mysql_fetch_row(result)) - { - c->Message(0, "%s - id: %lu, version: %lu", database.GetZoneName(atoi(row[1])), + for (auto row = results.begin(); row != results.end(); ++row) { + client->Message(0, "%s - id: %lu, version: %lu", database.GetZoneName(atoi(row[1])), (unsigned long)atoi(row[0]), (unsigned long)atoi(row[2])); - } - - mysql_free_result(result); - } - else - { - safe_delete_array(query); - } + } } void ZoneDatabase::QGlobalPurge() From b497b07fedfaa90548fcd639e684e571cbb0faf6 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 21 Aug 2014 13:22:21 -0700 Subject: [PATCH 054/127] QGlobalPurge converted to QueryDatabase --- zone/zonedb.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 5f2a746f5..7623ccc39 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1906,11 +1906,8 @@ void ZoneDatabase::ListAllInstances(Client* client, uint32 charid) void ZoneDatabase::QGlobalPurge() { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - database.RunQuery(query, MakeAnyLenString(&query, "DELETE FROM quest_globals WHERE expdate < UNIX_TIMESTAMP()"), - errbuf); - safe_delete_array(query); + const std::string query = "DELETE FROM quest_globals WHERE expdate < UNIX_TIMESTAMP()"; + database.QueryDatabase(query); } void ZoneDatabase::InsertDoor(uint32 ddoordbid, uint16 ddoorid, const char* ddoor_name, float dxpos, float dypos, float dzpos, float dheading, uint8 dopentype, uint16 dguildid, uint32 dlockpick, uint32 dkeyitem, uint8 ddoor_param, uint8 dinvert, int dincline, uint16 dsize){ From 743175d4ff3125f1f285378f9ff4ca7671268d74 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 21 Aug 2014 13:26:38 -0700 Subject: [PATCH 055/127] InsertDoor converted to QueryDatabase --- zone/zonedb.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 7623ccc39..056432a89 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1911,12 +1911,18 @@ void ZoneDatabase::QGlobalPurge() } void ZoneDatabase::InsertDoor(uint32 ddoordbid, uint16 ddoorid, const char* ddoor_name, float dxpos, float dypos, float dzpos, float dheading, uint8 dopentype, uint16 dguildid, uint32 dlockpick, uint32 dkeyitem, uint8 ddoor_param, uint8 dinvert, int dincline, uint16 dsize){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - if (!RunQuery(query, MakeAnyLenString(&query, "replace into doors (id, doorid,zone,version,name,pos_x,pos_y,pos_z,heading,opentype,guild,lockpick,keyitem,door_param,invert_state,incline,size) values('%i','%i','%s','%i', '%s','%f','%f','%f','%f','%i','%i','%i', '%i','%i','%i','%i','%i')", ddoordbid ,ddoorid ,zone->GetShortName(), zone->GetInstanceVersion(), ddoor_name, dxpos, dypos, dzpos, dheading, dopentype, dguildid, dlockpick, dkeyitem, ddoor_param, dinvert, dincline, dsize), errbuf)) { - std::cerr << "Error in InsertDoor" << query << "' " << errbuf << std::endl; - } - safe_delete_array(query); + + std::string query = StringFormat("REPLACE INTO doors (id, doorid, zone, version, name, " + "pos_x, pos_y, pos_z, heading, opentype, guild, lockpick, " + "keyitem, door_param, invert_state, incline, size) " + "VALUES('%i', '%i', '%s', '%i', '%s', '%f', '%f', " + "'%f', '%f', '%i', '%i', '%i', '%i', '%i', '%i', '%i', '%i')", + ddoordbid, ddoorid, zone->GetShortName(), zone->GetInstanceVersion(), + ddoor_name, dxpos, dypos, dzpos, dheading, dopentype, dguildid, + dlockpick, dkeyitem, ddoor_param, dinvert, dincline, dsize); + auto results = QueryDatabase(query); + if (!results.Success()) + std::cerr << "Error in InsertDoor" << query << "' " << results.ErrorMessage() << std::endl; } void ZoneDatabase::LoadAltCurrencyValues(uint32 char_id, std::map ¤cy) { From fc0d589f1289244a3f0099e104a3f45bfda54622 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 21 Aug 2014 13:34:19 -0700 Subject: [PATCH 056/127] LoadAltCurrencyValues converted to QueryDatabase --- zone/zonedb.cpp | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 056432a89..a0df3ea7d 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1926,23 +1926,19 @@ void ZoneDatabase::InsertDoor(uint32 ddoordbid, uint16 ddoorid, const char* ddoo } void ZoneDatabase::LoadAltCurrencyValues(uint32 char_id, std::map ¤cy) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT currency_id, amount FROM character_alt_currency where char_id='%u'", char_id), errbuf, &result)) { - safe_delete_array(query); - while ((row = mysql_fetch_row(result))) - { - currency[atoi(row[0])] = atoi(row[1]); - } - mysql_free_result(result); - } - else { - LogFile->write(EQEMuLog::Error, "Error in LoadAltCurrencyValues query '%s': %s", query, errbuf); - safe_delete_array(query); - } + std::string query = StringFormat("SELECT currency_id, amount " + "FROM character_alt_currency " + "WHERE char_id = '%u'", char_id); + auto results = QueryDatabase(query); + if (!results.Success()) { + LogFile->write(EQEMuLog::Error, "Error in LoadAltCurrencyValues query '%s': %s", query.c_str(), results.ErrorMessage().c_str()); + return; + } + + for (auto row = results.begin(); row != results.end(); ++row) + currency[atoi(row[0])] = atoi(row[1]); + } void ZoneDatabase::UpdateAltCurrencyValue(uint32 char_id, uint32 currency_id, uint32 value) { From cab43f41be1592202fef6644f8a3df621d8e3fb5 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 21 Aug 2014 13:36:01 -0700 Subject: [PATCH 057/127] UpdateAltCurrencyValues converted to QueryDatabase --- zone/zonedb.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index a0df3ea7d..2503aa793 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1942,12 +1942,11 @@ void ZoneDatabase::LoadAltCurrencyValues(uint32 char_id, std::map Date: Thu, 21 Aug 2014 13:42:02 -0700 Subject: [PATCH 058/127] SaveBuffs converted to QueryDatabase --- zone/zonedb.cpp | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 2503aa793..58d1f991c 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1949,29 +1949,33 @@ void ZoneDatabase::UpdateAltCurrencyValue(uint32 char_id, uint32 currency_id, ui } -void ZoneDatabase::SaveBuffs(Client *c) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; +void ZoneDatabase::SaveBuffs(Client *client) { - database.RunQuery(query, MakeAnyLenString(&query, "DELETE FROM `character_buffs` WHERE `character_id`='%u'", c->CharacterID()), - errbuf); + std::string query = StringFormat("DELETE FROM `character_buffs` WHERE `character_id` = '%u'", client->CharacterID()); + database.QueryDatabase(query); + + uint32 buff_count = client->GetMaxBuffSlots(); + Buffs_Struct *buffs = client->GetBuffs(); + + for (int index = 0; index < buff_count; index++) { + if(buffs[index].spellid == SPELL_UNKNOWN) + continue; + + query = StringFormat("INSERT INTO `character_buffs` (character_id, slot_id, spell_id, " + "caster_level, caster_name, ticsremaining, counters, numhits, melee_rune, " + "magic_rune, persistent, dot_rune, caston_x, caston_y, caston_z, ExtraDIChance) " + "VALUES('%u', '%u', '%u', '%u', '%s', '%u', '%u', '%u', '%u', '%u', '%u', '%u', " + "'%i', '%i', '%i', '%i')", client->CharacterID(), index, buffs[index].spellid, + buffs[index].casterlevel, buffs[index].caster_name, buffs[index].ticsremaining, + buffs[index].counters, buffs[index].numhits, buffs[index].melee_rune, + buffs[index].magic_rune, buffs[index].persistant_buff, buffs[index].dot_rune, + buffs[index].caston_x, buffs[index].caston_y, buffs[index].caston_z, + buffs[index].ExtraDIChance); + auto results = QueryDatabase(query); + if (!results.Success()) + LogFile->write(EQEMuLog::Error, "Error in SaveBuffs query '%s': %s", query.c_str(), results.ErrorMessage().c_str()); - uint32 buff_count = c->GetMaxBuffSlots(); - Buffs_Struct *buffs = c->GetBuffs(); - for (int i = 0; i < buff_count; i++) { - if(buffs[i].spellid != SPELL_UNKNOWN) { - if(!database.RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `character_buffs` (character_id, slot_id, spell_id, " - "caster_level, caster_name, ticsremaining, counters, numhits, melee_rune, magic_rune, persistent, dot_rune, " - "caston_x, caston_y, caston_z, ExtraDIChance) VALUES('%u', '%u', '%u', '%u', '%s', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%i', '%i', '%i', '%i')", - c->CharacterID(), i, buffs[i].spellid, buffs[i].casterlevel, buffs[i].caster_name, buffs[i].ticsremaining, - buffs[i].counters, buffs[i].numhits, buffs[i].melee_rune, buffs[i].magic_rune, buffs[i].persistant_buff, - buffs[i].dot_rune, buffs[i].caston_x, buffs[i].caston_y, buffs[i].caston_z, buffs[i].ExtraDIChance), - errbuf)) { - LogFile->write(EQEMuLog::Error, "Error in SaveBuffs query '%s': %s", query, errbuf); - } - } } - safe_delete_array(query); } void ZoneDatabase::LoadBuffs(Client *c) { From 10d384f1310c5aa4a3bba0e938b089cdef8cd02e Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 21 Aug 2014 13:53:54 -0700 Subject: [PATCH 059/127] LoadBuffs converted to QueryDatabase --- zone/zonedb.cpp | 173 ++++++++++++++++++++++-------------------------- 1 file changed, 79 insertions(+), 94 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 58d1f991c..75862b8d8 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1978,108 +1978,93 @@ void ZoneDatabase::SaveBuffs(Client *client) { } } -void ZoneDatabase::LoadBuffs(Client *c) { - Buffs_Struct *buffs = c->GetBuffs(); - uint32 max_slots = c->GetMaxBuffSlots(); - for(int i = 0; i < max_slots; ++i) { - buffs[i].spellid = SPELL_UNKNOWN; - } +void ZoneDatabase::LoadBuffs(Client *client) { + Buffs_Struct *buffs = client->GetBuffs(); + uint32 max_slots = client->GetMaxBuffSlots(); - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT spell_id, slot_id, caster_level, caster_name, ticsremaining, counters, " - "numhits, melee_rune, magic_rune, persistent, dot_rune, caston_x, caston_y, caston_z, ExtraDIChance FROM `character_buffs` WHERE " - "`character_id`='%u'", - c->CharacterID()), errbuf, &result)) - { - safe_delete_array(query); - while ((row = mysql_fetch_row(result))) - { - uint32 slot_id = atoul(row[1]); - if(slot_id >= c->GetMaxBuffSlots()) { - continue; - } + for(int index = 0; index < max_slots; ++index) + buffs[index].spellid = SPELL_UNKNOWN; - uint32 spell_id = atoul(row[0]); - if(!IsValidSpell(spell_id)) { - continue; - } - - Client *caster = entity_list.GetClientByName(row[3]); - uint32 caster_level = atoi(row[2]); - uint32 ticsremaining = atoul(row[4]); - uint32 counters = atoul(row[5]); - uint32 numhits = atoul(row[6]); - uint32 melee_rune = atoul(row[7]); - uint32 magic_rune = atoul(row[8]); - uint8 persistent = atoul(row[9]); - uint32 dot_rune = atoul(row[10]); - int32 caston_x = atoul(row[11]); - int32 caston_y = atoul(row[12]); - int32 caston_z = atoul(row[13]); - int32 ExtraDIChance = atoul(row[14]); - - buffs[slot_id].spellid = spell_id; - buffs[slot_id].casterlevel = caster_level; - if(caster) { - buffs[slot_id].casterid = caster->GetID(); - strcpy(buffs[slot_id].caster_name, caster->GetName()); - buffs[slot_id].client = true; - } else { - buffs[slot_id].casterid = 0; - strcpy(buffs[slot_id].caster_name, ""); - buffs[slot_id].client = false; - } - - buffs[slot_id].ticsremaining = ticsremaining; - buffs[slot_id].counters = counters; - buffs[slot_id].numhits = numhits; - buffs[slot_id].melee_rune = melee_rune; - buffs[slot_id].magic_rune = magic_rune; - buffs[slot_id].persistant_buff = persistent ? true : false; - buffs[slot_id].dot_rune = dot_rune; - buffs[slot_id].caston_x = caston_x; - buffs[slot_id].caston_y = caston_y; - buffs[slot_id].caston_z = caston_z; - buffs[slot_id].ExtraDIChance = ExtraDIChance; - buffs[slot_id].RootBreakChance = 0; - buffs[slot_id].UpdateClient = false; - - } - mysql_free_result(result); - } - else { - LogFile->write(EQEMuLog::Error, "Error in LoadBuffs query '%s': %s", query, errbuf); - safe_delete_array(query); + std::string query = StringFormat("SELECT spell_id, slot_id, caster_level, caster_name, ticsremaining, " + "counters, numhits, melee_rune, magic_rune, persistent, dot_rune, " + "caston_x, caston_y, caston_z, ExtraDIChance " + "FROM `character_buffs` WHERE `character_id` = '%u'", client->CharacterID()); + auto results = QueryDatabase(query); + if (!results.Success()) { + LogFile->write(EQEMuLog::Error, "Error in LoadBuffs query '%s': %s", query.c_str(), results.ErrorMessage().c_str()); return; - } + } - max_slots = c->GetMaxBuffSlots(); - for(int i = 0; i < max_slots; ++i) { - if(!IsValidSpell(buffs[i].spellid)) { + for (auto row = results.begin(); row != results.end(); ++row) { + uint32 slot_id = atoul(row[1]); + if(slot_id >= client->GetMaxBuffSlots()) continue; - } - for(int j = 0; j < 12; ++j) { - bool cont = false; - switch(spells[buffs[i].spellid].effectid[j]) { - case SE_Charm: - buffs[i].spellid = SPELL_UNKNOWN; - cont = true; - break; - case SE_Illusion: - if(!buffs[i].persistant_buff) { - buffs[i].spellid = SPELL_UNKNOWN; - cont = true; - } - break; - } + uint32 spell_id = atoul(row[0]); + if(!IsValidSpell(spell_id)) + continue; - if(cont) { - break; + Client *caster = entity_list.GetClientByName(row[3]); + uint32 caster_level = atoi(row[2]); + uint32 ticsremaining = atoul(row[4]); + uint32 counters = atoul(row[5]); + uint32 numhits = atoul(row[6]); + uint32 melee_rune = atoul(row[7]); + uint32 magic_rune = atoul(row[8]); + uint8 persistent = atoul(row[9]); + uint32 dot_rune = atoul(row[10]); + int32 caston_x = atoul(row[11]); + int32 caston_y = atoul(row[12]); + int32 caston_z = atoul(row[13]); + int32 ExtraDIChance = atoul(row[14]); + + buffs[slot_id].spellid = spell_id; + buffs[slot_id].casterlevel = caster_level; + + if(caster) { + buffs[slot_id].casterid = caster->GetID(); + strcpy(buffs[slot_id].caster_name, caster->GetName()); + buffs[slot_id].client = true; + } else { + buffs[slot_id].casterid = 0; + strcpy(buffs[slot_id].caster_name, ""); + buffs[slot_id].client = false; + } + + buffs[slot_id].ticsremaining = ticsremaining; + buffs[slot_id].counters = counters; + buffs[slot_id].numhits = numhits; + buffs[slot_id].melee_rune = melee_rune; + buffs[slot_id].magic_rune = magic_rune; + buffs[slot_id].persistant_buff = persistent? true: false; + buffs[slot_id].dot_rune = dot_rune; + buffs[slot_id].caston_x = caston_x; + buffs[slot_id].caston_y = caston_y; + buffs[slot_id].caston_z = caston_z; + buffs[slot_id].ExtraDIChance = ExtraDIChance; + buffs[slot_id].RootBreakChance = 0; + buffs[slot_id].UpdateClient = false; + + } + + max_slots = client->GetMaxBuffSlots(); + for(int index = 0; index < max_slots; ++index) { + if(!IsValidSpell(buffs[index].spellid)) + continue; + + for(int effectIndex = 0; effectIndex < 12; ++effectIndex) { + + if (spells[buffs[index].spellid].effectid[effectIndex] == SE_Charm) { + buffs[index].spellid = SPELL_UNKNOWN; + break; + } + + if (spells[buffs[index].spellid].effectid[effectIndex] == SE_Illusion) { + if(buffs[index].persistant_buff) + break; + + buffs[index].spellid = SPELL_UNKNOWN; } } } From cf7574d9b8cdae194044ef8ca34dc73cd2dd2531 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 21 Aug 2014 15:30:27 -0700 Subject: [PATCH 060/127] SavePetInfo converted to QueryDatabase --- zone/zonedb.cpp | 153 ++++++++++++++++++++++++------------------------ 1 file changed, 76 insertions(+), 77 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 75862b8d8..f0c2f2afc 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -2070,95 +2070,94 @@ void ZoneDatabase::LoadBuffs(Client *client) { } } -void ZoneDatabase::SavePetInfo(Client *c) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - int i = 0; - PetInfo *petinfo = c->GetPetInfo(0); - PetInfo *suspended = c->GetPetInfo(1); +void ZoneDatabase::SavePetInfo(Client *client) { - if(!database.RunQuery(query, MakeAnyLenString(&query, "DELETE FROM `character_pet_buffs` WHERE `char_id`=%u", c->CharacterID()), - errbuf)) { - safe_delete_array(query); + PetInfo *petinfo = client->GetPetInfo(0); + PetInfo *suspended = client->GetPetInfo(1); + + std::string query = StringFormat("DELETE FROM `character_pet_buffs` WHERE `char_id` = %u", client->CharacterID()); + auto results = database.QueryDatabase(query); + if(!results.Success()) return; - } - safe_delete_array(query); - if (!database.RunQuery(query, MakeAnyLenString(&query, "DELETE FROM `character_pet_inventory` WHERE `char_id`=%u", c->CharacterID()), - errbuf)) { - safe_delete_array(query); - // error report + + query = StringFormat("DELETE FROM `character_pet_buffs` WHERE `char_id` = %u", client->CharacterID()); + results = database.QueryDatabase(query); + if(!results.Success()) return; - } - safe_delete_array(query); - if(!database.RunQuery(query, MakeAnyLenString(&query, - "INSERT INTO `character_pet_info` (`char_id`, `pet`, `petname`, `petpower`, `spell_id`, `hp`, `mana`, `size`) " - "values (%u, 0, '%s', %i, %u, %u, %u, %f) " - "ON DUPLICATE KEY UPDATE `petname`='%s', `petpower`=%i, `spell_id`=%u, `hp`=%u, `mana`=%u, `size`=%f", - c->CharacterID(), petinfo->Name, petinfo->petpower, petinfo->SpellID, petinfo->HP, petinfo->Mana, petinfo->size, - petinfo->Name, petinfo->petpower, petinfo->SpellID, petinfo->HP, petinfo->Mana, petinfo->size), - errbuf)) - { - safe_delete_array(query); + query = StringFormat("INSERT INTO `character_pet_info` " + "(`char_id`, `pet`, `petname`, `petpower`, `spell_id`, `hp`, `mana`, `size`) " + "VALUES (%u, 0, '%s', %i, %u, %u, %u, %f) " + "ON DUPLICATE KEY UPDATE `petname` = '%s', `petpower` = %i, `spell_id` = %u, " + "`hp` = %u, `mana` = %u, `size` = %f", + client->CharacterID(), petinfo->Name, petinfo->petpower, petinfo->SpellID, + petinfo->HP, petinfo->Mana, petinfo->size, petinfo->Name, petinfo->petpower, + petinfo->SpellID, petinfo->HP, petinfo->Mana, petinfo->size); + results = database.QueryDatabase(query); + if(!results.Success()) return; - } - safe_delete_array(query); - for(i=0; i < RuleI(Spells, MaxTotalSlotsPET); i++) { - if (petinfo->Buffs[i].spellid != SPELL_UNKNOWN && petinfo->Buffs[i].spellid != 0) { - database.RunQuery(query, MakeAnyLenString(&query, - "INSERT INTO `character_pet_buffs` (`char_id`, `pet`, `slot`, `spell_id`, `caster_level`, " - "`ticsremaining`, `counters`) values " - "(%u, 0, %u, %u, %u, %u, %d)", - c->CharacterID(), i, petinfo->Buffs[i].spellid, petinfo->Buffs[i].level, petinfo->Buffs[i].duration, - petinfo->Buffs[i].counters), - errbuf); - safe_delete_array(query); - } - if (suspended->Buffs[i].spellid != SPELL_UNKNOWN && suspended->Buffs[i].spellid != 0) { - database.RunQuery(query, MakeAnyLenString(&query, - "INSERT INTO `character_pet_buffs` (`char_id`, `pet`, `slot`, `spell_id`, `caster_level`, " - "`ticsremaining`, `counters`) values " - "(%u, 1, %u, %u, %u, %u, %d)", - c->CharacterID(), i, suspended->Buffs[i].spellid, suspended->Buffs[i].level, suspended->Buffs[i].duration, - suspended->Buffs[i].counters), - errbuf); - safe_delete_array(query); - } + for(int index = 0; index < RuleI(Spells, MaxTotalSlotsPET); index++) { + if (petinfo->Buffs[index].spellid == SPELL_UNKNOWN || petinfo->Buffs[index].spellid == 0) + continue; + + query = StringFormat("INSERT INTO `character_pet_buffs` " + "(`char_id`, `pet`, `slot`, `spell_id`, `caster_level`, " + "`ticsremaining`, `counters`) " + "VALUES (%u, 0, %u, %u, %u, %u, %d)", + client->CharacterID(), index, petinfo->Buffs[index].spellid, + petinfo->Buffs[index].level, petinfo->Buffs[index].duration, + petinfo->Buffs[index].counters); + database.QueryDatabase(query); + } + + for(int index = 0; index < RuleI(Spells, MaxTotalSlotsPET); index++) { + if (petinfo->Buffs[index].spellid == SPELL_UNKNOWN || petinfo->Buffs[index].spellid == 0) + continue; + + query = StringFormat("INSERT INTO `character_pet_buffs` " + "(`char_id`, `pet`, `slot`, `spell_id`, `caster_level`, " + "`ticsremaining`, `counters`) " + "VALUES (%u, 1, %u, %u, %u, %u, %d)", + client->CharacterID(), index, suspended->Buffs[index].spellid, + suspended->Buffs[index].level, suspended->Buffs[index].duration, + suspended->Buffs[index].counters); + database.QueryDatabase(query); } - for (i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; i++) { - if(petinfo->Items[i]) { - database.RunQuery(query, MakeAnyLenString(&query, - "INSERT INTO `character_pet_inventory` (`char_id`, `pet`, `slot`, `item_id`) values (%u, 0, %u, %u)", - c->CharacterID(), i, petinfo->Items[i]), errbuf); - // should check for errors - safe_delete_array(query); - } + for (int index = EmuConstants::EQUIPMENT_BEGIN; index <= EmuConstants::EQUIPMENT_END; index++) { + if(!petinfo->Items[index]) + continue; + + query = StringFormat("INSERT INTO `character_pet_inventory` " + "(`char_id`, `pet`, `slot`, `item_id`) " + "VALUES (%u, 0, %u, %u)", + client->CharacterID(), index, petinfo->Items[index]); + database.QueryDatabase(query); } - - if(!database.RunQuery(query, MakeAnyLenString(&query, - "INSERT INTO `character_pet_info` (`char_id`, `pet`, `petname`, `petpower`, `spell_id`, `hp`, `mana`, `size`) " - "values (%u, 1, '%s', %u, %u, %u, %u, %f) " - "ON DUPLICATE KEY UPDATE `petname`='%s', `petpower`=%i, `spell_id`=%u, `hp`=%u, `mana`=%u, `size`=%f", - c->CharacterID(), suspended->Name, suspended->petpower, suspended->SpellID, suspended->HP, suspended->Mana, suspended->size, - suspended->Name, suspended->petpower, suspended->SpellID, suspended->HP, suspended->Mana, suspended->size), - errbuf)) - { - safe_delete_array(query); + query = StringFormat("INSERT INTO `character_pet_info` " + "(`char_id`, `pet`, `petname`, `petpower`, `spell_id`, `hp`, `mana`, `size`) " + "VALUES (%u, 1, '%s', %u, %u, %u, %u, %f) " + "ON DUPLICATE KEY UPDATE " + "`petname`='%s', `petpower`=%i, `spell_id`=%u, `hp`=%u, `mana`=%u, `size`=%f", + client->CharacterID(), suspended->Name, suspended->petpower, suspended->SpellID, + suspended->HP, suspended->Mana, suspended->size, suspended->Name, suspended->petpower, + suspended->SpellID, suspended->HP, suspended->Mana, suspended->size); + results = database.QueryDatabase(query); + if(!results.Success()) return; - } - safe_delete_array(query); - for (i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; i++) { - if(suspended->Items[i]) { - database.RunQuery(query, MakeAnyLenString(&query, - "INSERT INTO `character_pet_inventory` (`char_id`, `pet`, `slot`, `item_id`) values (%u, 1, %u, %u)", - c->CharacterID(), i, suspended->Items[i]), errbuf); - // should check for errors - safe_delete_array(query); - } + + for (int index = EmuConstants::EQUIPMENT_BEGIN; index <= EmuConstants::EQUIPMENT_END; index++) { + if(!suspended->Items[index]) + continue; + + query = StringFormat("INSERT INTO `character_pet_inventory` " + "(`char_id`, `pet`, `slot`, `item_id`) " + "VALUES (%u, 1, %u, %u)", + client->CharacterID(), index, suspended->Items[index]); + database.QueryDatabase(query); } } From e731cfd48d15f51b81f7466ece7529e1d9d4d611 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 21 Aug 2014 15:32:20 -0700 Subject: [PATCH 061/127] RemoveTempFactions converted to QueryDatabase --- zone/zonedb.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index f0c2f2afc..bfad721e2 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -2162,14 +2162,15 @@ void ZoneDatabase::SavePetInfo(Client *client) { } -void ZoneDatabase::RemoveTempFactions(Client *c){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; +void ZoneDatabase::RemoveTempFactions(Client *client) { + + std::string query = StringFormat("DELETE FROM faction_values " + "WHERE temp = 1 AND char_id = %u", + client->CharacterID()); + auto results = QueryDatabase(query); + if (!results.Success()) + std::cerr << "Error in RemoveTempFactions query '" << query << "' " << results.ErrorMessage() << std::endl; - if (!RunQuery(query, MakeAnyLenString(&query, "DELETE FROM faction_values WHERE temp = 1 AND char_id=%u", c->CharacterID()), errbuf)) { - std::cerr << "Error in RemoveTempFactions query '" << query << "' " << errbuf << std::endl; - } - safe_delete_array(query); } void ZoneDatabase::LoadPetInfo(Client *c) { From 833227f7f68753f982c1b0cfd2819315d6a16f10 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 21 Aug 2014 15:58:11 -0700 Subject: [PATCH 062/127] LoadPetInfo converted to QueryDatabase --- zone/zonedb.cpp | 194 ++++++++++++++++++++++-------------------------- 1 file changed, 87 insertions(+), 107 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index bfad721e2..184f7e5c8 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -2173,129 +2173,109 @@ void ZoneDatabase::RemoveTempFactions(Client *client) { } -void ZoneDatabase::LoadPetInfo(Client *c) { - // Load current pet and suspended pet - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES *result; - MYSQL_ROW row; +void ZoneDatabase::LoadPetInfo(Client *client) { - PetInfo *petinfo = c->GetPetInfo(0); - PetInfo *suspended = c->GetPetInfo(1); - PetInfo *pi; - uint16 pet; + // Load current pet and suspended pet + PetInfo *petinfo = client->GetPetInfo(0); + PetInfo *suspended = client->GetPetInfo(1); memset(petinfo, 0, sizeof(PetInfo)); memset(suspended, 0, sizeof(PetInfo)); - if(database.RunQuery(query, MakeAnyLenString(&query, - "SELECT `pet`, `petname`, `petpower`, `spell_id`, `hp`, `mana`, `size` from `character_pet_info` where `char_id`=%u", - c->CharacterID()), errbuf, &result)) - { - safe_delete_array(query); - while ((row = mysql_fetch_row(result))) { - pet = atoi(row[0]); - if (pet == 0) - pi = petinfo; - else if (pet == 1) - pi = suspended; - else - continue; - - strncpy(pi->Name,row[1],64); - pi->petpower = atoi(row[2]); - pi->SpellID = atoi(row[3]); - pi->HP = atoul(row[4]); - pi->Mana = atoul(row[5]); - pi->size = atof(row[6]); - } - mysql_free_result(result); - } - else - { - LogFile->write(EQEMuLog::Error, "Error in LoadPetInfo query '%s': %s", query, errbuf); - safe_delete_array(query); + std::string query = StringFormat("SELECT `pet`, `petname`, `petpower`, `spell_id`, " + "`hp`, `mana`, `size` FROM `character_pet_info` " + "WHERE `char_id` = %u", client->CharacterID()); + auto results = database.QueryDatabase(query); + if(!results.Success()) { + LogFile->write(EQEMuLog::Error, "Error in LoadPetInfo query '%s': %s", query.c_str(), results.ErrorMessage().c_str()); return; } + PetInfo *pi; + for (auto row = results.begin(); row != results.end(); ++row) { + uint16 pet = atoi(row[0]); - if (RunQuery(query, MakeAnyLenString(&query, - "SELECT `pet`, `slot`, `spell_id`, `caster_level`, `castername`, " - "`ticsremaining`, `counters` FROM `character_pet_buffs` " - "WHERE `char_id`=%u", - c->CharacterID()), errbuf, &result)) - { - safe_delete_array(query); - while ((row = mysql_fetch_row(result))) - { - pet = atoi(row[0]); - if (pet == 0) - pi = petinfo; - else if (pet == 1) - pi = suspended; - else - continue; + if (pet == 0) + pi = petinfo; + else if (pet == 1) + pi = suspended; + else + continue; - uint32 slot_id = atoul(row[1]); - if(slot_id >= RuleI(Spells, MaxTotalSlotsPET)) { - continue; - } - - uint32 spell_id = atoul(row[2]); - if(!IsValidSpell(spell_id)) { - continue; - } - uint32 caster_level = atoi(row[3]); - int caster_id = 0; - // The castername field is currently unused - //Client *caster = entity_list.GetClientByName(row[4]); - //if (caster) { caster_id = caster->GetID(); } - uint32 ticsremaining = atoul(row[5]); - uint32 counters = atoul(row[6]); - - pi->Buffs[slot_id].spellid = spell_id; - pi->Buffs[slot_id].level = caster_level; - pi->Buffs[slot_id].player_id = caster_id; - pi->Buffs[slot_id].slotid = 2; // Always 2 in buffs struct for real buffs - - pi->Buffs[slot_id].duration = ticsremaining; - pi->Buffs[slot_id].counters = counters; - } - mysql_free_result(result); + strncpy(pi->Name,row[1],64); + pi->petpower = atoi(row[2]); + pi->SpellID = atoi(row[3]); + pi->HP = atoul(row[4]); + pi->Mana = atoul(row[5]); + pi->size = atof(row[6]); } - else { - LogFile->write(EQEMuLog::Error, "Error in LoadPetInfo query '%s': %s", query, errbuf); - safe_delete_array(query); + + query = StringFormat("SELECT `pet`, `slot`, `spell_id`, `caster_level`, `castername`, " + "`ticsremaining`, `counters` FROM `character_pet_buffs` " + "WHERE `char_id` = %u", client->CharacterID()); + results = QueryDatabase(query); + if (!results.Success()) { + LogFile->write(EQEMuLog::Error, "Error in LoadPetInfo query '%s': %s", query.c_str(), results.ErrorMessage().c_str()); + return; + } + + for (auto row = results.begin(); row != results.end(); ++row) { + uint16 pet = atoi(row[0]); + if (pet == 0) + pi = petinfo; + else if (pet == 1) + pi = suspended; + else + continue; + + uint32 slot_id = atoul(row[1]); + if(slot_id >= RuleI(Spells, MaxTotalSlotsPET)) + continue; + + uint32 spell_id = atoul(row[2]); + if(!IsValidSpell(spell_id)) + continue; + + uint32 caster_level = atoi(row[3]); + int caster_id = 0; + // The castername field is currently unused + uint32 ticsremaining = atoul(row[5]); + uint32 counters = atoul(row[6]); + + pi->Buffs[slot_id].spellid = spell_id; + pi->Buffs[slot_id].level = caster_level; + pi->Buffs[slot_id].player_id = caster_id; + pi->Buffs[slot_id].slotid = 2; // Always 2 in buffs struct for real buffs + + pi->Buffs[slot_id].duration = ticsremaining; + pi->Buffs[slot_id].counters = counters; + } + + query = StringFormat("SELECT `pet`, `slot`, `item_id` " + "FROM `character_pet_inventory` " + "WHERE `char_id`=%u",client->CharacterID()); + results = database.QueryDatabase(query); + if (!results.Success()) { + LogFile->write(EQEMuLog::Error, "Error in LoadPetInfo query '%s': %s", query.c_str(), results.ErrorMessage().c_str()); return; } - if (database.RunQuery(query, MakeAnyLenString(&query, - "SELECT `pet`, `slot`, `item_id` FROM `character_pet_inventory` WHERE `char_id`=%u", - c->CharacterID()), errbuf, &result)) - { - safe_delete_array(query); - while((row = mysql_fetch_row(result))) { - pet = atoi(row[0]); - if (pet == 0) - pi = petinfo; - else if (pet == 1) - pi = suspended; - else - continue; + for(auto row = results.begin(); row != results.end(); ++row) { + uint16 pet = atoi(row[0]); + if (pet == 0) + pi = petinfo; + else if (pet == 1) + pi = suspended; + else + continue; - int slot = atoi(row[1]); - if (slot < EmuConstants::EQUIPMENT_BEGIN || slot > EmuConstants::EQUIPMENT_END) - continue; + int slot = atoi(row[1]); + if (slot < EmuConstants::EQUIPMENT_BEGIN || slot > EmuConstants::EQUIPMENT_END) + continue; + + pi->Items[slot] = atoul(row[2]); + } - pi->Items[slot] = atoul(row[2]); - } - mysql_free_result(result); - } - else { - LogFile->write(EQEMuLog::Error, "Error in LoadPetInfo query '%s': %s", query, errbuf); - safe_delete_array(query); - return; - } } bool ZoneDatabase::GetFactionData(FactionMods* fm, uint32 class_mod, uint32 race_mod, uint32 deity_mod, int32 faction_id) { From 2e847815943ec146d95983cb3282f8a03655a129 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 21 Aug 2014 17:00:50 -0700 Subject: [PATCH 063/127] LoadFactionValues_result converted to MySQLRequestResult --- zone/zonedb.cpp | 8 ++++---- zone/zonedb.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 184f7e5c8..3b8d45e6d 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -2350,11 +2350,11 @@ bool ZoneDatabase::LoadFactionValues(uint32 char_id, faction_map & val_list) { return false; } -bool ZoneDatabase::LoadFactionValues_result(MYSQL_RES* result, faction_map & val_list) { - MYSQL_ROW row; - while((row = mysql_fetch_row(result))) { +bool ZoneDatabase::LoadFactionValues_result(MySQLRequestResult results, faction_map & val_list) { + + for (auto row = results.begin(); row != results.begin(); ++row) val_list[atoi(row[0])] = atoi(row[1]); - } + return true; } diff --git a/zone/zonedb.h b/zone/zonedb.h index cab3e84a9..dae8c6490 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -302,7 +302,7 @@ public: bool SetCharacterFactionLevel(uint32 char_id, int32 faction_id, int32 value, uint8 temp, faction_map &val_list); // rembrant, needed for factions Dec, 16 2001 bool LoadFactionData(); bool LoadFactionValues(uint32 char_id, faction_map & val_list); - bool LoadFactionValues_result(MYSQL_RES* result, faction_map & val_list); + bool LoadFactionValues_result(MySQLRequestResult result, faction_map & val_list); /* * AAs From 2df823d2dbb96ac159f14243070834b5927b33d2 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 21 Aug 2014 17:04:08 -0700 Subject: [PATCH 064/127] LoadFactionValues converted to QueryDatabase --- zone/zonedb.cpp | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 3b8d45e6d..f813febfd 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -2333,21 +2333,18 @@ bool ZoneDatabase::GetFactionData(FactionMods* fm, uint32 class_mod, uint32 race return true; } -bool ZoneDatabase::LoadFactionValues(uint32 char_id, faction_map & val_list) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT faction_id,current_value FROM faction_values WHERE char_id = %i",char_id), errbuf, &result)) { - safe_delete_array(query); - bool ret = LoadFactionValues_result(result, val_list); - mysql_free_result(result); - return ret; - } - else { - std::cerr << "Error in LoadFactionValues query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - } - return false; +bool ZoneDatabase::LoadFactionValues(uint32 char_id, faction_map& val_list) { + + std::string query = StringFormat("SELECT faction_id,current_value " + "FROM faction_values " + "WHERE char_id = %i", char_id); + auto results = QueryDatabase(query); + if (!results.Success()) { + std::cerr << "Error in LoadFactionValues query '" << query << "' " << results.ErrorMessage() << std::endl; + return false; + } + + return LoadFactionValues_result(std::move(results), val_list); } bool ZoneDatabase::LoadFactionValues_result(MySQLRequestResult results, faction_map & val_list) { From 850d1e7c283d9f5dd75f72e195e651d3f7eedb0f Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 21 Aug 2014 17:08:31 -0700 Subject: [PATCH 065/127] SetCharacterFactionLevel converted to QueryDatabase --- zone/zonedb.cpp | 37 ++++++++++++++----------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index f813febfd..e4b74c772 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -2402,23 +2402,18 @@ bool ZoneDatabase::GetNPCFactionList(uint32 npcfaction_id, int32* faction_id, in //o-------------------------------------------------------------- bool ZoneDatabase::SetCharacterFactionLevel(uint32 char_id, int32 faction_id, int32 value, uint8 temp, faction_map &val_list) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; - if (!RunQuery(query, MakeAnyLenString(&query, - "DELETE FROM faction_values WHERE char_id=%i AND faction_id = %i", - char_id, faction_id), errbuf)) { - std::cerr << "Error in SetCharacterFactionLevel query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + std::string query = StringFormat("DELETE FROM faction_values " + "WHERE char_id=%i AND faction_id = %i", + char_id, faction_id); + auto results = QueryDatabase(query); + if (!results.Success()) { + std::cerr << "Error in SetCharacterFactionLevel query '" << query << "' " << results.ErrorMessage() << std::endl; return false; - } + } if(value == 0) - { - safe_delete_array(query); return true; - } if(temp == 2) temp = 0; @@ -2426,23 +2421,19 @@ bool ZoneDatabase::SetCharacterFactionLevel(uint32 char_id, int32 faction_id, in if(temp == 3) temp = 1; - if (!RunQuery(query, MakeAnyLenString(&query, - "INSERT INTO faction_values (char_id,faction_id,current_value,temp) VALUES (%i,%i,%i,%i)", - char_id, faction_id,value,temp), errbuf, 0, &affected_rows)) { - std::cerr << "Error in SetCharacterFactionLevel query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + query = StringFormat("INSERT INTO faction_values (char_id, faction_id, current_value, temp) " + "VALUES (%i, %i, %i, %i)", char_id, faction_id, value, temp); + results = QueryDatabase(query); + if (!results.Success()) { + std::cerr << "Error in SetCharacterFactionLevel query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } - safe_delete_array(query); - - if (affected_rows == 0) - { + if (results.RowsAffected() == 0) return false; - } val_list[faction_id] = value; - return(true); + return true; } bool ZoneDatabase::LoadFactionData() From 9ff0c414c178c5f4344aac62b3d24435b17c196f Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 21 Aug 2014 17:17:27 -0700 Subject: [PATCH 066/127] LoadFactionData converted to QueryDatabase --- zone/zonedb.cpp | 98 +++++++++++++++++++------------------------------ 1 file changed, 38 insertions(+), 60 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index e4b74c772..90b4773f1 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -2438,69 +2438,47 @@ bool ZoneDatabase::SetCharacterFactionLevel(uint32 char_id, int32 faction_id, in bool ZoneDatabase::LoadFactionData() { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - query = new char[256]; - strcpy(query, "SELECT MAX(id) FROM faction_list"); - - if (RunQuery(query, strlen(query), errbuf, &result)) { - safe_delete_array(query); - row = mysql_fetch_row(result); - if (row && row[0]) - { - max_faction = atoi(row[0]); - faction_array = new Faction*[max_faction+1]; - for(unsigned int i=0; iname, row[1], 50); - faction_array[index]->base = atoi(row[2]); - - char sec_errbuf[MYSQL_ERRMSG_SIZE]; - MYSQL_RES *sec_result; - MYSQL_ROW sec_row; - MakeAnyLenString(&query, "SELECT `mod`, `mod_name` FROM `faction_list_mod` WHERE faction_id=%u", index); - if (RunQuery(query, strlen(query), sec_errbuf, &sec_result)) { - while((sec_row = mysql_fetch_row(sec_result))) - { - faction_array[index]->mods[sec_row[1]] = atoi(sec_row[0]); - } - mysql_free_result(sec_result); - } - safe_delete_array(query); - } - mysql_free_result(result); - } - else { - std::cerr << "Error in LoadFactionData '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return false; - } - } - else { - mysql_free_result(result); - } - } - else { - std::cerr << "Error in LoadFactionData '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + std::string query = "SELECT MAX(id) FROM faction_list"; + auto results = QueryDatabase(query); + if (!results.Success()) { + std::cerr << "Error in LoadFactionData '" << query << "' " << results.ErrorMessage() << std::endl; return false; } - return true; + + if (results.RowCount() == 0) + return false; + + auto row = results.begin(); + + max_faction = atoi(row[0]); + faction_array = new Faction*[max_faction+1]; + for(unsigned int index=0; indexname, row[1], 50); + faction_array[index]->base = atoi(row[2]); + + + query = StringFormat("SELECT `mod`, `mod_name` FROM `faction_list_mod` WHERE faction_id = %u", index); + auto modResults = QueryDatabase(query); + if (!modResults.Success()) + continue; + + for (auto modRow = modResults.begin(); modRow != modResults.end(); ++modRow) + faction_array[index]->mods[modRow[1]] = atoi(modRow[0]); + + } } bool ZoneDatabase::GetFactionIdsForNPC(uint32 nfl_id, std::list *faction_list, int32* primary_faction) { From 8369570b507242323badaf46613768d0231df1e3 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 21 Aug 2014 17:24:48 -0700 Subject: [PATCH 067/127] GetAccountInfoForLogin_result converted to MySQLRequestResult --- zone/zonedb.cpp | 57 ++++++++++++++++++++++++++----------------------- zone/zonedb.h | 2 +- 2 files changed, 31 insertions(+), 28 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 90b4773f1..f0a04515b 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -348,37 +348,40 @@ void ZoneDatabase::UpdateBug(PetitionBug_Struct* bug){ } -bool ZoneDatabase::GetAccountInfoForLogin_result(MYSQL_RES* result, int16* admin, char* account_name, uint32* lsaccountid, uint8* gmspeed, bool* revoked,bool* gmhideme, uint32* account_creation) { - MYSQL_ROW row; - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - if (admin) - *admin = atoi(row[0]); - if (account_name) - strcpy(account_name, row[1]); - if (lsaccountid) { +bool ZoneDatabase::GetAccountInfoForLogin_result(MySQLRequestResult results, int16* admin, char* account_name, uint32* lsaccountid, uint8* gmspeed, bool* revoked,bool* gmhideme, uint32* account_creation) { - if (row[2]) - *lsaccountid = atoi(row[2]); - else - *lsaccountid = 0; + if (results.RowCount() != 1) + return false; + auto row = results.begin(); - } - if (gmspeed) - *gmspeed = atoi(row[3]); - if (revoked) - *revoked = atoi(row[4]); - if(gmhideme) - *gmhideme = atoi(row[5]); - if(account_creation) - *account_creation = atoul(row[6]); + if (admin) + *admin = atoi(row[0]); + + if (account_name) + strcpy(account_name, row[1]); + + if (lsaccountid) { + if (row[2]) + *lsaccountid = atoi(row[2]); + else + *lsaccountid = 0; + } + + if (gmspeed) + *gmspeed = atoi(row[3]); + + if (revoked) + *revoked = atoi(row[4]); + + if(gmhideme) + *gmhideme = atoi(row[5]); + + if(account_creation) + *account_creation = atoul(row[6]); + + return true; - return true; - } - else { - return false; - } } diff --git a/zone/zonedb.h b/zone/zonedb.h index dae8c6490..3e5785987 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -246,7 +246,7 @@ public: /* * General Character Related Stuff */ - bool GetAccountInfoForLogin_result(MYSQL_RES* result, int16* admin = 0, char* account_name = 0, + bool GetAccountInfoForLogin_result(MySQLRequestResult results, int16* admin = 0, char* account_name = 0, uint32* lsaccountid = 0, uint8* gmspeed = 0, bool* revoked = 0, bool* gmhideme = nullptr, uint32* account_creation = 0); bool GetCharacterInfoForLogin_result(MYSQL_RES* result, uint32* character_id = 0, char* current_zone = 0, From 2a4a5b1beb3e9400634c9116aa957af1e7cbf09d Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sat, 23 Aug 2014 22:46:29 -0700 Subject: [PATCH 068/127] KeyRingLoad converted to QueryDatabase --- zone/client.cpp | 54 +++++++++++++++++++++---------------------------- 1 file changed, 23 insertions(+), 31 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index d986dbe22..ef6a228a4 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -324,7 +324,7 @@ Client::Client(EQStreamInterface* ieqs) initial_respawn_selection = 0; alternate_currency_loaded = false; - + EngagedRaidTarget = false; SavedRaidRestTimer = 0; } @@ -1029,7 +1029,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s Message(13, "Command '%s' not recognized.", message); } } else { - if(!RuleB(Chat, SuppressCommandErrors)) + if(!RuleB(Chat, SuppressCommandErrors)) Message(13, "Command '%s' not recognized.", message); } } @@ -3998,25 +3998,17 @@ void Client::SendWindow(uint32 PopupID, uint32 NegativeID, uint32 Buttons, const void Client::KeyRingLoad() { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - query = new char[256]; - - sprintf(query, "SELECT item_id FROM keyring WHERE char_id='%i' ORDER BY item_id",character_id); - if (database.RunQuery(query, strlen(query), errbuf, &result)) - { - safe_delete_array(query); - while(0 != (row = mysql_fetch_row(result))){ - keyring.push_back(atoi(row[0])); - } - mysql_free_result(result); - }else { - std::cerr << "Error in Client::KeyRingLoad query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); + std::string query = StringFormat("SELECT item_id FROM keyring " + "WHERE char_id = '%i' ORDER BY item_id", character_id); + auto results = database.QueryDatabase(query); + if (!results.Success()) { + std::cerr << "Error in Client::KeyRingLoad query '" << query << "' " << results.ErrorMessage() << std::endl; return; - } + } + + for (auto row = results.begin(); row != results.end(); ++row) + keyring.push_back(atoi(row[0])); + } void Client::KeyRingAdd(uint32 item_id) @@ -4342,15 +4334,15 @@ void Client::IncrementAggroCount() { if(!RuleI(Character, RestRegenPercent)) return; - + // If we already had aggro before this method was called, the combat indicator should already be up for SoF clients, // so we don't need to send it again. // if(AggroCount > 1) return; - + // Pause the rest timer - if (AggroCount == 1) + if (AggroCount == 1) SavedRaidRestTimer = rest_timer.GetRemainingTime(); if(GetClientVersion() >= EQClientSoF) { @@ -4395,9 +4387,9 @@ void Client::DecrementAggroCount() { time_until_rest = RuleI(Character, RestRegenTimeToActivate) * 1000; } } - + rest_timer.Start(time_until_rest); - + if(GetClientVersion() >= EQClientSoF) { EQApplicationPacket *outapp = new EQApplicationPacket(OP_RestState, 5); @@ -4502,7 +4494,7 @@ void Client::SendRespawnBinds() int num_options = respawn_options.size(); uint32 PacketLength = 17 + (26 * num_options); //Header size + per-option invariant size - + std::list::iterator itr; RespawnOption* opt; @@ -7672,7 +7664,7 @@ void Client::SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, ui tmpValue = current_value + mod + npc_value[i]; int16 FactionModPct = spellbonuses.FactionModPct + itembonuses.FactionModPct + aabonuses.FactionModPct; - tmpValue += (tmpValue * FactionModPct) / 100; + tmpValue += (tmpValue * FactionModPct) / 100; // Make sure faction hits don't go to GMs... if (m_pp.gm==1 && (tmpValue < current_value)) { @@ -7948,7 +7940,7 @@ void Client::TryItemTimer(int slot) } ++it_iter; } - + if(slot > EmuConstants::EQUIPMENT_END) { return; } @@ -8271,10 +8263,10 @@ void Client::ExpeditionSay(const char *str, int ExpID) { while((row = mysql_fetch_row(result))) { const char* CharName = row[0]; if(strcmp(CharName, this->GetCleanName()) != 0) - worldserver.SendEmoteMessage(CharName, 0, 0, 14, "%s says to the expedition, '%s'", this->GetCleanName(), str); + worldserver.SendEmoteMessage(CharName, 0, 0, 14, "%s says to the expedition, '%s'", this->GetCleanName(), str); // ChannelList->CreateChannel(ChannelName, ChannelOwner, ChannelPassword, true, atoi(row[3])); - } + } mysql_free_result(result); - + } From 97f59282cf990de59b47faaf6f2bfc06bef06b55 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sat, 23 Aug 2014 22:49:27 -0700 Subject: [PATCH 069/127] KeyRingAdd converted to QueryDatabase --- zone/client.cpp | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index ef6a228a4..ba16d7cca 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -4013,27 +4013,23 @@ void Client::KeyRingLoad() void Client::KeyRingAdd(uint32 item_id) { - if(0==item_id)return; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; - query = new char[256]; - bool bFound = KeyRingCheck(item_id); - if(!bFound){ - sprintf(query, "INSERT INTO keyring(char_id,item_id) VALUES(%i,%i)",character_id,item_id); - if(database.RunQuery(query, strlen(query), errbuf, 0, &affected_rows)) - { - Message(4,"Added to keyring."); - safe_delete_array(query); - } - else - { - std::cerr << "Error in Doors::HandleClick query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return; - } - keyring.push_back(item_id); - } + if(0==item_id) + return; + + bool found = KeyRingCheck(item_id); + if (found) + return; + + std::string query = StringFormat("INSERT INTO keyring(char_id, item_id) VALUES(%i, %i)", character_id, item_id); + auto results = database.QueryDatabase(query); + if (!results.Success()) { + std::cerr << "Error in Doors::HandleClick query '" << query << "' " << results.ErrorMessage() << std::endl; + return; + } + + Message(4,"Added to keyring."); + + keyring.push_back(item_id); } bool Client::KeyRingCheck(uint32 item_id) From 44f9e5495eaf14ca36d8662ad9c7372216f0d88f Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sat, 23 Aug 2014 22:52:46 -0700 Subject: [PATCH 070/127] IsDiscovered converted to QueryDatabase --- zone/client.cpp | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index ba16d7cca..525bf16e7 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -4060,28 +4060,16 @@ void Client::KeyRingList() bool Client::IsDiscovered(uint32 itemid) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; + std::string query = StringFormat("SELECT count(*) FROM discovered_items WHERE item_id = '%lu'", itemid); + auto results = database.QueryDatabase(query); + if (!results.Success()) { + std::cerr << "Error in IsDiscovered query '" << query << "' " << results.ErrorMessage() << std::endl; + return false; + } - if (database.RunQuery(query, MakeAnyLenString(&query, "SELECT count(*) FROM discovered_items WHERE item_id = '%lu'", itemid), errbuf, &result)) - { - row = mysql_fetch_row(result); - if (atoi(row[0])) - { - mysql_free_result(result); - safe_delete_array(query); - return true; - } - } - else - { - std::cerr << "Error in IsDiscovered query '" << query << "' " << errbuf << std::endl; - } - mysql_free_result(result); - safe_delete_array(query); - return false; + auto row = results.begin(); + + return atoi(row[0]) != 0; } void Client::DiscoverItem(uint32 itemid) { From 46980e52608077efbf494c9a642312a0fdb7be4a Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sat, 23 Aug 2014 22:59:38 -0700 Subject: [PATCH 071/127] DiscoverItem converted to QueryDatabase --- zone/client.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index 525bf16e7..4d1fabe1e 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -4074,14 +4074,11 @@ bool Client::IsDiscovered(uint32 itemid) { void Client::DiscoverItem(uint32 itemid) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES *result; - if (database.RunQuery(query,MakeAnyLenString(&query, "INSERT INTO discovered_items SET item_id=%lu, char_name='%s', discovered_date=UNIX_TIMESTAMP(), account_status=%i", itemid, GetName(), Admin()), errbuf, &result)) - { - mysql_free_result(result); - } - safe_delete_array(query); + std::string query = StringFormat("INSERT INTO discovered_items SET " + "item_id = %lu, char_name = '%s', " + "discovered_date = UNIX_TIMESTAMP(), account_status=%i", + itemid, GetName(), Admin()); + auto results = database.QueryDatabase(query); parse->EventPlayer(EVENT_DISCOVER_ITEM, this, "", itemid); } From a48138dfd61f6d694d43e2598fb4373c8994bb7d Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sat, 23 Aug 2014 23:05:58 -0700 Subject: [PATCH 072/127] SendRewards converted to QueryDatabase --- zone/client.cpp | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index 4d1fabe1e..8e9c86cd7 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -5261,32 +5261,22 @@ const bool Client::IsMQExemptedArea(uint32 zoneID, float x, float y, float z) co void Client::SendRewards() { std::vector rewards; - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - - if(database.RunQuery(query,MakeAnyLenString(&query,"SELECT reward_id, amount FROM" - " account_rewards WHERE account_id=%i ORDER by reward_id", AccountID()), - errbuf,&result)) - { - while((row = mysql_fetch_row(result))) - { - ClientReward cr; - cr.id = atoi(row[0]); - cr.amount = atoi(row[1]); - rewards.push_back(cr); - } - mysql_free_result(result); - safe_delete_array(query); - } - else - { - LogFile->write(EQEMuLog::Error, "Error in Client::SendRewards(): %s (%s)", query, errbuf); - safe_delete_array(query); + std::string query = StringFormat("SELECT reward_id, amount FROM " + "account_rewards WHERE account_id = %i " + "ORDER BY reward_id", AccountID()); + auto results = database.QueryDatabase(query); + if (!results.Success()) { + LogFile->write(EQEMuLog::Error, "Error in Client::SendRewards(): %s (%s)", query.c_str(), results.ErrorMessage().c_str()); return; } + for (auto row = results.begin(); row != results.end(); ++row) { + ClientReward cr; + cr.id = atoi(row[0]); + cr.amount = atoi(row[1]); + rewards.push_back(cr); + } + if(rewards.size() > 0) { EQApplicationPacket *vetapp = new EQApplicationPacket(OP_VetRewardsAvaliable, (sizeof(InternalVeteranReward) * rewards.size())); From 7f92e96ae70d6716259f2801bce7000bdda958ae Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sat, 23 Aug 2014 23:15:49 -0700 Subject: [PATCH 073/127] TryReward converted to QueryDatabase --- zone/client.cpp | 94 ++++++++++++++++--------------------------------- 1 file changed, 30 insertions(+), 64 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index 8e9c86cd7..a85792668 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -5336,88 +5336,54 @@ bool Client::TryReward(uint32 claim_id) } if(free_slot == 0xFFFFFFFF) - { return false; - } - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - uint32 amt = 0; - - if(database.RunQuery(query,MakeAnyLenString(&query,"SELECT amount FROM" - " account_rewards WHERE account_id=%i AND reward_id=%i", AccountID(), claim_id), - errbuf,&result)) - { - row = mysql_fetch_row(result); - if(row) - { - amt = atoi(row[0]); - } - else - { - mysql_free_result(result); - safe_delete_array(query); - return false; - } - mysql_free_result(result); - safe_delete_array(query); - } - else - { - LogFile->write(EQEMuLog::Error, "Error in Client::TryReward(): %s (%s)", query, errbuf); - safe_delete_array(query); + std::string query = StringFormat("SELECT amount FROM account_rewards " + "WHERE account_id=%i AND reward_id=%i", + AccountID(), claim_id); + auto results = database.QueryDatabase(query); + if (!results.Success()) { + LogFile->write(EQEMuLog::Error, "Error in Client::TryReward(): %s (%s)", query.c_str(), results.ErrorMessage().c_str()); return false; - } + } + + if (results.RowCount() == 0) + return false; + + uint32 amt = 0; + auto row = results.begin(); + + amt = atoi(row[0]); if(amt == 0) - { return false; - } - std::list::iterator iter = zone->VeteranRewards.begin(); - while(iter != zone->VeteranRewards.end()) - { + auto iter = zone->VeteranRewards.begin(); + for (; iter != zone->VeteranRewards.end(); ++iter) if((*iter).claim_id == claim_id) - { break; - } - ++iter; - } if(iter == zone->VeteranRewards.end()) - { return false; - } if(amt == 1) { - if(!database.RunQuery(query,MakeAnyLenString(&query,"DELETE FROM" - " account_rewards WHERE account_id=%i AND reward_id=%i", AccountID(), claim_id), - errbuf)) - { - LogFile->write(EQEMuLog::Error, "Error in Client::TryReward(): %s (%s)", query, errbuf); - safe_delete_array(query); - } - else - { - safe_delete_array(query); - } + query = StringFormat("DELETE FROM account_rewards " + "WHERE account_id=%i AND reward_id=%i", + AccountID(), claim_id); + results = database.QueryDatabase(query); + if(!results.ErrorMessage().c_str()) + LogFile->write(EQEMuLog::Error, "Error in Client::TryReward(): %s (%s)", query.c_str(), results.ErrorMessage().c_str()); + } else { - if(!database.RunQuery(query,MakeAnyLenString(&query,"UPDATE account_rewards SET amount=(amount-1)" - " WHERE account_id=%i AND reward_id=%i", AccountID(), claim_id), - errbuf)) - { - LogFile->write(EQEMuLog::Error, "Error in Client::TryReward(): %s (%s)", query, errbuf); - safe_delete_array(query); - } - else - { - safe_delete_array(query); - } + query = StringFormat("UPDATE account_rewards SET amount=(amount-1) " + "WHERE account_id=%i AND reward_id=%i", AccountID(), claim_id); + results = database.QueryDatabase(query); + if(!results.Success()) + LogFile->write(EQEMuLog::Error, "Error in Client::TryReward(): %s (%s)", query.c_str(), results.ErrorMessage().c_str()); + } InternalVeteranReward ivr = (*iter); From eb98563fa1149b28d38e8f670ddedd5186113296 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sat, 23 Aug 2014 23:20:55 -0700 Subject: [PATCH 074/127] LoadAccountFlags converted to QueryDatabase --- zone/client.cpp | 35 ++++++++++++++--------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index a85792668..802e9031a 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -7738,28 +7738,21 @@ void Client::SendFactionMessage(int32 tmpvalue, int32 faction_id, int32 totalval void Client::LoadAccountFlags() { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - accountflags.clear(); - MakeAnyLenString(&query, "SELECT p_flag, p_value FROM account_flags WHERE p_accid = '%d'", account_id); - if(database.RunQuery(query, strlen(query), errbuf, &result)) - { - while(row = mysql_fetch_row(result)) - { - std::string fname(row[0]); - std::string fval(row[1]); - accountflags[fname] = fval; - } - mysql_free_result(result); - } - else - { - std::cerr << "Error in LoadAccountFlags query '" << query << "' " << errbuf << std::endl; - } - safe_delete_array(query); + + std::string query = StringFormat("SELECT p_flag, p_value FROM account_flags WHERE p_accid = '%d'", account_id); + auto results = database.QueryDatabase(query); + if (!results.Success()) { + std::cerr << "Error in LoadAccountFlags query '" << query << "' " << results.ErrorMessage() << std::endl; + return; + } + + for (auto row = results.begin(); row != results.end(); ++row) { + std::string fname(row[0]); + std::string fval(row[1]); + accountflags[fname] = fval; + } + } void Client::SetAccountFlag(std::string flag, std::string val) From 2dbd6167254b1c90343b6eaf11678bd37daf9e28 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sat, 23 Aug 2014 23:23:26 -0700 Subject: [PATCH 075/127] SetAccountFlag converted to QueryDatabase --- zone/client.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index 802e9031a..8b0abda53 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -7757,15 +7757,11 @@ void Client::LoadAccountFlags() void Client::SetAccountFlag(std::string flag, std::string val) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - - MakeAnyLenString(&query, "REPLACE INTO account_flags (p_accid, p_flag, p_value) VALUES( '%d', '%s', '%s')", account_id, flag.c_str(), val.c_str()); - if(!database.RunQuery(query, strlen(query), errbuf)) - { - std::cerr << "Error in SetAccountFlags query '" << query << "' " << errbuf << std::endl; - } - safe_delete_array(query); + std::string query = StringFormat("REPLACE INTO account_flags (p_accid, p_flag, p_value) " + "VALUES( '%d', '%s', '%s')", account_id, flag.c_str(), val.c_str()); + auto results = database.QueryDatabase(query); + if(!results.Success()) + std::cerr << "Error in SetAccountFlags query '" << query << "' " << results.ErrorMessage() << std::endl; accountflags[flag] = val; } From 3262bee6c5bbdec9ed7392ce541edcd1c796670c Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sat, 23 Aug 2014 23:26:45 -0700 Subject: [PATCH 076/127] ExpeditionSay converted to QueryDatabase --- zone/client.cpp | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index 8b0abda53..b1ed375de 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -8170,29 +8170,21 @@ void Client::PlayMP3(const char* fname) safe_delete(outapp); } -void Client::ExpeditionSay(const char *str, int ExpID) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES *result; - MYSQL_ROW row; +void Client::ExpeditionSay(const char *str, int expID) { - if (!database.RunQuery(query,MakeAnyLenString(&query, "SELECT `player_name` FROM `cust_inst_players` WHERE `inst_id` = %i", ExpID),errbuf,&result)){ - safe_delete_array(query); + std::string query = StringFormat("SELECT `player_name` FROM " + "`cust_inst_players` WHERE " + "`inst_id` = %i", expID); + auto results = database.QueryDatabase(query); + if (!results.Success()) return; + + this->Message(14, "You say to the expedition, '%s'", str); + + for (auto row = results.begin(); row != results.end(); ++row) { + const char* charName = row[0]; + if(strcmp(charName, this->GetCleanName()) != 0) + worldserver.SendEmoteMessage(charName, 0, 0, 14, "%s says to the expedition, '%s'", this->GetCleanName(), str); } - safe_delete_array(query); - - if(result) - this->Message(14, "You say to the expedition, '%s'", str); - - while((row = mysql_fetch_row(result))) { - const char* CharName = row[0]; - if(strcmp(CharName, this->GetCleanName()) != 0) - worldserver.SendEmoteMessage(CharName, 0, 0, 14, "%s says to the expedition, '%s'", this->GetCleanName(), str); - // ChannelList->CreateChannel(ChannelName, ChannelOwner, ChannelPassword, true, atoi(row[3])); - } - - mysql_free_result(result); - } From a0fc9844fd4a87a4bd7a4cea3331f0226aef4d0d Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 27 Aug 2014 23:21:09 -0700 Subject: [PATCH 077/127] AddSpeech converted to QueryDatabase --- queryserv/database.cpp | 53 ++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/queryserv/database.cpp b/queryserv/database.cpp index cfc4a8892..631073018 100644 --- a/queryserv/database.cpp +++ b/queryserv/database.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include @@ -96,27 +96,30 @@ Close the connection to the database Database::~Database() { } - + void Database::AddSpeech(const char* from, const char* to, const char* message, uint16 minstatus, uint32 guilddbid, uint8 type) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - char *S1 = new char[strlen(from) * 2 + 1]; - char *S2 = new char[strlen(to) * 2 + 1]; - char *S3 = new char[strlen(message) * 2 + 1]; - DoEscapeString(S1, from, strlen(from)); - DoEscapeString(S2, to, strlen(to)); - DoEscapeString(S3, message, strlen(message)); + char *escapedFrom = new char[strlen(from) * 2 + 1]; + char *escapedTo = new char[strlen(to) * 2 + 1]; + char *escapedMessage = new char[strlen(message) * 2 + 1]; + DoEscapeString(escapedFrom, from, strlen(from)); + DoEscapeString(escapedTo, to, strlen(to)); + DoEscapeString(escapedMessage, message, strlen(message)); - if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_player_speech` SET `from`='%s', `to`='%s', `message`='%s', `minstatus`='%i', `guilddbid`='%i', `type`='%i'", S1, S2, S3, minstatus, guilddbid, type), errbuf, 0, 0)) { - _log(QUERYSERV__ERROR, "Failed Speech Entry Insert: %s", errbuf); - _log(QUERYSERV__ERROR, "%s", query); + std::string query = StringFormat("INSERT INTO `qs_player_speech` " + "SET `from` = '%s', `to` = '%s', `message`='%s', " + "`minstatus`='%i', `guilddbid`='%i', `type`='%i'", + escapedFrom, escapedTo, escapedMessage, minstatus, guilddbid, type); + safe_delete_array(escapedFrom); + safe_delete_array(escapedTo); + safe_delete_array(escapedMessage); + auto results = QueryDatabase(query); + if(!results.Success()) { + _log(QUERYSERV__ERROR, "Failed Speech Entry Insert: %s", results.ErrorMessage().c_str()); + _log(QUERYSERV__ERROR, "%s", query.c_str()); } - safe_delete_array(query); - safe_delete_array(S1); - safe_delete_array(S2); - safe_delete_array(S3); + } void Database::LogPlayerTrade(QSPlayerLogTrade_Struct* QS, uint32 DetailCount) { @@ -149,7 +152,7 @@ void Database::LogPlayerTrade(QSPlayerLogTrade_Struct* QS, uint32 DetailCount) { } } -void Database::LogPlayerHandin(QSPlayerLogHandin_Struct* QS, uint32 DetailCount) { +void Database::LogPlayerHandin(QSPlayerLogHandin_Struct* QS, uint32 DetailCount) { char errbuf[MYSQL_ERRMSG_SIZE]; char* query = 0; uint32 lastid = 0; @@ -225,7 +228,7 @@ void Database::LogPlayerDelete(QSPlayerLogDelete_Struct* QS, uint32 Items) { } } -void Database::LogPlayerMove(QSPlayerLogMove_Struct* QS, uint32 Items) { +void Database::LogPlayerMove(QSPlayerLogMove_Struct* QS, uint32 Items) { /* These are item moves */ char errbuf[MYSQL_ERRMSG_SIZE]; char* query = 0; @@ -236,7 +239,7 @@ void Database::LogPlayerMove(QSPlayerLogMove_Struct* QS, uint32 Items) { errbuf, 0, 0, &lastid)) { _log(QUERYSERV__ERROR, "Failed Move Log Record Insert: %s", errbuf); _log(QUERYSERV__ERROR, "%s", query); - } + } if(Items > 0) { for(int i = 0; i < Items; i++) { if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_player_move_record_entries` SET `event_id`='%i', " @@ -276,7 +279,7 @@ void Database::LogMerchantTransaction(QSMerchantLogTransaction_Struct* QS, uint3 QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5, errbuf, 0, 0))) { _log(QUERYSERV__ERROR, "Failed Transaction Log Record Entry Insert: %s", errbuf); - _log(QUERYSERV__ERROR, "%s", query); + _log(QUERYSERV__ERROR, "%s", query); } } } @@ -293,11 +296,11 @@ void Database::GeneralQueryReceive(ServerPacket *pack) { char errbuf[MYSQL_ERRMSG_SIZE]; char* query = 0; uint32 lastid = 0; - if (!RunQuery(query, MakeAnyLenString(&query, Query), errbuf, 0, 0, &lastid)) { + if (!RunQuery(query, MakeAnyLenString(&query, Query), errbuf, 0, 0, &lastid)) { _log(QUERYSERV__ERROR, "Failed Delete Log Record Insert: %s", errbuf); - _log(QUERYSERV__ERROR, "%s", query); + _log(QUERYSERV__ERROR, "%s", query); } safe_delete_array(query); - safe_delete(pack); - safe_delete(Query); + safe_delete(pack); + safe_delete(Query); } From bed8dc7d3432d9852947f1722a6545cc736589d3 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 27 Aug 2014 23:36:36 -0700 Subject: [PATCH 078/127] LogPlayerTrade converted to QueryDatabase --- queryserv/database.cpp | 61 +++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/queryserv/database.cpp b/queryserv/database.cpp index 631073018..7b9730c43 100644 --- a/queryserv/database.cpp +++ b/queryserv/database.cpp @@ -122,34 +122,45 @@ void Database::AddSpeech(const char* from, const char* to, const char* message, } -void Database::LogPlayerTrade(QSPlayerLogTrade_Struct* QS, uint32 DetailCount) { +void Database::LogPlayerTrade(QSPlayerLogTrade_Struct* QS, uint32 detailCount) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - uint32 lastid = 0; - if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_player_trade_record` SET `time`=NOW(), " - "`char1_id`='%i', `char1_pp`='%i', `char1_gp`='%i', `char1_sp`='%i', `char1_cp`='%i', `char1_items`='%i', " - "`char2_id`='%i', `char2_pp`='%i', `char2_gp`='%i', `char2_sp`='%i', `char2_cp`='%i', `char2_items`='%i'", - QS->char1_id, QS->char1_money.platinum, QS->char1_money.gold, QS->char1_money.silver, QS->char1_money.copper, QS->char1_count, - QS->char2_id, QS->char2_money.platinum, QS->char2_money.gold, QS->char2_money.silver, QS->char2_money.copper, QS->char2_count), - errbuf, 0, 0, &lastid)) { - _log(QUERYSERV__ERROR, "Failed Trade Log Record Insert: %s", errbuf); - _log(QUERYSERV__ERROR, "%s", query); + std::string query = StringFormat("INSERT INTO `qs_player_trade_record` SET `time` = NOW(), " + "`char1_id` = '%i', `char1_pp` = '%i', `char1_gp` = '%i', " + "`char1_sp` = '%i', `char1_cp` = '%i', `char1_items` = '%i', " + "`char2_id` = '%i', `char2_pp` = '%i', `char2_gp` = '%i', " + "`char2_sp` = '%i', `char2_cp` = '%i', `char2_items` = '%i'", + QS->char1_id, QS->char1_money.platinum, QS->char1_money.gold, + QS->char1_money.silver, QS->char1_money.copper, QS->char1_count, + QS->char2_id, QS->char2_money.platinum, QS->char2_money.gold, + QS->char2_money.silver, QS->char2_money.copper, QS->char2_count); + auto results = QueryDatabase(query); + if(!results.Success()) { + _log(QUERYSERV__ERROR, "Failed Trade Log Record Insert: %s", results.ErrorMessage().c_str()); + _log(QUERYSERV__ERROR, "%s", query.c_str()); } - if(DetailCount > 0) { - for(int i = 0; i < DetailCount; i++) { - if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_player_trade_record_entries` SET `event_id`='%i', " - "`from_id`='%i', `from_slot`='%i', `to_id`='%i', `to_slot`='%i', `item_id`='%i', " - "`charges`='%i', `aug_1`='%i', `aug_2`='%i', `aug_3`='%i', `aug_4`='%i', `aug_5`='%i'", - lastid, QS->items[i].from_id, QS->items[i].from_slot, QS->items[i].to_id, QS->items[i].to_slot, QS->items[i].item_id, - QS->items[i].charges, QS->items[i].aug_1, QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5, - errbuf, 0, 0))) { - _log(QUERYSERV__ERROR, "Failed Trade Log Record Entry Insert: %s", errbuf); - _log(QUERYSERV__ERROR, "%s", query); - } - } - } + if(detailCount == 0) + return; + + int lastIndex = results.LastInsertedID(); + + for(int i = 0; i < detailCount; i++) { + query = StringFormat("INSERT INTO `qs_player_trade_record_entries` SET `event_id` = '%i', " + "`from_id` = '%i', `from_slot` = '%i', `to_id` = '%i', `to_slot` = '%i', " + "`item_id` = '%i', `charges` = '%i', `aug_1` = '%i', `aug_2` = '%i', " + "`aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'", + lastIndex, QS->items[i].from_id, QS->items[i].from_slot, + QS->items[i].to_id, QS->items[i].to_slot, QS->items[i].item_id, + QS->items[i].charges, QS->items[i].aug_1, QS->items[i].aug_2, + QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5); + results = QueryDatabase(query); + if(!results.Success()) { + _log(QUERYSERV__ERROR, "Failed Trade Log Record Entry Insert: %s", results.ErrorMessage().c_str()); + _log(QUERYSERV__ERROR, "%s", query.c_str()); + } + + } + } void Database::LogPlayerHandin(QSPlayerLogHandin_Struct* QS, uint32 DetailCount) { From 18dbcf16cc5deeeafc167f5c5da1794431c4b3c3 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 27 Aug 2014 23:44:03 -0700 Subject: [PATCH 079/127] LogPlayerHandin converted to QueryDatabase --- queryserv/database.cpp | 62 +++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/queryserv/database.cpp b/queryserv/database.cpp index 7b9730c43..9df711651 100644 --- a/queryserv/database.cpp +++ b/queryserv/database.cpp @@ -163,33 +163,45 @@ void Database::LogPlayerTrade(QSPlayerLogTrade_Struct* QS, uint32 detailCount) { } -void Database::LogPlayerHandin(QSPlayerLogHandin_Struct* QS, uint32 DetailCount) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - uint32 lastid = 0; - if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_player_handin_record` SET `time`=NOW(), `quest_id`='%i', " - "`char_id`='%i', `char_pp`='%i', `char_gp`='%i', `char_sp`='%i', `char_cp`='%i', `char_items`='%i', " - "`npc_id`='%i', `npc_pp`='%i', `npc_gp`='%i', `npc_sp`='%i', `npc_cp`='%i', `npc_items`='%i'", - QS->quest_id, QS->char_id, QS->char_money.platinum, QS->char_money.gold, QS->char_money.silver, QS->char_money.copper, QS->char_count, - QS->npc_id, QS->npc_money.platinum, QS->npc_money.gold, QS->npc_money.silver, QS->npc_money.copper, QS->npc_count), - errbuf, 0, 0, &lastid)) { - _log(QUERYSERV__ERROR, "Failed Handin Log Record Insert: %s", errbuf); - _log(QUERYSERV__ERROR, "%s", query); +void Database::LogPlayerHandin(QSPlayerLogHandin_Struct* QS, uint32 detailCount) { + + std::string query = StringFormat("INSERT INTO `qs_player_handin_record` SET `time` = NOW(), " + "`quest_id` = '%i', `char_id` = '%i', `char_pp` = '%i', " + "`char_gp` = '%i', `char_sp` = '%i', `char_cp` = '%i', " + "`char_items` = '%i', `npc_id` = '%i', `npc_pp` = '%i', " + "`npc_gp` = '%i', `npc_sp` = '%i', `npc_cp` = '%i', " + "`npc_items`='%i'", + QS->quest_id, QS->char_id, QS->char_money.platinum, + QS->char_money.gold, QS->char_money.silver, QS->char_money.copper, + QS->char_count, QS->npc_id, QS->npc_money.platinum, + QS->npc_money.gold, QS->npc_money.silver, QS->npc_money.copper, + QS->npc_count); + auto results = QueryDatabase(query); + if(!results.Success()) { + _log(QUERYSERV__ERROR, "Failed Handin Log Record Insert: %s", results.ErrorMessage().c_str()); + _log(QUERYSERV__ERROR, "%s", query.c_str()); } - if(DetailCount > 0) { - for(int i = 0; i < DetailCount; i++) { - if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_player_handin_record_entries` SET `event_id`='%i', " - "`action_type`='%s', `char_slot`='%i', `item_id`='%i', `charges`='%i', " - "`aug_1`='%i', `aug_2`='%i', `aug_3`='%i', `aug_4`='%i', `aug_5`='%i'", - lastid, QS->items[i].action_type, QS->items[i].char_slot, QS->items[i].item_id, QS->items[i].charges, - QS->items[i].aug_1, QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5, - errbuf, 0, 0))) { - _log(QUERYSERV__ERROR, "Failed Handin Log Record Entry Insert: %s", errbuf); - _log(QUERYSERV__ERROR, "%s", query); - } - } - } + if(detailCount == 0) + return; + + int lastIndex = results.LastInsertedID(); + + for(int i = 0; i < detailCount; i++) { + query = StringFormat("INSERT INTO `qs_player_handin_record_entries` SET `event_id` = '%i', " + "`action_type` = '%s', `char_slot` = '%i', `item_id` = '%i', " + "`charges` = '%i', `aug_1` = '%i', `aug_2` = '%i', `aug_3` = '%i', " + "`aug_4` = '%i', `aug_5` = '%i'", + lastIndex, QS->items[i].action_type, QS->items[i].char_slot, + QS->items[i].item_id, QS->items[i].charges, QS->items[i].aug_1, + QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4, + QS->items[i].aug_5); + if(!results.Success()) { + _log(QUERYSERV__ERROR, "Failed Handin Log Record Entry Insert: %s", results.ErrorMessage().c_str()); + _log(QUERYSERV__ERROR, "%s", query.c_str()); + } + } + } void Database::LogPlayerNPCKill(QSPlayerLogNPCKill_Struct* QS, uint32 Members){ From 3a10a0129a3312b942080f85eef72115f9bcdd59 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 27 Aug 2014 23:50:58 -0700 Subject: [PATCH 080/127] LogPlayerNPCKill converted to QueryDatabase --- queryserv/database.cpp | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/queryserv/database.cpp b/queryserv/database.cpp index 9df711651..a66d810fb 100644 --- a/queryserv/database.cpp +++ b/queryserv/database.cpp @@ -204,23 +204,35 @@ void Database::LogPlayerHandin(QSPlayerLogHandin_Struct* QS, uint32 detailCount) } -void Database::LogPlayerNPCKill(QSPlayerLogNPCKill_Struct* QS, uint32 Members){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - uint32 lastid = 0; - if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_player_npc_kill_record` SET `npc_id`='%i', `type`='%i', `zone_id`='%i', `time`=NOW()", QS->s1.NPCID, QS->s1.Type, QS->s1.ZoneID), errbuf, 0, 0, &lastid)) { - _log(QUERYSERV__ERROR, "Failed NPC Kill Log Record Insert: %s", errbuf); - _log(QUERYSERV__ERROR, "%s", query); +void Database::LogPlayerNPCKill(QSPlayerLogNPCKill_Struct* QS, uint32 members){ + + std::string query = StringFormat("INSERT INTO `qs_player_npc_kill_record` " + "SET `npc_id` = '%i', `type` = '%i', " + "`zone_id` = '%i', `time` = NOW()", + QS->s1.NPCID, QS->s1.Type, QS->s1.ZoneID); + auto results = QueryDatabase(query); + if(!results.Success()) { + _log(QUERYSERV__ERROR, "Failed NPC Kill Log Record Insert: %s", results.ErrorMessage().c_str()); + _log(QUERYSERV__ERROR, "%s", query.c_str()); } - if(Members > 0){ - for (int i = 0; i < Members; i++) { - if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_player_npc_kill_record_entries` SET `event_id`='%i', `char_id`='%i'", lastid, QS->Chars[i].char_id, errbuf, 0, 0))) { - _log(QUERYSERV__ERROR, "Failed NPC Kill Log Entry Insert: %s", errbuf); - _log(QUERYSERV__ERROR, "%s", query); - } + if(members == 0) + return; + + int lastIndex = results.LastInsertedID(); + + for (int i = 0; i < members; i++) { + query = StringFormat("INSERT INTO `qs_player_npc_kill_record_entries` " + "SET `event_id` = '%i', `char_id` = '%i'", + lastIndex, QS->Chars[i].char_id); + auto results = QueryDatabase(query); + if(!results.Success()) { + _log(QUERYSERV__ERROR, "Failed NPC Kill Log Entry Insert: %s", results.ErrorMessage().c_str()); + _log(QUERYSERV__ERROR, "%s", query.c_str()); } + } + } void Database::LogPlayerDelete(QSPlayerLogDelete_Struct* QS, uint32 Items) { From e0acc937b32703aa44920d5191b190feabc761b6 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 27 Aug 2014 23:57:55 -0700 Subject: [PATCH 081/127] LogPlayerDelete converted to QueryDatabase --- queryserv/database.cpp | 51 +++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/queryserv/database.cpp b/queryserv/database.cpp index a66d810fb..e5078b377 100644 --- a/queryserv/database.cpp +++ b/queryserv/database.cpp @@ -235,32 +235,37 @@ void Database::LogPlayerNPCKill(QSPlayerLogNPCKill_Struct* QS, uint32 members){ } -void Database::LogPlayerDelete(QSPlayerLogDelete_Struct* QS, uint32 Items) { +void Database::LogPlayerDelete(QSPlayerLogDelete_Struct* QS, uint32 items) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - uint32 lastid = 0; - if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_player_delete_record` SET `time`=NOW(), " - "`char_id`='%i', `stack_size`='%i', `char_items`='%i'", - QS->char_id, QS->stack_size, QS->char_count, QS->char_count), - errbuf, 0, 0, &lastid)) { - _log(QUERYSERV__ERROR, "Failed Delete Log Record Insert: %s", errbuf); - _log(QUERYSERV__ERROR, "%s", query); + std::string query = StringFormat("INSERT INTO `qs_player_delete_record` SET `time` = NOW(), " + "`char_id` = '%i', `stack_size` = '%i', `char_items` = '%i'", + QS->char_id, QS->stack_size, QS->char_count, QS->char_count); + auto results = QueryDatabase(query); + if(!results.Success()) { + _log(QUERYSERV__ERROR, "Failed Delete Log Record Insert: %s", results.ErrorMessage().c_str()); + _log(QUERYSERV__ERROR, "%s", query.c_str()); } - if(Items > 0) { - for(int i = 0; i < Items; i++) { - if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_player_delete_record_entries` SET `event_id`='%i', " - "`char_slot`='%i', `item_id`='%i', `charges`='%i', `aug_1`='%i', " - "`aug_2`='%i', `aug_3`='%i', `aug_4`='%i', `aug_5`='%i'", - lastid, QS->items[i].char_slot, QS->items[i].item_id, QS->items[i].charges, QS->items[i].aug_1, - QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5, - errbuf, 0, 0))) { - _log(QUERYSERV__ERROR, "Failed Delete Log Record Entry Insert: %s", errbuf); - _log(QUERYSERV__ERROR, "%s", query); - } - } - } + if(items == 0) + return; + + int lastIndex = results.LastInsertedID(); + + for(int i = 0; i < items; i++) { + query = StringFormat("INSERT INTO `qs_player_delete_record_entries` SET `event_id` = '%i', " + "`char_slot` = '%i', `item_id` = '%i', `charges` = '%i', `aug_1` = '%i', " + "`aug_2` = '%i', `aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'", + lastIndex, QS->items[i].char_slot, QS->items[i].item_id, QS->items[i].charges, + QS->items[i].aug_1, QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4, + QS->items[i].aug_5); + results = QueryDatabase(query); + if(!results.Success()) { + _log(QUERYSERV__ERROR, "Failed Delete Log Record Entry Insert: %s", results.ErrorMessage().c_str()); + _log(QUERYSERV__ERROR, "%s", query.c_str()); + } + + } + } void Database::LogPlayerMove(QSPlayerLogMove_Struct* QS, uint32 Items) { From 1bc06c9c245194a1b0255f32d612ee7c34167770 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 28 Aug 2014 00:03:32 -0700 Subject: [PATCH 082/127] LogPlayerMove converted to QueryDatabase --- queryserv/database.cpp | 61 ++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/queryserv/database.cpp b/queryserv/database.cpp index e5078b377..14882c866 100644 --- a/queryserv/database.cpp +++ b/queryserv/database.cpp @@ -268,34 +268,43 @@ void Database::LogPlayerDelete(QSPlayerLogDelete_Struct* QS, uint32 items) { } -void Database::LogPlayerMove(QSPlayerLogMove_Struct* QS, uint32 Items) { +void Database::LogPlayerMove(QSPlayerLogMove_Struct* QS, uint32 items) { /* These are item moves */ - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - uint32 lastid = 0; - if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_player_move_record` SET `time`=NOW(), " - "`char_id`='%i', `from_slot`='%i', `to_slot`='%i', `stack_size`='%i', `char_items`='%i', `postaction`='%i'", - QS->char_id, QS->from_slot, QS->to_slot, QS->stack_size, QS->char_count, QS->postaction), - errbuf, 0, 0, &lastid)) { - _log(QUERYSERV__ERROR, "Failed Move Log Record Insert: %s", errbuf); - _log(QUERYSERV__ERROR, "%s", query); - } - if(Items > 0) { - for(int i = 0; i < Items; i++) { - if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_player_move_record_entries` SET `event_id`='%i', " - "`from_slot`='%i', `to_slot`='%i', `item_id`='%i', `charges`='%i', " - "`aug_1`='%i', `aug_2`='%i', `aug_3`='%i', `aug_4`='%i', `aug_5`='%i'", lastid, - QS->items[i].from_slot, QS->items[i].to_slot, QS->items[i].item_id, QS->items[i].charges, - QS->items[i].aug_1, QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5, - errbuf, 0, 0))) { - _log(QUERYSERV__ERROR, "Failed Move Log Record Entry Insert: %s", errbuf); - _log(QUERYSERV__ERROR, "%s", query); - } - } + + std::string query = StringFormat("INSERT INTO `qs_player_move_record` SET `time` = NOW(), " + "`char_id` = '%i', `from_slot` = '%i', `to_slot` = '%i', " + "`stack_size` = '%i', `char_items` = '%i', `postaction` = '%i'", + QS->char_id, QS->from_slot, QS->to_slot, QS->stack_size, + QS->char_count, QS->postaction); + auto results = QueryDatabase(query); + if(!results.Success()) { + _log(QUERYSERV__ERROR, "Failed Move Log Record Insert: %s", results.ErrorMessage().c_str()); + _log(QUERYSERV__ERROR, "%s", query.c_str()); } + + if(items == 0) + return; + + int lastIndex = results.LastInsertedID(); + + for(int i = 0; i < items; i++) { + query = StringFormat("INSERT INTO `qs_player_move_record_entries` SET `event_id` = '%i', " + "`from_slot` = '%i', `to_slot` = '%i', `item_id` = '%i', `charges` = '%i', " + "`aug_1` = '%i', `aug_2` = '%i', `aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'", + lastIndex, QS->items[i].from_slot, QS->items[i].to_slot, QS->items[i].item_id, + QS->items[i].charges, QS->items[i].aug_1, QS->items[i].aug_2, + QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5); + results = QueryDatabase(query); + if(!results.Success()) { + _log(QUERYSERV__ERROR, "Failed Move Log Record Entry Insert: %s", results.ErrorMessage().c_str()); + _log(QUERYSERV__ERROR, "%s", query.c_str()); + } + + } + } -void Database::LogMerchantTransaction(QSMerchantLogTransaction_Struct* QS, uint32 Items) { +void Database::LogMerchantTransaction(QSMerchantLogTransaction_Struct* QS, uint32 items) { /* Merchant transactions are from the perspective of the merchant, not the player -U */ char errbuf[MYSQL_ERRMSG_SIZE]; char* query = 0; @@ -310,8 +319,8 @@ void Database::LogMerchantTransaction(QSMerchantLogTransaction_Struct* QS, uint3 _log(QUERYSERV__ERROR, "%s", query); } - if(Items > 0) { - for(int i = 0; i < Items; i++) { + if(items > 0) { + for(int i = 0; i < items; i++) { if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_merchant_transaction_record_entries` SET `event_id`='%i', " "`char_slot`='%i', `item_id`='%i', `charges`='%i', `aug_1`='%i', " "`aug_2`='%i', `aug_3`='%i', `aug_4`='%i', `aug_5`='%i'", From 0a9732a26732e187cd43f4a60eca1cd7dfe312ad Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Thu, 28 Aug 2014 00:10:55 -0700 Subject: [PATCH 083/127] LogMerchantTransaction converted to QueryDatabase --- queryserv/database.cpp | 60 ++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/queryserv/database.cpp b/queryserv/database.cpp index 14882c866..f2dfebb56 100644 --- a/queryserv/database.cpp +++ b/queryserv/database.cpp @@ -306,33 +306,43 @@ void Database::LogPlayerMove(QSPlayerLogMove_Struct* QS, uint32 items) { void Database::LogMerchantTransaction(QSMerchantLogTransaction_Struct* QS, uint32 items) { /* Merchant transactions are from the perspective of the merchant, not the player -U */ - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - uint32 lastid = 0; - if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_merchant_transaction_record` SET `time`=NOW(), " - "`zone_id`='%i', `merchant_id`='%i', `merchant_pp`='%i', `merchant_gp`='%i', `merchant_sp`='%i', `merchant_cp`='%i', `merchant_items`='%i', " - "`char_id`='%i', `char_pp`='%i', `char_gp`='%i', `char_sp`='%i', `char_cp`='%i', `char_items`='%i'", - QS->zone_id, QS->merchant_id, QS->merchant_money.platinum, QS->merchant_money.gold, QS->merchant_money.silver, QS->merchant_money.copper, QS->merchant_count, - QS->char_id, QS->char_money.platinum, QS->char_money.gold, QS->char_money.silver, QS->char_money.copper, QS->char_count), - errbuf, 0, 0, &lastid)) { - _log(QUERYSERV__ERROR, "Failed Transaction Log Record Insert: %s", errbuf); - _log(QUERYSERV__ERROR, "%s", query); + std::string query = StringFormat("INSERT INTO `qs_merchant_transaction_record` SET `time` = NOW(), " + "`zone_id` = '%i', `merchant_id` = '%i', `merchant_pp` = '%i', " + "`merchant_gp` = '%i', `merchant_sp` = '%i', `merchant_cp` = '%i', " + "`merchant_items` = '%i', `char_id` = '%i', `char_pp` = '%i', " + "`char_gp` = '%i', `char_sp` = '%i', `char_cp` = '%i', " + "`char_items` = '%i'", + QS->zone_id, QS->merchant_id, QS->merchant_money.platinum, + QS->merchant_money.gold, QS->merchant_money.silver, + QS->merchant_money.copper, QS->merchant_count, QS->char_id, + QS->char_money.platinum, QS->char_money.gold, QS->char_money.silver, + QS->char_money.copper, QS->char_count); + auto results = QueryDatabase(query); + if(!results.Success()) { + _log(QUERYSERV__ERROR, "Failed Transaction Log Record Insert: %s", results.ErrorMessage().c_str()); + _log(QUERYSERV__ERROR, "%s", query.c_str()); } - if(items > 0) { - for(int i = 0; i < items; i++) { - if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_merchant_transaction_record_entries` SET `event_id`='%i', " - "`char_slot`='%i', `item_id`='%i', `charges`='%i', `aug_1`='%i', " - "`aug_2`='%i', `aug_3`='%i', `aug_4`='%i', `aug_5`='%i'", - lastid, QS->items[i].char_slot, QS->items[i].item_id, QS->items[i].charges, QS->items[i].aug_1, - QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5, - errbuf, 0, 0))) { - _log(QUERYSERV__ERROR, "Failed Transaction Log Record Entry Insert: %s", errbuf); - _log(QUERYSERV__ERROR, "%s", query); - } - } - } - safe_delete_array(query); + if(items == 0) + return; + + int lastIndex = results.LastInsertedID(); + + for(int i = 0; i < items; i++) { + query = StringFormat("INSERT INTO `qs_merchant_transaction_record_entries` SET `event_id` = '%i', " + "`char_slot` = '%i', `item_id` = '%i', `charges` = '%i', `aug_1` = '%i', " + "`aug_2` = '%i', `aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'", + lastIndex, QS->items[i].char_slot, QS->items[i].item_id, QS->items[i].charges, + QS->items[i].aug_1, QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4, + QS->items[i].aug_5); + results = QueryDatabase(query); + if(!results.Success()) { + _log(QUERYSERV__ERROR, "Failed Transaction Log Record Entry Insert: %s", results.ErrorMessage().c_str()); + _log(QUERYSERV__ERROR, "%s", query.c_str()); + } + + } + } void Database::GeneralQueryReceive(ServerPacket *pack) { From 8e529105cf47fea317e55c87939d749658969235 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 3 Sep 2014 19:07:49 -0700 Subject: [PATCH 084/127] CheckGuildDoor converted to QueryDatabase --- zone/guild.cpp | 45 ++++++++++++++------------------------------- 1 file changed, 14 insertions(+), 31 deletions(-) diff --git a/zone/guild.cpp b/zone/guild.cpp index 6512bedec..18570d221 100644 --- a/zone/guild.cpp +++ b/zone/guild.cpp @@ -165,7 +165,7 @@ void Client::SendGuildSpawnAppearance() { switch (rank) { case 0: { rank = 5; break; } // GUILD_MEMBER 0 case 1: { rank = 3; break; } // GUILD_OFFICER 1 - case 2: { rank = 1; break; } // GUILD_LEADER 2 + case 2: { rank = 1; break; } // GUILD_LEADER 2 default: { break; } // GUILD_NONE } } @@ -417,38 +417,21 @@ void Client::GuildChangeRank(const char* name, uint32 guild_id, uint32 oldrank, }*/ -bool ZoneDatabase::CheckGuildDoor(uint8 doorid,uint16 guild_id,const char* zone) { - MYSQL_ROW row; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - if (!RunQuery(query, MakeAnyLenString(&query, - "SELECT guild FROM doors where doorid=%i AND zone='%s'", - doorid-128, zone), errbuf, &result)) - { - LogFile->write(EQEMuLog::Error, "Error in CheckGuildDoor query '%s': %s", query, errbuf); - safe_delete_array(query); - return false; - } else { - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - if (atoi(row[0]) == guild_id) - { - mysql_free_result(result); - return true; - } - else - { - mysql_free_result(result); - return false; - } +bool ZoneDatabase::CheckGuildDoor(uint8 doorid, uint16 guild_id, const char* zone) { - // code below will never be reached - mysql_free_result(result); - return false; - } + std::string query = StringFormat("SELECT guild FROM doors WHERE doorid = %i AND zone = '%s'", + doorid-128, zone); + auto results = QueryDatabase(query); + if (!results.Success()) { + LogFile->write(EQEMuLog::Error, "Error in CheckGuildDoor query '%s': %s", query.c_str(), results.ErrorMessage().c_str()); + return false; } - return false; + + if (results.RowCount() != 1) + return false; + + auto row = results.begin(); + return atoi(row[0]) == guild_id; } bool ZoneDatabase::SetGuildDoor(uint8 doorid,uint16 guild_id, const char* zone) { From f215874486672247be18c16fb91244b1a47eae45 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 3 Sep 2014 19:10:27 -0700 Subject: [PATCH 085/127] SetGuildDoor converted to QueryDatabase --- zone/guild.cpp | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/zone/guild.cpp b/zone/guild.cpp index 18570d221..5f8378d2b 100644 --- a/zone/guild.cpp +++ b/zone/guild.cpp @@ -435,22 +435,18 @@ bool ZoneDatabase::CheckGuildDoor(uint8 doorid, uint16 guild_id, const char* zon } bool ZoneDatabase::SetGuildDoor(uint8 doorid,uint16 guild_id, const char* zone) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; + if (doorid > 127) doorid = doorid - 128; - if (!RunQuery(query, MakeAnyLenString(&query, - "UPDATE doors SET guild = %i WHERE (doorid=%i) AND (zone='%s')", - guild_id, doorid, zone), errbuf, 0,&affected_rows)) - { - LogFile->write(EQEMuLog::Error, "Error in SetGuildDoor query '%s': %s", query, errbuf); - safe_delete_array(query); + + std::string query = StringFormat("UPDATE doors SET guild = %i WHERE (doorid=%i) AND (zone='%s')", + guild_id, doorid, zone); + auto results = QueryDatabase(query); + if (!results.Success()) { + LogFile->write(EQEMuLog::Error, "Error in SetGuildDoor query '%s': %s", query.c_str(), results.ErrorMessage().c_str()); return false; } - safe_delete_array(query); - - return(affected_rows > 0); + return (results.RowsAffected() > 0); } From 610f3ed37f597f88dfbc8025cdd599220dbe1669 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 3 Sep 2014 19:17:55 -0700 Subject: [PATCH 086/127] AddItem converted to QueryDatabase --- zone/guild_mgr.cpp | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/zone/guild_mgr.cpp b/zone/guild_mgr.cpp index cc23d14c9..d21ae6bf6 100644 --- a/zone/guild_mgr.cpp +++ b/zone/guild_mgr.cpp @@ -903,24 +903,16 @@ bool GuildBankManager::AddItem(uint32 GuildID, uint8 Area, uint32 ItemID, int32 return false; } - const char *Query="INSERT INTO `guild_bank` (`guildid`, `area`, `slot`, `itemid`, `qty`, `donator`, `permissions`, `WhoFor`) " - "VALUES (%i, %i, %i, %i, %i, '%s', %i, '%s')"; - - char errbuf[MYSQL_ERRMSG_SIZE]; - - char* query = 0; - - if(!database.RunQuery(query, MakeAnyLenString(&query, Query, GuildID, Area, Slot, ItemID, QtyOrCharges, Donator, Permissions, WhoFor), errbuf)) - { - _log(GUILDS__BANK_ERROR, "Insert Error: %s : %s", query, errbuf); - - safe_delete_array(query); - + std::string query = StringFormat("INSERT INTO `guild_bank` " + "(`guildid`, `area`, `slot`, `itemid`, `qty`, `donator`, `permissions`, `WhoFor`) " + "VALUES (%i, %i, %i, %i, %i, '%s', %i, '%s')", + GuildID, Area, Slot, ItemID, QtyOrCharges, Donator, Permissions, WhoFor); + auto results = database.QueryDatabase(query); + if(!results.Success()) { + _log(GUILDS__BANK_ERROR, "Insert Error: %s : %s", query.c_str(), results.ErrorMessage().c_str()); return false; } - safe_delete_array(query); - const Item_Struct *Item = database.GetItem(ItemID); GuildBankItemUpdate_Struct gbius; From f5e49441b66e643459f996677d6cf2f76b13fb2b Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 3 Sep 2014 19:28:25 -0700 Subject: [PATCH 087/127] GetHighestGrid converted to QueryDatabase --- zone/waypoints.cpp | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index c3a19a6f3..aa58496e7 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -1007,26 +1007,19 @@ void Mob::SendToFixZ(float new_x, float new_y, float new_z) { } int ZoneDatabase::GetHighestGrid(uint32 zoneid) { - char *query = 0; - char errbuff[MYSQL_ERRMSG_SIZE]; - MYSQL_RES *result; - MYSQL_ROW row; - int res = 0; - if (RunQuery(query, MakeAnyLenString(&query, - "SELECT COALESCE(MAX(id), 0) FROM grid WHERE zoneid = %i", - zoneid),errbuff,&result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - res = atoi( row[0] ); - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error in GetHighestGrid query '%s': %s", query, errbuff); - safe_delete_array(query); - } - return(res); + std::string query = StringFormat("SELECT COALESCE(MAX(id), 0) FROM grid WHERE zoneid = %i", zoneid); + auto results = QueryDatabase(query); + if (!results.Success()) { + LogFile->write(EQEMuLog::Error, "Error in GetHighestGrid query '%s': %s", query.c_str(), results.ErrorMessage().c_str()); + return 0; + } + + if (results.RowCount() != 1) + return 0; + + auto row = results.begin(); + return atoi(row[0]); } uint8 ZoneDatabase::GetGridType2(uint32 grid, uint16 zoneid) { From 7d8d96c049b0af09ad74a8f5800b26ad1f6ad30c Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 3 Sep 2014 20:45:38 -0700 Subject: [PATCH 088/127] LoadTitles converted to QueryDatabase --- zone/titles.cpp | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/zone/titles.cpp b/zone/titles.cpp index 802d33935..6ddca0e36 100644 --- a/zone/titles.cpp +++ b/zone/titles.cpp @@ -31,25 +31,17 @@ bool TitleManager::LoadTitles() { Titles.clear(); - TitleEntry Title; - - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = nullptr; - MYSQL_RES *result; - MYSQL_ROW row; - - if (!database.RunQuery(query, MakeAnyLenString(&query, - "SELECT `id`, `skill_id`, `min_skill_value`, `max_skill_value`, `min_aa_points`, `max_aa_points`, `class`, `gender`, " - "`char_id`, `status`, `item_id`, `prefix`, `suffix`, `title_set` from titles"), errbuf, &result)) - { - LogFile->write(EQEMuLog::Error, "Unable to load titles: %s : %s", query, errbuf); - safe_delete_array(query); - return(false); + std::string query = "SELECT `id`, `skill_id`, `min_skill_value`, `max_skill_value`, " + "`min_aa_points`, `max_aa_points`, `class`, `gender`, `char_id`, " + "`status`, `item_id`, `prefix`, `suffix`, `title_set` FROM titles"; + auto results = database.QueryDatabase(query); + if (!results.Success()) { + LogFile->write(EQEMuLog::Error, "Unable to load titles: %s : %s", query.c_str(), results.ErrorMessage().c_str()); + return false; } - safe_delete_array(query); - - while ((row = mysql_fetch_row(result))) { + for (auto row = results.begin(); row != results.end(); ++row) { + TitleEntry Title; Title.TitleID = atoi(row[0]); Title.SkillID = (SkillUseTypes) atoi(row[1]); Title.MinSkillValue = atoi(row[2]); @@ -66,9 +58,8 @@ bool TitleManager::LoadTitles() Title.TitleSet = atoi(row[13]); Titles.push_back(Title); } - mysql_free_result(result); - return(true); + return true; } EQApplicationPacket *TitleManager::MakeTitlesPacket(Client *c) From 81cf748b2b765c3ea4c24b89625909d6a5f9d6aa Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 3 Sep 2014 20:52:00 -0700 Subject: [PATCH 089/127] CreateNewPlayerTitle converted to QueryDatabase --- zone/titles.cpp | 57 ++++++++++++++++++++----------------------------- 1 file changed, 23 insertions(+), 34 deletions(-) diff --git a/zone/titles.cpp b/zone/titles.cpp index 6ddca0e36..1e6941476 100644 --- a/zone/titles.cpp +++ b/zone/titles.cpp @@ -235,48 +235,37 @@ bool TitleManager::IsNewTradeSkillTitleAvailable(int SkillID, int SkillValue) return false; } -void TitleManager::CreateNewPlayerTitle(Client *c, const char *Title) +void TitleManager::CreateNewPlayerTitle(Client *client, const char *title) { - if(!c || !Title) + if(!client || !title) return; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = nullptr; - MYSQL_RES *result; + char *escTitle = new char[strlen(title) * 2 + 1]; - char *EscTitle = new char[strlen(Title) * 2 + 1]; + client->SetAATitle(title); - c->SetAATitle(Title); - - database.DoEscapeString(EscTitle, Title, strlen(Title)); - - if (database.RunQuery(query, MakeAnyLenString(&query, - "SELECT `id` from titles where `prefix` = '%s' and char_id = %i", EscTitle, c->CharacterID()), errbuf, &result)) - { - if(mysql_num_rows(result) > 0) - { - mysql_free_result(result); - safe_delete_array(query); - safe_delete_array(EscTitle); - return; - } - mysql_free_result(result); + database.DoEscapeString(escTitle, title, strlen(title)); + auto query = StringFormat("SELECT `id` FROM titles " + "WHERE `prefix` = '%s' AND char_id = %i", + escTitle, client->CharacterID()); + auto results = database.QueryDatabase(query); + if (results.Success() && results.RowCount() > 0){ + safe_delete_array(escTitle); + return; } - safe_delete_array(query); - - if(!database.RunQuery(query,MakeAnyLenString(&query, "INSERT into titles (`char_id`, `prefix`) VALUES(%i, '%s')", - c->CharacterID(), EscTitle), errbuf)) - LogFile->write(EQEMuLog::Error, "Error adding title: %s %s", query, errbuf); - else - { - ServerPacket* pack = new ServerPacket(ServerOP_ReloadTitles, 0); - worldserver.SendPacket(pack); - safe_delete(pack); - } - safe_delete_array(query); - safe_delete_array(EscTitle); + query = StringFormat("INSERT INTO titles (`char_id`, `prefix`) VALUES(%i, '%s')", + client->CharacterID(), escTitle); + safe_delete_array(escTitle); + results = database.QueryDatabase(query); + if(!results.Success()) { + LogFile->write(EQEMuLog::Error, "Error adding title: %s %s", query.c_str(), results.ErrorMessage().c_str()); + return; + } + ServerPacket* pack = new ServerPacket(ServerOP_ReloadTitles, 0); + worldserver.SendPacket(pack); + safe_delete(pack); } void TitleManager::CreateNewPlayerSuffix(Client *c, const char *Suffix) From 9a4d01da8f5448135223ac9f17abe0465221b739 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 3 Sep 2014 20:57:26 -0700 Subject: [PATCH 090/127] CreateNewPlayerSuffix converted to QueryDatabase --- zone/titles.cpp | 57 ++++++++++++++++++++----------------------------- 1 file changed, 23 insertions(+), 34 deletions(-) diff --git a/zone/titles.cpp b/zone/titles.cpp index 1e6941476..3b4dce8f6 100644 --- a/zone/titles.cpp +++ b/zone/titles.cpp @@ -268,48 +268,37 @@ void TitleManager::CreateNewPlayerTitle(Client *client, const char *title) safe_delete(pack); } -void TitleManager::CreateNewPlayerSuffix(Client *c, const char *Suffix) +void TitleManager::CreateNewPlayerSuffix(Client *client, const char *suffix) { - if(!c || !Suffix) + if(!client || !suffix) return; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = nullptr; - MYSQL_RES *result; + client->SetTitleSuffix(suffix); - char *EscSuffix = new char[strlen(Suffix) * 2 + 1]; + char *escSuffix = new char[strlen(suffix) * 2 + 1]; + database.DoEscapeString(escSuffix, suffix, strlen(suffix)); - c->SetTitleSuffix(Suffix); - - database.DoEscapeString(EscSuffix, Suffix, strlen(Suffix)); - - if (database.RunQuery(query, MakeAnyLenString(&query, - "SELECT `id` from titles where `suffix` = '%s' and char_id = %i", EscSuffix, c->CharacterID()), errbuf, &result)) - { - if(mysql_num_rows(result) > 0) - { - mysql_free_result(result); - safe_delete_array(query); - safe_delete_array(EscSuffix); + std::string query = StringFormat("SELECT `id` FROM titles " + "WHERE `suffix` = '%s' AND char_id = %i", + escSuffix, client->CharacterID()); + auto results = database.QueryDatabase(query); + if (results.Success() && results.RowCount() > 0) { + safe_delete_array(escSuffix); return; - } - mysql_free_result(result); - } + } - safe_delete_array(query); - - if(!database.RunQuery(query,MakeAnyLenString(&query, "INSERT into titles (`char_id`, `suffix`) VALUES(%i, '%s')", - c->CharacterID(), EscSuffix), errbuf)) - LogFile->write(EQEMuLog::Error, "Error adding title suffix: %s %s", query, errbuf); - else - { - ServerPacket* pack = new ServerPacket(ServerOP_ReloadTitles, 0); - worldserver.SendPacket(pack); - safe_delete(pack); - } - safe_delete_array(query); - safe_delete_array(EscSuffix); + query = StringFormat("INSERT INTO titles (`char_id`, `suffix`) VALUES(%i, '%s')", + client->CharacterID(), escSuffix); + safe_delete_array(escSuffix); + results = database.QueryDatabase(query); + if(!results.Success()) { + LogFile->write(EQEMuLog::Error, "Error adding title suffix: %s %s", query.c_str(), results.ErrorMessage().c_str()); + return; + } + ServerPacket* pack = new ServerPacket(ServerOP_ReloadTitles, 0); + worldserver.SendPacket(pack); + safe_delete(pack); } void Client::SetAATitle(const char *Title) From fd08e9f2ad865c9270ba6aacfe4931bcc53ce6d2 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 3 Sep 2014 21:00:15 -0700 Subject: [PATCH 091/127] EnableTitle converted to QueryDatabase --- zone/titles.cpp | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/zone/titles.cpp b/zone/titles.cpp index 3b4dce8f6..24559a693 100644 --- a/zone/titles.cpp +++ b/zone/titles.cpp @@ -337,24 +337,18 @@ void Client::SetTitleSuffix(const char *Suffix) safe_delete(outapp); } -void Client::EnableTitle(int titleset) { +void Client::EnableTitle(int titleSet) { - if (CheckTitle(titleset)) { + if (CheckTitle(titleSet)) return; - } - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; + std::string query = StringFormat("INSERT INTO player_titlesets " + "(char_id, title_set) VALUES (%i, %i)", + CharacterID(), titleSet); + auto results = database.QueryDatabase(query); + if(!results.Success()) + LogFile->write(EQEMuLog::Error, "Error in EnableTitle query for titleset %i and charid %i", titleSet, CharacterID()); - if(!database.RunQuery(query,MakeAnyLenString(&query, "INSERT INTO player_titlesets (char_id, title_set) VALUES (%i, %i)", CharacterID(), titleset), errbuf)) { - LogFile->write(EQEMuLog::Error, "Error in EnableTitle query for titleset %i and charid %i", titleset, CharacterID()); - safe_delete_array(query); - return; - } - else { - safe_delete_array(query); - return; - } } bool Client::CheckTitle(int titleset) { From b7c409e11bf835aa0c5880584b813177bc93cdbe Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 3 Sep 2014 21:03:00 -0700 Subject: [PATCH 092/127] CheckTitle converted to QueryDatabase --- zone/titles.cpp | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/zone/titles.cpp b/zone/titles.cpp index 24559a693..7d30b63fd 100644 --- a/zone/titles.cpp +++ b/zone/titles.cpp @@ -351,27 +351,21 @@ void Client::EnableTitle(int titleSet) { } -bool Client::CheckTitle(int titleset) { +bool Client::CheckTitle(int titleSet) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - - if (database.RunQuery(query, MakeAnyLenString(&query, "SELECT `id` FROM player_titlesets WHERE `title_set`=%i AND `char_id`=%i LIMIT 1", titleset, CharacterID()), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) >= 1) { - mysql_free_result(result); - return(true); - } - mysql_free_result(result); + std::string query = StringFormat("SELECT `id` FROM player_titlesets " + "WHERE `title_set`=%i AND `char_id`=%i LIMIT 1", + titleSet, CharacterID()); + auto results = database.QueryDatabase(query); + if (!results.Success()) { + LogFile->write(EQEMuLog::Error, "Error in CheckTitle query '%s': %s", query.c_str(), results.ErrorMessage().c_str()); + return false; } - else { - LogFile->write(EQEMuLog::Error, "Error in CheckTitle query '%s': %s", query, errbuf); - safe_delete_array(query); - } + if (results.RowCount() == 0) + return false; - return(false); + return true; } void Client::RemoveTitle(int titleset) { From 399bf96a0cbb07fa005d9d715809c37a167f58cb Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Wed, 3 Sep 2014 21:05:31 -0700 Subject: [PATCH 093/127] RemoveTitle converted to QueryDatabase --- zone/titles.cpp | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/zone/titles.cpp b/zone/titles.cpp index 7d30b63fd..eeae38b8a 100644 --- a/zone/titles.cpp +++ b/zone/titles.cpp @@ -368,24 +368,17 @@ bool Client::CheckTitle(int titleSet) { return true; } -void Client::RemoveTitle(int titleset) { +void Client::RemoveTitle(int titleSet) { - if (!CheckTitle(titleset)) { + if (!CheckTitle(titleSet)) return; - } - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; + std::string query = StringFormat("DELETE FROM player_titlesets " + "WHERE `title_set` = %i AND `char_id` = %i", + titleSet, CharacterID()); + auto results = database.QueryDatabase(query); + if (!results.Success()) + LogFile->write(EQEMuLog::Error, "Error in RemoveTitle query '%s': %s", query.c_str(), results.ErrorMessage().c_str()); - if (database.RunQuery(query, MakeAnyLenString(&query, "DELETE FROM player_titlesets WHERE `title_set`=%i AND `char_id`=%i", titleset, CharacterID()), errbuf)) { - safe_delete_array(query); - } - - else { - LogFile->write(EQEMuLog::Error, "Error in RemoveTitle query '%s': %s", query, errbuf); - safe_delete_array(query); - } - - return; } From b1587f0326be4e9eed9cdb58f75d227aef16f954 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sat, 6 Sep 2014 12:51:50 -0700 Subject: [PATCH 094/127] Delete client.cpp.orig not supposed to be in there. --- zone/client.cpp.orig | 8232 ------------------------------------------ 1 file changed, 8232 deletions(-) delete mode 100644 zone/client.cpp.orig diff --git a/zone/client.cpp.orig b/zone/client.cpp.orig deleted file mode 100644 index cc4d04977..000000000 --- a/zone/client.cpp.orig +++ /dev/null @@ -1,8232 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.org) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#include "../common/debug.h" -#include -#include -#include -#include -#include -#include -#include -#include - -// for windows compile -#ifdef _WINDOWS - #define abs64 _abs64 -#else - #include - #include - #include - #include "../common/unix.h" - #define abs64 abs -#endif - -extern volatile bool RunLoops; - -#include "../common/features.h" -#include "masterentity.h" -#include "worldserver.h" -#include "../common/misc.h" -#include "zonedb.h" -#include "../common/spdat.h" -#include "net.h" -#include "../common/packet_dump.h" -#include "../common/packet_functions.h" -#include "petitions.h" -#include "../common/serverinfo.h" -#include "../common/zone_numbers.h" -#include "../common/moremath.h" -#include "../common/guilds.h" -#include "../common/breakdowns.h" -#include "../common/rulesys.h" -#include "../common/string_util.h" -#include "forage.h" -#include "command.h" -#include "string_ids.h" -#include "npc_ai.h" -#include "client_logs.h" -#include "guild_mgr.h" -#include "quest_parser_collection.h" -#include "queryserv.h" - -extern QueryServ* QServ; -extern EntityList entity_list; -extern Zone* zone; -extern volatile bool ZoneLoaded; -extern WorldServer worldserver; -extern uint32 numclients; -extern PetitionList petition_list; -bool commandlogged; -char entirecommand[255]; -extern DBAsyncFinishedQueue MTdbafq; -extern DBAsync *dbasync; - -Client::Client(EQStreamInterface* ieqs) -: Mob("No name", // name - "", // lastname - 0, // cur_hp - 0, // max_hp - 0, // gender - 0, // race - 0, // class - BT_Humanoid, // bodytype - 0, // deity - 0, // level - 0, // npctypeid - 0, // size - 0.7, // runspeed - 0, // heading - 0, // x - 0, // y - 0, // z - 0, // light - 0xFF, // texture - 0xFF, // helmtexture - 0, // ac - 0, // atk - 0, // str - 0, // sta - 0, // dex - 0, // agi - 0, // int - 0, // wis - 0, // cha - 0, // Luclin Hair Colour - 0, // Luclin Beard Color - 0, // Luclin Eye1 - 0, // Luclin Eye2 - 0, // Luclin Hair Style - 0, // Luclin Face - 0, // Luclin Beard - 0, // Drakkin Heritage - 0, // Drakkin Tattoo - 0, // Drakkin Details - 0, // Armor Tint - 0xff, // AA Title - 0, // see_invis - 0, // see_invis_undead - 0, - 0, - 0, - 0, - 0, // qglobal - 0, // maxlevel - 0 // scalerate - - ), - //these must be listed in the order they appear in client.h - position_timer(250), - hpupdate_timer(1800), - camp_timer(29000), - process_timer(100), - stamina_timer(40000), - zoneinpacket_timer(3000), - linkdead_timer(RuleI(Zone,ClientLinkdeadMS)), - dead_timer(2000), - global_channel_timer(1000), - shield_timer(500), - fishing_timer(8000), - endupkeep_timer(1000), - forget_timer(0), - autosave_timer(RuleI(Character, AutosaveIntervalS)*1000), -#ifdef REVERSE_AGGRO - scanarea_timer(AIClientScanarea_delay), -#endif - tribute_timer(Tribute_duration), - proximity_timer(ClientProximity_interval), - TaskPeriodic_Timer(RuleI(TaskSystem, PeriodicCheckTimer) * 1000), - charm_update_timer(6000), - rest_timer(1), - charm_class_attacks_timer(3000), - charm_cast_timer(3500), - qglobal_purge_timer(30000), - TrackingTimer(2000), - RespawnFromHoverTimer(0), - merc_timer(RuleI(Mercs, UpkeepIntervalMS)), - ItemTickTimer(10000), - ItemQuestTimer(500) -{ - for(int cf=0; cf < _FilterCount; cf++) - ClientFilters[cf] = FilterShow; - character_id = 0; - conn_state = NoPacketsReceived; - client_data_loaded = false; - feigned = false; - berserk = false; - dead = false; - eqs = ieqs; - ip = eqs->GetRemoteIP(); - port = ntohs(eqs->GetRemotePort()); - client_state = CLIENT_CONNECTING; - Trader=false; - Buyer = false; - CustomerID = 0; - TrackingID = 0; - WID = 0; - account_id = 0; - admin = 0; - lsaccountid = 0; - shield_target = nullptr; - SQL_log = nullptr; - guild_id = GUILD_NONE; - guildrank = 0; - GuildBanker = false; - memset(lskey, 0, sizeof(lskey)); - strcpy(account_name, ""); - tellsoff = false; - last_reported_mana = 0; - last_reported_endur = 0; - gmhideme = false; - AFK = false; - LFG = false; - LFGFromLevel = 0; - LFGToLevel = 0; - LFGMatchFilter = false; - LFGComments[0] = '\0'; - LFP = false; - gmspeed = 0; - playeraction = 0; - SetTarget(0); - auto_attack = false; - auto_fire = false; - linkdead_timer.Disable(); - zonesummon_x = -2; - zonesummon_y = -2; - zonesummon_z = -2; - zonesummon_id = 0; - zonesummon_ignorerestrictions = 0; - zoning = false; - zone_mode = ZoneUnsolicited; - proximity_x = FLT_MAX; //arbitrary large number - proximity_y = FLT_MAX; - proximity_z = FLT_MAX; - casting_spell_id = 0; - npcflag = false; - npclevel = 0; - pQueuedSaveWorkID = 0; - position_timer_counter = 0; - fishing_timer.Disable(); - shield_timer.Disable(); - dead_timer.Disable(); - camp_timer.Disable(); - autosave_timer.Disable(); - GetMercTimer()->Disable(); - instalog = false; - pLastUpdate = 0; - pLastUpdateWZ = 0; - m_pp.autosplit = false; - // initialise haste variable - m_tradeskill_object = nullptr; - delaytimer = false; - PendingRezzXP = -1; - PendingRezzDBID = 0; - PendingRezzSpellID = 0; - numclients++; - // emuerror; - UpdateWindowTitle(); - horseId = 0; - tgb = false; - tribute_master_id = 0xFFFFFFFF; - tribute_timer.Disable(); - taskstate = nullptr; - TotalSecondsPlayed = 0; - keyring.clear(); - bind_sight_target = nullptr; - mercid = 0; - mercSlot = 0; - InitializeMercInfo(); - SetMerc(0); - - logging_enabled = CLIENT_DEFAULT_LOGGING_ENABLED; - - //for good measure: - memset(&m_pp, 0, sizeof(m_pp)); - memset(&m_epp, 0, sizeof(m_epp)); - PendingTranslocate = false; - PendingSacrifice = false; - BoatID = 0; - - KarmaUpdateTimer = new Timer(RuleI(Chat, KarmaUpdateIntervalMS)); - GlobalChatLimiterTimer = new Timer(RuleI(Chat, IntervalDurationMS)); - AttemptedMessages = 0; - TotalKarma = 0; - ClientVersion = EQClientUnknown; - ClientVersionBit = 0; - AggroCount = 0; - RestRegenHP = 0; - RestRegenMana = 0; - RestRegenEndurance = 0; - XPRate = 100; - cur_end = 0; - - m_TimeSinceLastPositionCheck = 0; - m_DistanceSinceLastPositionCheck = 0.0f; - m_ShadowStepExemption = 0; - m_KnockBackExemption = 0; - m_PortExemption = 0; - m_SenseExemption = 0; - m_AssistExemption = 0; - m_CheatDetectMoved = false; - CanUseReport = true; - aa_los_me.x = 0; - aa_los_me.y = 0; - aa_los_me.z = 0; - aa_los_me_heading = 0; - aa_los_them.x = 0; - aa_los_them.y = 0; - aa_los_them.z = 0; - aa_los_them_mob = nullptr; - los_status = false; - los_status_facing = false; - qGlobals = nullptr; - HideCorpseMode = HideCorpseNone; - PendingGuildInvitation = false; - - cur_end = 0; - - InitializeBuffSlots(); - - adventure_request_timer = nullptr; - adventure_create_timer = nullptr; - adventure_leave_timer = nullptr; - adventure_door_timer = nullptr; - adv_requested_data = nullptr; - adventure_stats_timer = nullptr; - adventure_leaderboard_timer = nullptr; - adv_data = nullptr; - adv_requested_theme = 0; - adv_requested_id = 0; - adv_requested_member_count = 0; - - for(int i = 0; i < XTARGET_HARDCAP; ++i) - { - XTargets[i].Type = Auto; - XTargets[i].ID = 0; - XTargets[i].Name[0] = 0; - } - MaxXTargets = 5; - XTargetAutoAddHaters = true; - LoadAccountFlags(); - - initial_respawn_selection = 0; - alternate_currency_loaded = false; - - EngagedRaidTarget = false; - SavedRaidRestTimer = 0; -} - -Client::~Client() { -#ifdef BOTS - Bot::ProcessBotOwnerRefDelete(this); -#endif - if(IsInAGuild()) - guild_mgr.SendGuildMemberUpdateToWorld(GetName(), GuildID(), 0, time(nullptr)); - - Mob* horse = entity_list.GetMob(this->CastToClient()->GetHorseId()); - if (horse) - horse->Depop(); - - Mob* merc = entity_list.GetMob(this->GetMercID()); - if (merc) - merc->Depop(); - - if(Trader) - database.DeleteTraderItem(this->CharacterID()); - - if(Buyer) - ToggleBuyerMode(false); - - if(conn_state != ClientConnectFinished) { - LogFile->write(EQEMuLog::Debug, "Client '%s' was destroyed before reaching the connected state:", GetName()); - ReportConnectingState(); - } - - if(m_tradeskill_object != nullptr) { - m_tradeskill_object->Close(); - m_tradeskill_object = nullptr; - } - -#ifdef CLIENT_LOGS - client_logs.unsubscribeAll(this); -#endif - - ChangeSQLLog(nullptr); - if(IsDueling() && GetDuelTarget() != 0) { - Entity* entity = entity_list.GetID(GetDuelTarget()); - if(entity != nullptr && entity->IsClient()) { - entity->CastToClient()->SetDueling(false); - entity->CastToClient()->SetDuelTarget(0); - entity_list.DuelMessage(entity->CastToClient(),this,true); - } - } - - if (shield_target) { - for (int y = 0; y < 2; y++) { - if (shield_target->shielder[y].shielder_id == GetID()) { - shield_target->shielder[y].shielder_id = 0; - shield_target->shielder[y].shielder_bonus = 0; - } - } - shield_target = nullptr; - } - - if(GetTarget()) - GetTarget()->IsTargeted(-1); - - //if we are in a group and we are not zoning, force leave the group - if(isgrouped && !zoning && ZoneLoaded) - LeaveGroup(); - - UpdateWho(2); - - if(IsHoveringForRespawn()) - { - m_pp.zone_id = m_pp.binds[0].zoneId; - m_pp.zoneInstance = 0; - x_pos = m_pp.binds[0].x; - y_pos = m_pp.binds[0].y; - z_pos = m_pp.binds[0].z; - } - - // we save right now, because the client might be zoning and the world - // will need this data right away - Save(2); // This fails when database destructor is called first on shutdown - - safe_delete(taskstate); - safe_delete(KarmaUpdateTimer); - safe_delete(GlobalChatLimiterTimer); - safe_delete(qGlobals); - safe_delete(adventure_request_timer); - safe_delete(adventure_create_timer); - safe_delete(adventure_leave_timer); - safe_delete(adventure_door_timer); - safe_delete(adventure_stats_timer); - safe_delete(adventure_leaderboard_timer); - safe_delete_array(adv_requested_data); - safe_delete_array(adv_data); - - ClearRespawnOptions(); - - numclients--; - UpdateWindowTitle(); - if(zone) - zone->RemoveAuth(GetName()); - - //let the stream factory know were done with this stream - eqs->Close(); - eqs->ReleaseFromUse(); - - UninitializeBuffSlots(); -} - -void Client::SendLogoutPackets() { - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_CancelTrade, sizeof(CancelTrade_Struct)); - CancelTrade_Struct* ct = (CancelTrade_Struct*) outapp->pBuffer; - ct->fromid = GetID(); - ct->action = groupActUpdate; - FastQueuePacket(&outapp); - - outapp = new EQApplicationPacket(OP_PreLogoutReply); - FastQueuePacket(&outapp); - -} - -void Client::ReportConnectingState() { - switch(conn_state) { - case NoPacketsReceived: //havent gotten anything - LogFile->write(EQEMuLog::Debug, "Client has not sent us an initial zone entry packet."); - break; - case ReceivedZoneEntry: //got the first packet, loading up PP - LogFile->write(EQEMuLog::Debug, "Client sent initial zone packet, but we never got their player info from the database."); - break; - case PlayerProfileLoaded: //our DB work is done, sending it - LogFile->write(EQEMuLog::Debug, "We were sending the player profile, tributes, tasks, spawns, time and weather, but never finished."); - break; - case ZoneInfoSent: //includes PP, tributes, tasks, spawns, time and weather - LogFile->write(EQEMuLog::Debug, "We successfully sent player info and spawns, waiting for client to request new zone."); - break; - case NewZoneRequested: //received and sent new zone request - LogFile->write(EQEMuLog::Debug, "We received client's new zone request, waiting for client spawn request."); - break; - case ClientSpawnRequested: //client sent ReqClientSpawn - LogFile->write(EQEMuLog::Debug, "We received the client spawn request, and were sending objects, doors, zone points and some other stuff, but never finished."); - break; - case ZoneContentsSent: //objects, doors, zone points - LogFile->write(EQEMuLog::Debug, "The rest of the zone contents were successfully sent, waiting for client ready notification."); - break; - case ClientReadyReceived: //client told us its ready, send them a bunch of crap like guild MOTD, etc - LogFile->write(EQEMuLog::Debug, "We received client ready notification, but never finished Client::CompleteConnect"); - break; - case ClientConnectFinished: //client finally moved to finished state, were done here - LogFile->write(EQEMuLog::Debug, "Client is successfully connected."); - break; - }; -} - -bool Client::Save(uint8 iCommitNow) { -#if 0 -// Orig. Offset: 344 / 0x00000000 -// Length: 36 / 0x00000024 - unsigned char rawData[36] = -{ - 0x0D, 0x30, 0xE1, 0x30, 0x1E, 0x10, 0x22, 0x10, 0x20, 0x10, 0x21, 0x10, 0x1C, 0x20, 0x1F, 0x10, - 0x7C, 0x10, 0x68, 0x10, 0x51, 0x10, 0x78, 0x10, 0xBD, 0x10, 0xD2, 0x10, 0xCD, 0x10, 0xD1, 0x10, - 0x01, 0x10, 0x6D, 0x10 -} ; - for (int tmp = 0;tmp <=35;tmp++){ - m_pp.unknown0256[89+tmp] = rawData[tmp]; - } -#endif - - if(!ClientDataLoaded()) - return false; - - m_pp.x = x_pos; - m_pp.y = y_pos; - m_pp.z = z_pos; - m_pp.guildrank=guildrank; - m_pp.heading = heading; - - // Temp Hack for signed values until we get the root of the problem changed over to signed... - if (m_pp.copper < 0) { m_pp.copper = 0; } - if (m_pp.silver < 0) { m_pp.silver = 0; } - if (m_pp.gold < 0) { m_pp.gold = 0; } - if (m_pp.platinum < 0) { m_pp.platinum = 0; } - if (m_pp.copper_bank < 0) { m_pp.copper_bank = 0; } - if (m_pp.silver_bank < 0) { m_pp.silver_bank = 0; } - if (m_pp.gold_bank < 0) { m_pp.gold_bank = 0; } - if (m_pp.platinum_bank < 0) { m_pp.platinum_bank = 0; } - - - int spentpoints=0; - for(int a=0;a < MAX_PP_AA_ARRAY;a++) { - uint32 points = aa[a]->value; - if(points > HIGHEST_AA_VALUE) // Unifying this - { - aa[a]->value = HIGHEST_AA_VALUE; - points = HIGHEST_AA_VALUE; - } - if (points > 0) - { - SendAA_Struct* curAA = zone->FindAA(aa[a]->AA-aa[a]->value+1); - if(curAA) - { - for (int rank=0; rank::iterator RequiredLevel = AARequiredLevelAndCost.find(aa[a]->AA-aa[a]->value + 1 + rank); - - if(RequiredLevel != AARequiredLevelAndCost.end()) - { - spentpoints += RequiredLevel->second.Cost; - } - else - spentpoints += (curAA->cost + (curAA->cost_inc * rank)); - } - } - } - } - - m_pp.aapoints_spent = spentpoints + m_epp.expended_aa; - - if (GetHP() <= 0) { - m_pp.cur_hp = GetMaxHP(); - } - else - m_pp.cur_hp = GetHP(); - - m_pp.mana = cur_mana; - m_pp.endurance = cur_end; - - database.SaveBuffs(this); - - TotalSecondsPlayed += (time(nullptr) - m_pp.lastlogin); - m_pp.timePlayedMin = (TotalSecondsPlayed / 60); - m_pp.RestTimer = rest_timer.GetRemainingTime() / 1000; - - if(GetMercInfo().MercTimerRemaining > RuleI(Mercs, UpkeepIntervalMS)) - GetMercInfo().MercTimerRemaining = RuleI(Mercs, UpkeepIntervalMS); - - if(GetMercTimer()->Enabled()) { - GetMercInfo().MercTimerRemaining = GetMercTimer()->GetRemainingTime(); - } - - if (GetMerc() && !dead) { - - } else { - memset(&m_mercinfo, 0, sizeof(struct MercInfo)); - } - - m_pp.lastlogin = time(nullptr); - if (pQueuedSaveWorkID) { - dbasync->CancelWork(pQueuedSaveWorkID); - pQueuedSaveWorkID = 0; - } - - if (GetPet() && !GetPet()->IsFamiliar() && GetPet()->CastToNPC()->GetPetSpellID() && !dead) { - NPC *pet = GetPet()->CastToNPC(); - m_petinfo.SpellID = pet->CastToNPC()->GetPetSpellID(); - m_petinfo.HP = pet->GetHP(); - m_petinfo.Mana = pet->GetMana(); - pet->GetPetState(m_petinfo.Buffs, m_petinfo.Items, m_petinfo.Name); - m_petinfo.petpower = pet->GetPetPower(); - m_petinfo.size = pet->GetSize(); - } else { - memset(&m_petinfo, 0, sizeof(struct PetInfo)); - } - database.SavePetInfo(this); - - if(tribute_timer.Enabled()) { - m_pp.tribute_time_remaining = tribute_timer.GetRemainingTime(); - } else { - m_pp.tribute_time_remaining = 0xFFFFFFFF; - m_pp.tribute_active = 0; - } - - p_timers.Store(&database); - -// printf("Dumping inventory on save:\n"); -// m_inv.dumpEntireInventory(); - - SaveTaskState(); - if (iCommitNow <= 1) { - char* query = 0; - uint32_breakdown workpt; - workpt.b4() = DBA_b4_Entity; - workpt.w2_3() = GetID(); - workpt.b1() = DBA_b1_Entity_Client_Save; - DBAsyncWork* dbaw = new DBAsyncWork(&database, &MTdbafq, workpt, DBAsync::Write, 0xFFFFFFFF); - dbaw->AddQuery(iCommitNow == 0 ? true : false, &query, database.SetPlayerProfile_MQ(&query, account_id, character_id, &m_pp, &m_inv, &m_epp, 0, 0, MaxXTargets), false); - if (iCommitNow == 0){ - pQueuedSaveWorkID = dbasync->AddWork(&dbaw, 2500); - } - else { - dbasync->AddWork(&dbaw, 0); - SaveBackup(); - } - safe_delete_array(query); - return true; - } - else if (database.SetPlayerProfile(account_id, character_id, &m_pp, &m_inv, &m_epp, 0, 0, MaxXTargets)) { - SaveBackup(); - } - else { - std::cerr << "Failed to update player profile" << std::endl; - return false; - } - - /* Mirror Character Data */ - database.StoreCharacterLookup(this->CharacterID()); - - return true; -} - -void Client::SaveBackup() { - if (!RunLoops) - return; - char* query = 0; - DBAsyncWork* dbaw = new DBAsyncWork(&database, &DBAsyncCB_CharacterBackup, this->CharacterID(), DBAsync::Read); - dbaw->AddQuery(0, &query, MakeAnyLenString(&query, "Select id, UNIX_TIMESTAMP()-UNIX_TIMESTAMP(ts) as age from character_backup where charid=%u and backupreason=0 order by ts asc", this->CharacterID()), true); - dbasync->AddWork(&dbaw, 0); -} - -CLIENTPACKET::CLIENTPACKET() -{ - app = nullptr; - ack_req = false; -} - -CLIENTPACKET::~CLIENTPACKET() -{ - safe_delete(app); -} - -//this assumes we do not own pApp, and clones it. -bool Client::AddPacket(const EQApplicationPacket *pApp, bool bAckreq) { - if (!pApp) - return false; - if(!zoneinpacket_timer.Enabled()) { - //drop the packet because it will never get sent. - return(false); - } - CLIENTPACKET *c = new CLIENTPACKET; - - c->ack_req = bAckreq; - c->app = pApp->Copy(); - - clientpackets.Append(c); - return true; -} - -//this assumes that it owns the object pointed to by *pApp -bool Client::AddPacket(EQApplicationPacket** pApp, bool bAckreq) { - if (!pApp || !(*pApp)) - return false; - if(!zoneinpacket_timer.Enabled()) { - //drop the packet because it will never get sent. - return(false); - } - CLIENTPACKET *c = new CLIENTPACKET; - - c->ack_req = bAckreq; - c->app = *pApp; - *pApp = 0; - - clientpackets.Append(c); - return true; -} - -bool Client::SendAllPackets() { - LinkedListIterator iterator(clientpackets); - - CLIENTPACKET* cp = 0; - iterator.Reset(); - while(iterator.MoreElements()) { - cp = iterator.GetData(); - if(eqs) - eqs->FastQueuePacket((EQApplicationPacket **)&cp->app, cp->ack_req); - iterator.RemoveCurrent(); -#if EQDEBUG >= 6 - LogFile->write(EQEMuLog::Normal, "Transmitting a packet"); -#endif - } - return true; -} - -void Client::QueuePacket(const EQApplicationPacket* app, bool ack_req, CLIENT_CONN_STATUS required_state, eqFilterType filter) { - if(filter!=FilterNone){ - //this is incomplete... no support for FilterShowGroupOnly or FilterShowSelfOnly - if(GetFilter(filter) == FilterHide) - return; //Client has this filter on, no need to send packet - } - if(client_state != CLIENT_CONNECTED && required_state == CLIENT_CONNECTED){ - AddPacket(app, ack_req); - return; - } - - // if the program doesnt care about the status or if the status isnt what we requested - if (required_state != CLIENT_CONNECTINGALL && client_state != required_state) - { - // todo: save packets for later use - AddPacket(app, ack_req); - } - else - if(eqs) - eqs->QueuePacket(app, ack_req); -} - -void Client::FastQueuePacket(EQApplicationPacket** app, bool ack_req, CLIENT_CONN_STATUS required_state) { - - //std::cout << "Sending: 0x" << std::hex << std::setw(4) << std::setfill('0') << (*app)->GetOpcode() << std::dec << ", size=" << (*app)->size << std::endl; - - // if the program doesnt care about the status or if the status isnt what we requested - if (required_state != CLIENT_CONNECTINGALL && client_state != required_state) { - // todo: save packets for later use - AddPacket(app, ack_req); -// LogFile->write(EQEMuLog::Normal, "Adding Packet to list (%d) (%d)", (*app)->GetOpcode(), (int)required_state); - return; - } - else { - if(eqs) - eqs->FastQueuePacket((EQApplicationPacket **)app, ack_req); - else if (app && (*app)) - delete *app; - *app = 0; - } - return; -} - -void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_skill, const char* orig_message, const char* targetname) { - char message[4096]; - strn0cpy(message, orig_message, sizeof(message)); - - - #if EQDEBUG >= 11 - LogFile->write(EQEMuLog::Debug,"Client::ChannelMessageReceived() Channel:%i message:'%s'", chan_num, message); - #endif - - if (targetname == nullptr) { - targetname = (!GetTarget()) ? "" : GetTarget()->GetName(); - } - - if(RuleB(Chat, EnableAntiSpam)) - { - if(strcmp(targetname, "discard") != 0) - { - if(chan_num == 3 || chan_num == 4 || chan_num == 5 || chan_num == 7) - { - if(GlobalChatLimiterTimer) - { - if(GlobalChatLimiterTimer->Check(false)) - { - GlobalChatLimiterTimer->Start(RuleI(Chat, IntervalDurationMS)); - AttemptedMessages = 0; - } - } - - uint32 AllowedMessages = RuleI(Chat, MinimumMessagesPerInterval) + TotalKarma; - AllowedMessages = AllowedMessages > RuleI(Chat, MaximumMessagesPerInterval) ? RuleI(Chat, MaximumMessagesPerInterval) : AllowedMessages; - - if(RuleI(Chat, MinStatusToBypassAntiSpam) <= Admin()) - AllowedMessages = 10000; - - AttemptedMessages++; - if(AttemptedMessages > AllowedMessages) - { - if(AttemptedMessages > RuleI(Chat, MaxMessagesBeforeKick)) - { - Kick(); - return; - } - if(GlobalChatLimiterTimer) - { - Message(0, "You have been rate limited, you can send more messages in %i seconds.", - GlobalChatLimiterTimer->GetRemainingTime() / 1000); - return; - } - else - { - Message(0, "You have been rate limited, you can send more messages in 60 seconds."); - return; - } - } - } - } - } - - /* Logs Player Chat */ - if (RuleB(QueryServ, PlayerLogChat)) { - ServerPacket* pack = new ServerPacket(ServerOP_Speech, sizeof(Server_Speech_Struct) + strlen(message) + 1); - Server_Speech_Struct* sem = (Server_Speech_Struct*) pack->pBuffer; - - if(chan_num == 0) - sem->guilddbid = GuildID(); - else - sem->guilddbid = 0; - - strcpy(sem->message, message); - sem->minstatus = this->Admin(); - sem->type = chan_num; - if(targetname != 0) - strcpy(sem->to, targetname); - - if(GetName() != 0) - strcpy(sem->from, GetName()); - - pack->Deflate(); - if(worldserver.Connected()) - worldserver.SendPacket(pack); - safe_delete(pack); - } - - //Return true to proceed, false to return - if(!mod_client_message(message, chan_num)) { return; } - - // Garble the message based on drunkness - if (m_pp.intoxication > 0) { - GarbleMessage(message, (int)(m_pp.intoxication / 3)); - language = 0; // No need for language when drunk - } - - switch(chan_num) - { - case 0: { /* Guild Chat */ - if (!IsInAGuild()) - Message_StringID(MT_DefaultText, GUILD_NOT_MEMBER2); //You are not a member of any guild. - else if (!guild_mgr.CheckPermission(GuildID(), GuildRank(), GUILD_SPEAK)) - Message(0, "Error: You dont have permission to speak to the guild."); - else if (!worldserver.SendChannelMessage(this, targetname, chan_num, GuildID(), language, message)) - Message(0, "Error: World server disconnected"); - break; - } - case 2: { /* Group Chat */ - Raid* raid = entity_list.GetRaidByClient(this); - if(raid) { - raid->RaidGroupSay((const char*) message, this); - break; - } - - Group* group = GetGroup(); - if(group != nullptr) { - group->GroupMessage(this,language,lang_skill,(const char*) message); - } - break; - } - case 15: { /* Raid Say */ - Raid* raid = entity_list.GetRaidByClient(this); - if(raid){ - raid->RaidSay((const char*) message, this); - } - break; - } - case 3: { /* Shout */ - Mob *sender = this; - if (GetPet() && GetPet()->FindType(SE_VoiceGraft)) - sender = GetPet(); - - entity_list.ChannelMessage(sender, chan_num, language, lang_skill, message); - break; - } - case 4: { /* Auction */ - if(RuleB(Chat, ServerWideAuction)) - { - if(!global_channel_timer.Check()) - { - if(strlen(targetname) == 0) - ChannelMessageReceived(5, language, lang_skill, message, "discard"); //Fast typer or spammer?? - else - return; - } - - if(GetRevoked()) - { - Message(0, "You have been revoked. You may not talk on Auction."); - return; - } - - if(TotalKarma < RuleI(Chat, KarmaGlobalChatLimit)) - { - if(GetLevel() < RuleI(Chat, GlobalChatLevelLimit)) - { - Message(0, "You do not have permission to talk in Auction at this time."); - return; - } - } - - if (!worldserver.SendChannelMessage(this, 0, 4, 0, language, message)) - Message(0, "Error: World server disconnected"); - } - else if(!RuleB(Chat, ServerWideAuction)) { - Mob *sender = this; - - if (GetPet() && GetPet()->FindType(SE_VoiceGraft)) - sender = GetPet(); - - entity_list.ChannelMessage(sender, chan_num, language, message); - } - break; - } - case 5: { /* OOC */ - if(RuleB(Chat, ServerWideOOC)) - { - if(!global_channel_timer.Check()) - { - if(strlen(targetname) == 0) - ChannelMessageReceived(5, language, lang_skill, message, "discard"); //Fast typer or spammer?? - else - return; - } - if(worldserver.IsOOCMuted() && admin < 100) - { - Message(0,"OOC has been muted. Try again later."); - return; - } - - if(GetRevoked()) - { - Message(0, "You have been revoked. You may not talk on OOC."); - return; - } - - if(TotalKarma < RuleI(Chat, KarmaGlobalChatLimit)) - { - if(GetLevel() < RuleI(Chat, GlobalChatLevelLimit)) - { - Message(0, "You do not have permission to talk in OOC at this time."); - return; - } - } - - if (!worldserver.SendChannelMessage(this, 0, 5, 0, language, message)) - { - Message(0, "Error: World server disconnected"); - } - } - else if(!RuleB(Chat, ServerWideOOC)) - { - Mob *sender = this; - - if (GetPet() && GetPet()->FindType(SE_VoiceGraft)) - sender = GetPet(); - - entity_list.ChannelMessage(sender, chan_num, language, message); - } - break; - } - case 6: /* Broadcast */ - case 11: { /* GM Say */ - if (!(admin >= 80)) - Message(0, "Error: Only GMs can use this channel"); - else if (!worldserver.SendChannelMessage(this, targetname, chan_num, 0, language, message)) - Message(0, "Error: World server disconnected"); - break; - } - case 7: { /* Tell */ - if(!global_channel_timer.Check()) - { - if(strlen(targetname) == 0) - ChannelMessageReceived(7, language, lang_skill, message, "discard"); //Fast typer or spammer?? - else - return; - } - - if(GetRevoked()) - { - Message(0, "You have been revoked. You may not send tells."); - return; - } - - if(TotalKarma < RuleI(Chat, KarmaGlobalChatLimit)) - { - if(GetLevel() < RuleI(Chat, GlobalChatLevelLimit)) - { - Message(0, "You do not have permission to send tells at this time."); - return; - } - } - - char target_name[64]; - - if(targetname) - { - size_t i = strlen(targetname); - int x; - for(x = 0; x < i; ++x) - { - if(targetname[x] == '%') - { - target_name[x] = '/'; - } - else - { - target_name[x] = targetname[x]; - } - } - target_name[x] = '\0'; - } - - if(!worldserver.SendChannelMessage(this, target_name, chan_num, 0, language, message)) - Message(0, "Error: World server disconnected"); - break; - } - case 8: { /* Say */ - if(message[0] == COMMAND_CHAR) { - if(command_dispatch(this, message) == -2) { - if(parse->PlayerHasQuestSub(EVENT_COMMAND)) { - int i = parse->EventPlayer(EVENT_COMMAND, this, message, 0); - if(i == 0 && !RuleB(Chat, SuppressCommandErrors)) { - Message(13, "Command '%s' not recognized.", message); - } - } else { - if(!RuleB(Chat, SuppressCommandErrors)) - Message(13, "Command '%s' not recognized.", message); - } - } - break; - } - - Mob* sender = this; - if (GetPet() && GetPet()->FindType(SE_VoiceGraft)) - sender = GetPet(); - - entity_list.ChannelMessage(sender, chan_num, language, lang_skill, message); - parse->EventPlayer(EVENT_SAY, this, message, language); - - if (sender != this) - break; - - if(quest_manager.ProximitySayInUse()) - entity_list.ProcessProximitySay(message, this, language); - - if (GetTarget() != 0 && GetTarget()->IsNPC()) { - if(!GetTarget()->CastToNPC()->IsEngaged()) { - CheckLDoNHail(GetTarget()); - CheckEmoteHail(GetTarget(), message); - - - if(DistNoRootNoZ(*GetTarget()) <= 200) { - NPC *tar = GetTarget()->CastToNPC(); - parse->EventNPC(EVENT_SAY, tar->CastToNPC(), this, message, language); - - if(RuleB(TaskSystem, EnableTaskSystem)) { - if(UpdateTasksOnSpeakWith(tar->GetNPCTypeID())) { - tar->DoQuestPause(this); - } - } - } - } - else { - if (DistNoRootNoZ(*GetTarget()) <= 200) { - parse->EventNPC(EVENT_AGGRO_SAY, GetTarget()->CastToNPC(), this, message, language); - } - } - - } - break; - } - case 20: - { - // UCS Relay for Underfoot and later. - if(!worldserver.SendChannelMessage(this, 0, chan_num, 0, language, message)) - Message(0, "Error: World server disconnected"); - break; - } - case 22: - { - // Emotes for Underfoot and later. - // crash protection -- cheater - message[1023] = '\0'; - size_t msg_len = strlen(message); - if (msg_len > 512) - message[512] = '\0'; - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Emote, 4 + msg_len + strlen(GetName()) + 2); - Emote_Struct* es = (Emote_Struct*)outapp->pBuffer; - char *Buffer = (char *)es; - Buffer += 4; - snprintf(Buffer, sizeof(Emote_Struct) - 4, "%s %s", GetName(), message); - entity_list.QueueCloseClients(this, outapp, true, 100, 0, true, FilterSocials); - safe_delete(outapp); - break; - } - default: { - Message(0, "Channel (%i) not implemented", (uint16)chan_num); - } - } -} - -// if no language skill is specified, call the function with a skill of 100. -void Client::ChannelMessageSend(const char* from, const char* to, uint8 chan_num, uint8 language, const char* message, ...) { - ChannelMessageSend(from, to, chan_num, language, 100, message); -} - -void Client::ChannelMessageSend(const char* from, const char* to, uint8 chan_num, uint8 language, uint8 lang_skill, const char* message, ...) { - if ((chan_num==11 && !(this->GetGM())) || (chan_num==10 && this->Admin()<80)) // dont need to send /pr & /petition to everybody - return; - va_list argptr; - char buffer[4096]; - char message_sender[64]; - - va_start(argptr, message); - vsnprintf(buffer, 4096, message, argptr); - va_end(argptr); - - EQApplicationPacket app(OP_ChannelMessage, sizeof(ChannelMessage_Struct)+strlen(buffer)+1); - ChannelMessage_Struct* cm = (ChannelMessage_Struct*)app.pBuffer; - - if (from == 0) - strcpy(cm->sender, "ZServer"); - else if (from[0] == 0) - strcpy(cm->sender, "ZServer"); - else { - CleanMobName(from, message_sender); - strcpy(cm->sender, message_sender); - } - if (to != 0) - strcpy((char *) cm->targetname, to); - else if (chan_num == 7) - strcpy(cm->targetname, m_pp.name); - else - cm->targetname[0] = 0; - - uint8 ListenerSkill; - - if (language < MAX_PP_LANGUAGE) { - ListenerSkill = m_pp.languages[language]; - if (ListenerSkill == 0) { - cm->language = (MAX_PP_LANGUAGE - 1); // in an unknown tongue - } - else { - cm->language = language; - } - } - else { - ListenerSkill = m_pp.languages[0]; - cm->language = 0; - } - - // set effective language skill = lower of sender and receiver skills - int32 EffSkill = (lang_skill < ListenerSkill ? lang_skill : ListenerSkill); - if (EffSkill > 100) // maximum language skill is 100 - EffSkill = 100; - cm->skill_in_language = EffSkill; - - // Garble the message based on listener skill - if (ListenerSkill < 100) { - GarbleMessage(buffer, (100 - ListenerSkill)); - } - - cm->chan_num = chan_num; - strcpy(&cm->message[0], buffer); - QueuePacket(&app); - - if ((chan_num == 2) && (ListenerSkill < 100)) { // group message in unmastered language, check for skill up - if ((m_pp.languages[language] <= lang_skill) && (from != this->GetName())) - CheckLanguageSkillIncrease(language, lang_skill); - } -} - -void Client::Message(uint32 type, const char* message, ...) { - if (GetFilter(FilterSpellDamage) == FilterHide && type == MT_NonMelee) - return; - if (GetFilter(FilterMeleeCrits) == FilterHide && type == MT_CritMelee) //98 is self... - return; - if (GetFilter(FilterSpellCrits) == FilterHide && type == MT_SpellCrits) - return; - - va_list argptr; - char *buffer = new char[4096]; - va_start(argptr, message); - vsnprintf(buffer, 4096, message, argptr); - va_end(argptr); - - size_t len = strlen(buffer); - - //client dosent like our packet all the time unless - //we make it really big, then it seems to not care that - //our header is malformed. - //len = 4096 - sizeof(SpecialMesg_Struct); - - uint32 len_packet = sizeof(SpecialMesg_Struct)+len; - EQApplicationPacket* app = new EQApplicationPacket(OP_SpecialMesg, len_packet); - SpecialMesg_Struct* sm=(SpecialMesg_Struct*)app->pBuffer; - sm->header[0] = 0x00; // Header used for #emote style messages.. - sm->header[1] = 0x00; // Play around with these to see other types - sm->header[2] = 0x00; - sm->msg_type = type; - memcpy(sm->message, buffer, len+1); - - FastQueuePacket(&app); - - safe_delete_array(buffer); -} - -void Client::QuestJournalledMessage(const char *npcname, const char* message) { - - // npcnames longer than 60 characters crash the client when they log back in - const int MaxNPCNameLength = 60; - // I assume there is an upper safe limit on the message length. Don't know what it is, but 4000 doesn't crash - // the client. - const int MaxMessageLength = 4000; - - char OutNPCName[MaxNPCNameLength+1]; - char OutMessage[MaxMessageLength+1]; - - // Apparently Visual C++ snprintf is not C99 compliant and doesn't put the null terminator - // in if the formatted string >= the maximum length, so we put it in. - // - snprintf(OutNPCName, MaxNPCNameLength, "%s", npcname); OutNPCName[MaxNPCNameLength]='\0'; - snprintf(OutMessage, MaxMessageLength, "%s", message); OutMessage[MaxMessageLength]='\0'; - - uint32 len_packet = sizeof(SpecialMesg_Struct) + strlen(OutNPCName) + strlen(OutMessage); - EQApplicationPacket* app = new EQApplicationPacket(OP_SpecialMesg, len_packet); - SpecialMesg_Struct* sm=(SpecialMesg_Struct*)app->pBuffer; - - sm->header[0] = 0; - sm->header[1] = 2; - sm->header[2] = 0; - sm->msg_type = 0x0a; - sm->target_spawn_id = GetID(); - - char *dest = &sm->sayer[0]; - - memcpy(dest, OutNPCName, strlen(OutNPCName) + 1); - - dest = dest + strlen(OutNPCName) + 13; - - memcpy(dest, OutMessage, strlen(OutMessage) + 1); - - QueuePacket(app); - - safe_delete(app); -} - -void Client::SetMaxHP() { - if(dead) - return; - SetHP(CalcMaxHP()); - SendHPUpdate(); - Save(); -} - -bool Client::UpdateLDoNPoints(int32 points, uint32 theme) -{ - -/* make sure total stays in sync with individual buckets - m_pp.ldon_points_available = m_pp.ldon_points_guk - +m_pp.ldon_points_mir - +m_pp.ldon_points_mmc - +m_pp.ldon_points_ruj - +m_pp.ldon_points_tak; */ - - if(points < 0) - { - if(m_pp.ldon_points_available < (0-points)) - return false; - } - switch(theme) - { - // handle generic points (theme=0) - case 0: - { // no theme, so distribute evenly across all - int splitpts=points/5; - int gukpts=splitpts+(points%5); - int mirpts=splitpts; - int mmcpts=splitpts; - int rujpts=splitpts; - int takpts=splitpts; - - splitpts=0; - - if(points < 0) - { - if(m_pp.ldon_points_available < (0-points)) - { - return false; - } - if(m_pp.ldon_points_guk < (0-gukpts)) - { - mirpts+=gukpts+m_pp.ldon_points_guk; - gukpts=0-m_pp.ldon_points_guk; - } - if(m_pp.ldon_points_mir < (0-mirpts)) - { - mmcpts+=mirpts+m_pp.ldon_points_mir; - mirpts=0-m_pp.ldon_points_mir; - } - if(m_pp.ldon_points_mmc < (0-mmcpts)) - { - rujpts+=mmcpts+m_pp.ldon_points_mmc; - mmcpts=0-m_pp.ldon_points_mmc; - } - if(m_pp.ldon_points_ruj < (0-rujpts)) - { - takpts+=rujpts+m_pp.ldon_points_ruj; - rujpts=0-m_pp.ldon_points_ruj; - } - if(m_pp.ldon_points_tak < (0-takpts)) - { - splitpts=takpts+m_pp.ldon_points_tak; - takpts=0-m_pp.ldon_points_tak; - } - } - m_pp.ldon_points_guk += gukpts; - m_pp.ldon_points_mir+=mirpts; - m_pp.ldon_points_mmc += mmcpts; - m_pp.ldon_points_ruj += rujpts; - m_pp.ldon_points_tak += takpts; - points-=splitpts; - // if anything left, recursively loop thru again - if (splitpts !=0) - UpdateLDoNPoints(splitpts,0); - break; - } - case 1: - { - if(points < 0) - { - if(m_pp.ldon_points_guk < (0-points)) - return false; - } - m_pp.ldon_points_guk += points; - break; - } - case 2: - { - if(points < 0) - { - if(m_pp.ldon_points_mir < (0-points)) - return false; - } - m_pp.ldon_points_mir += points; - break; - } - case 3: - { - if(points < 0) - { - if(m_pp.ldon_points_mmc < (0-points)) - return false; - } - m_pp.ldon_points_mmc += points; - break; - } - case 4: - { - if(points < 0) - { - if(m_pp.ldon_points_ruj < (0-points)) - return false; - } - m_pp.ldon_points_ruj += points; - break; - } - case 5: - { - if(points < 0) - { - if(m_pp.ldon_points_tak < (0-points)) - return false; - } - m_pp.ldon_points_tak += points; - break; - } - } - m_pp.ldon_points_available += points; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AdventurePointsUpdate, sizeof(AdventurePoints_Update_Struct)); - AdventurePoints_Update_Struct* apus = (AdventurePoints_Update_Struct*)outapp->pBuffer; - apus->ldon_available_points = m_pp.ldon_points_available; - apus->ldon_guk_points = m_pp.ldon_points_guk; - apus->ldon_mirugal_points = m_pp.ldon_points_mir; - apus->ldon_mistmoore_points = m_pp.ldon_points_mmc; - apus->ldon_rujarkian_points = m_pp.ldon_points_ruj; - apus->ldon_takish_points = m_pp.ldon_points_tak; - outapp->priority = 6; - QueuePacket(outapp); - safe_delete(outapp); - return true; - - return(false); -} - -void Client::SetSkill(SkillUseTypes skillid, uint16 value) { - if (skillid > HIGHEST_SKILL) - return; - m_pp.skills[skillid] = value; // We need to be able to #setskill 254 and 255 to reset skills - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SkillUpdate, sizeof(SkillUpdate_Struct)); - SkillUpdate_Struct* skill = (SkillUpdate_Struct*)outapp->pBuffer; - skill->skillId=skillid; - skill->value=value; - QueuePacket(outapp); - safe_delete(outapp); -} - -void Client::IncreaseLanguageSkill(int skill_id, int value) { - - if (skill_id >= MAX_PP_LANGUAGE) - return; //Invalid lang id - - m_pp.languages[skill_id] += value; - - if (m_pp.languages[skill_id] > 100) //Lang skill above max - m_pp.languages[skill_id] = 100; - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SkillUpdate, sizeof(SkillUpdate_Struct)); - SkillUpdate_Struct* skill = (SkillUpdate_Struct*)outapp->pBuffer; - skill->skillId = 100 + skill_id; - skill->value = m_pp.languages[skill_id]; - QueuePacket(outapp); - safe_delete(outapp); - - Message_StringID( MT_Skills, LANG_SKILL_IMPROVED ); //Notify client -} - -void Client::AddSkill(SkillUseTypes skillid, uint16 value) { - if (skillid > HIGHEST_SKILL) - return; - value = GetRawSkill(skillid) + value; - uint16 max = GetMaxSkillAfterSpecializationRules(skillid, MaxSkill(skillid)); - if (value > max) - value = max; - SetSkill(skillid, value); -} - -void Client::SendSound(){//Makes a sound. - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Sound, 68); - unsigned char x[68]; - memset(x, 0, 68); - x[0]=0x22; - memset(&x[4],0x8002,sizeof(uint16)); - memset(&x[8],0x8624,sizeof(uint16)); - memset(&x[12],0x4A01,sizeof(uint16)); - x[16]=0x05; - x[28]=0x00;//change this value to give gold to the client - memset(&x[40],0xFFFFFFFF,sizeof(uint32)); - memset(&x[44],0xFFFFFFFF,sizeof(uint32)); - memset(&x[48],0xFFFFFFFF,sizeof(uint32)); - memset(&x[52],0xFFFFFFFF,sizeof(uint32)); - memset(&x[56],0xFFFFFFFF,sizeof(uint32)); - memset(&x[60],0xFFFFFFFF,sizeof(uint32)); - memset(&x[64],0xffffffff,sizeof(uint32)); - memcpy(outapp->pBuffer,x,outapp->size); - QueuePacket(outapp); - safe_delete(outapp); - -} -void Client::UpdateWho(uint8 remove) { - if (account_id == 0) - return; - if (!worldserver.Connected()) - return; - ServerPacket* pack = new ServerPacket(ServerOP_ClientList, sizeof(ServerClientList_Struct)); - ServerClientList_Struct* scl = (ServerClientList_Struct*) pack->pBuffer; - scl->remove = remove; - scl->wid = this->GetWID(); - scl->IP = this->GetIP(); - scl->charid = this->CharacterID(); - strcpy(scl->name, this->GetName()); - - scl->gm = GetGM(); - scl->Admin = this->Admin(); - scl->AccountID = this->AccountID(); - strcpy(scl->AccountName, this->AccountName()); - scl->LSAccountID = this->LSAccountID(); - strn0cpy(scl->lskey, lskey, sizeof(scl->lskey)); - scl->zone = zone->GetZoneID(); - scl->instance_id = zone->GetInstanceID(); - scl->race = this->GetRace(); - scl->class_ = GetClass(); - scl->level = GetLevel(); - if (m_pp.anon == 0) - scl->anon = 0; - else if (m_pp.anon == 1) - scl->anon = 1; - else if (m_pp.anon >= 2) - scl->anon = 2; - - scl->ClientVersion = GetClientVersion(); - scl->tellsoff = tellsoff; - scl->guild_id = guild_id; - scl->LFG = LFG; - if(LFG) { - scl->LFGFromLevel = LFGFromLevel; - scl->LFGToLevel = LFGToLevel; - scl->LFGMatchFilter = LFGMatchFilter; - memcpy(scl->LFGComments, LFGComments, sizeof(scl->LFGComments)); - } - - worldserver.SendPacket(pack); - safe_delete(pack); -} - -void Client::WhoAll(Who_All_Struct* whom) { - - if (!worldserver.Connected()) - Message(0, "Error: World server disconnected"); - else { - ServerPacket* pack = new ServerPacket(ServerOP_Who, sizeof(ServerWhoAll_Struct)); - ServerWhoAll_Struct* whoall = (ServerWhoAll_Struct*) pack->pBuffer; - whoall->admin = this->Admin(); - whoall->fromid=this->GetID(); - strcpy(whoall->from, this->GetName()); - strn0cpy(whoall->whom, whom->whom, 64); - whoall->lvllow = whom->lvllow; - whoall->lvlhigh = whom->lvlhigh; - whoall->gmlookup = whom->gmlookup; - whoall->wclass = whom->wclass; - whoall->wrace = whom->wrace; - worldserver.SendPacket(pack); - safe_delete(pack); - } -} - -void Client::FriendsWho(char *FriendsString) { - - if (!worldserver.Connected()) - Message(0, "Error: World server disconnected"); - else { - ServerPacket* pack = new ServerPacket(ServerOP_FriendsWho, sizeof(ServerFriendsWho_Struct) + strlen(FriendsString)); - ServerFriendsWho_Struct* FriendsWho = (ServerFriendsWho_Struct*) pack->pBuffer; - FriendsWho->FromID = this->GetID(); - strcpy(FriendsWho->FromName, GetName()); - strcpy(FriendsWho->FriendsString, FriendsString); - worldserver.SendPacket(pack); - safe_delete(pack); - } -} - - -void Client::UpdateAdmin(bool iFromDB) { - int16 tmp = admin; - if (iFromDB) - admin = database.CheckStatus(account_id); - if (tmp == admin && iFromDB) - return; - - if(m_pp.gm) - { -#if EQDEBUG >= 5 - printf("%s is a GM\n", GetName()); -#endif -// no need for this, having it set in pp you already start as gm -// and it's also set in your spawn packet so other people see it too -// SendAppearancePacket(AT_GM, 1, false); - petition_list.UpdateGMQueue(); - } - - UpdateWho(); -} - -void Client::SetStats(uint8 type,int16 set_val){ - if(type>STAT_DISEASE){ - printf("Error in Client::IncStats, received invalid type of: %i\n",type); - return; - } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_IncreaseStats,sizeof(IncreaseStat_Struct)); - IncreaseStat_Struct* iss=(IncreaseStat_Struct*)outapp->pBuffer; - switch(type){ - case STAT_STR: - if(set_val>0) - iss->str=set_val; - if(set_val<0) - m_pp.STR=0; - else if(set_val>255) - m_pp.STR=255; - else - m_pp.STR=set_val; - break; - case STAT_STA: - if(set_val>0) - iss->sta=set_val; - if(set_val<0) - m_pp.STA=0; - else if(set_val>255) - m_pp.STA=255; - else - m_pp.STA=set_val; - break; - case STAT_AGI: - if(set_val>0) - iss->agi=set_val; - if(set_val<0) - m_pp.AGI=0; - else if(set_val>255) - m_pp.AGI=255; - else - m_pp.AGI=set_val; - break; - case STAT_DEX: - if(set_val>0) - iss->dex=set_val; - if(set_val<0) - m_pp.DEX=0; - else if(set_val>255) - m_pp.DEX=255; - else - m_pp.DEX=set_val; - break; - case STAT_INT: - if(set_val>0) - iss->int_=set_val; - if(set_val<0) - m_pp.INT=0; - else if(set_val>255) - m_pp.INT=255; - else - m_pp.INT=set_val; - break; - case STAT_WIS: - if(set_val>0) - iss->wis=set_val; - if(set_val<0) - m_pp.WIS=0; - else if(set_val>255) - m_pp.WIS=255; - else - m_pp.WIS=set_val; - break; - case STAT_CHA: - if(set_val>0) - iss->cha=set_val; - if(set_val<0) - m_pp.CHA=0; - else if(set_val>255) - m_pp.CHA=255; - else - m_pp.CHA=set_val; - break; - } - QueuePacket(outapp); - safe_delete(outapp); -} - -void Client::IncStats(uint8 type,int16 increase_val){ - if(type>STAT_DISEASE){ - printf("Error in Client::IncStats, received invalid type of: %i\n",type); - return; - } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_IncreaseStats,sizeof(IncreaseStat_Struct)); - IncreaseStat_Struct* iss=(IncreaseStat_Struct*)outapp->pBuffer; - switch(type){ - case STAT_STR: - if(increase_val>0) - iss->str=increase_val; - if((m_pp.STR+increase_val*2)<0) - m_pp.STR=0; - else if((m_pp.STR+increase_val*2)>255) - m_pp.STR=255; - else - m_pp.STR+=increase_val*2; - break; - case STAT_STA: - if(increase_val>0) - iss->sta=increase_val; - if((m_pp.STA+increase_val*2)<0) - m_pp.STA=0; - else if((m_pp.STA+increase_val*2)>255) - m_pp.STA=255; - else - m_pp.STA+=increase_val*2; - break; - case STAT_AGI: - if(increase_val>0) - iss->agi=increase_val; - if((m_pp.AGI+increase_val*2)<0) - m_pp.AGI=0; - else if((m_pp.AGI+increase_val*2)>255) - m_pp.AGI=255; - else - m_pp.AGI+=increase_val*2; - break; - case STAT_DEX: - if(increase_val>0) - iss->dex=increase_val; - if((m_pp.DEX+increase_val*2)<0) - m_pp.DEX=0; - else if((m_pp.DEX+increase_val*2)>255) - m_pp.DEX=255; - else - m_pp.DEX+=increase_val*2; - break; - case STAT_INT: - if(increase_val>0) - iss->int_=increase_val; - if((m_pp.INT+increase_val*2)<0) - m_pp.INT=0; - else if((m_pp.INT+increase_val*2)>255) - m_pp.INT=255; - else - m_pp.INT+=increase_val*2; - break; - case STAT_WIS: - if(increase_val>0) - iss->wis=increase_val; - if((m_pp.WIS+increase_val*2)<0) - m_pp.WIS=0; - else if((m_pp.WIS+increase_val*2)>255) - m_pp.WIS=255; - else - m_pp.WIS+=increase_val*2; - break; - case STAT_CHA: - if(increase_val>0) - iss->cha=increase_val; - if((m_pp.CHA+increase_val*2)<0) - m_pp.CHA=0; - else if((m_pp.CHA+increase_val*2)>255) - m_pp.CHA=255; - else - m_pp.CHA+=increase_val*2; - break; - } - QueuePacket(outapp); - safe_delete(outapp); -} - -const int32& Client::SetMana(int32 amount) { - bool update = false; - if (amount < 0) - amount = 0; - if (amount > GetMaxMana()) - amount = GetMaxMana(); - if (amount != cur_mana) - update = true; - cur_mana = amount; - if (update) - Mob::SetMana(amount); - SendManaUpdatePacket(); - return cur_mana; -} - -void Client::SendManaUpdatePacket() { - if (!Connected() || IsCasting()) - return; - - if (GetClientVersion() >= EQClientSoD) { - SendManaUpdate(); - SendEnduranceUpdate(); - } - - //std::cout << "Sending mana update: " << (cur_mana - last_reported_mana) << std::endl; - if (last_reported_mana != cur_mana || last_reported_endur != cur_end) { - - - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ManaChange, sizeof(ManaChange_Struct)); - ManaChange_Struct* manachange = (ManaChange_Struct*)outapp->pBuffer; - manachange->new_mana = cur_mana; - manachange->stamina = cur_end; - manachange->spell_id = casting_spell_id; //always going to be 0... since we check IsCasting() - outapp->priority = 6; - QueuePacket(outapp); - safe_delete(outapp); - - Group *g = GetGroup(); - - if(g) - { - outapp = new EQApplicationPacket(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct)); - EQApplicationPacket *outapp2 = new EQApplicationPacket(OP_MobEnduranceUpdate, sizeof(MobEnduranceUpdate_Struct)); - - MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp->pBuffer; - MobEnduranceUpdate_Struct *meus = (MobEnduranceUpdate_Struct *)outapp2->pBuffer; - - mmus->spawn_id = meus->spawn_id = GetID(); - - mmus->mana = GetManaPercent(); - meus->endurance = GetEndurancePercent(); - - - for(int i = 0; i < MAX_GROUP_MEMBERS; ++i) - if(g->members[i] && g->members[i]->IsClient() && (g->members[i] != this) && (g->members[i]->CastToClient()->GetClientVersion() >= EQClientSoD)) - { - g->members[i]->CastToClient()->QueuePacket(outapp); - g->members[i]->CastToClient()->QueuePacket(outapp2); - } - - safe_delete(outapp); - safe_delete(outapp2); - } - - - last_reported_mana = cur_mana; - last_reported_endur = cur_end; - } -} - -// sends mana update to self -void Client::SendManaUpdate() -{ - EQApplicationPacket* mana_app = new EQApplicationPacket(OP_ManaUpdate,sizeof(ManaUpdate_Struct)); - ManaUpdate_Struct* mus = (ManaUpdate_Struct*)mana_app->pBuffer; - mus->cur_mana = GetMana(); - mus->max_mana = GetMaxMana(); - mus->spawn_id = GetID(); - QueuePacket(mana_app); - entity_list.QueueClientsByXTarget(this, mana_app, false); - safe_delete(mana_app); -} - -// sends endurance update to self -void Client::SendEnduranceUpdate() -{ - EQApplicationPacket* end_app = new EQApplicationPacket(OP_EnduranceUpdate,sizeof(EnduranceUpdate_Struct)); - EnduranceUpdate_Struct* eus = (EnduranceUpdate_Struct*)end_app->pBuffer; - eus->cur_end = GetEndurance(); - eus->max_end = GetMaxEndurance(); - eus->spawn_id = GetID(); - QueuePacket(end_app); - entity_list.QueueClientsByXTarget(this, end_app, false); - safe_delete(end_app); -} - -void Client::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) -{ - Mob::FillSpawnStruct(ns, ForWho); - - // Populate client-specific spawn information - ns->spawn.afk = AFK; - ns->spawn.lfg = LFG; // afk and lfg are cleared on zoning on live - ns->spawn.anon = m_pp.anon; - ns->spawn.gm = GetGM() ? 1 : 0; - ns->spawn.guildID = GuildID(); -// ns->spawn.linkdead = IsLD() ? 1 : 0; -// ns->spawn.pvp = GetPVP() ? 1 : 0; - - - strcpy(ns->spawn.title, m_pp.title); - strcpy(ns->spawn.suffix, m_pp.suffix); - - if (IsBecomeNPC() == true) - ns->spawn.NPC = 1; - else if (ForWho == this) - ns->spawn.NPC = 10; - else - ns->spawn.NPC = 0; - ns->spawn.is_pet = 0; - - if (!IsInAGuild()) { - ns->spawn.guildrank = 0xFF; - } else { - ns->spawn.guildrank = guild_mgr.GetDisplayedRank(GuildID(), GuildRank(), AccountID()); - } - ns->spawn.size = 0; // Changing size works, but then movement stops! (wth?) - ns->spawn.runspeed = (gmspeed == 0) ? runspeed : 3.125f; - if (!m_pp.showhelm) ns->spawn.showhelm = 0; - - // pp also hold this info; should we pull from there or inventory? - // (update: i think pp should do it, as this holds LoY dye - plus, this is ugly code with Inventory!) - const Item_Struct* item = nullptr; - const ItemInst* inst = nullptr; - if ((inst = m_inv[MainHands]) && inst->IsType(ItemClassCommon)) { - item = inst->GetItem(); - ns->spawn.equipment[MaterialHands] = item->Material; - ns->spawn.colors[MaterialHands].color = GetEquipmentColor(MaterialHands); - } - if ((inst = m_inv[MainHead]) && inst->IsType(ItemClassCommon)) { - item = inst->GetItem(); - ns->spawn.equipment[MaterialHead] = item->Material; - ns->spawn.colors[MaterialHead].color = GetEquipmentColor(MaterialHead); - } - if ((inst = m_inv[MainArms]) && inst->IsType(ItemClassCommon)) { - item = inst->GetItem(); - ns->spawn.equipment[MaterialArms] = item->Material; - ns->spawn.colors[MaterialArms].color = GetEquipmentColor(MaterialArms); - } - if ((inst = m_inv[MainWrist1]) && inst->IsType(ItemClassCommon)) { - item = inst->GetItem(); - ns->spawn.equipment[MaterialWrist]= item->Material; - ns->spawn.colors[MaterialWrist].color = GetEquipmentColor(MaterialWrist); - } - - /* - // non-live behavior - if ((inst = m_inv[SLOT_BRACER02]) && inst->IsType(ItemClassCommon)) { - item = inst->GetItem(); - ns->spawn.equipment[MaterialWrist]= item->Material; - ns->spawn.colors[MaterialWrist].color = GetEquipmentColor(MaterialWrist); - } - */ - - if ((inst = m_inv[MainChest]) && inst->IsType(ItemClassCommon)) { - item = inst->GetItem(); - ns->spawn.equipment[MaterialChest] = item->Material; - ns->spawn.colors[MaterialChest].color = GetEquipmentColor(MaterialChest); - } - if ((inst = m_inv[MainLegs]) && inst->IsType(ItemClassCommon)) { - item = inst->GetItem(); - ns->spawn.equipment[MaterialLegs] = item->Material; - ns->spawn.colors[MaterialLegs].color = GetEquipmentColor(MaterialLegs); - } - if ((inst = m_inv[MainFeet]) && inst->IsType(ItemClassCommon)) { - item = inst->GetItem(); - ns->spawn.equipment[MaterialFeet] = item->Material; - ns->spawn.colors[MaterialFeet].color = GetEquipmentColor(MaterialFeet); - } - if ((inst = m_inv[MainPrimary]) && inst->IsType(ItemClassCommon)) { - item = inst->GetItem(); - if (strlen(item->IDFile) > 2) - ns->spawn.equipment[MaterialPrimary] = atoi(&item->IDFile[2]); - } - if ((inst = m_inv[MainSecondary]) && inst->IsType(ItemClassCommon)) { - item = inst->GetItem(); - if (strlen(item->IDFile) > 2) - ns->spawn.equipment[MaterialSecondary] = atoi(&item->IDFile[2]); - } - - //these two may be related to ns->spawn.texture - /* - ns->spawn.npc_armor_graphic = texture; - ns->spawn.npc_helm_graphic = helmtexture; - */ - - //filling in some unknowns to make the client happy -// ns->spawn.unknown0002[2] = 3; - -} - -bool Client::GMHideMe(Client* client) { - if (gmhideme) { - if (client == 0) - return true; - else if (admin > client->Admin()) - return true; - else - return false; - } - else - return false; -} - -void Client::Duck() { - SetAppearance(eaCrouching, false); -} - -void Client::Stand() { - SetAppearance(eaStanding, false); -} - -void Client::ChangeLastName(const char* in_lastname) { - memset(m_pp.last_name, 0, sizeof(m_pp.last_name)); - strn0cpy(m_pp.last_name, in_lastname, sizeof(m_pp.last_name)); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GMLastName, sizeof(GMLastName_Struct)); - GMLastName_Struct* gmn = (GMLastName_Struct*)outapp->pBuffer; - strcpy(gmn->name, name); - strcpy(gmn->gmname, name); - strcpy(gmn->lastname, in_lastname); - gmn->unknown[0]=1; - gmn->unknown[1]=1; - gmn->unknown[2]=1; - gmn->unknown[3]=1; - entity_list.QueueClients(this, outapp, false); - // Send name update packet here... once know what it is - safe_delete(outapp); -} - -bool Client::ChangeFirstName(const char* in_firstname, const char* gmname) -{ - // check duplicate name - bool usedname = database.CheckUsedName((const char*) in_firstname); - if (!usedname) { - return false; - } - - // update character_ - if(!database.UpdateName(GetName(), in_firstname)) - return false; - - // update pp - memset(m_pp.name, 0, sizeof(m_pp.name)); - snprintf(m_pp.name, sizeof(m_pp.name), "%s", in_firstname); - strcpy(name, m_pp.name); - Save(); - - // send name update packet - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GMNameChange, sizeof(GMName_Struct)); - GMName_Struct* gmn=(GMName_Struct*)outapp->pBuffer; - strn0cpy(gmn->gmname,gmname,64); - strn0cpy(gmn->oldname,GetName(),64); - strn0cpy(gmn->newname,in_firstname,64); - gmn->unknown[0] = 1; - gmn->unknown[1] = 1; - gmn->unknown[2] = 1; - entity_list.QueueClients(this, outapp, false); - safe_delete(outapp); - - // finally, update the /who list - UpdateWho(); - - // success - return true; -} - -void Client::SetGM(bool toggle) { - m_pp.gm = toggle ? 1 : 0; - Message(13, "You are %s a GM.", m_pp.gm ? "now" : "no longer"); - SendAppearancePacket(AT_GM, m_pp.gm); - Save(); - UpdateWho(); -} - -void Client::ReadBook(BookRequest_Struct *book) { - char *txtfile = book->txtfile; - - if(txtfile[0] == '0' && txtfile[1] == '\0') { - //invalid book... coming up on non-book items. - return; - } - - std::string booktxt2 = database.GetBook(txtfile); - int length = booktxt2.length(); - - if (booktxt2[0] != '\0') { -#if EQDEBUG >= 6 - LogFile->write(EQEMuLog::Normal,"Client::ReadBook() textfile:%s Text:%s", txtfile, booktxt2.c_str()); -#endif - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ReadBook, length + sizeof(BookText_Struct)); - - BookText_Struct *out = (BookText_Struct *) outapp->pBuffer; - out->window = book->window; - if(GetClientVersion() >= EQClientSoF) - { - const ItemInst *inst = m_inv[book->invslot]; - if(inst) - out->type = inst->GetItem()->Book; - else - out->type = book->type; - } - else - { - out->type = book->type; - } - out->invslot = book->invslot; - memcpy(out->booktext, booktxt2.c_str(), length); - - QueuePacket(outapp); - safe_delete(outapp); - } -} - -void Client::QuestReadBook(const char* text, uint8 type) { - std::string booktxt2 = text; - int length = booktxt2.length(); - if (booktxt2[0] != '\0') { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ReadBook, length + sizeof(BookText_Struct)); - BookText_Struct *out = (BookText_Struct *) outapp->pBuffer; - out->window = 0xFF; - out->type = type; - out->invslot = 0; - memcpy(out->booktext, booktxt2.c_str(), length); - QueuePacket(outapp); - safe_delete(outapp); - } -} - -void Client::SendClientMoneyUpdate(uint8 type,uint32 amount){ - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TradeMoneyUpdate,sizeof(TradeMoneyUpdate_Struct)); - TradeMoneyUpdate_Struct* mus= (TradeMoneyUpdate_Struct*)outapp->pBuffer; - mus->amount=amount; - mus->trader=0; - mus->type=type; - QueuePacket(outapp); - safe_delete(outapp); -} - -bool Client::TakeMoneyFromPP(uint64 copper, bool updateclient) { - int64 copperpp,silver,gold,platinum; - copperpp = m_pp.copper; - silver = static_cast(m_pp.silver) * 10; - gold = static_cast(m_pp.gold) * 100; - platinum = static_cast(m_pp.platinum) * 1000; - - int64 clienttotal = copperpp + silver + gold + platinum; - - clienttotal -= copper; - if(clienttotal < 0) - { - return false; // Not enough money! - } - else - { - copperpp -= copper; - if(copperpp <= 0) - { - copper = abs64(copperpp); - m_pp.copper = 0; - } - else - { - m_pp.copper = copperpp; - if(updateclient) - SendMoneyUpdate(); - Save(); - return true; - } - silver -= copper; - if(silver <= 0) - { - copper = abs64(silver); - m_pp.silver = 0; - } - else - { - m_pp.silver = silver/10; - m_pp.copper += (silver-(m_pp.silver*10)); - if(updateclient) - SendMoneyUpdate(); - Save(); - return true; - } - - gold -=copper; - - if(gold <= 0) - { - copper = abs64(gold); - m_pp.gold = 0; - } - else - { - m_pp.gold = gold/100; - uint64 silvertest = (gold-(static_cast(m_pp.gold)*100))/10; - m_pp.silver += silvertest; - uint64 coppertest = (gold-(static_cast(m_pp.gold)*100+silvertest*10)); - m_pp.copper += coppertest; - if(updateclient) - SendMoneyUpdate(); - Save(); - return true; - } - - platinum -= copper; - - //Impossible for plat to be negative, already checked above - - m_pp.platinum = platinum/1000; - uint64 goldtest = (platinum-(static_cast(m_pp.platinum)*1000))/100; - m_pp.gold += goldtest; - uint64 silvertest = (platinum-(static_cast(m_pp.platinum)*1000+goldtest*100))/10; - m_pp.silver += silvertest; - uint64 coppertest = (platinum-(static_cast(m_pp.platinum)*1000+goldtest*100+silvertest*10)); - m_pp.copper = coppertest; - if(updateclient) - SendMoneyUpdate(); - RecalcWeight(); - Save(); - return true; - } -} - -void Client::AddMoneyToPP(uint64 copper, bool updateclient){ - uint64 tmp; - uint64 tmp2; - tmp = copper; - - // Add Amount of Platinum - tmp2 = tmp/1000; - int32 new_val = m_pp.platinum + tmp2; - if(new_val < 0) { - m_pp.platinum = 0; - } else { - m_pp.platinum = m_pp.platinum + tmp2; - } - tmp-=tmp2*1000; - - //if (updateclient) - // SendClientMoneyUpdate(3,tmp2); - - // Add Amount of Gold - tmp2 = tmp/100; - new_val = m_pp.gold + tmp2; - if(new_val < 0) { - m_pp.gold = 0; - } else { - m_pp.gold = m_pp.gold + tmp2; - } - tmp-=tmp2*100; - //if (updateclient) - // SendClientMoneyUpdate(2,tmp2); - - // Add Amount of Silver - tmp2 = tmp/10; - new_val = m_pp.silver + tmp2; - if(new_val < 0) { - m_pp.silver = 0; - } else { - m_pp.silver = m_pp.silver + tmp2; - } - tmp-=tmp2*10; - //if (updateclient) - // SendClientMoneyUpdate(1,tmp2); - - // Add Copper - //tmp = tmp - (tmp2* 10); - //if (updateclient) - // SendClientMoneyUpdate(0,tmp); - tmp2 = tmp; - new_val = m_pp.copper + tmp2; - if(new_val < 0) { - m_pp.copper = 0; - } else { - m_pp.copper = m_pp.copper + tmp2; - } - - - //send them all at once, since the above code stopped working. - if(updateclient) - SendMoneyUpdate(); - - RecalcWeight(); - - Save(); - - LogFile->write(EQEMuLog::Debug, "Client::AddMoneyToPP() %s should have: plat:%i gold:%i silver:%i copper:%i", GetName(), m_pp.platinum, m_pp.gold, m_pp.silver, m_pp.copper); -} - -void Client::AddMoneyToPP(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, bool updateclient){ - - /* Set a timestamp in an entity variable for plugin check_handin.pl in return_items - This will stopgap players from items being returned if global_npc.pl has a catch all return_items - */ - struct timeval read_time; - char buffer[50]; - gettimeofday(&read_time, 0); - sprintf(buffer, "%li.%li \n", read_time.tv_sec, read_time.tv_usec); - this->SetEntityVariable("Stop_Return", buffer); - - int32 new_value = m_pp.platinum + platinum; - if(new_value >= 0 && new_value > m_pp.platinum) - m_pp.platinum += platinum; - - new_value = m_pp.gold + gold; - if(new_value >= 0 && new_value > m_pp.gold) - m_pp.gold += gold; - - new_value = m_pp.silver + silver; - if(new_value >= 0 && new_value > m_pp.silver) - m_pp.silver += silver; - - new_value = m_pp.copper + copper; - if(new_value >= 0 && new_value > m_pp.copper) - m_pp.copper += copper; - - if(updateclient) - SendMoneyUpdate(); - - RecalcWeight(); - Save(); - -#if (EQDEBUG>=5) - LogFile->write(EQEMuLog::Debug, "Client::AddMoneyToPP() %s should have: plat:%i gold:%i silver:%i copper:%i", - GetName(), m_pp.platinum, m_pp.gold, m_pp.silver, m_pp.copper); -#endif -} - -void Client::SendMoneyUpdate() { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoneyUpdate,sizeof(MoneyUpdate_Struct)); - MoneyUpdate_Struct* mus= (MoneyUpdate_Struct*)outapp->pBuffer; - - mus->platinum = m_pp.platinum; - mus->gold = m_pp.gold; - mus->silver = m_pp.silver; - mus->copper = m_pp.copper; - - FastQueuePacket(&outapp); -} - -bool Client::HasMoney(uint64 Copper) { - - if ((static_cast(m_pp.copper) + - (static_cast(m_pp.silver) * 10) + - (static_cast(m_pp.gold) * 100) + - (static_cast(m_pp.platinum) * 1000)) >= Copper) - return true; - - return false; -} - -uint64 Client::GetCarriedMoney() { - - return ((static_cast(m_pp.copper) + - (static_cast(m_pp.silver) * 10) + - (static_cast(m_pp.gold) * 100) + - (static_cast(m_pp.platinum) * 1000))); -} - -uint64 Client::GetAllMoney() { - - return ( - (static_cast(m_pp.copper) + - (static_cast(m_pp.silver) * 10) + - (static_cast(m_pp.gold) * 100) + - (static_cast(m_pp.platinum) * 1000) + - (static_cast(m_pp.copper_bank) + - (static_cast(m_pp.silver_bank) * 10) + - (static_cast(m_pp.gold_bank) * 100) + - (static_cast(m_pp.platinum_bank) * 1000) + - (static_cast(m_pp.copper_cursor) + - (static_cast(m_pp.silver_cursor) * 10) + - (static_cast(m_pp.gold_cursor) * 100) + - (static_cast(m_pp.platinum_cursor) * 1000) + - (static_cast(m_pp.platinum_shared) * 1000))))); -} - -bool Client::CheckIncreaseSkill(SkillUseTypes skillid, Mob *against_who, int chancemodi) { - if (IsDead() || IsUnconscious()) - return false; - if (IsAIControlled()) // no skillups while chamred =p - return false; - if (skillid > HIGHEST_SKILL) - return false; - int skillval = GetRawSkill(skillid); - int maxskill = GetMaxSkillAfterSpecializationRules(skillid, MaxSkill(skillid)); - - if(against_who) - { - if(against_who->GetSpecialAbility(IMMUNE_AGGRO) || against_who->IsClient() || - GetLevelCon(against_who->GetLevel()) == CON_GREEN) - { - //false by default - if( !mod_can_increase_skill(skillid, against_who) ) { return(false); } - } - } - - // Make sure we're not already at skill cap - if (skillval < maxskill) - { - // the higher your current skill level, the harder it is - int16 Chance = 10 + chancemodi + ((252 - skillval) / 20); - if (Chance < 1) - Chance = 1; // Make it always possible - Chance = (Chance * RuleI(Character, SkillUpModifier) / 100); - - Chance = mod_increase_skill_chance(Chance, against_who); - - if(MakeRandomFloat(0, 99) < Chance) - { - SetSkill(skillid, GetRawSkill(skillid) + 1); - _log(SKILLS__GAIN, "Skill %d at value %d successfully gain with %.4f%%chance (mod %d)", skillid, skillval, Chance, chancemodi); - return true; - } else { - _log(SKILLS__GAIN, "Skill %d at value %d failed to gain with %.4f%%chance (mod %d)", skillid, skillval, Chance, chancemodi); - } - } else { - _log(SKILLS__GAIN, "Skill %d at value %d cannot increase due to maxmum %d", skillid, skillval, maxskill); - } - return false; -} - -void Client::CheckLanguageSkillIncrease(uint8 langid, uint8 TeacherSkill) { - if (IsDead() || IsUnconscious()) - return; - if (IsAIControlled()) - return; - if (langid >= MAX_PP_LANGUAGE) - return; // do nothing if langid is an invalid language - - int LangSkill = m_pp.languages[langid]; // get current language skill - - if (LangSkill < 100) { // if the language isn't already maxed - int16 Chance = 5 + ((TeacherSkill - LangSkill)/10); // greater chance to learn if teacher's skill is much higher than yours - Chance = (Chance * RuleI(Character, SkillUpModifier)/100); - - if(MakeRandomFloat(0,100) < Chance) { // if they make the roll - IncreaseLanguageSkill(langid); // increase the language skill by 1 - _log(SKILLS__GAIN, "Language %d at value %d successfully gain with %.4f%%chance", langid, LangSkill, Chance); - } - else - _log(SKILLS__GAIN, "Language %d at value %d failed to gain with %.4f%%chance", langid, LangSkill, Chance); - } -} - -bool Client::HasSkill(SkillUseTypes skill_id) const { - return((GetSkill(skill_id) > 0) && CanHaveSkill(skill_id)); -} - -bool Client::CanHaveSkill(SkillUseTypes skill_id) const { - return(database.GetSkillCap(GetClass(), skill_id, RuleI(Character, MaxLevel)) > 0); - //if you don't have it by max level, then odds are you never will? -} - -uint16 Client::MaxSkill(SkillUseTypes skillid, uint16 class_, uint16 level) const { - return(database.GetSkillCap(class_, skillid, level)); -} - -uint8 Client::SkillTrainLevel(SkillUseTypes skillid, uint16 class_){ - return(database.GetTrainLevel(class_, skillid, RuleI(Character, MaxLevel))); -} - -uint16 Client::GetMaxSkillAfterSpecializationRules(SkillUseTypes skillid, uint16 maxSkill) -{ - uint16 Result = maxSkill; - - uint16 PrimarySpecialization = 0, SecondaryForte = 0; - - uint16 PrimarySkillValue = 0, SecondarySkillValue = 0; - - uint16 MaxSpecializations = GetAA(aaSecondaryForte) ? 2 : 1; - - if(skillid >= SkillSpecializeAbjure && skillid <= SkillSpecializeEvocation) - { - bool HasPrimarySpecSkill = false; - - int NumberOfPrimarySpecSkills = 0; - - for(int i = SkillSpecializeAbjure; i <= SkillSpecializeEvocation; ++i) - { - if(m_pp.skills[i] > 50) - { - HasPrimarySpecSkill = true; - NumberOfPrimarySpecSkills++; - } - if(m_pp.skills[i] > PrimarySkillValue) - { - if(PrimarySkillValue > SecondarySkillValue) - { - SecondarySkillValue = PrimarySkillValue; - SecondaryForte = PrimarySpecialization; - } - - PrimarySpecialization = i; - PrimarySkillValue = m_pp.skills[i]; - } - else if(m_pp.skills[i] > SecondarySkillValue) - { - SecondaryForte = i; - SecondarySkillValue = m_pp.skills[i]; - } - } - - if(SecondarySkillValue <=50) - SecondaryForte = 0; - - if(HasPrimarySpecSkill) - { - if(NumberOfPrimarySpecSkills <= MaxSpecializations) - { - if(MaxSpecializations == 1) - { - if(skillid != PrimarySpecialization) - { - Result = 50; - } - } - else - { - if((skillid != PrimarySpecialization) && ((skillid == SecondaryForte) || (SecondaryForte == 0))) - { - if((PrimarySkillValue > 100) || (!SecondaryForte)) - Result = 100; - } - else if(skillid != PrimarySpecialization) - { - Result = 50; - } - } - } - else - { - Message(13, "Your spell casting specializations skills have been reset. " - "Only %i primary specialization skill is allowed.", MaxSpecializations); - - for(int i = SkillSpecializeAbjure; i <= SkillSpecializeEvocation; ++i) - SetSkill((SkillUseTypes)i, 1); - - Save(); - - LogFile->write(EQEMuLog::Normal, "Reset %s's caster specialization skills to 1. " - "Too many specializations skills were above 50.", GetCleanName()); - } - - } - } - // This should possibly be handled by bonuses rather than here. - switch(skillid) - { - case SkillTracking: - { - Result += ((GetAA(aaAdvancedTracking) * 10) + (GetAA(aaTuneofPursuance) * 10)); - break; - } - - default: - break; - } - - return Result; -} - -void Client::SetPVP(bool toggle) { - m_pp.pvp = toggle ? 1 : 0; - - if(GetPVP()) - this->Message_StringID(MT_Shout,PVP_ON); - else - Message(13, "You no longer follow the ways of discord."); - - SendAppearancePacket(AT_PVP, GetPVP()); - Save(); -} - -void Client::WorldKick() { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GMKick, sizeof(GMKick_Struct)); - GMKick_Struct* gmk = (GMKick_Struct *)outapp->pBuffer; - strcpy(gmk->name,GetName()); - QueuePacket(outapp); - safe_delete(outapp); - Kick(); -} - -void Client::GMKill() { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GMKill, sizeof(GMKill_Struct)); - GMKill_Struct* gmk = (GMKill_Struct *)outapp->pBuffer; - strcpy(gmk->name,GetName()); - QueuePacket(outapp); - safe_delete(outapp); -} - -bool Client::CheckAccess(int16 iDBLevel, int16 iDefaultLevel) { - if ((admin >= iDBLevel) || (iDBLevel == 255 && admin >= iDefaultLevel)) - return true; - else - return false; -} - -void Client::MemorizeSpell(uint32 slot,uint32 spellid,uint32 scribing){ - EQApplicationPacket* outapp = new EQApplicationPacket(OP_MemorizeSpell,sizeof(MemorizeSpell_Struct)); - MemorizeSpell_Struct* mss=(MemorizeSpell_Struct*)outapp->pBuffer; - mss->scribing=scribing; - mss->slot=slot; - mss->spell_id=spellid; - outapp->priority = 5; - QueuePacket(outapp); - safe_delete(outapp); -} - -void Client::SetFeigned(bool in_feigned) { - if (in_feigned) - { - if(RuleB(Character, FeignKillsPet)) - { - SetPet(0); - } - SetHorseId(0); - entity_list.ClearFeignAggro(this); - forget_timer.Start(FeignMemoryDuration); - } else { - forget_timer.Disable(); - } - feigned=in_feigned; - } - -void Client::LogMerchant(Client* player, Mob* merchant, uint32 quantity, uint32 price, const Item_Struct* item, bool buying) -{ - if(!player || !merchant || !item) - return; - - std::string LogText = "Qty: "; - - char Buffer[255]; - memset(Buffer, 0, sizeof(Buffer)); - - snprintf(Buffer, sizeof(Buffer)-1, "%3i", quantity); - LogText += Buffer; - snprintf(Buffer, sizeof(Buffer)-1, "%10i", price); - LogText += " TotalValue: "; - LogText += Buffer; - snprintf(Buffer, sizeof(Buffer)-1, " ItemID: %7i", item->ID); - LogText += Buffer; - LogText += " "; - snprintf(Buffer, sizeof(Buffer)-1, " %s", item->Name); - LogText += Buffer; - - if (buying==true) { - database.logevents(player->AccountName(),player->AccountID(),player->admin,player->GetName(),merchant->GetName(),"Buying from Merchant",LogText.c_str(),2); - } - else { - database.logevents(player->AccountName(),player->AccountID(),player->admin,player->GetName(),merchant->GetName(),"Selling to Merchant",LogText.c_str(),3); - } -} - -void Client::LogLoot(Client* player, Corpse* corpse, const Item_Struct* item){ - char* logtext; - char itemid[100]; - char itemname[100]; - char coinloot[100]; - if (item!=0){ - memset(itemid,0,sizeof(itemid)); - memset(itemname,0,sizeof(itemid)); - itoa(item->ID,itemid,10); - sprintf(itemname,"%s",item->Name); - logtext=itemname; - - strcat(logtext,"("); - strcat(logtext,itemid); - strcat(logtext,") Looted"); - database.logevents(player->AccountName(),player->AccountID(),player->admin,player->GetName(),corpse->orgname,"Looting Item",logtext,4); - } - else{ - if ((corpse->GetPlatinum() + corpse->GetGold() + corpse->GetSilver() + corpse->GetCopper())>0) { - memset(coinloot,0,sizeof(coinloot)); - sprintf(coinloot,"%i PP %i GP %i SP %i CP",corpse->GetPlatinum(),corpse->GetGold(),corpse->GetSilver(),corpse->GetCopper()); - logtext=coinloot; - strcat(logtext," Looted"); - if (corpse->GetPlatinum()>10000) - database.logevents(player->AccountName(),player->AccountID(),player->admin,player->GetName(),corpse->orgname,"Excessive Loot!",logtext,9); - else - database.logevents(player->AccountName(),player->AccountID(),player->admin,player->GetName(),corpse->orgname,"Looting Money",logtext,5); - } - } -} - - -bool Client::BindWound(Mob* bindmob, bool start, bool fail){ - EQApplicationPacket* outapp = 0; - if(!fail) { - outapp = new EQApplicationPacket(OP_Bind_Wound, sizeof(BindWound_Struct)); - BindWound_Struct* bind_out = (BindWound_Struct*) outapp->pBuffer; - // Start bind - if(!bindwound_timer.Enabled()) { - //make sure we actually have a bandage... and consume it. - int16 bslot = m_inv.HasItemByUse(ItemTypeBandage, 1, invWhereWorn|invWherePersonal); - if (bslot == INVALID_INDEX) { - bind_out->type = 3; - QueuePacket(outapp); - bind_out->type = 7; //this is the wrong message, dont know the right one. - QueuePacket(outapp); - return(true); - } - DeleteItemInInventory(bslot, 1, true); //do we need client update? - - // start complete timer - bindwound_timer.Start(10000); - bindwound_target = bindmob; - - // Send client unlock - bind_out->type = 3; - QueuePacket(outapp); - bind_out->type = 0; - // Client Unlocked - if(!bindmob) { - // send "bindmob dead" to client - bind_out->type = 4; - QueuePacket(outapp); - bind_out->type = 0; - bindwound_timer.Disable(); - bindwound_target = 0; - } - else { - // send bindmob "stand still" - if(!bindmob->IsAIControlled() && bindmob != this ) { - bind_out->type = 2; // ? - //bind_out->type = 3; // ? - bind_out->to = GetID(); // ? - bindmob->CastToClient()->QueuePacket(outapp); - bind_out->type = 0; - bind_out->to = 0; - } - else if (bindmob->IsAIControlled() && bindmob != this ){ - ; // Tell IPC to stand still? - } - else { - ; // Binding self - } - } - } else { - // finish bind - // disable complete timer - bindwound_timer.Disable(); - bindwound_target = 0; - if(!bindmob){ - // send "bindmob gone" to client - bind_out->type = 5; // not in zone - QueuePacket(outapp); - bind_out->type = 0; - } - - else { - if (!GetFeigned() && (bindmob->DistNoRoot(*this) <= 400)) { - // send bindmob bind done - if(!bindmob->IsAIControlled() && bindmob != this ) { - - } - else if(bindmob->IsAIControlled() && bindmob != this ) { - // Tell IPC to resume?? - } - else { - // Binding self - } - // Send client bind done - - bind_out->type = 1; // Done - QueuePacket(outapp); - bind_out->type = 0; - CheckIncreaseSkill(SkillBindWound, nullptr, 5); - - int maxHPBonus = spellbonuses.MaxBindWound + itembonuses.MaxBindWound + aabonuses.MaxBindWound; - - int max_percent = 50 + 10 * maxHPBonus; - - if(GetClass() == MONK && GetSkill(SkillBindWound) > 200) { - max_percent = 70 + 10 * maxHPBonus; - } - - max_percent = mod_bindwound_percent(max_percent, bindmob); - - int max_hp = bindmob->GetMaxHP()*max_percent/100; - - // send bindmob new hp's - if (bindmob->GetHP() < bindmob->GetMaxHP() && bindmob->GetHP() <= (max_hp)-1){ - // 0.120 per skill point, 0.60 per skill level, minimum 3 max 30 - int bindhps = 3; - - - if (GetSkill(SkillBindWound) > 200) { - bindhps += GetSkill(SkillBindWound)*4/10; - } else if (GetSkill(SkillBindWound) >= 10) { - bindhps += GetSkill(SkillBindWound)/4; - } - - //Implementation of aaMithanielsBinding is a guess (the multiplier) - int bindBonus = spellbonuses.BindWound + itembonuses.BindWound + aabonuses.BindWound; - - bindhps += bindhps*bindBonus / 100; - - bindhps = mod_bindwound_hp(bindhps, bindmob); - - //if the bind takes them above the max bindable - //cap it at that value. Dont know if live does it this way - //but it makes sense to me. - int chp = bindmob->GetHP() + bindhps; - if(chp > max_hp) - chp = max_hp; - - bindmob->SetHP(chp); - bindmob->SendHPUpdate(); - } - else { - //I dont have the real, live - Message(15, "You cannot bind wounds above %d%% hitpoints.", max_percent); - if(bindmob->IsClient()) - bindmob->CastToClient()->Message(15, "You cannot have your wounds bound above %d%% hitpoints.", max_percent); - // Too many hp message goes here. - } - } - else { - // Send client bind failed - if(bindmob != this) - bind_out->type = 6; // They moved - else - bind_out->type = 7; // Bandager moved - - QueuePacket(outapp); - bind_out->type = 0; - } - } - } - } - else if (bindwound_timer.Enabled()) { - // You moved - outapp = new EQApplicationPacket(OP_Bind_Wound, sizeof(BindWound_Struct)); - BindWound_Struct* bind_out = (BindWound_Struct*) outapp->pBuffer; - bindwound_timer.Disable(); - bindwound_target = 0; - bind_out->type = 7; - QueuePacket(outapp); - bind_out->type = 3; - QueuePacket(outapp); - } - safe_delete(outapp); - return true; -} - -void Client::SetMaterial(int16 in_slot, uint32 item_id) { - const Item_Struct* item = database.GetItem(item_id); - if (item && (item->ItemClass==ItemClassCommon)) { - if (in_slot==MainHead) - m_pp.item_material[MaterialHead] = item->Material; - else if (in_slot==MainChest) - m_pp.item_material[MaterialChest] = item->Material; - else if (in_slot==MainArms) - m_pp.item_material[MaterialArms] = item->Material; - else if (in_slot==MainWrist1) - m_pp.item_material[MaterialWrist] = item->Material; - /* - // non-live behavior - else if (in_slot==SLOT_BRACER02) - m_pp.item_material[MaterialWrist] = item->Material; - */ - else if (in_slot==MainHands) - m_pp.item_material[MaterialHands] = item->Material; - else if (in_slot==MainLegs) - m_pp.item_material[MaterialLegs] = item->Material; - else if (in_slot==MainFeet) - m_pp.item_material[MaterialFeet] = item->Material; - else if (in_slot==MainPrimary) - m_pp.item_material[MaterialPrimary] = atoi(item->IDFile+2); - else if (in_slot==MainSecondary) - m_pp.item_material[MaterialSecondary] = atoi(item->IDFile+2); - } -} - -void Client::ServerFilter(SetServerFilter_Struct* filter){ - -/* this code helps figure out the filter IDs in the packet if needed - static SetServerFilter_Struct ssss; - int r; - uint32 *o = (uint32 *) &ssss; - uint32 *n = (uint32 *) filter; - for(r = 0; r < (sizeof(SetServerFilter_Struct)/4); r++) { - if(*o != *n) - LogFile->write(EQEMuLog::Debug, "Filter %d changed from %d to %d", r, *o, *n); - o++; n++; - } - memcpy(&ssss, filter, sizeof(SetServerFilter_Struct)); -*/ -#define Filter0(type) \ - if(filter->filters[type] == 1) \ - ClientFilters[type] = FilterShow; \ - else \ - ClientFilters[type] = FilterHide; -#define Filter1(type) \ - if(filter->filters[type] == 0) \ - ClientFilters[type] = FilterShow; \ - else \ - ClientFilters[type] = FilterHide; - - Filter0(FilterGuildChat); - Filter0(FilterSocials); - Filter0(FilterGroupChat); - Filter0(FilterShouts); - Filter0(FilterAuctions); - Filter0(FilterOOC); - Filter0(FilterBadWords); - - if(filter->filters[FilterPCSpells] == 0) - ClientFilters[FilterPCSpells] = FilterShow; - else if(filter->filters[FilterPCSpells] == 1) - ClientFilters[FilterPCSpells] = FilterHide; - else - ClientFilters[FilterPCSpells] = FilterShowGroupOnly; - - Filter1(FilterNPCSpells); - - if(filter->filters[FilterBardSongs] == 0) - ClientFilters[FilterBardSongs] = FilterShow; - else if(filter->filters[FilterBardSongs] == 1) - ClientFilters[FilterBardSongs] = FilterShowSelfOnly; - else if(filter->filters[FilterBardSongs] == 2) - ClientFilters[FilterBardSongs] = FilterShowGroupOnly; - else - ClientFilters[FilterBardSongs] = FilterHide; - - if(filter->filters[FilterSpellCrits] == 0) - ClientFilters[FilterSpellCrits] = FilterShow; - else if(filter->filters[FilterSpellCrits] == 1) - ClientFilters[FilterSpellCrits] = FilterShowSelfOnly; - else - ClientFilters[FilterSpellCrits] = FilterHide; - - if (filter->filters[FilterMeleeCrits] == 0) - ClientFilters[FilterMeleeCrits] = FilterShow; - else if (filter->filters[FilterMeleeCrits] == 1) - ClientFilters[FilterMeleeCrits] = FilterShowSelfOnly; - else - ClientFilters[FilterMeleeCrits] = FilterHide; - - if(filter->filters[FilterSpellDamage] == 0) - ClientFilters[FilterSpellDamage] = FilterShow; - else if(filter->filters[FilterSpellDamage] == 1) - ClientFilters[FilterSpellDamage] = FilterShowSelfOnly; - else - ClientFilters[FilterSpellDamage] = FilterHide; - - Filter0(FilterMyMisses); - Filter0(FilterOthersMiss); - Filter0(FilterOthersHit); - Filter0(FilterMissedMe); - Filter1(FilterDamageShields); - - if (GetClientVersionBit() & BIT_SoDAndLater) { - if (filter->filters[FilterDOT] == 0) - ClientFilters[FilterDOT] = FilterShow; - else if (filter->filters[FilterDOT] == 1) - ClientFilters[FilterDOT] = FilterShowSelfOnly; - else if (filter->filters[FilterDOT] == 2) - ClientFilters[FilterDOT] = FilterShowGroupOnly; - else - ClientFilters[FilterDOT] = FilterHide; - } else { - if (filter->filters[FilterDOT] == 0) // show functions as self only - ClientFilters[FilterDOT] = FilterShowSelfOnly; - else - ClientFilters[FilterDOT] = FilterHide; - } - - Filter1(FilterPetHits); - Filter1(FilterPetMisses); - Filter1(FilterFocusEffects); - Filter1(FilterPetSpells); - - if (GetClientVersionBit() & BIT_SoDAndLater) { - if (filter->filters[FilterHealOverTime] == 0) - ClientFilters[FilterHealOverTime] = FilterShow; - // This is called 'Show Mine Only' in the clients, but functions the same as show - // so instead of apply special logic, just set to show - else if (filter->filters[FilterHealOverTime] == 1) - ClientFilters[FilterHealOverTime] = FilterShow; - else - ClientFilters[FilterHealOverTime] = FilterHide; - } else { - // these clients don't have a 'self only' filter - Filter1(FilterHealOverTime); - } -} - -// this version is for messages with no parameters -void Client::Message_StringID(uint32 type, uint32 string_id, uint32 distance) -{ - if (GetFilter(FilterSpellDamage) == FilterHide && type == MT_NonMelee) - return; - if (GetFilter(FilterMeleeCrits) == FilterHide && type == MT_CritMelee) //98 is self... - return; - if (GetFilter(FilterSpellCrits) == FilterHide && type == MT_SpellCrits) - return; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SimpleMessage,12); - SimpleMessage_Struct* sms = (SimpleMessage_Struct*)outapp->pBuffer; - sms->color=type; - sms->string_id=string_id; - - sms->unknown8=0; - - if(distance>0) - entity_list.QueueCloseClients(this,outapp,false,distance); - else - QueuePacket(outapp); - safe_delete(outapp); -} - -// -// this list of 9 args isn't how I want to do it, but to use va_arg -// you have to know how many args you're expecting, and to do that we have -// to load the eqstr file and count them in the string. -// This hack sucks but it's gonna work for now. -// -void Client::Message_StringID(uint32 type, uint32 string_id, const char* message1, - const char* message2,const char* message3,const char* message4, - const char* message5,const char* message6,const char* message7, - const char* message8,const char* message9, uint32 distance) -{ - if (GetFilter(FilterSpellDamage) == FilterHide && type == MT_NonMelee) - return; - if (GetFilter(FilterMeleeCrits) == FilterHide && type == MT_CritMelee) //98 is self... - return; - if (GetFilter(FilterSpellCrits) == FilterHide && type == MT_SpellCrits) - return; - if (GetFilter(FilterDamageShields) == FilterHide && type == MT_DS) - return; - - int i, argcount, length; - char *bufptr; - const char *message_arg[9] = {0}; - - if(type==MT_Emote) - type=4; - - if(!message1) - { - Message_StringID(type, string_id); // use the simple message instead - return; - } - - i = 0; - message_arg[i++] = message1; - message_arg[i++] = message2; - message_arg[i++] = message3; - message_arg[i++] = message4; - message_arg[i++] = message5; - message_arg[i++] = message6; - message_arg[i++] = message7; - message_arg[i++] = message8; - message_arg[i++] = message9; - - for(argcount = length = 0; message_arg[argcount]; argcount++) - length += strlen(message_arg[argcount]) + 1; - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_FormattedMessage, length+13); - FormattedMessage_Struct *fm = (FormattedMessage_Struct *)outapp->pBuffer; - fm->string_id = string_id; - fm->type = type; - bufptr = fm->message; - for(i = 0; i < argcount; i++) - { - strcpy(bufptr, message_arg[i]); - bufptr += strlen(message_arg[i]) + 1; - } - - - if(distance>0) - entity_list.QueueCloseClients(this,outapp,false,distance); - else - QueuePacket(outapp); - safe_delete(outapp); -} - -// helper function, returns true if we should see the message -bool Client::FilteredMessageCheck(Mob *sender, eqFilterType filter) -{ - eqFilterMode mode = GetFilter(filter); - // easy ones first - if (mode == FilterShow) - return true; - else if (mode == FilterHide) - return false; - - if (!sender && mode == FilterHide) { - return false; - } else if (sender) { - if (this == sender) { - if (mode == FilterHide) // don't need to check others - return false; - } else if (mode == FilterShowSelfOnly) { // we know sender isn't us - return false; - } else if (mode == FilterShowGroupOnly) { - Group *g = GetGroup(); - Raid *r = GetRaid(); - if (g) { - if (g->IsGroupMember(sender)) - return true; - } else if (r && sender->IsClient()) { - uint32 rgid1 = r->GetGroup(this); - uint32 rgid2 = r->GetGroup(sender->CastToClient()); - if (rgid1 != 0xFFFFFFFF && rgid1 == rgid2) - return true; - } else { - return false; - } - } - } - - // we passed our checks - return true; -} - -void Client::FilteredMessage_StringID(Mob *sender, uint32 type, - eqFilterType filter, uint32 string_id) -{ - if (!FilteredMessageCheck(sender, filter)) - return; - - EQApplicationPacket *outapp = new EQApplicationPacket(OP_SimpleMessage, 12); - SimpleMessage_Struct *sms = (SimpleMessage_Struct *)outapp->pBuffer; - sms->color = type; - sms->string_id = string_id; - - sms->unknown8 = 0; - - QueuePacket(outapp); - safe_delete(outapp); - - return; -} - -void Client::FilteredMessage_StringID(Mob *sender, uint32 type, eqFilterType filter, uint32 string_id, - const char *message1, const char *message2, const char *message3, - const char *message4, const char *message5, const char *message6, - const char *message7, const char *message8, const char *message9) -{ - if (!FilteredMessageCheck(sender, filter)) - return; - - int i, argcount, length; - char *bufptr; - const char *message_arg[9] = {0}; - - if (type == MT_Emote) - type = 4; - - if (!message1) { - FilteredMessage_StringID(sender, type, filter, string_id); // use the simple message instead - return; - } - - i = 0; - message_arg[i++] = message1; - message_arg[i++] = message2; - message_arg[i++] = message3; - message_arg[i++] = message4; - message_arg[i++] = message5; - message_arg[i++] = message6; - message_arg[i++] = message7; - message_arg[i++] = message8; - message_arg[i++] = message9; - - for (argcount = length = 0; message_arg[argcount]; argcount++) - length += strlen(message_arg[argcount]) + 1; - - EQApplicationPacket *outapp = new EQApplicationPacket(OP_FormattedMessage, length+13); - FormattedMessage_Struct *fm = (FormattedMessage_Struct *)outapp->pBuffer; - fm->string_id = string_id; - fm->type = type; - bufptr = fm->message; - for (i = 0; i < argcount; i++) { - strcpy(bufptr, message_arg[i]); - bufptr += strlen(message_arg[i]) + 1; - } - - QueuePacket(outapp); - safe_delete(outapp); -} - -void Client::SetTint(int16 in_slot, uint32 color) { - Color_Struct new_color; - new_color.color = color; - SetTint(in_slot, new_color); -} - -// Still need to reconcile bracer01 versus bracer02 -void Client::SetTint(int16 in_slot, Color_Struct& color) { - if (in_slot==MainHead) - m_pp.item_tint[MaterialHead].color=color.color; - else if (in_slot==MainArms) - m_pp.item_tint[MaterialArms].color=color.color; - else if (in_slot==MainWrist1) - m_pp.item_tint[MaterialWrist].color=color.color; - /* - // non-live behavior - else if (in_slot==SLOT_BRACER02) - m_pp.item_tint[MaterialWrist].color=color.color; - */ - else if (in_slot==MainHands) - m_pp.item_tint[MaterialHands].color=color.color; - else if (in_slot==MainPrimary) - m_pp.item_tint[MaterialPrimary].color=color.color; - else if (in_slot==MainSecondary) - m_pp.item_tint[MaterialSecondary].color=color.color; - else if (in_slot==MainChest) - m_pp.item_tint[MaterialChest].color=color.color; - else if (in_slot==MainLegs) - m_pp.item_tint[MaterialLegs].color=color.color; - else if (in_slot==MainFeet) - m_pp.item_tint[MaterialFeet].color=color.color; -} - -void Client::SetHideMe(bool flag) -{ - EQApplicationPacket app; - - gmhideme = flag; - - if(gmhideme) - { - database.SetHideMe(AccountID(),true); - CreateDespawnPacket(&app, false); - entity_list.RemoveFromTargets(this); - trackable = false; - } - else - { - database.SetHideMe(AccountID(),false); - CreateSpawnPacket(&app); - trackable = true; - } - - entity_list.QueueClientsStatus(this, &app, true, 0, Admin()-1); -} - -void Client::SetLanguageSkill(int langid, int value) -{ - if (langid >= MAX_PP_LANGUAGE) - return; //Invalid Language - - if (value > 100) - value = 100; //Max lang value - - m_pp.languages[langid] = value; - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SkillUpdate, sizeof(SkillUpdate_Struct)); - SkillUpdate_Struct* skill = (SkillUpdate_Struct*)outapp->pBuffer; - skill->skillId = 100 + langid; - skill->value = m_pp.languages[langid]; - QueuePacket(outapp); - safe_delete(outapp); - - Message_StringID( MT_Skills, LANG_SKILL_IMPROVED ); //Notify the client -} - -void Client::LinkDead() -{ - if (GetGroup()) - { - entity_list.MessageGroup(this,true,15,"%s has gone linkdead.",GetName()); - GetGroup()->DelMember(this); - } - Raid *raid = entity_list.GetRaidByClient(this); - if(raid){ - raid->MemberZoned(this); - } -// save_timer.Start(2500); - linkdead_timer.Start(RuleI(Zone,ClientLinkdeadMS)); - SendAppearancePacket(AT_Linkdead, 1); - client_state = CLIENT_LINKDEAD; - AI_Start(CLIENT_LD_TIMEOUT); -} - -uint8 Client::SlotConvert(uint8 slot,bool bracer){ - uint8 slot2=0; // why are we returning MainCharm instead of INVALID_INDEX? (must be a pre-charm segment...) - if(bracer) - return MainWrist2; - switch(slot){ - case MaterialHead: - slot2=MainHead; - break; - case MaterialChest: - slot2=MainChest; - break; - case MaterialArms: - slot2=MainArms; - break; - case MaterialWrist: - slot2=MainWrist1; - break; - case MaterialHands: - slot2=MainHands; - break; - case MaterialLegs: - slot2=MainLegs; - break; - case MaterialFeet: - slot2=MainFeet; - break; - } - return slot2; -} - -uint8 Client::SlotConvert2(uint8 slot){ - uint8 slot2=0; // same as above... - switch(slot){ - case MainHead: - slot2=MaterialHead; - break; - case MainChest: - slot2=MaterialChest; - break; - case MainArms: - slot2=MaterialArms; - break; - case MainWrist1: - slot2=MaterialWrist; - break; - case MainHands: - slot2=MaterialHands; - break; - case MainLegs: - slot2=MaterialLegs; - break; - case MainFeet: - slot2=MaterialFeet; - break; - } - return slot2; -} - -void Client::Escape() -{ - entity_list.RemoveFromTargets(this, true); - SetInvisible(1); - - Message_StringID(MT_Skills, ESCAPE); -} - -float Client::CalcPriceMod(Mob* other, bool reverse) -{ - float chaformula = 0; - if (other) - { - int factionlvl = GetFactionLevel(CharacterID(), other->CastToNPC()->GetNPCTypeID(), GetRace(), GetClass(), GetDeity(), other->CastToNPC()->GetPrimaryFaction(), other); - if (factionlvl >= FACTION_APPREHENSIVE) // Apprehensive or worse. - { - if (GetCHA() > 103) - { - chaformula = (GetCHA() - 103)*((-(RuleR(Merchant, ChaBonusMod))/100)*(RuleI(Merchant, PriceBonusPct))); // This will max out price bonus. - if (chaformula < -1*(RuleI(Merchant, PriceBonusPct))) - chaformula = -1*(RuleI(Merchant, PriceBonusPct)); - } - else if (GetCHA() < 103) - { - chaformula = (103 - GetCHA())*(((RuleR(Merchant, ChaPenaltyMod))/100)*(RuleI(Merchant, PricePenaltyPct))); // This will bottom out price penalty. - if (chaformula > 1*(RuleI(Merchant, PricePenaltyPct))) - chaformula = 1*(RuleI(Merchant, PricePenaltyPct)); - } - } - if (factionlvl <= FACTION_INDIFFERENT) // Indifferent or better. - { - if (GetCHA() > 75) - { - chaformula = (GetCHA() - 75)*((-(RuleR(Merchant, ChaBonusMod))/100)*(RuleI(Merchant, PriceBonusPct))); // This will max out price bonus. - if (chaformula < -1*(RuleI(Merchant, PriceBonusPct))) - chaformula = -1*(RuleI(Merchant, PriceBonusPct)); - } - else if (GetCHA() < 75) - { - chaformula = (75 - GetCHA())*(((RuleR(Merchant, ChaPenaltyMod))/100)*(RuleI(Merchant, PricePenaltyPct))); // Faction modifier keeps up from reaching bottom price penalty. - if (chaformula > 1*(RuleI(Merchant, PricePenaltyPct))) - chaformula = 1*(RuleI(Merchant, PricePenaltyPct)); - } - } - } - - if (reverse) - chaformula *= -1; //For selling - //Now we have, for example, 10 - chaformula /= 100; //Convert to 0.10 - chaformula += 1; //Convert to 1.10; - return chaformula; //Returns 1.10, expensive stuff! -} - -//neat idea from winter's roar, not implemented -void Client::Insight(uint32 t_id) -{ - Mob* who = entity_list.GetMob(t_id); - if (!who) - return; - if (!who->IsNPC()) - { - Message(0,"This ability can only be used on NPCs."); - return; - } - if (Dist(*who) > 200) - { - Message(0,"You must get closer to your target!"); - return; - } - if (!CheckLosFN(who)) - { - Message(0,"You must be able to see your target!"); - return; - } - char hitpoints[64]; - char resists[320]; - char dmg[64]; - memset(hitpoints,0,sizeof(hitpoints)); - memset(resists,0,sizeof(resists)); - memset(dmg,0,sizeof(dmg)); - //Start with HP blah - int avg_hp = GetLevelHP(who->GetLevel()); - int cur_hp = who->GetHP(); - if (cur_hp == avg_hp) - { - strn0cpy(hitpoints,"averagely tough",32); - } - else if (cur_hp >= avg_hp*5) - { - strn0cpy(hitpoints,"extremely tough",32); - } - else if (cur_hp >= avg_hp*4) - { - strn0cpy(hitpoints,"exceptionally tough",32); - } - else if (cur_hp >= avg_hp*3) - { - strn0cpy(hitpoints,"very tough",32); - } - else if (cur_hp >= avg_hp*2) - { - strn0cpy(hitpoints,"quite tough",32); - } - else if (cur_hp >= avg_hp*1.25) - { - strn0cpy(hitpoints,"rather tough",32); - } - else if (cur_hp > avg_hp) - { - strn0cpy(hitpoints,"slightly tough",32); - } - else if (cur_hp <= avg_hp*0.20) - { - strn0cpy(hitpoints,"extremely frail",32); - } - else if (cur_hp <= avg_hp*0.25) - { - strn0cpy(hitpoints,"exceptionally frail",32); - } - else if (cur_hp <= avg_hp*0.33) - { - strn0cpy(hitpoints,"very frail",32); - } - else if (cur_hp <= avg_hp*0.50) - { - strn0cpy(hitpoints,"quite frail",32); - } - else if (cur_hp <= avg_hp*0.75) - { - strn0cpy(hitpoints,"rather frail",32); - } - else if (cur_hp < avg_hp) - { - strn0cpy(hitpoints,"slightly frail",32); - } - - int avg_dmg = who->CastToNPC()->GetMaxDamage(who->GetLevel()); - int cur_dmg = who->CastToNPC()->GetMaxDMG(); - if (cur_dmg == avg_dmg) - { - strn0cpy(dmg,"averagely strong",32); - } - else if (cur_dmg >= avg_dmg*4) - { - strn0cpy(dmg,"extremely strong",32); - } - else if (cur_dmg >= avg_dmg*3) - { - strn0cpy(dmg,"exceptionally strong",32); - } - else if (cur_dmg >= avg_dmg*2) - { - strn0cpy(dmg,"very strong",32); - } - else if (cur_dmg >= avg_dmg*1.25) - { - strn0cpy(dmg,"quite strong",32); - } - else if (cur_dmg >= avg_dmg*1.10) - { - strn0cpy(dmg,"rather strong",32); - } - else if (cur_dmg > avg_dmg) - { - strn0cpy(dmg,"slightly strong",32); - } - else if (cur_dmg <= avg_dmg*0.20) - { - strn0cpy(dmg,"extremely weak",32); - } - else if (cur_dmg <= avg_dmg*0.25) - { - strn0cpy(dmg,"exceptionally weak",32); - } - else if (cur_dmg <= avg_dmg*0.33) - { - strn0cpy(dmg,"very weak",32); - } - else if (cur_dmg <= avg_dmg*0.50) - { - strn0cpy(dmg,"quite weak",32); - } - else if (cur_dmg <= avg_dmg*0.75) - { - strn0cpy(dmg,"rather weak",32); - } - else if (cur_dmg < avg_dmg) - { - strn0cpy(dmg,"slightly weak",32); - } - - //Resists - int res; - int i = 1; - - //MR - res = who->GetResist(i); - i++; - if (res >= 1000) - { - strcat(resists,"immune"); - } - else if (res >= 500) - { - strcat(resists,"practically immune"); - } - else if (res >= 250) - { - strcat(resists,"exceptionally resistant"); - } - else if (res >= 150) - { - strcat(resists,"very resistant"); - } - else if (res >= 100) - { - strcat(resists,"fairly resistant"); - } - else if (res >= 50) - { - strcat(resists,"averagely resistant"); - } - else if (res >= 25) - { - strcat(resists,"weakly resistant"); - } - else - { - strcat(resists,"barely resistant"); - } - strcat(resists," to magic, "); - - //FR - res = who->GetResist(i); - i++; - if (res >= 1000) - { - strcat(resists,"immune"); - } - else if (res >= 500) - { - strcat(resists,"practically immune"); - } - else if (res >= 250) - { - strcat(resists,"exceptionally resistant"); - } - else if (res >= 150) - { - strcat(resists,"very resistant"); - } - else if (res >= 100) - { - strcat(resists,"fairly resistant"); - } - else if (res >= 50) - { - strcat(resists,"averagely resistant"); - } - else if (res >= 25) - { - strcat(resists,"weakly resistant"); - } - else - { - strcat(resists,"barely resistant"); - } - strcat(resists," to fire, "); - - //CR - res = who->GetResist(i); - i++; - if (res >= 1000) - { - strcat(resists,"immune"); - } - else if (res >= 500) - { - strcat(resists,"practically immune"); - } - else if (res >= 250) - { - strcat(resists,"exceptionally resistant"); - } - else if (res >= 150) - { - strcat(resists,"very resistant"); - } - else if (res >= 100) - { - strcat(resists,"fairly resistant"); - } - else if (res >= 50) - { - strcat(resists,"averagely resistant"); - } - else if (res >= 25) - { - strcat(resists,"weakly resistant"); - } - else - { - strcat(resists,"barely resistant"); - } - strcat(resists," to cold, "); - - //PR - res = who->GetResist(i); - i++; - if (res >= 1000) - { - strcat(resists,"immune"); - } - else if (res >= 500) - { - strcat(resists,"practically immune"); - } - else if (res >= 250) - { - strcat(resists,"exceptionally resistant"); - } - else if (res >= 150) - { - strcat(resists,"very resistant"); - } - else if (res >= 100) - { - strcat(resists,"fairly resistant"); - } - else if (res >= 50) - { - strcat(resists,"averagely resistant"); - } - else if (res >= 25) - { - strcat(resists,"weakly resistant"); - } - else - { - strcat(resists,"barely resistant"); - } - strcat(resists," to poison, and "); - - //MR - res = who->GetResist(i); - i++; - if (res >= 1000) - { - strcat(resists,"immune"); - } - else if (res >= 500) - { - strcat(resists,"practically immune"); - } - else if (res >= 250) - { - strcat(resists,"exceptionally resistant"); - } - else if (res >= 150) - { - strcat(resists,"very resistant"); - } - else if (res >= 100) - { - strcat(resists,"fairly resistant"); - } - else if (res >= 50) - { - strcat(resists,"averagely resistant"); - } - else if (res >= 25) - { - strcat(resists,"weakly resistant"); - } - else - { - strcat(resists,"barely resistant"); - } - strcat(resists," to disease."); - - Message(0,"Your target is a level %i %s. It appears %s and %s for its level. It seems %s",who->GetLevel(),GetEQClassName(who->GetClass(),1),dmg,hitpoints,resists); -} - -void Client::ChangeSQLLog(const char *file) { - if(SQL_log != nullptr) { - fclose(SQL_log); - SQL_log = nullptr; - } - if(file != nullptr) { - if(strstr(file, "..") != nullptr) { - Message(13, ".. is forbibben in SQL log file names."); - return; - } - char buf[512]; - snprintf(buf, 511, "%s%s", SQL_LOG_PATH, file); - buf[511] = '\0'; - SQL_log = fopen(buf, "a"); - if(SQL_log == nullptr) { - Message(13, "Unable to open SQL log file: %s\n", strerror(errno)); - } - } -} - -void Client::LogSQL(const char *fmt, ...) { - if(SQL_log == nullptr) - return; - - va_list argptr; - va_start(argptr, fmt); - vfprintf(SQL_log, fmt, argptr ); - fputc('\n', SQL_log); - va_end(argptr); -} - -void Client::GetGroupAAs(GroupLeadershipAA_Struct *into) const { - memcpy(into, &m_pp.leader_abilities, sizeof(GroupLeadershipAA_Struct)); -} - -void Client::EnteringMessages(Client* client) -{ - //server rules - char *rules; - rules = new char [4096]; - - if(database.GetVariable("Rules", rules, 4096)) - { - uint8 flag = database.GetAgreementFlag(client->AccountID()); - if(!flag) - { - client->Message(13,"You must agree to the Rules, before you can move. (type #serverrules to view the rules)"); - client->Message(13,"You must agree to the Rules, before you can move. (type #serverrules to view the rules)"); - client->Message(13,"You must agree to the Rules, before you can move. (type #serverrules to view the rules)"); - client->SendAppearancePacket(AT_Anim, ANIM_FREEZE); - } - } - safe_delete_array(rules); -} - -void Client::SendRules(Client* client) -{ - char *rules; - rules = new char [4096]; - char *ptr; - - database.GetVariable("Rules", rules, 4096); - - ptr = strtok(rules, "\n"); - while(ptr != nullptr) - { - - client->Message(0,"%s",ptr); - ptr = strtok(nullptr, "\n"); - } - safe_delete_array(rules); -} - -void Client::SetEndurance(int32 newEnd) -{ - /*Endurance can't be less than 0 or greater than max*/ - if(newEnd < 0) - newEnd = 0; - else if(newEnd > GetMaxEndurance()){ - newEnd = GetMaxEndurance(); - } - - cur_end = newEnd; - SendManaUpdatePacket(); -} - -void Client::SacrificeConfirm(Client *caster) { - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Sacrifice, sizeof(Sacrifice_Struct)); - Sacrifice_Struct *ss = (Sacrifice_Struct*)outapp->pBuffer; - - if(!caster || PendingSacrifice) return; - - if(GetLevel() < RuleI(Spells, SacrificeMinLevel)){ - caster->Message_StringID(13, SAC_TOO_LOW); //This being is not a worthy sacrifice. - return; - } - if (GetLevel() > RuleI(Spells, SacrificeMaxLevel)) { - caster->Message_StringID(13, SAC_TOO_HIGH); - return; - } - - ss->CasterID = caster->GetID(); - ss->TargetID = GetID(); - ss->Confirm = 0; - QueuePacket(outapp); - safe_delete(outapp); - // We store the Caster's name, because when the packet comes back, it only has the victim's entityID in it, - // not the caster. - SacrificeCaster += caster->GetName(); - PendingSacrifice = true; -} - -//Essentially a special case death function -void Client::Sacrifice(Client *caster) -{ - if(GetLevel() >= RuleI(Spells, SacrificeMinLevel) && GetLevel() <= RuleI(Spells, SacrificeMaxLevel)){ - int exploss = (int)(GetLevel() * (GetLevel() / 18.0) * 12000); - if(exploss < GetEXP()){ - SetEXP(GetEXP()-exploss, GetAAXP()); - SendLogoutPackets(); - - //make our become corpse packet, and queue to ourself before OP_Death. - EQApplicationPacket app2(OP_BecomeCorpse, sizeof(BecomeCorpse_Struct)); - BecomeCorpse_Struct* bc = (BecomeCorpse_Struct*)app2.pBuffer; - bc->spawn_id = GetID(); - bc->x = GetX(); - bc->y = GetY(); - bc->z = GetZ(); - QueuePacket(&app2); - - // make death packet - EQApplicationPacket app(OP_Death, sizeof(Death_Struct)); - Death_Struct* d = (Death_Struct*)app.pBuffer; - d->spawn_id = GetID(); - d->killer_id = caster ? caster->GetID() : 0; - d->bindzoneid = GetPP().binds[0].zoneId; - d->spell_id = SPELL_UNKNOWN; - d->attack_skill = 0xe7; - d->damage = 0; - app.priority = 6; - entity_list.QueueClients(this, &app); - - BuffFadeAll(); - UnmemSpellAll(); - Group *g = GetGroup(); - if(g){ - g->MemberZoned(this); - } - Raid *r = entity_list.GetRaidByClient(this); - if(r){ - r->MemberZoned(this); - } - ClearAllProximities(); - if(RuleB(Character, LeaveCorpses)){ - Corpse *new_corpse = new Corpse(this, 0); - entity_list.AddCorpse(new_corpse, GetID()); - SetID(0); - entity_list.QueueClients(this, &app2, true); - } - Save(); - GoToDeath(); - caster->SummonItem(RuleI(Spells, SacrificeItemID)); - } - } - else{ - caster->Message_StringID(13, SAC_TOO_LOW); //This being is not a worthy sacrifice. - } -} - -void Client::SendOPTranslocateConfirm(Mob *Caster, uint16 SpellID) { - - if(!Caster || PendingTranslocate) return; - - const SPDat_Spell_Struct &Spell = spells[SpellID]; - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Translocate, sizeof(Translocate_Struct)); - Translocate_Struct *ts = (Translocate_Struct*)outapp->pBuffer; - - strcpy(ts->Caster, Caster->GetName()); - ts->SpellID = SpellID; - - if((SpellID == 1422) || (SpellID == 1334) || (SpellID == 3243)) { - ts->ZoneID = m_pp.binds[0].zoneId; - ts->x = m_pp.binds[0].x; - ts->y = m_pp.binds[0].y; - ts->z = m_pp.binds[0].z; - } - else { - ts->ZoneID = database.GetZoneID(Spell.teleport_zone); - ts->y = Spell.base[0]; - ts->x = Spell.base[1]; - ts->z = Spell.base[2]; - } - - ts->unknown008 = 0; - ts->Complete = 0; - - PendingTranslocateData = *ts; - PendingTranslocate=true; - TranslocateTime = time(nullptr); - - QueuePacket(outapp); - safe_delete(outapp); - - return; -} -void Client::SendPickPocketResponse(Mob *from, uint32 amt, int type, const Item_Struct* item){ - EQApplicationPacket* outapp = new EQApplicationPacket(OP_PickPocket, sizeof(sPickPocket_Struct)); - sPickPocket_Struct* pick_out = (sPickPocket_Struct*) outapp->pBuffer; - pick_out->coin = amt; - pick_out->from = GetID(); - pick_out->to = from->GetID(); - pick_out->myskill = GetSkill(SkillPickPockets); - - if((type >= PickPocketPlatinum) && (type <= PickPocketCopper) && (amt == 0)) - type = PickPocketFailed; - - pick_out->type = type; - if(item) - strcpy(pick_out->itemname, item->Name); - else - pick_out->itemname[0] = '\0'; - //if we do not send this packet the client will lock up and require the player to relog. - QueuePacket(outapp); - safe_delete(outapp); -} - -void Client::SetHoTT(uint32 mobid) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_TargetHoTT, sizeof(ClientTarget_Struct)); - ClientTarget_Struct *ct = (ClientTarget_Struct *) outapp->pBuffer; - ct->new_target = mobid; - QueuePacket(outapp); - safe_delete(outapp); -} - -void Client::SendPopupToClient(const char *Title, const char *Text, uint32 PopupID, uint32 Buttons, uint32 Duration) { - - EQApplicationPacket *outapp = new EQApplicationPacket(OP_OnLevelMessage, sizeof(OnLevelMessage_Struct)); - OnLevelMessage_Struct *olms = (OnLevelMessage_Struct *) outapp->pBuffer; - - if((strlen(Title) > (sizeof(olms->Title)-1)) || - (strlen(Text) > (sizeof(olms->Text)-1))) return; - - strcpy(olms->Title, Title); - strcpy(olms->Text, Text); - - olms->Buttons = Buttons; - - if(Duration > 0) - olms->Duration = Duration * 1000; - else - olms->Duration = 0xffffffff; - - olms->PopupID = PopupID; - olms->NegativeID = 0; - - sprintf(olms->ButtonName0, "%s", "Yes"); - sprintf(olms->ButtonName1, "%s", "No"); - QueuePacket(outapp); - safe_delete(outapp); -} - -void Client::SendWindow(uint32 PopupID, uint32 NegativeID, uint32 Buttons, const char *ButtonName0, const char *ButtonName1, uint32 Duration, int title_type, Client* target, const char *Title, const char *Text, ...) { - va_list argptr; - char buffer[4096]; - - va_start(argptr, Text); - vsnprintf(buffer, sizeof(buffer), Text, argptr); - va_end(argptr); - - size_t len = strlen(buffer); - - EQApplicationPacket* app = new EQApplicationPacket(OP_OnLevelMessage, sizeof(OnLevelMessage_Struct)); - OnLevelMessage_Struct* olms=(OnLevelMessage_Struct*)app->pBuffer; - - if(strlen(Text) > (sizeof(olms->Text)-1)) - return; - - if(!target) - title_type = 0; - - switch (title_type) - { - case 1: { - char name[64] = ""; - strcpy(name, target->GetName()); - if(target->GetLastName()) { - char last_name[64] = ""; - strcpy(last_name, target->GetLastName()); - strcat(name, " "); - strcat(name, last_name); - } - strcpy(olms->Title, name); - break; - } - case 2: { - if(target->GuildID()) { - char *guild_name = (char*)guild_mgr.GetGuildName(target->GuildID()); - strcpy(olms->Title, guild_name); - } - else { - strcpy(olms->Title, "No Guild"); - } - break; - } - default: { - strcpy(olms->Title, Title); - break; - } - } - - memcpy(olms->Text, buffer, len+1); - - olms->Buttons = Buttons; - - sprintf(olms->ButtonName0, "%s", ButtonName0); - sprintf(olms->ButtonName1, "%s", ButtonName1); - - if(Duration > 0) - olms->Duration = Duration * 1000; - else - olms->Duration = 0xffffffff; - - olms->PopupID = PopupID; - olms->NegativeID = NegativeID; - - FastQueuePacket(&app); -} - -void Client::KeyRingLoad() -{ - std::string query = StringFormat("SELECT item_id FROM keyring " - "WHERE char_id = '%i' ORDER BY item_id", character_id); - auto results = database.QueryDatabase(query); - if (!results.Success()) { - std::cerr << "Error in Client::KeyRingLoad query '" << query << "' " << results.ErrorMessage() << std::endl; - return; - } - - for (auto row = results.begin(); row != results.end(); ++row) - keyring.push_back(atoi(row[0])); - -} - -void Client::KeyRingAdd(uint32 item_id) -{ -<<<<<<< HEAD - if(0==item_id) - return; - - bool found = KeyRingCheck(item_id); - if (found) - return; - - std::string query = StringFormat("INSERT INTO keyring(char_id, item_id) VALUES(%i, %i)", character_id, item_id); - auto results = database.QueryDatabase(query); - if (!results.Success()) { - std::cerr << "Error in Doors::HandleClick query '" << query << "' " << results.ErrorMessage() << std::endl; - return; - } - - Message(4,"Added to keyring."); - - keyring.push_back(item_id); -======= - if(0==item_id)return; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; - query = new char[256]; - bool bFound = KeyRingCheck(item_id); - if(!bFound){ - sprintf(query, "INSERT INTO keyring(char_id,item_id) VALUES(%i,%i)",character_id,item_id); - if(database.RunQuery(query, strlen(query), errbuf, 0, &affected_rows)) { - Message(4,"Added to keyring."); - - /* QS: PlayerLogKeyringAddition */ - if (RuleB(QueryServ, PlayerLogKeyringAddition)){ - std::string event_desc = StringFormat("itemid:%i in zoneid:%i instid:%i", item_id, this->GetZoneID(), this->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Keyring_Addition, this->CharacterID(), event_desc); - } - safe_delete_array(query); - } - else { - std::cerr << "Error in Doors::HandleClick query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return; - } - keyring.push_back(item_id); - } ->>>>>>> ca84040a3939b71e835701e2cc52fe199e386382 -} - -bool Client::KeyRingCheck(uint32 item_id) -{ - for(std::list::iterator iter = keyring.begin(); - iter != keyring.end(); - ++iter) - { - if(*iter == item_id) - return true; - } - return false; -} - -void Client::KeyRingList() -{ - Message(4,"Keys on Keyring:"); - const Item_Struct *item = 0; - for(std::list::iterator iter = keyring.begin(); - iter != keyring.end(); - ++iter) - { - if ((item = database.GetItem(*iter))!=nullptr) { - Message(4,item->Name); - } - } -} - -bool Client::IsDiscovered(uint32 itemid) { - - std::string query = StringFormat("SELECT count(*) FROM discovered_items WHERE item_id = '%lu'", itemid); - auto results = database.QueryDatabase(query); - if (!results.Success()) { - std::cerr << "Error in IsDiscovered query '" << query << "' " << results.ErrorMessage() << std::endl; - return false; - } - - auto row = results.begin(); - - return atoi(row[0]) != 0; -} - -void Client::DiscoverItem(uint32 itemid) { - - std::string query = StringFormat("INSERT INTO discovered_items SET " - "item_id = %lu, char_name = '%s', " - "discovered_date = UNIX_TIMESTAMP(), account_status=%i", - itemid, GetName(), Admin()); - auto results = database.QueryDatabase(query); - - parse->EventPlayer(EVENT_DISCOVER_ITEM, this, "", itemid); -} - -void Client::UpdateLFP() { - - Group *g = GetGroup(); - - if(g && !g->IsLeader(this)) { - database.SetLFP(CharacterID(), false); - worldserver.StopLFP(CharacterID()); - LFP = false; - return; - } - - GroupLFPMemberEntry LFPMembers[MAX_GROUP_MEMBERS]; - - for(unsigned int i=0; iGetZoneID(); - - if(g) { - // Fill the LFPMembers array with the rest of the group members, excluding ourself - // We don't fill in the class, level or zone, because we may not be able to determine - // them if the other group members are not in this zone. World will fill in this information - // for us, if it can. - int NextFreeSlot = 1; - for(unsigned int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if((g->membername[i][0] != '\0') && strcasecmp(g->membername[i], LFPMembers[0].Name)) - strcpy(LFPMembers[NextFreeSlot++].Name, g->membername[i]); - } - } - worldserver.UpdateLFP(CharacterID(), LFPMembers); -} - -uint16 Client::GetPrimarySkillValue() -{ - SkillUseTypes skill = HIGHEST_SKILL; //because nullptr == 0, which is 1H Slashing, & we want it to return 0 from GetSkill - bool equiped = m_inv.GetItem(MainPrimary); - - if (!equiped) - skill = SkillHandtoHand; - - else { - - uint8 type = m_inv.GetItem(MainPrimary)->GetItem()->ItemType; //is this the best way to do this? - - switch (type) - { - case ItemType1HSlash: // 1H Slashing - { - skill = Skill1HSlashing; - break; - } - case ItemType2HSlash: // 2H Slashing - { - skill = Skill2HSlashing; - break; - } - case ItemType1HPiercing: // Piercing - { - skill = Skill1HPiercing; - break; - } - case ItemType1HBlunt: // 1H Blunt - { - skill = Skill1HBlunt; - break; - } - case ItemType2HBlunt: // 2H Blunt - { - skill = Skill2HBlunt; - break; - } - case ItemType2HPiercing: // 2H Piercing - { - skill = Skill1HPiercing; // change to Skill2HPiercing once activated - break; - } - case ItemTypeMartial: // Hand to Hand - { - skill = SkillHandtoHand; - break; - } - default: // All other types default to Hand to Hand - { - skill = SkillHandtoHand; - break; - } - } - } - - return GetSkill(skill); -} - -uint16 Client::GetTotalATK() -{ - uint16 AttackRating = 0; - uint16 WornCap = itembonuses.ATK; - - if(IsClient()) { - AttackRating = ((WornCap * 1.342) + (GetSkill(SkillOffense) * 1.345) + ((GetSTR() - 66) * 0.9) + (GetPrimarySkillValue() * 2.69)); - AttackRating += aabonuses.ATK + GroupLeadershipAAOffenseEnhancement(); - - if (AttackRating < 10) - AttackRating = 10; - } - else - AttackRating = GetATK(); - - AttackRating += spellbonuses.ATK; - - return AttackRating; -} - -uint16 Client::GetATKRating() -{ - uint16 AttackRating = 0; - if(IsClient()) { - AttackRating = (GetSkill(SkillOffense) * 1.345) + ((GetSTR() - 66) * 0.9) + (GetPrimarySkillValue() * 2.69); - - if (AttackRating < 10) - AttackRating = 10; - } - return AttackRating; -} - -void Client::VoiceMacroReceived(uint32 Type, char *Target, uint32 MacroNumber) { - - uint32 GroupOrRaidID = 0; - - switch(Type) { - - case VoiceMacroGroup: { - - Group* g = GetGroup(); - - if(g) - GroupOrRaidID = g->GetID(); - else - return; - - break; - } - - case VoiceMacroRaid: { - - Raid* r = GetRaid(); - - if(r) - GroupOrRaidID = r->GetID(); - else - return; - - break; - } - } - - if(!worldserver.SendVoiceMacro(this, Type, Target, MacroNumber, GroupOrRaidID)) - Message(0, "Error: World server disconnected"); -} - -void Client::ClearGroupAAs() { - - for(unsigned int i = 0; i < MAX_GROUP_LEADERSHIP_AA_ARRAY; i++) - m_pp.leader_abilities.ranks[i] = 0; - - m_pp.group_leadership_points = 0; - m_pp.raid_leadership_points = 0; - m_pp.group_leadership_exp = 0; - m_pp.raid_leadership_exp = 0; - - Save(); -} - -void Client::UpdateGroupAAs(int32 points, uint32 type) { - - switch(type) - { - case 0: - { - m_pp.group_leadership_points += points; - break; - } - case 1: - { - m_pp.raid_leadership_points += points; - break; - } - } - SendLeadershipEXPUpdate(); -} - -bool Client::IsLeadershipEXPOn() -{ - - if(!m_pp.leadAAActive) - return false; - - Group *g = GetGroup(); - - if(g && g->IsLeader(this) && (g->GroupCount() > 2)) - return true; - - Raid *r = GetRaid(); - - if(r && r->IsLeader(this) && (r->RaidCount() > 17)) - return true; - - return false; - -} - -int Client::GetAggroCount() { - return AggroCount; -} - -void Client::IncrementAggroCount() { - - // This method is called when a client is added to a mob's hate list. It turns the clients aggro flag on so - // rest state regen is stopped, and for SoF, it sends the opcode to show the crossed swords in-combat indicator. - // - // - AggroCount++; - - if(!RuleI(Character, RestRegenPercent)) - return; - - // If we already had aggro before this method was called, the combat indicator should already be up for SoF clients, - // so we don't need to send it again. - // - if(AggroCount > 1) - return; - - // Pause the rest timer - if (AggroCount == 1) - SavedRaidRestTimer = rest_timer.GetRemainingTime(); - - if(GetClientVersion() >= EQClientSoF) { - - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RestState, 1); - char *Buffer = (char *)outapp->pBuffer; - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0x01); - QueuePacket(outapp); - safe_delete(outapp); - } - -} - -void Client::DecrementAggroCount() { - - // This should be called when a client is removed from a mob's hate list (it dies or is memblurred). - // It checks whether any other mob is aggro on the player, and if not, starts the rest timer. - // For SoF, the opcode to start the rest state countdown timer in the UI is sent. - // - - // If we didn't have aggro before, this method should not have been called. - if(!AggroCount) - return; - - AggroCount--; - - if(!RuleI(Character, RestRegenPercent)) - return; - - // Something else is still aggro on us, can't rest yet. - if(AggroCount) return; - - uint32 time_until_rest; - if (GetEngagedRaidTarget()) { - time_until_rest = RuleI(Character, RestRegenRaidTimeToActivate) * 1000; - SetEngagedRaidTarget(false); - } else { - if (SavedRaidRestTimer > (RuleI(Character, RestRegenTimeToActivate) * 1000)) { - time_until_rest = SavedRaidRestTimer; - SavedRaidRestTimer = 0; - } else { - time_until_rest = RuleI(Character, RestRegenTimeToActivate) * 1000; - } - } - - rest_timer.Start(time_until_rest); - - if(GetClientVersion() >= EQClientSoF) { - - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RestState, 5); - char *Buffer = (char *)outapp->pBuffer; - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0x00); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, (uint32)(time_until_rest / 1000)); - QueuePacket(outapp); - safe_delete(outapp); - } -} - -void Client::SendPVPStats() -{ - // This sends the data to the client to populate the PVP Stats Window. - // - // When the PVP Stats window is opened, no opcode is sent. Therefore this method should be called - // from Client::CompleteConnect, and also when the player makes a PVP kill. - // - EQApplicationPacket *outapp = new EQApplicationPacket(OP_PVPStats, sizeof(PVPStats_Struct)); - PVPStats_Struct *pvps = (PVPStats_Struct *)outapp->pBuffer; - - pvps->Kills = m_pp.PVPKills; - pvps->Deaths = m_pp.PVPDeaths; - pvps->PVPPointsAvailable = m_pp.PVPCurrentPoints; - pvps->TotalPVPPoints = m_pp.PVPCareerPoints; - pvps->BestKillStreak = m_pp.PVPBestKillStreak; - pvps->WorstDeathStreak = m_pp.PVPWorstDeathStreak; - pvps->CurrentKillStreak = m_pp.PVPCurrentKillStreak; - - // TODO: Record and send other PVP Stats - - QueuePacket(outapp); - safe_delete(outapp); -} - -void Client::SendCrystalCounts() -{ - EQApplicationPacket *outapp = new EQApplicationPacket(OP_CrystalCountUpdate, sizeof(CrystalCountUpdate_Struct)); - CrystalCountUpdate_Struct *ccus = (CrystalCountUpdate_Struct *)outapp->pBuffer; - - ccus->CurrentRadiantCrystals = GetRadiantCrystals(); - ccus->CurrentEbonCrystals = GetEbonCrystals(); - ccus->CareerRadiantCrystals = m_pp.careerRadCrystals; - ccus->CareerEbonCrystals = m_pp.careerEbonCrystals; - - - QueuePacket(outapp); - safe_delete(outapp); -} - -void Client::SendDisciplineTimers() -{ - - EQApplicationPacket *outapp = new EQApplicationPacket(OP_DisciplineTimer, sizeof(DisciplineTimer_Struct)); - DisciplineTimer_Struct *dts = (DisciplineTimer_Struct *)outapp->pBuffer; - - for(unsigned int i = 0; i < MAX_DISCIPLINE_TIMERS; ++i) - { - uint32 RemainingTime = p_timers.GetRemainingTime(pTimerDisciplineReuseStart + i); - - if(RemainingTime > 0) - { - dts->TimerID = i; - dts->Duration = RemainingTime; - QueuePacket(outapp); - } - } - - safe_delete(outapp); -} - -void Client::SendRespawnBinds() -{ - // This sends the data to the client to populate the Respawn from Death Window. - // - // This should be sent after OP_Death for SoF clients - // Client will respond with a 4 byte packet that includes the number of the selection made - // - - //If no options have been given, default to Bind + Rez - if (respawn_options.empty()) - { - BindStruct* b = &m_pp.binds[0]; - RespawnOption opt; - opt.name = "Bind Location"; - opt.zoneid = b->zoneId; - opt.x = b->x; - opt.y = b->y; - opt.z = b->z; - opt.heading = b->heading; - respawn_options.push_front(opt); - } - //Rez is always added at the end - RespawnOption rez; - rez.name = "Resurrect"; - rez.zoneid = zone->GetZoneID(); - rez.x = GetX(); - rez.y = GetY(); - rez.z = GetZ(); - rez.heading = GetHeading(); - respawn_options.push_back(rez); - - int num_options = respawn_options.size(); - uint32 PacketLength = 17 + (26 * num_options); //Header size + per-option invariant size - - std::list::iterator itr; - RespawnOption* opt; - - //Find string size for each option - for (itr = respawn_options.begin(); itr != respawn_options.end(); ++itr) - { - opt = &(*itr); - PacketLength += opt->name.size() + 1; //+1 for cstring - } - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RespawnWindow, PacketLength); - char* buffer = (char*)outapp->pBuffer; - - //Packet header - VARSTRUCT_ENCODE_TYPE(uint32, buffer, initial_respawn_selection); //initial selection (from 0) - VARSTRUCT_ENCODE_TYPE(uint32, buffer, RuleI(Character, RespawnFromHoverTimer) * 1000); - VARSTRUCT_ENCODE_TYPE(uint32, buffer, 0); //unknown - VARSTRUCT_ENCODE_TYPE(uint32, buffer, num_options); //number of options to display - - //Individual options - int count = 0; - for (itr = respawn_options.begin(); itr != respawn_options.end(); ++itr) - { - opt = &(*itr); - VARSTRUCT_ENCODE_TYPE(uint32, buffer, count++); //option num (from 0) - VARSTRUCT_ENCODE_TYPE(uint32, buffer, opt->zoneid); - VARSTRUCT_ENCODE_TYPE(float, buffer, opt->x); - VARSTRUCT_ENCODE_TYPE(float, buffer, opt->y); - VARSTRUCT_ENCODE_TYPE(float, buffer, opt->z); - VARSTRUCT_ENCODE_TYPE(float, buffer, opt->heading); - VARSTRUCT_ENCODE_STRING(buffer, opt->name.c_str()); - VARSTRUCT_ENCODE_TYPE(uint8, buffer, (count == num_options)); //is this one Rez (the last option)? - } - - QueuePacket(outapp); - safe_delete(outapp); - return; -} - -void Client::HandleLDoNOpen(NPC *target) -{ - if(target) - { - if(target->GetClass() != LDON_TREASURE) - { - LogFile->write(EQEMuLog::Debug, "%s tried to open %s but %s was not a treasure chest.", - GetName(), target->GetName(), target->GetName()); - return; - } - - if(DistNoRootNoZ(*target) > RuleI(Adventure, LDoNTrapDistanceUse)) - { - LogFile->write(EQEMuLog::Debug, "%s tried to open %s but %s was out of range", - GetName(), target->GetName(), target->GetName()); - Message(13, "Treasure chest out of range."); - return; - } - - if(target->IsLDoNTrapped()) - { - if(target->GetLDoNTrapSpellID() != 0) - { - Message_StringID(13, LDON_ACCIDENT_SETOFF2); - target->SpellFinished(target->GetLDoNTrapSpellID(), this, 10, 0, -1, spells[target->GetLDoNTrapSpellID()].ResistDiff); - target->SetLDoNTrapSpellID(0); - target->SetLDoNTrapped(false); - target->SetLDoNTrapDetected(false); - } - else - { - target->SetLDoNTrapSpellID(0); - target->SetLDoNTrapped(false); - target->SetLDoNTrapDetected(false); - } - } - - if(target->IsLDoNLocked()) - { - Message_StringID(MT_Skills, LDON_STILL_LOCKED, target->GetCleanName()); - return; - } - else - { - target->AddToHateList(this, 0, 500000, false, false, false); - if(target->GetLDoNTrapType() != 0) - { - if(GetRaid()) - { - GetRaid()->SplitExp(target->GetLevel()*target->GetLevel()*2625/10, target); - } - else if(GetGroup()) - { - GetGroup()->SplitExp(target->GetLevel()*target->GetLevel()*2625/10, target); - } - else - { - AddEXP(target->GetLevel()*target->GetLevel()*2625/10, GetLevelCon(target->GetLevel())); - } - } - target->Death(this, 1, SPELL_UNKNOWN, SkillHandtoHand); - } - } -} - -void Client::HandleLDoNSenseTraps(NPC *target, uint16 skill, uint8 type) -{ - if(target && target->GetClass() == LDON_TREASURE) - { - if(target->IsLDoNTrapped()) - { - if((target->GetLDoNTrapType() == LDoNTypeCursed || target->GetLDoNTrapType() == LDoNTypeMagical) && type != target->GetLDoNTrapType()) - { - Message_StringID(MT_Skills, LDON_CANT_DETERMINE_TRAP, target->GetCleanName()); - return; - } - - if(target->IsLDoNTrapDetected()) - { - Message_StringID(MT_Skills, LDON_CERTAIN_TRAP, target->GetCleanName()); - } - else - { - int check = LDoNChest_SkillCheck(target, skill); - switch(check) - { - case -1: - case 0: - Message_StringID(MT_Skills, LDON_DONT_KNOW_TRAPPED, target->GetCleanName()); - break; - case 1: - Message_StringID(MT_Skills, LDON_CERTAIN_TRAP, target->GetCleanName()); - target->SetLDoNTrapDetected(true); - break; - default: - break; - } - } - } - else - { - Message_StringID(MT_Skills, LDON_CERTAIN_NOT_TRAP, target->GetCleanName()); - } - } -} - -void Client::HandleLDoNDisarm(NPC *target, uint16 skill, uint8 type) -{ - if(target) - { - if(target->GetClass() == LDON_TREASURE) - { - if(!target->IsLDoNTrapped()) - { - Message_StringID(MT_Skills, LDON_WAS_NOT_TRAPPED, target->GetCleanName()); - return; - } - - if((target->GetLDoNTrapType() == LDoNTypeCursed || target->GetLDoNTrapType() == LDoNTypeMagical) && type != target->GetLDoNTrapType()) - { - Message_StringID(MT_Skills, LDON_HAVE_NOT_DISARMED, target->GetCleanName()); - return; - } - - int check = 0; - if(target->IsLDoNTrapDetected()) - { - check = LDoNChest_SkillCheck(target, skill); - } - else - { - check = LDoNChest_SkillCheck(target, skill*33/100); - } - switch(check) - { - case 1: - target->SetLDoNTrapDetected(false); - target->SetLDoNTrapped(false); - target->SetLDoNTrapSpellID(0); - Message_StringID(MT_Skills, LDON_HAVE_DISARMED, target->GetCleanName()); - break; - case 0: - Message_StringID(MT_Skills, LDON_HAVE_NOT_DISARMED, target->GetCleanName()); - break; - case -1: - Message_StringID(13, LDON_ACCIDENT_SETOFF2); - target->SpellFinished(target->GetLDoNTrapSpellID(), this, 10, 0, -1, spells[target->GetLDoNTrapSpellID()].ResistDiff); - target->SetLDoNTrapSpellID(0); - target->SetLDoNTrapped(false); - target->SetLDoNTrapDetected(false); - break; - } - } - } -} - -void Client::HandleLDoNPickLock(NPC *target, uint16 skill, uint8 type) -{ - if(target) - { - if(target->GetClass() == LDON_TREASURE) - { - if(target->IsLDoNTrapped()) - { - Message_StringID(13, LDON_ACCIDENT_SETOFF2); - target->SpellFinished(target->GetLDoNTrapSpellID(), this, 10, 0, -1, spells[target->GetLDoNTrapSpellID()].ResistDiff); - target->SetLDoNTrapSpellID(0); - target->SetLDoNTrapped(false); - target->SetLDoNTrapDetected(false); - } - - if(!target->IsLDoNLocked()) - { - Message_StringID(MT_Skills, LDON_WAS_NOT_LOCKED, target->GetCleanName()); - return; - } - - if((target->GetLDoNTrapType() == LDoNTypeCursed || target->GetLDoNTrapType() == LDoNTypeMagical) && type != target->GetLDoNTrapType()) - { - Message(MT_Skills, "You cannot unlock %s with this skill.", target->GetCleanName()); - return; - } - - int check = LDoNChest_SkillCheck(target, skill); - - switch(check) - { - case 0: - case -1: - Message_StringID(MT_Skills, LDON_PICKLOCK_FAILURE, target->GetCleanName()); - break; - case 1: - target->SetLDoNLocked(false); - Message_StringID(MT_Skills, LDON_PICKLOCK_SUCCESS, target->GetCleanName()); - break; - } - } - } -} - -int Client::LDoNChest_SkillCheck(NPC *target, int skill) -{ - if(!target) - return -1; - - int chest_difficulty = target->GetLDoNLockedSkill() == 0 ? (target->GetLevel() * 5) : target->GetLDoNLockedSkill(); - float base_difficulty = RuleR(Adventure, LDoNBaseTrapDifficulty); - - if(chest_difficulty == 0) - chest_difficulty = 5; - - float chance = ((100.0f - base_difficulty) * ((float)skill / (float)chest_difficulty)); - - if(chance > (100.0f - base_difficulty)) - { - chance = 100.0f - base_difficulty; - } - - float d100 = (float)MakeRandomFloat(0, 100); - - if(d100 <= chance) - return 1; - else - { - if(d100 > (chance + RuleR(Adventure, LDoNCriticalFailTrapThreshold))) - return -1; - } - - return 0; -} - -void Client::SummonAndRezzAllCorpses() -{ - PendingRezzXP = -1; - - ServerPacket *Pack = new ServerPacket(ServerOP_DepopAllPlayersCorpses, sizeof(ServerDepopAllPlayersCorpses_Struct)); - - ServerDepopAllPlayersCorpses_Struct *sdapcs = (ServerDepopAllPlayersCorpses_Struct*)Pack->pBuffer; - - sdapcs->CharacterID = CharacterID(); - sdapcs->ZoneID = zone->GetZoneID(); - sdapcs->InstanceID = zone->GetInstanceID(); - - worldserver.SendPacket(Pack); - - safe_delete(Pack); - - entity_list.RemoveAllCorpsesByCharID(CharacterID()); - - int CorpseCount = database.SummonAllPlayerCorpses(CharacterID(), zone->GetZoneID(), zone->GetInstanceID(), - GetX(), GetY(), GetZ(), GetHeading()); - if(CorpseCount <= 0) - { - Message(clientMessageYellow, "You have no corpses to summnon."); - return; - } - - int RezzExp = entity_list.RezzAllCorpsesByCharID(CharacterID()); - - if(RezzExp > 0) - SetEXP(GetEXP() + RezzExp, GetAAXP(), true); - - Message(clientMessageYellow, "All your corpses have been summoned to your feet and have received a 100% resurrection."); -} - -void Client::SummonAllCorpses(float dest_x, float dest_y, float dest_z, float dest_heading) -{ - - if(dest_x == 0 && dest_y == 0 && dest_z == 0 && dest_heading == 0) - { - dest_x = GetX(); dest_y = GetY(); dest_z = GetZ(); dest_heading = GetHeading(); - } - - ServerPacket *Pack = new ServerPacket(ServerOP_DepopAllPlayersCorpses, sizeof(ServerDepopAllPlayersCorpses_Struct)); - - ServerDepopAllPlayersCorpses_Struct *sdapcs = (ServerDepopAllPlayersCorpses_Struct*)Pack->pBuffer; - - sdapcs->CharacterID = CharacterID(); - sdapcs->ZoneID = zone->GetZoneID(); - sdapcs->InstanceID = zone->GetInstanceID(); - - worldserver.SendPacket(Pack); - - safe_delete(Pack); - - entity_list.RemoveAllCorpsesByCharID(CharacterID()); - - int CorpseCount = database.SummonAllPlayerCorpses(CharacterID(), zone->GetZoneID(), zone->GetInstanceID(), - dest_x, dest_y, dest_z, dest_heading); - if(CorpseCount <= 0) - { - return; - } -} - -void Client::DepopAllCorpses() -{ - ServerPacket *Pack = new ServerPacket(ServerOP_DepopAllPlayersCorpses, sizeof(ServerDepopAllPlayersCorpses_Struct)); - - ServerDepopAllPlayersCorpses_Struct *sdapcs = (ServerDepopAllPlayersCorpses_Struct*)Pack->pBuffer; - - sdapcs->CharacterID = CharacterID(); - sdapcs->ZoneID = zone->GetZoneID(); - sdapcs->InstanceID = zone->GetInstanceID(); - - worldserver.SendPacket(Pack); - - safe_delete(Pack); - - entity_list.RemoveAllCorpsesByCharID(CharacterID()); -} - -void Client::DepopPlayerCorpse(uint32 dbid) -{ - ServerPacket *Pack = new ServerPacket(ServerOP_DepopPlayerCorpse, sizeof(ServerDepopPlayerCorpse_Struct)); - - ServerDepopPlayerCorpse_Struct *sdpcs = (ServerDepopPlayerCorpse_Struct*)Pack->pBuffer; - - sdpcs->DBID = dbid; - sdpcs->ZoneID = zone->GetZoneID(); - sdpcs->InstanceID = zone->GetInstanceID(); - - worldserver.SendPacket(Pack); - - safe_delete(Pack); - - entity_list.RemoveCorpseByDBID(dbid); -} - -void Client::BuryPlayerCorpses() -{ - database.BuryAllPlayerCorpses(CharacterID()); -} - -void Client::NotifyNewTitlesAvailable() -{ - EQApplicationPacket *outapp = new EQApplicationPacket(OP_NewTitlesAvailable, 0); - - QueuePacket(outapp); - - safe_delete(outapp); - -} - -void Client::SetStartZone(uint32 zoneid, float x, float y, float z) -{ - // setting city to zero allows the player to use /setstartcity to set the city themselves - if(zoneid == 0) { - m_pp.binds[4].zoneId = 0; - this->Message(15,"Your starting city has been reset. Use /setstartcity to choose a new one"); - return; - } - - // check to make sure the zone is valid - const char *target_zone_name = database.GetZoneName(zoneid); - if(target_zone_name == nullptr) - return; - - m_pp.binds[4].zoneId = zoneid; - if (x == 0 && y == 0 && z ==0) - database.GetSafePoints(m_pp.binds[4].zoneId, 0, &m_pp.binds[4].x, &m_pp.binds[4].y, &m_pp.binds[4].z); - else { - m_pp.binds[4].x = x; - m_pp.binds[4].y = y; - m_pp.binds[4].z = z; - } -} - -uint32 Client::GetStartZone() -{ - return m_pp.binds[4].zoneId; -} - -void Client::ShowSkillsWindow() -{ - const char *WindowTitle = "Skills"; - std::string WindowText; - // using a map for easy alphabetizing of the skills list - std::map Skills; - std::map::iterator it; - - // this list of names must keep the same order as that in common/skills.h - const char* SkillName[] = {"1H Blunt","1H Slashing","2H Blunt","2H Slashing","Abjuration","Alteration","Apply Poison","Archery", - "Backstab","Bind Wound","Bash","Block","Brass Instruments","Channeling","Conjuration","Defense","Disarm","Disarm Traps","Divination", - "Dodge","Double Attack","Dragon Punch","Dual Wield","Eagle Strike","Evocation","Feign Death","Flying Kick","Forage","Hand to Hand", - "Hide","Kick","Meditate","Mend","Offense","Parry","Pick Lock","Piercing","Ripost","Round Kick","Safe Fall","Sense Heading", - "Singing","Sneak","Specialize Abjuration","Specialize Alteration","Specialize Conjuration","Specialize Divination","Specialize Evocation","Pick Pockets", - "Stringed Instruments","Swimming","Throwing","Tiger Claw","Tracking","Wind Instruments","Fishing","Make Poison","Tinkering","Research", - "Alchemy","Baking","Tailoring","Sense Traps","Blacksmithing","Fletching","Brewing","Alcohol Tolerance","Begging","Jewelry Making", - "Pottery","Percussion Instruments","Intimidation","Berserking","Taunt","Frenzy"}; - for(int i = 0; i <= (int)HIGHEST_SKILL; i++) - Skills[SkillName[i]] = (SkillUseTypes)i; - - // print out all available skills - for(it = Skills.begin(); it != Skills.end(); ++it) { - if(GetSkill(it->second) > 0 || MaxSkill(it->second) > 0) { - WindowText += it->first; - // line up the values - for (int j = 0; j < EmuConstants::ITEM_COMMON_SIZE; j++) - WindowText += " "; - WindowText += itoa(this->GetSkill(it->second)); - if (MaxSkill(it->second) > 0) { - WindowText += "/"; - WindowText += itoa(this->GetMaxSkillAfterSpecializationRules(it->second,this->MaxSkill(it->second))); - } - WindowText += "
"; - } - } - this->SendPopupToClient(WindowTitle, WindowText.c_str()); -} - - -void Client::SetShadowStepExemption(bool v) -{ - if(v == true) - { - uint32 cur_time = Timer::GetCurrentTime(); - if((cur_time - m_TimeSinceLastPositionCheck) > 1000) - { - float speed = (m_DistanceSinceLastPositionCheck * 100) / (float)(cur_time - m_TimeSinceLastPositionCheck); - float runs = GetRunspeed(); - if(speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor))) - { - printf("%s %i moving too fast! moved: %.2f in %ims, speed %.2f\n", __FILE__, __LINE__, - m_DistanceSinceLastPositionCheck, (cur_time - m_TimeSinceLastPositionCheck), speed); - if(!GetGMSpeed() && (runs >= GetBaseRunspeed() || (speed > (GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor))))) - { - if(IsShadowStepExempted()) - { - if(m_DistanceSinceLastPositionCheck > 800) - { - CheatDetected(MQWarpShadowStep, GetX(), GetY(), GetZ()); - } - } - else if(IsKnockBackExempted()) - { - //still potential to trigger this if you're knocked back off a - //HUGE fall that takes > 2.5 seconds - if(speed > 30.0f) - { - CheatDetected(MQWarpKnockBack, GetX(), GetY(), GetZ()); - } - } - else if(!IsPortExempted()) - { - if(!IsMQExemptedArea(zone->GetZoneID(), GetX(), GetY(), GetZ())) - { - if(speed > (runs * 2 * RuleR(Zone, MQWarpDetectionDistanceFactor))) - { - CheatDetected(MQWarp, GetX(), GetY(), GetZ()); - m_TimeSinceLastPositionCheck = cur_time; - m_DistanceSinceLastPositionCheck = 0.0f; - //Death(this, 10000000, SPELL_UNKNOWN, _1H_BLUNT); - } - else - { - CheatDetected(MQWarpLight, GetX(), GetY(), GetZ()); - } - } - } - } - } - } - m_TimeSinceLastPositionCheck = cur_time; - m_DistanceSinceLastPositionCheck = 0.0f; - } - m_ShadowStepExemption = v; -} - -void Client::SetKnockBackExemption(bool v) -{ - if(v == true) - { - uint32 cur_time = Timer::GetCurrentTime(); - if((cur_time - m_TimeSinceLastPositionCheck) > 1000) - { - float speed = (m_DistanceSinceLastPositionCheck * 100) / (float)(cur_time - m_TimeSinceLastPositionCheck); - float runs = GetRunspeed(); - if(speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor))) - { - if(!GetGMSpeed() && (runs >= GetBaseRunspeed() || (speed > (GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor))))) - { - printf("%s %i moving too fast! moved: %.2f in %ims, speed %.2f\n", __FILE__, __LINE__, - m_DistanceSinceLastPositionCheck, (cur_time - m_TimeSinceLastPositionCheck), speed); - if(IsShadowStepExempted()) - { - if(m_DistanceSinceLastPositionCheck > 800) - { - CheatDetected(MQWarpShadowStep, GetX(), GetY(), GetZ()); - } - } - else if(IsKnockBackExempted()) - { - //still potential to trigger this if you're knocked back off a - //HUGE fall that takes > 2.5 seconds - if(speed > 30.0f) - { - CheatDetected(MQWarpKnockBack, GetX(), GetY(), GetZ()); - } - } - else if(!IsPortExempted()) - { - if(!IsMQExemptedArea(zone->GetZoneID(), GetX(), GetY(), GetZ())) - { - if(speed > (runs * 2 * RuleR(Zone, MQWarpDetectionDistanceFactor))) - { - m_TimeSinceLastPositionCheck = cur_time; - m_DistanceSinceLastPositionCheck = 0.0f; - CheatDetected(MQWarp, GetX(), GetY(), GetZ()); - //Death(this, 10000000, SPELL_UNKNOWN, _1H_BLUNT); - } - else - { - CheatDetected(MQWarpLight, GetX(), GetY(), GetZ()); - } - } - } - } - } - } - m_TimeSinceLastPositionCheck = cur_time; - m_DistanceSinceLastPositionCheck = 0.0f; - } - m_KnockBackExemption = v; -} - -void Client::SetPortExemption(bool v) -{ - if(v == true) - { - uint32 cur_time = Timer::GetCurrentTime(); - if((cur_time - m_TimeSinceLastPositionCheck) > 1000) - { - float speed = (m_DistanceSinceLastPositionCheck * 100) / (float)(cur_time - m_TimeSinceLastPositionCheck); - float runs = GetRunspeed(); - if(speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor))) - { - if(!GetGMSpeed() && (runs >= GetBaseRunspeed() || (speed > (GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor))))) - { - printf("%s %i moving too fast! moved: %.2f in %ims, speed %.2f\n", __FILE__, __LINE__, - m_DistanceSinceLastPositionCheck, (cur_time - m_TimeSinceLastPositionCheck), speed); - if(IsShadowStepExempted()) - { - if(m_DistanceSinceLastPositionCheck > 800) - { - CheatDetected(MQWarpShadowStep, GetX(), GetY(), GetZ()); - } - } - else if(IsKnockBackExempted()) - { - //still potential to trigger this if you're knocked back off a - //HUGE fall that takes > 2.5 seconds - if(speed > 30.0f) - { - CheatDetected(MQWarpKnockBack, GetX(), GetY(), GetZ()); - } - } - else if(!IsPortExempted()) - { - if(!IsMQExemptedArea(zone->GetZoneID(), GetX(), GetY(), GetZ())) - { - if(speed > (runs * 2 * RuleR(Zone, MQWarpDetectionDistanceFactor))) - { - m_TimeSinceLastPositionCheck = cur_time; - m_DistanceSinceLastPositionCheck = 0.0f; - CheatDetected(MQWarp, GetX(), GetY(), GetZ()); - //Death(this, 10000000, SPELL_UNKNOWN, _1H_BLUNT); - } - else - { - CheatDetected(MQWarpLight, GetX(), GetY(), GetZ()); - } - } - } - } - } - } - m_TimeSinceLastPositionCheck = cur_time; - m_DistanceSinceLastPositionCheck = 0.0f; - } - m_PortExemption = v; -} - -void Client::Signal(uint32 data) -{ - char buf[32]; - snprintf(buf, 31, "%d", data); - buf[31] = '\0'; - parse->EventPlayer(EVENT_SIGNAL, this, buf, 0); -} - -const bool Client::IsMQExemptedArea(uint32 zoneID, float x, float y, float z) const -{ - float max_dist = 90000; - switch(zoneID) - { - case 2: - { - float delta = (x-(-713.6)); - delta *= delta; - float distance = delta; - delta = (y-(-160.2)); - delta *= delta; - distance += delta; - delta = (z-(-12.8)); - delta *= delta; - distance += delta; - - if(distance < max_dist) - return true; - - delta = (x-(-153.8)); - delta *= delta; - distance = delta; - delta = (y-(-30.3)); - delta *= delta; - distance += delta; - delta = (z-(8.2)); - delta *= delta; - distance += delta; - - if(distance < max_dist) - return true; - - break; - } - case 9: - { - float delta = (x-(-682.5)); - delta *= delta; - float distance = delta; - delta = (y-(147.0)); - delta *= delta; - distance += delta; - delta = (z-(-9.9)); - delta *= delta; - distance += delta; - - if(distance < max_dist) - return true; - - delta = (x-(-655.4)); - delta *= delta; - distance = delta; - delta = (y-(10.5)); - delta *= delta; - distance += delta; - delta = (z-(-51.8)); - delta *= delta; - distance += delta; - - if(distance < max_dist) - return true; - - break; - } - case 62: - case 75: - case 114: - case 209: - { - //The portals are so common in paineel/felwitheb that checking - //distances wouldn't be worth it cause unless you're porting to the - //start field you're going to be triggering this and that's a level of - //accuracy I'm willing to sacrifice - return true; - break; - } - - case 24: - { - float delta = (x-(-183.0)); - delta *= delta; - float distance = delta; - delta = (y-(-773.3)); - delta *= delta; - distance += delta; - delta = (z-(54.1)); - delta *= delta; - distance += delta; - - if(distance < max_dist) - return true; - - delta = (x-(-8.8)); - delta *= delta; - distance = delta; - delta = (y-(-394.1)); - delta *= delta; - distance += delta; - delta = (z-(41.1)); - delta *= delta; - distance += delta; - - if(distance < max_dist) - return true; - - delta = (x-(-310.3)); - delta *= delta; - distance = delta; - delta = (y-(-1411.6)); - delta *= delta; - distance += delta; - delta = (z-(-42.8)); - delta *= delta; - distance += delta; - - if(distance < max_dist) - return true; - - delta = (x-(-183.1)); - delta *= delta; - distance = delta; - delta = (y-(-1409.8)); - delta *= delta; - distance += delta; - delta = (z-(37.1)); - delta *= delta; - distance += delta; - - if(distance < max_dist) - return true; - - break; - } - - case 110: - case 34: - case 96: - case 93: - case 68: - case 84: - { - if(GetBoatID() != 0) - return true; - break; - } - default: - break; - } - return false; -} - -void Client::SendRewards() -{ - std::vector rewards; - std::string query = StringFormat("SELECT reward_id, amount FROM " - "account_rewards WHERE account_id = %i " - "ORDER BY reward_id", AccountID()); - auto results = database.QueryDatabase(query); - if (!results.Success()) { - LogFile->write(EQEMuLog::Error, "Error in Client::SendRewards(): %s (%s)", query.c_str(), results.ErrorMessage().c_str()); - return; - } - - for (auto row = results.begin(); row != results.end(); ++row) { - ClientReward cr; - cr.id = atoi(row[0]); - cr.amount = atoi(row[1]); - rewards.push_back(cr); - } - - if(rewards.size() > 0) - { - EQApplicationPacket *vetapp = new EQApplicationPacket(OP_VetRewardsAvaliable, (sizeof(InternalVeteranReward) * rewards.size())); - uchar *data = vetapp->pBuffer; - for(int i = 0; i < rewards.size(); ++i) - { - InternalVeteranReward *ivr = (InternalVeteranReward*)data; - ivr->claim_id = rewards[i].id; - ivr->number_available = rewards[i].amount; - std::list::iterator iter = zone->VeteranRewards.begin(); - while(iter != zone->VeteranRewards.end()) - { - if((*iter).claim_id == rewards[i].id) - { - break; - } - ++iter; - } - - if(iter != zone->VeteranRewards.end()) - { - InternalVeteranReward ivro = (*iter); - ivr->claim_count = ivro.claim_count; - for(int x = 0; x < ivro.claim_count; ++x) - { - ivr->items[x].item_id = ivro.items[x].item_id; - ivr->items[x].charges = ivro.items[x].charges; - strcpy(ivr->items[x].item_name, ivro.items[x].item_name); - } - } - - data += sizeof(InternalVeteranReward); - } - FastQueuePacket(&vetapp); - } -} - -bool Client::TryReward(uint32 claim_id) -{ - //Make sure we have an open spot - //Make sure we have it in our acct and count > 0 - //Make sure the entry was found - //If we meet all the criteria: - //Decrement our count by 1 if it > 1 delete if it == 1 - //Create our item in bag if necessary at the free inv slot - //save - uint32 free_slot = 0xFFFFFFFF; - - for(int i = EmuConstants::GENERAL_BEGIN; i <= EmuConstants::GENERAL_END; ++i) - { - ItemInst *item = GetInv().GetItem(i); - if(!item) - { - free_slot = i; - break; - } - } - - if(free_slot == 0xFFFFFFFF) - return false; - - std::string query = StringFormat("SELECT amount FROM account_rewards " - "WHERE account_id=%i AND reward_id=%i", - AccountID(), claim_id); - auto results = database.QueryDatabase(query); - if (!results.Success()) { - LogFile->write(EQEMuLog::Error, "Error in Client::TryReward(): %s (%s)", query.c_str(), results.ErrorMessage().c_str()); - return false; - } - - if (results.RowCount() == 0) - return false; - - uint32 amt = 0; - auto row = results.begin(); - - amt = atoi(row[0]); - - if(amt == 0) - return false; - - auto iter = zone->VeteranRewards.begin(); - for (; iter != zone->VeteranRewards.end(); ++iter) - if((*iter).claim_id == claim_id) - break; - - if(iter == zone->VeteranRewards.end()) - return false; - - if(amt == 1) - { - query = StringFormat("DELETE FROM account_rewards " - "WHERE account_id=%i AND reward_id=%i", - AccountID(), claim_id); - results = database.QueryDatabase(query); - if(!results.ErrorMessage().c_str()) - LogFile->write(EQEMuLog::Error, "Error in Client::TryReward(): %s (%s)", query.c_str(), results.ErrorMessage().c_str()); - - } - else - { - query = StringFormat("UPDATE account_rewards SET amount=(amount-1) " - "WHERE account_id=%i AND reward_id=%i", AccountID(), claim_id); - results = database.QueryDatabase(query); - if(!results.Success()) - LogFile->write(EQEMuLog::Error, "Error in Client::TryReward(): %s (%s)", query.c_str(), results.ErrorMessage().c_str()); - - } - - InternalVeteranReward ivr = (*iter); - ItemInst *claim = database.CreateItem(ivr.items[0].item_id, ivr.items[0].charges); - if(claim) - { - bool lore_conflict = false; - if(CheckLoreConflict(claim->GetItem())) - { - lore_conflict = true; - } - - for(int y = 1; y < 8; y++) - { - if(ivr.items[y].item_id) - { - if(claim->GetItem()->ItemClass == 1) - { - ItemInst *item_temp = database.CreateItem(ivr.items[y].item_id, ivr.items[y].charges); - if(item_temp) - { - if(CheckLoreConflict(item_temp->GetItem())) - { - lore_conflict = true; - DuplicateLoreMessage(ivr.items[y].item_id); - } - claim->PutItem(y-1, *item_temp); - } - } - } - } - - if(lore_conflict) - { - safe_delete(claim); - return true; - } - else - { - PutItemInInventory(free_slot, *claim); - SendItemPacket(free_slot, claim, ItemPacketTrade); - } - } - - Save(); - return true; -} - -uint32 Client::GetLDoNPointsTheme(uint32 t) -{ - switch(t) - { - case 1: - return m_pp.ldon_points_guk; - case 2: - return m_pp.ldon_points_mir; - case 3: - return m_pp.ldon_points_mmc; - case 4: - return m_pp.ldon_points_ruj; - case 5: - return m_pp.ldon_points_tak; - default: - return 0; - } -} - -uint32 Client::GetLDoNWinsTheme(uint32 t) -{ - switch(t) - { - case 1: - return m_pp.ldon_wins_guk; - case 2: - return m_pp.ldon_wins_mir; - case 3: - return m_pp.ldon_wins_mmc; - case 4: - return m_pp.ldon_wins_ruj; - case 5: - return m_pp.ldon_wins_tak; - default: - return 0; - } -} - -uint32 Client::GetLDoNLossesTheme(uint32 t) -{ - switch(t) - { - case 1: - return m_pp.ldon_losses_guk; - case 2: - return m_pp.ldon_losses_mir; - case 3: - return m_pp.ldon_losses_mmc; - case 4: - return m_pp.ldon_losses_ruj; - case 5: - return m_pp.ldon_losses_tak; - default: - return 0; - } -} - -void Client::UpdateLDoNWins(uint32 t, int32 n) -{ - switch(t) - { - case 1: - m_pp.ldon_wins_guk = n; - break; - case 2: - m_pp.ldon_wins_mir = n; - break; - case 3: - m_pp.ldon_wins_mmc = n; - break; - case 4: - m_pp.ldon_wins_ruj = n; - break; - case 5: - m_pp.ldon_wins_tak = n; - break; - default: - return; - } -} - -void Client::UpdateLDoNLosses(uint32 t, int32 n) -{ - switch(t) - { - case 1: - m_pp.ldon_losses_guk = n; - break; - case 2: - m_pp.ldon_losses_mir = n; - break; - case 3: - m_pp.ldon_losses_mmc = n; - break; - case 4: - m_pp.ldon_losses_ruj = n; - break; - case 5: - m_pp.ldon_losses_tak = n; - break; - default: - return; - } -} - - -void Client::SuspendMinion() -{ - NPC *CurrentPet = GetPet()->CastToNPC(); - - int AALevel = GetAA(aaSuspendedMinion); - - if(AALevel == 0) - return; - - if(GetLevel() < 62) - return; - - if(!CurrentPet) - { - if(m_suspendedminion.SpellID > 0) - { - MakePoweredPet(m_suspendedminion.SpellID, spells[m_suspendedminion.SpellID].teleport_zone, - m_suspendedminion.petpower, m_suspendedminion.Name, m_suspendedminion.size); - - CurrentPet = GetPet()->CastToNPC(); - - if(!CurrentPet) - { - Message(13, "Failed to recall suspended minion."); - return; - } - - if(AALevel >= 2) - { - CurrentPet->SetPetState(m_suspendedminion.Buffs, m_suspendedminion.Items); - - CurrentPet->SendPetBuffsToClient(); - } - CurrentPet->CalcBonuses(); - - CurrentPet->SetHP(m_suspendedminion.HP); - - CurrentPet->SetMana(m_suspendedminion.Mana); - - Message_StringID(clientMessageTell, SUSPEND_MINION_UNSUSPEND, CurrentPet->GetCleanName()); - - memset(&m_suspendedminion, 0, sizeof(struct PetInfo)); - } - else - return; - - } - else - { - uint16 SpellID = CurrentPet->GetPetSpellID(); - - if(SpellID) - { - if(m_suspendedminion.SpellID > 0) - { - Message_StringID(clientMessageError,ONLY_ONE_PET); - - return; - } - else if(CurrentPet->IsEngaged()) - { - Message_StringID(clientMessageError,SUSPEND_MINION_FIGHTING); - - return; - } - else if(entity_list.Fighting(CurrentPet)) - { - Message_StringID(clientMessageBlue,SUSPEND_MINION_HAS_AGGRO); - } - else - { - m_suspendedminion.SpellID = SpellID; - - m_suspendedminion.HP = CurrentPet->GetHP();; - - m_suspendedminion.Mana = CurrentPet->GetMana(); - m_suspendedminion.petpower = CurrentPet->GetPetPower(); - m_suspendedminion.size = CurrentPet->GetSize(); - - if(AALevel >= 2) - CurrentPet->GetPetState(m_suspendedminion.Buffs, m_suspendedminion.Items, m_suspendedminion.Name); - else - strn0cpy(m_suspendedminion.Name, CurrentPet->GetName(), 64); // Name stays even at rank 1 - - Message_StringID(clientMessageTell, SUSPEND_MINION_SUSPEND, CurrentPet->GetCleanName()); - - CurrentPet->Depop(false); - - SetPetID(0); - } - } - else - { - Message_StringID(clientMessageError, ONLY_SUMMONED_PETS); - - return; - } - } -} - -void Client::AddPVPPoints(uint32 Points) -{ - m_pp.PVPCurrentPoints += Points; - m_pp.PVPCareerPoints += Points; - - Save(); - - SendPVPStats(); -} - -void Client::AddCrystals(uint32 Radiant, uint32 Ebon) -{ - m_pp.currentRadCrystals += Radiant; - m_pp.careerRadCrystals += Radiant; - m_pp.currentEbonCrystals += Ebon; - m_pp.careerEbonCrystals += Ebon; - - Save(); - - SendCrystalCounts(); -} - -// Processes a client request to inspect a SoF+ client's equipment. -void Client::ProcessInspectRequest(Client* requestee, Client* requester) { - if(requestee && requester) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_InspectAnswer, sizeof(InspectResponse_Struct)); - InspectResponse_Struct* insr = (InspectResponse_Struct*) outapp->pBuffer; - insr->TargetID = requester->GetID(); - insr->playerid = requestee->GetID(); - - const Item_Struct* item = nullptr; - const ItemInst* inst = nullptr; - - for(int16 L = 0; L <= 20; L++) { - inst = requestee->GetInv().GetItem(L); - - if(inst) { - item = inst->GetItem(); - if(item) { - strcpy(insr->itemnames[L], item->Name); - insr->itemicons[L] = item->Icon; - } - else - insr->itemicons[L] = 0xFFFFFFFF; - } - } - - inst = requestee->GetInv().GetItem(MainPowerSource); - - if(inst) { - item = inst->GetItem(); - if(item) { - // we shouldn't do this..but, that's the way it's coded atm... - // (this type of action should be handled exclusively in the client translator) - strcpy(insr->itemnames[SoF::slots::MainPowerSource], item->Name); - insr->itemicons[SoF::slots::MainPowerSource] = item->Icon; - } - else - insr->itemicons[SoF::slots::MainPowerSource] = 0xFFFFFFFF; - } - - inst = requestee->GetInv().GetItem(MainAmmo); - - if(inst) { - item = inst->GetItem(); - if(item) { - strcpy(insr->itemnames[SoF::slots::MainAmmo], item->Name); - insr->itemicons[SoF::slots::MainAmmo] = item->Icon; - } - else - insr->itemicons[SoF::slots::MainAmmo] = 0xFFFFFFFF; - } - - strcpy(insr->text, requestee->GetInspectMessage().text); - - // There could be an OP for this..or not... (Ti clients are not processed here..this message is generated client-side) - if(requestee->IsClient() && (requestee != requester)) { requestee->Message(0, "%s is looking at your equipment...", requester->GetName()); } - - requester->QueuePacket(outapp); // Send answer to requester - safe_delete(outapp); - } -} - -void Client::GuildBankAck() -{ - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GuildBank, sizeof(GuildBankAck_Struct)); - - GuildBankAck_Struct *gbas = (GuildBankAck_Struct*) outapp->pBuffer; - - gbas->Action = GuildBankAcknowledge; - - FastQueuePacket(&outapp); -} - -void Client::GuildBankDepositAck(bool Fail) -{ - - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GuildBank, sizeof(GuildBankDepositAck_Struct)); - - GuildBankDepositAck_Struct *gbdas = (GuildBankDepositAck_Struct*) outapp->pBuffer; - - gbdas->Action = GuildBankDeposit; - - gbdas->Fail = Fail ? 1 : 0; - - FastQueuePacket(&outapp); -} - -void Client::ClearGuildBank() -{ - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GuildBank, sizeof(GuildBankClear_Struct)); - - GuildBankClear_Struct *gbcs = (GuildBankClear_Struct*) outapp->pBuffer; - - gbcs->Action = GuildBankBulkItems; - gbcs->DepositAreaCount = 0; - gbcs->MainAreaCount = 0; - - FastQueuePacket(&outapp); -} - -void Client::SendGroupCreatePacket() -{ - // For SoD and later clients, this is sent the Group Leader upon initial creation of the group - // - EQApplicationPacket *outapp=new EQApplicationPacket(OP_GroupUpdateB, 32 + strlen(GetName())); - - char *Buffer = (char *)outapp->pBuffer; - // Header - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 1); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // Null Leader name - - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // Member 0 - VARSTRUCT_ENCODE_STRING(Buffer, GetName()); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // This is a string - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, GetLevel()); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint16, Buffer, 0); - - FastQueuePacket(&outapp); -} - -void Client::SendGroupLeaderChangePacket(const char *LeaderName) -{ - // For SoD and later, send name of Group Leader to this client - - EQApplicationPacket *outapp=new EQApplicationPacket(OP_GroupLeaderChange, sizeof(GroupLeaderChange_Struct)); - - GroupLeaderChange_Struct *glcs = (GroupLeaderChange_Struct*)outapp->pBuffer; - - strn0cpy(glcs->LeaderName, LeaderName, sizeof(glcs->LeaderName)); - - FastQueuePacket(&outapp); -} - -void Client::SendGroupJoinAcknowledge() -{ - // For SoD and later, This produces the 'You have joined the group' message. - EQApplicationPacket* outapp=new EQApplicationPacket(OP_GroupAcknowledge, 4); - FastQueuePacket(&outapp); -} - -void Client::SendAdventureError(const char *error) -{ - size_t error_size = strlen(error); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AdventureInfo, (error_size + 2)); - strn0cpy((char*)outapp->pBuffer, error, error_size); - FastQueuePacket(&outapp); -} - -void Client::SendAdventureDetails() -{ - if(adv_data) - { - ServerSendAdventureData_Struct *ad = (ServerSendAdventureData_Struct*)adv_data; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AdventureData, sizeof(AdventureRequestResponse_Struct)); - AdventureRequestResponse_Struct *arr = (AdventureRequestResponse_Struct*)outapp->pBuffer; - arr->unknown000 = 0xBFC40100; - arr->unknown2080 = 0x0A; - arr->risk = ad->risk; - strcpy(arr->text, ad->text); - - if(ad->time_to_enter != 0) - { - arr->timetoenter = ad->time_to_enter; - } - else - { - arr->timeleft = ad->time_left; - } - - if(ad->zone_in_id == zone->GetZoneID()) - { - arr->y = ad->x; - arr->x = ad->y; - arr->showcompass = 1; - } - FastQueuePacket(&outapp); - - SendAdventureCount(ad->count, ad->total); - } - else - { - ServerSendAdventureData_Struct *ad = (ServerSendAdventureData_Struct*)adv_data; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AdventureData, sizeof(AdventureRequestResponse_Struct)); - FastQueuePacket(&outapp); - } -} - -void Client::SendAdventureCount(uint32 count, uint32 total) -{ - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AdventureUpdate, sizeof(AdventureCountUpdate_Struct)); - AdventureCountUpdate_Struct *acu = (AdventureCountUpdate_Struct*)outapp->pBuffer; - acu->current = count; - acu->total = total; - FastQueuePacket(&outapp); -} - -void Client::NewAdventure(int id, int theme, const char *text, int member_count, const char *members) -{ - size_t text_size = strlen(text); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AdventureDetails, text_size + 2); - strn0cpy((char*)outapp->pBuffer, text, text_size); - FastQueuePacket(&outapp); - - adv_requested_id = id; - adv_requested_theme = theme; - safe_delete_array(adv_requested_data); - adv_requested_member_count = member_count; - adv_requested_data = new char[64 * member_count]; - memcpy(adv_requested_data, members, (64 * member_count)); -} - -void Client::ClearPendingAdventureData() -{ - adv_requested_id = 0; - adv_requested_theme = 0; - safe_delete_array(adv_requested_data); - adv_requested_member_count = 0; -} - -bool Client::IsOnAdventure() -{ - if(adv_data) - { - ServerSendAdventureData_Struct *ad = (ServerSendAdventureData_Struct*)adv_data; - if(ad->zone_in_id == 0) - { - return false; - } - else - { - return true; - } - } - return false; -} - -void Client::LeaveAdventure() -{ - if(!GetPendingAdventureLeave()) - { - PendingAdventureLeave(); - ServerPacket *pack = new ServerPacket(ServerOP_AdventureLeave, 64); - strcpy((char*)pack->pBuffer, GetName()); - pack->Deflate(); - worldserver.SendPacket(pack); - delete pack; - } -} - -void Client::ClearCurrentAdventure() -{ - if(adv_data) - { - ServerSendAdventureData_Struct* ds = (ServerSendAdventureData_Struct*)adv_data; - if(ds->finished_adventures > 0) - { - ds->instance_id = 0; - ds->risk = 0; - memset(ds->text, 0, 512); - ds->time_left = 0; - ds->time_to_enter = 0; - ds->x = 0; - ds->y = 0; - ds->zone_in_id = 0; - ds->zone_in_object = 0; - } - else - { - safe_delete(adv_data); - } - - SendAdventureError("You are not currently assigned to an adventure."); - } -} - -void Client::AdventureFinish(bool win, int theme, int points) -{ - UpdateLDoNPoints(points, theme); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AdventureFinish, sizeof(AdventureFinish_Struct)); - AdventureFinish_Struct *af = (AdventureFinish_Struct*)outapp->pBuffer; - af->win_lose = win ? 1 : 0; - af->points = points; - FastQueuePacket(&outapp); -} - -void Client::CheckLDoNHail(Mob *target) -{ - if(!zone->adv_data) - { - return; - } - - if(!target || !target->IsNPC()) - { - return; - } - - if(target->GetOwnerID() != 0) - { - return; - } - - ServerZoneAdventureDataReply_Struct* ds = (ServerZoneAdventureDataReply_Struct*)zone->adv_data; - if(ds->type != Adventure_Rescue) - { - return; - } - - if(ds->data_id != target->GetNPCTypeID()) - { - return; - } - - if(entity_list.CheckNPCsClose(target) != 0) - { - target->Say("You're here to save me? I couldn't possibly risk leaving yet. There are " - "far too many of those horrid things out there waiting to recapture me! Please get" - " rid of some more of those vermin and then we can try to leave."); - return; - } - - Mob *pet = GetPet(); - if(pet) - { - if(pet->GetPetType() == petCharmed) - { - pet->BuffFadeByEffect(SE_Charm); - } - else if(pet->GetPetType() == petNPCFollow) - { - pet->SetOwnerID(0); - } - else - { - pet->Depop(); - } - } - - SetPet(target); - target->SetOwnerID(GetID()); - target->Say("Wonderful! Someone to set me free! I feared for my life for so long," - " never knowing when they might choose to end my life. Now that you're here though" - " I can rest easy. Please help me find my way out of here as soon as you can" - " I'll stay close behind you!"); -} - -void Client::CheckEmoteHail(Mob *target, const char* message) -{ - if( - (message[0] != 'H' && - message[0] != 'h') || - message[1] != 'a' || - message[2] != 'i' || - message[3] != 'l'){ - return; - } - - if(!target || !target->IsNPC()) - { - return; - } - - if(target->GetOwnerID() != 0) - { - return; - } - uint16 emoteid = target->GetEmoteID(); - if(emoteid != 0) - target->CastToNPC()->DoNPCEmote(HAILED,emoteid); -} - -void Client::MarkSingleCompassLoc(float in_x, float in_y, float in_z, uint8 count) -{ - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_DzCompass, sizeof(ExpeditionInfo_Struct) + sizeof(ExpeditionCompassEntry_Struct) * count); - ExpeditionCompass_Struct *ecs = (ExpeditionCompass_Struct*)outapp->pBuffer; - //ecs->clientid = GetID(); - ecs->count = count; - - if (count) { - ecs->entries[0].x = in_x; - ecs->entries[0].y = in_y; - ecs->entries[0].z = in_z; - } - - FastQueuePacket(&outapp); - safe_delete(outapp); -} - -void Client::SendZonePoints() -{ - int count = 0; - LinkedListIterator iterator(zone->zone_point_list); - iterator.Reset(); - while(iterator.MoreElements()) - { - ZonePoint* data = iterator.GetData(); - if(GetClientVersionBit() & data->client_version_mask) - { - count++; - } - iterator.Advance(); - } - - uint32 zpsize = sizeof(ZonePoints) + ((count + 1) * sizeof(ZonePoint_Entry)); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SendZonepoints, zpsize); - ZonePoints* zp = (ZonePoints*)outapp->pBuffer; - zp->count = count; - - int i = 0; - iterator.Reset(); - while(iterator.MoreElements()) - { - ZonePoint* data = iterator.GetData(); - if(GetClientVersionBit() & data->client_version_mask) - { - zp->zpe[i].iterator = data->number; - zp->zpe[i].x = data->target_x; - zp->zpe[i].y = data->target_y; - zp->zpe[i].z = data->target_z; - zp->zpe[i].heading = data->target_heading; - zp->zpe[i].zoneid = data->target_zone_id; - zp->zpe[i].zoneinstance = data->target_zone_instance; - i++; - } - iterator.Advance(); - } - FastQueuePacket(&outapp); -} - -void Client::SendTargetCommand(uint32 EntityID) -{ - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TargetCommand, sizeof(ClientTarget_Struct)); - ClientTarget_Struct *cts = (ClientTarget_Struct*)outapp->pBuffer; - cts->new_target = EntityID; - FastQueuePacket(&outapp); -} - -void Client::LocateCorpse() -{ - Corpse *ClosestCorpse = nullptr; - if(!GetTarget()) - ClosestCorpse = entity_list.GetClosestCorpse(this, nullptr); - else if(GetTarget()->IsCorpse()) - ClosestCorpse = entity_list.GetClosestCorpse(this, GetTarget()->CastToCorpse()->GetOwnerName()); - else - ClosestCorpse = entity_list.GetClosestCorpse(this, GetTarget()->GetCleanName()); - - if(ClosestCorpse) - { - Message_StringID(MT_Spells, SENSE_CORPSE_DIRECTION); - SetHeading(CalculateHeadingToTarget(ClosestCorpse->GetX(), ClosestCorpse->GetY())); - SetTarget(ClosestCorpse); - SendTargetCommand(ClosestCorpse->GetID()); - SendPosUpdate(2); - } - else if(!GetTarget()) - Message_StringID(clientMessageError, SENSE_CORPSE_NONE); - else - Message_StringID(clientMessageError, SENSE_CORPSE_NOT_NAME); -} - -void Client::NPCSpawn(NPC *target_npc, const char *identifier, uint32 extra) -{ - if (!target_npc || !identifier) - return; - - std::string id = identifier; - for(int i = 0; i < id.length(); ++i) - { - id[i] = tolower(id[i]); - } - - if (id == "create") { - // extra tries to create the npc_type ID within the range for the current zone (zone_id * 1000) - database.NPCSpawnDB(0, zone->GetShortName(), zone->GetInstanceVersion(), this, target_npc->CastToNPC(), extra); - } - else if (id == "add") { - // extra sets the respawn timer for add - database.NPCSpawnDB(1, zone->GetShortName(), zone->GetInstanceVersion(), this, target_npc->CastToNPC(), extra); - } - else if (id == "update") { - database.NPCSpawnDB(2, zone->GetShortName(), zone->GetInstanceVersion(), this, target_npc->CastToNPC()); - } - else if (id == "remove") { - database.NPCSpawnDB(3, zone->GetShortName(), zone->GetInstanceVersion(), this, target_npc->CastToNPC()); - target_npc->Depop(false); - } - else if (id == "delete") { - database.NPCSpawnDB(4, zone->GetShortName(), zone->GetInstanceVersion(), this, target_npc->CastToNPC()); - target_npc->Depop(false); - } - else { - return; - } -} - -bool Client::IsDraggingCorpse(uint16 CorpseID) -{ - for (auto It = DraggedCorpses.begin(); It != DraggedCorpses.end(); ++It) { - if (It->second == CorpseID) - return true; - } - - return false; -} - -void Client::DragCorpses() -{ - for (auto It = DraggedCorpses.begin(); It != DraggedCorpses.end(); ++It) { - Mob *corpse = entity_list.GetMob(It->second); - - if (corpse && corpse->IsPlayerCorpse() && - (DistNoRootNoZ(*corpse) <= RuleR(Character, DragCorpseDistance))) - continue; - - if (!corpse || !corpse->IsPlayerCorpse() || - corpse->CastToCorpse()->IsBeingLooted() || - !corpse->CastToCorpse()->Summon(this, false, false)) { - Message_StringID(MT_DefaultText, CORPSEDRAG_STOP); - It = DraggedCorpses.erase(It); - } - } -} - -void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_override, int pet_count, int pet_duration) -{ - if(!target || !IsValidSpell(spell_id) || this->GetID() == target->GetID()) - return; - - PetRecord record; - if(!database.GetPetEntry(spells[spell_id].teleport_zone, &record)) - { - LogFile->write(EQEMuLog::Error, "Unknown doppelganger spell id: %d, check pets table", spell_id); - Message(13, "Unable to find data for pet %s", spells[spell_id].teleport_zone); - return; - } - - AA_SwarmPet pet; - pet.count = pet_count; - pet.duration = pet_duration; - pet.npc_id = record.npc_type; - - NPCType *made_npc = nullptr; - - const NPCType *npc_type = database.GetNPCType(pet.npc_id); - if(npc_type == nullptr) { - LogFile->write(EQEMuLog::Error, "Unknown npc type for doppelganger spell id: %d", spell_id); - Message(0,"Unable to find pet!"); - return; - } - // make a custom NPC type for this - made_npc = new NPCType; - memcpy(made_npc, npc_type, sizeof(NPCType)); - - strcpy(made_npc->name, name_override); - made_npc->level = GetLevel(); - made_npc->race = GetRace(); - made_npc->gender = GetGender(); - made_npc->size = GetSize(); - made_npc->AC = GetAC(); - made_npc->STR = GetSTR(); - made_npc->STA = GetSTA(); - made_npc->DEX = GetDEX(); - made_npc->AGI = GetAGI(); - made_npc->MR = GetMR(); - made_npc->FR = GetFR(); - made_npc->CR = GetCR(); - made_npc->DR = GetDR(); - made_npc->PR = GetPR(); - made_npc->Corrup = GetCorrup(); - // looks - made_npc->texture = GetEquipmentMaterial(MaterialChest); - made_npc->helmtexture = GetEquipmentMaterial(MaterialHead); - made_npc->haircolor = GetHairColor(); - made_npc->beardcolor = GetBeardColor(); - made_npc->eyecolor1 = GetEyeColor1(); - made_npc->eyecolor2 = GetEyeColor2(); - made_npc->hairstyle = GetHairStyle(); - made_npc->luclinface = GetLuclinFace(); - made_npc->beard = GetBeard(); - made_npc->drakkin_heritage = GetDrakkinHeritage(); - made_npc->drakkin_tattoo = GetDrakkinTattoo(); - made_npc->drakkin_details = GetDrakkinDetails(); - made_npc->d_meele_texture1 = GetEquipmentMaterial(MaterialPrimary); - made_npc->d_meele_texture2 = GetEquipmentMaterial(MaterialSecondary); - for (int i = EmuConstants::MATERIAL_BEGIN; i <= EmuConstants::MATERIAL_END; i++) { - made_npc->armor_tint[i] = GetEquipmentColor(i); - } - made_npc->loottable_id = 0; - - npc_type = made_npc; - - int summon_count = 0; - summon_count = pet.count; - - if(summon_count > MAX_SWARM_PETS) - summon_count = MAX_SWARM_PETS; - - static const float swarm_pet_x[MAX_SWARM_PETS] = { 5, -5, 5, -5, 10, -10, 10, -10, 8, -8, 8, -8 }; - static const float swarm_pet_y[MAX_SWARM_PETS] = { 5, 5, -5, -5, 10, 10, -10, -10, 8, 8, -8, -8 }; - TempPets(true); - - while(summon_count > 0) { - NPCType *npc_dup = nullptr; - if(made_npc != nullptr) { - npc_dup = new NPCType; - memcpy(npc_dup, made_npc, sizeof(NPCType)); - } - - NPC* npca = new NPC( - (npc_dup!=nullptr)?npc_dup:npc_type, //make sure we give the NPC the correct data pointer - 0, - GetX()+swarm_pet_x[summon_count], GetY()+swarm_pet_y[summon_count], - GetZ(), GetHeading(), FlyMode3); - - if(!npca->GetSwarmInfo()){ - AA_SwarmPetInfo* nSI = new AA_SwarmPetInfo; - npca->SetSwarmInfo(nSI); - npca->GetSwarmInfo()->duration = new Timer(pet_duration*1000); - } - else{ - npca->GetSwarmInfo()->duration->Start(pet_duration*1000); - } - - npca->GetSwarmInfo()->owner_id = GetID(); - - // Give the pets alittle more agro than the caster and then agro them on the target - target->AddToHateList(npca, (target->GetHateAmount(this) + 100), (target->GetDamageAmount(this) + 100)); - npca->AddToHateList(target, 1000, 1000); - npca->GetSwarmInfo()->target = target->GetID(); - - //we allocated a new NPC type object, give the NPC ownership of that memory - if(npc_dup != nullptr) - npca->GiveNPCTypeData(npc_dup); - - entity_list.AddNPC(npca); - summon_count--; - } -} - -void Client::AssignToInstance(uint16 instance_id) -{ - database.AddClientToInstance(instance_id, CharacterID()); -} - -void Client::SendStatsWindow(Client* client, bool use_window) -{ - // Define the types of page breaks we need - std::string indP = " "; - std::string indS = "          "; - std::string indM = "                          "; - std::string indL = "                                 "; - std::string div = " | "; - - std::string color_red = ""; - std::string color_blue = ""; - std::string color_green = ""; - std::string bright_green = ""; - std::string bright_red = ""; - std::string heroic_color = " +"; - - // Set Class - std::string class_Name = itoa(GetClass()); - std::string class_List[] = { "WAR", "CLR", "PAL", "RNG", "SK", "DRU", "MNK", "BRD", "ROG", "SHM", "NEC", "WIZ", "MAG", "ENC", "BST", "BER" }; - - if(GetClass() < 17 && GetClass() > 0) { class_Name = class_List[GetClass()-1]; } - - // Race - std::string race_Name = itoa(GetRace()); - switch(GetRace()) - { - case 1: race_Name = "Human"; break; - case 2: race_Name = "Barbarian"; break; - case 3: race_Name = "Erudite"; break; - case 4: race_Name = "Wood Elf"; break; - case 5: race_Name = "High Elf"; break; - case 6: race_Name = "Dark Elf"; break; - case 7: race_Name = "Half Elf"; break; - case 8: race_Name = "Dwarf"; break; - case 9: race_Name = "Troll"; break; - case 10: race_Name = "Ogre"; break; - case 11: race_Name = "Halfing"; break; - case 12: race_Name = "Gnome"; break; - case 128: race_Name = "Iksar"; break; - case 130: race_Name = "Vah Shir"; break; - case 330: race_Name = "Froglok"; break; - case 522: race_Name = "Drakkin"; break; - default: break; - } - /*########################################################## - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - H/M/E String - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - ##########################################################*/ - std::string HME_row = ""; - //Loop Variables - /*===========================*/ - std::string cur_field = ""; - std::string total_field = ""; - std::string cur_name = ""; - std::string cur_spacing = ""; - std::string cur_color = ""; - - int hme_rows = 3; // Rows in display - int max_HME_value_len = 9; // 9 digits in the displayed value - - for(int hme_row_counter = 0; hme_row_counter < hme_rows; hme_row_counter++) - { - switch(hme_row_counter) { - case 0: { - cur_name = " H: "; - cur_field = itoa(GetHP()); - total_field = itoa(GetMaxHP()); - break; - } - case 1: { - if(CalcMaxMana() > 0) { - cur_name = " M: "; - cur_field = itoa(GetMana()); - total_field = itoa(CalcMaxMana()); - } - else { continue; } - - break; - } - case 2: { - cur_name = " E: "; - cur_field = itoa(GetEndurance()); - total_field = itoa(GetMaxEndurance()); - break; - } - default: { break; } - } - if(cur_field.compare(total_field) == 0) { cur_color = bright_green; } - else { cur_color = bright_red; } - - cur_spacing.clear(); - for(int a = cur_field.size(); a < max_HME_value_len; a++) { cur_spacing += " ."; } - - HME_row += indM + cur_name + cur_spacing + cur_color + cur_field + " / " + total_field + "
"; - } - /*########################################################## - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Regen String - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - ##########################################################*/ - std::string regen_string; - //Loop Variables - /*===========================*/ - std::string regen_row_header = ""; - std::string regen_row_color = ""; - std::string base_regen_field = ""; - std::string base_regen_spacing = ""; - std::string item_regen_field = ""; - std::string item_regen_spacing = ""; - std::string cap_regen_field = ""; - std::string cap_regen_spacing = ""; - std::string spell_regen_field = ""; - std::string spell_regen_spacing = ""; - std::string aa_regen_field = ""; - std::string aa_regen_spacing = ""; - std::string total_regen_field = ""; - int regen_rows = 3; // Number of rows - int max_regen_value_len = 5; // 5 digits in the displayed value(larger values will not get cut off, this is just a baseline) - - for(int regen_row_counter = 0; regen_row_counter < regen_rows; regen_row_counter++) - { - switch(regen_row_counter) - { - case 0: { - regen_row_header = "H: "; - regen_row_color = color_red; - - base_regen_field = itoa(LevelRegen()); - item_regen_field = itoa(itembonuses.HPRegen); - cap_regen_field = itoa(CalcHPRegenCap()); - spell_regen_field = itoa(spellbonuses.HPRegen); - aa_regen_field = itoa(aabonuses.HPRegen); - total_regen_field = itoa(CalcHPRegen()); - break; - } - case 1: { - if(CalcMaxMana() > 0) { - regen_row_header = "M: "; - regen_row_color = color_blue; - - base_regen_field = itoa(CalcBaseManaRegen()); - item_regen_field = itoa(itembonuses.ManaRegen); - cap_regen_field = itoa(CalcManaRegenCap()); - spell_regen_field = itoa(spellbonuses.ManaRegen); - aa_regen_field = itoa(aabonuses.ManaRegen); - total_regen_field = itoa(CalcManaRegen()); - } - else { continue; } - break; - } - case 2: { - regen_row_header = "E: "; - regen_row_color = color_green; - - base_regen_field = itoa(((GetLevel() * 4 / 10) + 2)); - item_regen_field = itoa(itembonuses.EnduranceRegen); - cap_regen_field = itoa(CalcEnduranceRegenCap()); - spell_regen_field = itoa(spellbonuses.EnduranceRegen); - aa_regen_field = itoa(aabonuses.EnduranceRegen); - total_regen_field = itoa(CalcEnduranceRegen()); - break; - } - default: { break; } - } - - base_regen_spacing.clear(); - item_regen_spacing.clear(); - cap_regen_spacing.clear(); - spell_regen_spacing.clear(); - aa_regen_spacing.clear(); - - for(int b = base_regen_field.size(); b < max_regen_value_len; b++) { base_regen_spacing += " ."; } - for(int b = item_regen_field.size(); b < max_regen_value_len; b++) { item_regen_spacing += " ."; } - for(int b = cap_regen_field.size(); b < max_regen_value_len; b++) { cap_regen_spacing += " ."; } - for(int b = spell_regen_field.size(); b < max_regen_value_len; b++) { spell_regen_spacing += " ."; } - for(int b = aa_regen_field.size(); b < max_regen_value_len; b++) { aa_regen_spacing += " ."; } - - regen_string += indS + regen_row_color + regen_row_header + base_regen_spacing + base_regen_field; - regen_string += div + item_regen_spacing + item_regen_field + " (" + cap_regen_field; - regen_string += ") " + cap_regen_spacing + div + spell_regen_spacing + spell_regen_field; - regen_string += div + aa_regen_spacing + aa_regen_field + div + total_regen_field + "

"; - } - /*########################################################## - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Stat String - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - ##########################################################*/ - std::string stat_field = ""; - //Loop Variables - /*===========================*/ - //first field(stat) - std::string a_stat = "";; - std::string a_stat_name = ""; - std::string a_stat_spacing = ""; - //second field(heroic stat) - std::string h_stat = ""; - std::string h_stat_spacing = ""; - //third field(resist) - std::string a_resist = ""; - std::string a_resist_name = ""; - std::string a_resist_spacing = ""; - //fourth field(heroic resist) - std::string h_resist_field = ""; - - int stat_rows = 7; // Number of rows - int max_stat_value_len = 3; // 3 digits in the displayed value - - for(int stat_row_counter = 0; stat_row_counter < stat_rows; stat_row_counter++) - { - switch(stat_row_counter) { - case 0: { - a_stat_name = " STR: "; - a_resist_name = "MR: "; - a_stat = itoa(GetSTR()); - h_stat = itoa(GetHeroicSTR()); - a_resist = itoa(GetMR()); - h_resist_field = itoa(GetHeroicMR()); - break; - } - case 1: { - a_stat_name = " STA: "; - a_resist_name = "CR: "; - a_stat = itoa(GetSTA()); - h_stat = itoa(GetHeroicSTA()); - a_resist = itoa(GetCR()); - h_resist_field = itoa(GetHeroicCR()); - break; - } - case 2: { - a_stat_name = " AGI : "; - a_resist_name = "FR: "; - a_stat = itoa(GetAGI()); - h_stat = itoa(GetHeroicAGI()); - a_resist = itoa(GetFR()); - h_resist_field = itoa(GetHeroicFR()); - break; - } - case 3: { - a_stat_name = " DEX: "; - a_resist_name = "PR: "; - a_stat = itoa(GetDEX()); - h_stat = itoa(GetHeroicDEX()); - a_resist = itoa(GetPR()); - h_resist_field = itoa(GetHeroicPR()); - break; - } - case 4: { - a_stat_name = " INT : "; - a_resist_name = "DR: "; - a_stat = itoa(GetINT()); - h_stat = itoa(GetHeroicINT()); - a_resist = itoa(GetDR()); - h_resist_field = itoa(GetHeroicDR()); - break; - } - case 5: { - a_stat_name = " WIS: "; - a_resist_name = "Cp: "; - a_stat = itoa(GetWIS()); - h_stat = itoa(GetHeroicWIS()); - a_resist = itoa(GetCorrup()); - h_resist_field = itoa(GetHeroicCorrup()); - break; - } - case 6: { - a_stat_name = " CHA: "; - a_stat = itoa(GetCHA()); - h_stat = itoa(GetHeroicCHA()); - break; - } - default: { break; } - } - - a_stat_spacing.clear(); - h_stat_spacing.clear(); - a_resist_spacing.clear(); - - for(int a = a_stat.size(); a < max_stat_value_len; a++) { a_stat_spacing += " . "; } - for(int h = h_stat.size(); h < 20; h++) { h_stat_spacing += " . "; } - for(int h = a_resist.size(); h < max_stat_value_len; h++) { a_resist_spacing += " . "; } - - stat_field += indP + a_stat_name + a_stat_spacing + a_stat + heroic_color + h_stat + "
"; - if(stat_row_counter < 6) { - stat_field += h_stat_spacing + a_resist_name + a_resist_spacing + a_resist + heroic_color + h_resist_field + "

"; - } - } - /*########################################################## - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Mod2 String - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - ##########################################################*/ - std::string mod2_field = ""; - //Loop Variables - /*===========================*/ - std::string mod2a = ""; - std::string mod2a_name = ""; - std::string mod2a_spacing = ""; - std::string mod2a_cap = ""; - std::string mod_row_spacing = ""; - std::string mod2b = ""; - std::string mod2b_name = ""; - std::string mod2b_spacing = ""; - std::string mod2b_cap = ""; - int mod2a_space_count; - int mod2b_space_count; - - int mod2_rows = 4; - int max_mod2_value_len = 3; // 3 digits in the displayed value - - for(int mod2_row_counter = 0; mod2_row_counter < mod2_rows; mod2_row_counter++) - { - switch (mod2_row_counter) - { - case 0: { - mod2a_name = "Avoidance: "; - mod2b_name = "Combat Effects: "; - mod2a = itoa(GetAvoidance()); - mod2a_cap = itoa(RuleI(Character, ItemAvoidanceCap)); - mod2b = itoa(GetCombatEffects()); - mod2b_cap = itoa(RuleI(Character, ItemCombatEffectsCap)); - mod2a_space_count = 2; - mod2b_space_count = 0; - break; - } - case 1: { - mod2a_name = "Accuracy: "; - mod2b_name = "Strike Through: "; - mod2a = itoa(GetAccuracy()); - mod2a_cap = itoa(RuleI(Character, ItemAccuracyCap)); - mod2b = itoa(GetStrikeThrough()); - mod2b_cap = itoa(RuleI(Character, ItemStrikethroughCap)); - mod2a_space_count = 3; - mod2b_space_count = 1; - break; - } - case 2: { - mod2a_name = "Shielding: "; - mod2b_name = "Spell Shielding: "; - mod2a = itoa(GetShielding()); - mod2a_cap = itoa(RuleI(Character, ItemShieldingCap)); - mod2b = itoa(GetSpellShield()); - mod2b_cap = itoa(RuleI(Character, ItemSpellShieldingCap)); - mod2a_space_count = 2; - mod2b_space_count = 1; - break; - } - case 3: { - mod2a_name = "Stun Resist: "; - mod2b_name = "DoT Shielding: "; - mod2a = itoa(GetStunResist()); - mod2a_cap = itoa(RuleI(Character, ItemStunResistCap)); - mod2b = itoa(GetDoTShield()); - mod2b_cap = itoa(RuleI(Character, ItemDoTShieldingCap)); - mod2a_space_count = 0; - mod2b_space_count = 2; - break; - } - } - - mod2a_spacing.clear(); - mod_row_spacing.clear(); - mod2b_spacing.clear(); - - for(int a = mod2a.size(); a < (max_mod2_value_len + mod2a_space_count); a++) { mod2a_spacing += " . "; } - for(int a = mod2a_cap.size(); a < 6 ; a++) { mod_row_spacing += " . "; } - for(int a = mod2b.size(); a < (max_mod2_value_len + mod2b_space_count); a++) { mod2b_spacing += " . "; } - - mod2_field += indP + mod2a_name + mod2a_spacing + mod2a + " / " + mod2a_cap + mod_row_spacing; - mod2_field += mod2b_name + mod2b_spacing + mod2b + " / " + mod2b_cap + "
"; - } - - uint32 rune_number = 0; - uint32 magic_rune_number = 0; - uint32 buff_count = GetMaxTotalSlots(); - for (int i=0; i < buff_count; i++) { - if (buffs[i].spellid != SPELL_UNKNOWN) { - if (buffs[i].melee_rune > 0) { rune_number += buffs[i].melee_rune; } - - if (buffs[i].magic_rune > 0) { magic_rune_number += buffs[i].magic_rune; } - } - } - - int shield_ac = 0; - GetRawACNoShield(shield_ac); - - std::string skill_list[] = { - "1H Blunt","1H Slashing","2H Blunt","2H Slashing","Abjuration","Alteration","Apply Poison","Archery","Backstab","Bind Wound","Bash","Block","Brass Instruments","Channeling","Conjuration", - "Defense","Disarm","Disarm Traps","Divination","Dodge","Double Attack","Dragon Punch","Dual Wield","Eagle Strike","Evocation","Feign Death","Flying Kick","Forage","Hand To Hand","Hide","Kick", - "Meditate","Mend","Offense","Parry","Pick Lock","Piercing","Riposte","Round Kick","Safe Fall","Sense Heading","Singing","Sneak","Specialize Abjuration","Specialize Alteration","Specialize Conjuration", - "Specialize Divination","Specialize Evocation","Pick Pockets","Stringed_Instruments","Swimming","Throwing","Tiger Claw","Tracking","Wind Instruments","Fishing","Make Poison","Tinkering","Research","Alchemy", - "Baking","Tailoring","Sense Traps","Blacksmithing","Fletching","Brewing","Alcohol_Tolerance","Begging","Jewelry Making","Pottery","Percussion Instruments","Intimidation","Berserking","Taunt","Frenzy" - }; - - std::string skill_mods = ""; - for(int j = 0; j <= HIGHEST_SKILL; j++) { - if(itembonuses.skillmod[j] > 0) - skill_mods += indP + skill_list[j] + " : +" + itoa(itembonuses.skillmod[j]) + "%
"; - else if(itembonuses.skillmod[j] < 0) - skill_mods += indP + skill_list[j] + " : -" + itoa(itembonuses.skillmod[j]) + "%
"; - } - - std::string skill_dmgs = ""; - for(int j = 0; j <= HIGHEST_SKILL; j++) { - if((itembonuses.SkillDamageAmount[j] + spellbonuses.SkillDamageAmount[j]) > 0) - skill_dmgs += indP + skill_list[j] + " : +" + itoa(itembonuses.SkillDamageAmount[j] + spellbonuses.SkillDamageAmount[j]) + "
"; - else if((itembonuses.SkillDamageAmount[j] + spellbonuses.SkillDamageAmount[j]) < 0) - skill_dmgs += indP + skill_list[j] + " : -" + itoa(itembonuses.SkillDamageAmount[j] + spellbonuses.SkillDamageAmount[j]) + "
"; - } - - std::string faction_item_string = ""; - char faction_buf[256]; - - for(std::map ::iterator iter = item_faction_bonuses.begin(); - iter != item_faction_bonuses.end(); - ++iter) - { - memset(&faction_buf, 0, sizeof(faction_buf)); - - if(!database.GetFactionName((int32)((*iter).first), faction_buf, sizeof(faction_buf))) - strcpy(faction_buf, "Not in DB"); - - if((*iter).second > 0) { - faction_item_string += indP + faction_buf + " : +" + itoa((*iter).second) + "
"; - } - else if((*iter).second < 0) { - faction_item_string += indP + faction_buf + " : -" + itoa((*iter).second) + "
"; - } - } - - std::string bard_info = ""; - if(GetClass() == BARD) { - bard_info = indP + "Singing: " + itoa(GetSingMod()) + "
" + - indP + "Brass: " + itoa(GetBrassMod()) + "
" + - indP + "String: " + itoa(GetStringMod()) + "
" + - indP + "Percussion: " + itoa(GetPercMod()) + "
" + - indP + "Wind: " + itoa(GetWindMod()) + "
"; - } - - std::ostringstream final_string; - final_string << - /* C/L/R */ indP << "Class: " << class_Name << indS << "Level: " << static_cast(GetLevel()) << indS << "Race: " << race_Name << "
" << - /* Runes */ indP << "Rune: " << rune_number << indL << indS << "Spell Rune: " << magic_rune_number << "
" << - /* HP/M/E */ HME_row << - /* DS */ indP << "DS: " << (itembonuses.DamageShield + spellbonuses.DamageShield*-1) << " (Spell: " << (spellbonuses.DamageShield*-1) << " + Item: " << itembonuses.DamageShield << " / " << RuleI(Character, ItemDamageShieldCap) << ")
" << - /* Atk */ indP << "ATK: " << GetTotalATK() << "
" << - /* Atk2 */ indP << "- Base: " << GetATKRating() << " | Item: " << itembonuses.ATK << " (" << RuleI(Character, ItemATKCap) << ")~Used: " << (itembonuses.ATK * 1.342) << " | Spell: " << spellbonuses.ATK << "
" << - /* AC */ indP << "AC: " << CalcAC() << "
" << - /* AC2 */ indP << "- Mit: " << GetACMit() << " | Avoid: " << GetACAvoid() << " | Spell: " << spellbonuses.AC << " | Shield: " << shield_ac << "
" << - /* Haste */ indP << "Haste: " << GetHaste() << "
" << - /* Haste2 */ indP << " - Item: " << itembonuses.haste << " + Spell: " << (spellbonuses.haste + spellbonuses.hastetype2) << " (Cap: " << RuleI(Character, HasteCap) << ") | Over: " << (spellbonuses.hastetype3 + ExtraHaste) << "

" << - /* RegenLbl */ indL << indS << "Regen
" << indS << indP << indP << " Base | Items (Cap) " << indP << " | Spell | A.A.s | Total
" << - /* Regen */ regen_string << "
" << - /* Stats */ stat_field << "

" << - /* Mod2s */ mod2_field << "
" << - /* HealAmt */ indP << "Heal Amount: " << GetHealAmt() << " / " << RuleI(Character, ItemHealAmtCap) << "
" << - /* SpellDmg*/ indP << "Spell Dmg: " << GetSpellDmg() << " / " << RuleI(Character, ItemSpellDmgCap) << "
" << - /* Clair */ indP << "Clairvoyance: " << GetClair() << " / " << RuleI(Character, ItemClairvoyanceCap) << "
" << - /* DSMit */ indP << "Dmg Shld Mit: " << GetDSMit() << " / " << RuleI(Character, ItemDSMitigationCap) << "

"; - if(GetClass() == BARD) - final_string << bard_info << "
"; - if(skill_mods.size() > 0) - final_string << skill_mods << "
"; - if(skill_dmgs.size() > 0) - final_string << skill_dmgs << "
"; - if(faction_item_string.size() > 0) - final_string << faction_item_string; - - std::string final_stats = final_string.str(); - - if(use_window) { - if(final_stats.size() < 4096) - { - uint32 Buttons = (client->GetClientVersion() < EQClientSoD) ? 0 : 1; - client->SendWindow(0, POPUPID_UPDATE_SHOWSTATSWINDOW, Buttons, "Cancel", "Update", 0, 1, this, "", "%s", final_stats.c_str()); - goto Extra_Info; - } - else { - client->Message(15, "The window has exceeded its character limit, displaying stats to chat window:"); - } - } - - client->Message(15, "~~~~~ %s %s ~~~~~", GetCleanName(), GetLastName()); - client->Message(0, " Level: %i Class: %i Race: %i DS: %i/%i Size: %1.1f Weight: %.1f/%d ", GetLevel(), GetClass(), GetRace(), GetDS(), RuleI(Character, ItemDamageShieldCap), GetSize(), (float)CalcCurrentWeight() / 10.0f, GetSTR()); - client->Message(0, " HP: %i/%i HP Regen: %i/%i",GetHP(), GetMaxHP(), CalcHPRegen(), CalcHPRegenCap()); - client->Message(0, " AC: %i ( Mit.: %i + Avoid.: %i + Spell: %i ) | Shield AC: %i", CalcAC(), GetACMit(), GetACAvoid(), spellbonuses.AC, shield_ac); - if(CalcMaxMana() > 0) - client->Message(0, " Mana: %i/%i Mana Regen: %i/%i", GetMana(), GetMaxMana(), CalcManaRegen(), CalcManaRegenCap()); - client->Message(0, " End.: %i/%i End. Regen: %i/%i",GetEndurance(), GetMaxEndurance(), CalcEnduranceRegen(), CalcEnduranceRegenCap()); - client->Message(0, " ATK: %i Worn/Spell ATK %i/%i Server Side ATK: %i", GetTotalATK(), RuleI(Character, ItemATKCap), GetATKBonus(), GetATK()); - client->Message(0, " Haste: %i / %i (Item: %i + Spell: %i + Over: %i)", GetHaste(), RuleI(Character, HasteCap), itembonuses.haste, spellbonuses.haste + spellbonuses.hastetype2, spellbonuses.hastetype3 + ExtraHaste); - client->Message(0, " STR: %i STA: %i DEX: %i AGI: %i INT: %i WIS: %i CHA: %i", GetSTR(), GetSTA(), GetDEX(), GetAGI(), GetINT(), GetWIS(), GetCHA()); - client->Message(0, " hSTR: %i hSTA: %i hDEX: %i hAGI: %i hINT: %i hWIS: %i hCHA: %i", GetHeroicSTR(), GetHeroicSTA(), GetHeroicDEX(), GetHeroicAGI(), GetHeroicINT(), GetHeroicWIS(), GetHeroicCHA()); - client->Message(0, " MR: %i PR: %i FR: %i CR: %i DR: %i Corruption: %i", GetMR(), GetPR(), GetFR(), GetCR(), GetDR(), GetCorrup()); - client->Message(0, " hMR: %i hPR: %i hFR: %i hCR: %i hDR: %i hCorruption: %i", GetHeroicMR(), GetHeroicPR(), GetHeroicFR(), GetHeroicCR(), GetHeroicDR(), GetHeroicCorrup()); - client->Message(0, " Shielding: %i Spell Shield: %i DoT Shielding: %i Stun Resist: %i Strikethrough: %i Avoidance: %i Accuracy: %i Combat Effects: %i", GetShielding(), GetSpellShield(), GetDoTShield(), GetStunResist(), GetStrikeThrough(), GetAvoidance(), GetAccuracy(), GetCombatEffects()); - client->Message(0, " Heal Amt.: %i Spell Dmg.: %i Clairvoyance: %i DS Mitigation: %i", GetHealAmt(), GetSpellDmg(), GetClair(), GetDSMit()); - if(GetClass() == BARD) - client->Message(0, " Singing: %i Brass: %i String: %i Percussion: %i Wind: %i", GetSingMod(), GetBrassMod(), GetStringMod(), GetPercMod(), GetWindMod()); - - Extra_Info: - - client->Message(0, " BaseRace: %i Gender: %i BaseGender: %i Texture: %i HelmTexture: %i", GetBaseRace(), GetGender(), GetBaseGender(), GetTexture(), GetHelmTexture()); - if (client->Admin() >= 100) { - client->Message(0, " CharID: %i EntityID: %i PetID: %i OwnerID: %i AIControlled: %i Targetted: %i", CharacterID(), GetID(), GetPetID(), GetOwnerID(), IsAIControlled(), targeted); - } -} - -void Client::SendAltCurrencies() { - if(GetClientVersion() >= EQClientSoF) { - uint32 count = zone->AlternateCurrencies.size(); - if(count == 0) { - return; - } - - EQApplicationPacket *outapp = new EQApplicationPacket(OP_AltCurrency, - sizeof(AltCurrencyPopulate_Struct) + sizeof(AltCurrencyPopulateEntry_Struct) * count); - AltCurrencyPopulate_Struct *altc = (AltCurrencyPopulate_Struct*)outapp->pBuffer; - altc->opcode = ALT_CURRENCY_OP_POPULATE; - altc->count = count; - - uint32 i = 0; - std::list::iterator iter = zone->AlternateCurrencies.begin(); - while(iter != zone->AlternateCurrencies.end()) { - const Item_Struct* item = database.GetItem((*iter).item_id); - altc->entries[i].currency_number = (*iter).id; - altc->entries[i].unknown00 = 1; - altc->entries[i].currency_number2 = (*iter).id; - altc->entries[i].item_id = (*iter).item_id; - if(item) { - altc->entries[i].item_icon = item->Icon; - altc->entries[i].stack_size = item->StackSize; - } else { - altc->entries[i].item_icon = 1000; - altc->entries[i].stack_size = 1000; - } - i++; - ++iter; - } - - FastQueuePacket(&outapp); - } -} - -void Client::SetAlternateCurrencyValue(uint32 currency_id, uint32 new_amount) -{ - alternate_currency[currency_id] = new_amount; - database.UpdateAltCurrencyValue(CharacterID(), currency_id, new_amount); - SendAlternateCurrencyValue(currency_id); -} - -void Client::AddAlternateCurrencyValue(uint32 currency_id, int32 amount, int8 method) -{ - - /* Added via Quest, rest of the logging methods may be done inline due to information available in that area of the code */ - if (method == 1){ - /* QS: PlayerLogAlternateCurrencyTransactions :: Cursor to Item Storage */ - if (RuleB(QueryServ, PlayerLogAlternateCurrencyTransactions)){ - std::string event_desc = StringFormat("Added via Quest :: Cursor to Item :: alt_currency_id:%i amount:%i in zoneid:%i instid:%i", currency_id, this->GetZoneID(), this->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Alternate_Currency_Transactions, this->CharacterID(), event_desc); - } - } - - if(amount == 0) { - return; - } - - if(!alternate_currency_loaded) { - alternate_currency_queued_operations.push(std::make_pair(currency_id, amount)); - return; - } - - int new_value = 0; - std::map::iterator iter = alternate_currency.find(currency_id); - if(iter == alternate_currency.end()) { - new_value = amount; - } else { - new_value = (*iter).second + amount; - } - - if(new_value < 0) { - alternate_currency[currency_id] = 0; - database.UpdateAltCurrencyValue(CharacterID(), currency_id, 0); - } else { - alternate_currency[currency_id] = new_value; - database.UpdateAltCurrencyValue(CharacterID(), currency_id, new_value); - } - SendAlternateCurrencyValue(currency_id); -} - -void Client::SendAlternateCurrencyValues() -{ - std::list::iterator iter = zone->AlternateCurrencies.begin(); - while(iter != zone->AlternateCurrencies.end()) { - SendAlternateCurrencyValue((*iter).id, false); - ++iter; - } -} - -void Client::SendAlternateCurrencyValue(uint32 currency_id, bool send_if_null) -{ - uint32 value = GetAlternateCurrencyValue(currency_id); - if(value > 0 || (value == 0 && send_if_null)) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AltCurrency, sizeof(AltCurrencyUpdate_Struct)); - AltCurrencyUpdate_Struct *update = (AltCurrencyUpdate_Struct*)outapp->pBuffer; - update->opcode = 7; - strcpy(update->name, GetName()); - update->currency_number = currency_id; - update->amount = value; - update->unknown072 = 1; - FastQueuePacket(&outapp); - } -} - -uint32 Client::GetAlternateCurrencyValue(uint32 currency_id) const -{ - std::map::const_iterator iter = alternate_currency.find(currency_id); - if(iter == alternate_currency.end()) { - return 0; - } else { - return (*iter).second; - } -} - -void Client::ProcessAlternateCurrencyQueue() { - while(!alternate_currency_queued_operations.empty()) { - std::pair op = alternate_currency_queued_operations.front(); - - AddAlternateCurrencyValue(op.first, op.second); - - alternate_currency_queued_operations.pop(); - } -} - -void Client::OpenLFGuildWindow() -{ - EQApplicationPacket *outapp = new EQApplicationPacket(OP_LFGuild, 8); - - outapp->WriteUInt32(6); - - FastQueuePacket(&outapp); -} - -bool Client::IsXTarget(const Mob *m) const -{ - if(!XTargettingAvailable() || !m || (m->GetID() == 0)) - return false; - - for(int i = 0; i < GetMaxXTargets(); ++i) - { - if(XTargets[i].ID == m->GetID()) - return true; - } - return false; -} - -bool Client::IsClientXTarget(const Client *c) const -{ - if(!XTargettingAvailable() || !c) - return false; - - for(int i = 0; i < GetMaxXTargets(); ++i) - { - if(!strcasecmp(XTargets[i].Name, c->GetName())) - return true; - } - return false; -} - - -void Client::UpdateClientXTarget(Client *c) -{ - if(!XTargettingAvailable() || !c) - return; - - for(int i = 0; i < GetMaxXTargets(); ++i) - { - if(!strcasecmp(XTargets[i].Name, c->GetName())) - { - XTargets[i].ID = c->GetID(); - SendXTargetPacket(i, c); - } - } -} - -void Client::AddAutoXTarget(Mob *m) -{ - if(!XTargettingAvailable() || !XTargetAutoAddHaters) - return; - - if(IsXTarget(m)) - return; - - for(int i = 0; i < GetMaxXTargets(); ++i) - { - if((XTargets[i].Type == Auto) && (XTargets[i].ID == 0)) - { - XTargets[i].ID = m->GetID(); - SendXTargetPacket(i, m); - break; - } - } -} - -void Client::RemoveXTarget(Mob *m, bool OnlyAutoSlots) -{ - if(!XTargettingAvailable()) - return; - - bool HadFreeAutoSlotsBefore = false; - - int FreedAutoSlots = 0; - - if(m->GetID() == 0) - return; - - for(int i = 0; i < GetMaxXTargets(); ++i) - { - if(OnlyAutoSlots && (XTargets[i].Type !=Auto)) - continue; - - if(XTargets[i].ID == m->GetID()) - { - if(XTargets[i].Type == CurrentTargetNPC) - XTargets[i].Type = Auto; - - if(XTargets[i].Type == Auto) - ++FreedAutoSlots; - - XTargets[i].ID = 0; - - SendXTargetPacket(i, nullptr); - } - else - { - if((XTargets[i].Type == Auto) && (XTargets[i].ID == 0)) - HadFreeAutoSlotsBefore = true; - } - } - // If there are more mobs aggro on us than we had auto-hate slots, add one of those haters into the slot(s) we just freed up. - if(!HadFreeAutoSlotsBefore && FreedAutoSlots) - entity_list.RefreshAutoXTargets(this); -} - -void Client::UpdateXTargetType(XTargetType Type, Mob *m, const char *Name) -{ - if(!XTargettingAvailable()) - return; - - for(int i = 0; i < GetMaxXTargets(); ++i) - { - if(XTargets[i].Type == Type) - { - if(m) - XTargets[i].ID = m->GetID(); - else - XTargets[i].ID = 0; - - if(Name) - strncpy(XTargets[i].Name, Name, 64); - - SendXTargetPacket(i, m); - } - } -} - -void Client::SendXTargetPacket(uint32 Slot, Mob *m) -{ - if(!XTargettingAvailable()) - return; - - uint32 PacketSize = 18; - - if(m) - PacketSize += strlen(m->GetCleanName()); - else - { - PacketSize += strlen(XTargets[Slot].Name); - } - - EQApplicationPacket *outapp = new EQApplicationPacket(OP_XTargetResponse, PacketSize); - outapp->WriteUInt32(GetMaxXTargets()); - outapp->WriteUInt32(1); - outapp->WriteUInt32(Slot); - if(m) - { - outapp->WriteUInt8(1); - } - else - { - if (strlen(XTargets[Slot].Name) && ((XTargets[Slot].Type == CurrentTargetPC) || - (XTargets[Slot].Type == GroupTank) || - (XTargets[Slot].Type == GroupAssist) || - (XTargets[Slot].Type == Puller) || - (XTargets[Slot].Type == RaidAssist1) || - (XTargets[Slot].Type == RaidAssist2) || - (XTargets[Slot].Type == RaidAssist3))) - { - outapp->WriteUInt8(2); - } - else - { - outapp->WriteUInt8(0); - } - } - outapp->WriteUInt32(XTargets[Slot].ID); - outapp->WriteString(m ? m->GetCleanName() : XTargets[Slot].Name); - FastQueuePacket(&outapp); -} - -void Client::RemoveGroupXTargets() -{ - if(!XTargettingAvailable()) - return; - - for(int i = 0; i < GetMaxXTargets(); ++i) - { - if ((XTargets[i].Type == GroupTank) || - (XTargets[i].Type == GroupAssist) || - (XTargets[i].Type == Puller) || - (XTargets[i].Type == RaidAssist1) || - (XTargets[i].Type == RaidAssist2) || - (XTargets[i].Type == RaidAssist3) || - (XTargets[i].Type == GroupMarkTarget1) || - (XTargets[i].Type == GroupMarkTarget2) || - (XTargets[i].Type == GroupMarkTarget3)) - { - XTargets[i].ID = 0; - XTargets[i].Name[0] = 0; - SendXTargetPacket(i, nullptr); - } - } -} - -void Client::RemoveAutoXTargets() -{ - if(!XTargettingAvailable()) - return; - - for(int i = 0; i < GetMaxXTargets(); ++i) - { - if(XTargets[i].Type == Auto) - { - XTargets[i].ID = 0; - XTargets[i].Name[0] = 0; - SendXTargetPacket(i, nullptr); - } - } -} - -void Client::ShowXTargets(Client *c) -{ - if(!c) - return; - - for(int i = 0; i < GetMaxXTargets(); ++i) - c->Message(0, "Xtarget Slot: %i, Type: %2i, ID: %4i, Name: %s", i, XTargets[i].Type, XTargets[i].ID, XTargets[i].Name); -} - -void Client::SetMaxXTargets(uint8 NewMax) -{ - if(!XTargettingAvailable()) - return; - - if(NewMax > XTARGET_HARDCAP) - return; - - MaxXTargets = NewMax; - - Save(0); - - for(int i = MaxXTargets; i < XTARGET_HARDCAP; ++i) - { - XTargets[i].Type = Auto; - XTargets[i].ID = 0; - XTargets[i].Name[0] = 0; - } - - EQApplicationPacket *outapp = new EQApplicationPacket(OP_XTargetResponse, 8); - outapp->WriteUInt32(GetMaxXTargets()); - outapp->WriteUInt32(0); - FastQueuePacket(&outapp); -} - -const char* Client::GetRacePlural(Client* client) { - - switch (client->CastToMob()->GetRace()) { - case HUMAN: - return "Humans"; break; - case BARBARIAN: - return "Barbarians"; break; - case ERUDITE: - return "Erudites"; break; - case WOOD_ELF: - return "Wood Elves"; break; - case HIGH_ELF: - return "High Elves"; break; - case DARK_ELF: - return "Dark Elves"; break; - case HALF_ELF: - return "Half Elves"; break; - case DWARF: - return "Dwarves"; break; - case TROLL: - return "Trolls"; break; - case OGRE: - return "Ogres"; break; - case HALFLING: - return "Halflings"; break; - case GNOME: - return "Gnomes"; break; - case IKSAR: - return "Iksar"; break; - case VAHSHIR: - return "Vah Shir"; break; - case FROGLOK: - return "Frogloks"; break; - case DRAKKIN: - return "Drakkin"; break; - default: - return "Races"; break; - } -} - -const char* Client::GetClassPlural(Client* client) { - - switch (client->CastToMob()->GetClass()) { - case WARRIOR: - return "Warriors"; break; - case CLERIC: - return "Clerics"; break; - case PALADIN: - return "Paladins"; break; - case RANGER: - return "Rangers"; break; - case SHADOWKNIGHT: - return "Shadowknights"; break; - case DRUID: - return "Druids"; break; - case MONK: - return "Monks"; break; - case BARD: - return "Bards"; break; - case ROGUE: - return "Rogues"; break; - case SHAMAN: - return "Shamen"; break; - case NECROMANCER: - return "Necromancers"; break; - case WIZARD: - return "Wizards"; break; - case MAGICIAN: - return "Magicians"; break; - case ENCHANTER: - return "Enchanters"; break; - case BEASTLORD: - return "Beastlords"; break; - case BERSERKER: - return "Berserkers"; break; - default: - return "Classes"; break; - } -} - - -void Client::SendWebLink(const char *website) -{ - size_t len = strlen(website) + 1; - if(website != 0 && len > 1) - { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Weblink, sizeof(Weblink_Struct) + len); - Weblink_Struct *wl = (Weblink_Struct*)outapp->pBuffer; - memcpy(wl->weblink, website, len); - wl->weblink[len] = '\0'; - - FastQueuePacket(&outapp); - } -} - -void Client::SendMercPersonalInfo() -{ - uint32 mercTypeCount = 1; - uint32 mercCount = 1; //TODO: Un-hardcode this and support multiple mercs like in later clients than SoD. - //uint32 packetSize = 0; - uint32 i=0; - uint32 altCurrentType = 19; //TODO: Implement alternate currency purchases involving mercs! - - if (GetClientVersion() >= EQClientRoF) - { - MercTemplate *mercData = &zone->merc_templates[GetMercInfo().MercTemplateID]; - - if (mercData) - { - int i = 0; - int stancecount = 0; - stancecount += zone->merc_stance_list[GetMercInfo().MercTemplateID].size(); - - if(stancecount > MAX_MERC_STANCES || mercCount > MAX_MERC || mercTypeCount > MAX_MERC_GRADES) - { - SendMercMerchantResponsePacket(0); - return; - } - if (mercCount > 0 && mercCount) - { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenaryDataUpdate, sizeof(MercenaryDataUpdate_Struct)); - MercenaryDataUpdate_Struct* mdus = (MercenaryDataUpdate_Struct*)outapp->pBuffer; - mdus->MercStatus = 0; - mdus->MercCount = mercCount; - mdus->MercData[i].MercID = mercData->MercTemplateID; - mdus->MercData[i].MercType = mercData->MercType; - mdus->MercData[i].MercSubType = mercData->MercSubType; - mdus->MercData[i].PurchaseCost = Merc::CalcPurchaseCost(mercData->MercTemplateID, GetLevel(), 0); - mdus->MercData[i].UpkeepCost = Merc::CalcUpkeepCost(mercData->MercTemplateID, GetLevel(), 0); - mdus->MercData[i].Status = 0; - mdus->MercData[i].AltCurrencyCost = Merc::CalcPurchaseCost(mercData->MercTemplateID, GetLevel(), altCurrentType); - mdus->MercData[i].AltCurrencyUpkeep = Merc::CalcPurchaseCost(mercData->MercTemplateID, GetLevel(), altCurrentType); - mdus->MercData[i].AltCurrencyType = altCurrentType; - mdus->MercData[i].MercUnk01 = 0; - mdus->MercData[i].TimeLeft = GetMercInfo().MercTimerRemaining; //GetMercTimer().GetRemainingTime(); - mdus->MercData[i].MerchantSlot = i + 1; - mdus->MercData[i].MercUnk02 = 1; - mdus->MercData[i].StanceCount = zone->merc_stance_list[mercData->MercTemplateID].size(); - mdus->MercData[i].MercUnk03 = 0; - mdus->MercData[i].MercUnk04 = 1; - strn0cpy(mdus->MercData[i].MercName, GetMercInfo().merc_name , sizeof(mdus->MercData[i].MercName)); - uint32 stanceindex = 0; - if (mdus->MercData[i].StanceCount != 0) - { - std::list::iterator iter = zone->merc_stance_list[mercData->MercTemplateID].begin(); - while(iter != zone->merc_stance_list[mercData->MercTemplateID].end()) - { - mdus->MercData[i].Stances[stanceindex].StanceIndex = stanceindex; - mdus->MercData[i].Stances[stanceindex].Stance = (iter->StanceID); - stanceindex++; - ++iter; - } - } - - mdus->MercData[i].MercUnk05 = 1; - FastQueuePacket(&outapp); - return; - } - } - } - else - { - int stancecount = 0; - stancecount += zone->merc_stance_list[GetMercInfo().MercTemplateID].size(); - - if(mercCount > MAX_MERC || mercTypeCount > MAX_MERC_GRADES) - { - if (GetClientVersion() == EQClientSoD) - { - SendMercMerchantResponsePacket(0); - } - return; - } - - EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenaryDataResponse, sizeof(MercenaryMerchantList_Struct)); - MercenaryMerchantList_Struct* mml = (MercenaryMerchantList_Struct*)outapp->pBuffer; - MercTemplate *mercData = &zone->merc_templates[GetMercInfo().MercTemplateID]; - - - if(mercData) - { - if(mercTypeCount > 0) - { - mml->MercTypeCount = mercTypeCount; //We only should have one merc entry. - mml->MercGrades[i] = 1; - } - mml->MercCount = mercCount; - if(mercCount > 0) - { - - mml->Mercs[i].MercID = mercData->MercTemplateID; - mml->Mercs[i].MercType = mercData->MercType; - mml->Mercs[i].MercSubType = mercData->MercSubType; - mml->Mercs[i].PurchaseCost = RuleB(Mercs, ChargeMercPurchaseCost) ? Merc::CalcPurchaseCost(mercData->MercTemplateID, GetLevel(), 0): 0; - mml->Mercs[i].UpkeepCost = RuleB(Mercs, ChargeMercUpkeepCost) ? Merc::CalcUpkeepCost(mercData->MercTemplateID, GetLevel(), 0): 0; - mml->Mercs[i].Status = 0; - mml->Mercs[i].AltCurrencyCost = RuleB(Mercs, ChargeMercPurchaseCost) ? Merc::CalcPurchaseCost(mercData->MercTemplateID, GetLevel(), altCurrentType): 0; - mml->Mercs[i].AltCurrencyUpkeep = RuleB(Mercs, ChargeMercUpkeepCost) ? Merc::CalcUpkeepCost(mercData->MercTemplateID, GetLevel(), altCurrentType): 0; - mml->Mercs[i].AltCurrencyType = altCurrentType; - mml->Mercs[i].MercUnk01 = 0; - mml->Mercs[i].TimeLeft = GetMercInfo().MercTimerRemaining; - mml->Mercs[i].MerchantSlot = i + 1; - mml->Mercs[i].MercUnk02 = 1; - mml->Mercs[i].StanceCount = zone->merc_stance_list[mercData->MercTemplateID].size(); - mml->Mercs[i].MercUnk03 = 0; - mml->Mercs[i].MercUnk04 = 1; - //mml->Mercs[i].MercName; - int stanceindex = 0; - if(mml->Mercs[i].StanceCount != 0) - { - std::list::iterator iter = zone->merc_stance_list[mercData->MercTemplateID].begin(); - while(iter != zone->merc_stance_list[mercData->MercTemplateID].end()) - { - mml->Mercs[i].Stances[stanceindex].StanceIndex = stanceindex; - mml->Mercs[i].Stances[stanceindex].Stance = (iter->StanceID); - stanceindex++; - ++iter; - } - } - FastQueuePacket(&outapp); - } - else - { - safe_delete(outapp); - if (GetClientVersion() == EQClientSoD) - { - SendMercMerchantResponsePacket(0); - } - return; - } - if (GetClientVersion() == EQClientSoD) - { - SendMercMerchantResponsePacket(0); - } - } - else - { - safe_delete(outapp); - if (GetClientVersion() == EQClientSoD) - { - SendMercMerchantResponsePacket(0); - } - return; - } - } -} - -void Client::SendClearMercInfo() -{ - EQApplicationPacket* outapp = new EQApplicationPacket(OP_MercenaryDataUpdate, sizeof(NoMercenaryHired_Struct)); - NoMercenaryHired_Struct *nmhs = (NoMercenaryHired_Struct*)outapp->pBuffer; - nmhs->MercStatus = -1; - nmhs->MercCount = 0; - nmhs->MercID = 1; - FastQueuePacket(&outapp); -} - - -void Client::DuplicateLoreMessage(uint32 ItemID) -{ - if(!(ClientVersionBit & BIT_RoFAndLater)) - { - Message_StringID(0, PICK_LORE); - return; - } - - const Item_Struct *item = database.GetItem(ItemID); - - if(!item) - return; - - Message_StringID(0, PICK_LORE, item->Name); -} - -void Client::GarbleMessage(char *message, uint8 variance) -{ - // Garble message by variance% - const char alpha_list[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; // only change alpha characters for now - - for (size_t i = 0; i < strlen(message); i++) { - uint8 chance = (uint8)MakeRandomInt(0, 115); // variation just over worst possible scrambling - if (isalpha(message[i]) && (chance <= variance)) { - uint8 rand_char = (uint8)MakeRandomInt(0,51); // choose a random character from the alpha list - message[i] = alpha_list[rand_char]; - } - } -} - -// returns what Other thinks of this -FACTION_VALUE Client::GetReverseFactionCon(Mob* iOther) { - if (GetOwnerID()) { - return GetOwnerOrSelf()->GetReverseFactionCon(iOther); - } - - iOther = iOther->GetOwnerOrSelf(); - - if (iOther->GetPrimaryFaction() < 0) - return GetSpecialFactionCon(iOther); - - if (iOther->GetPrimaryFaction() == 0) - return FACTION_INDIFFERENT; - - return GetFactionLevel(CharacterID(), 0, GetRace(), GetClass(), GetDeity(), iOther->GetPrimaryFaction(), iOther); -} - -//o-------------------------------------------------------------- -//| Name: GetFactionLevel; rembrant, Dec. 16, 2001 -//o-------------------------------------------------------------- -//| Notes: Gets the characters faction standing with the specified NPC. -//| Will return Indifferent on failure. -//o-------------------------------------------------------------- -FACTION_VALUE Client::GetFactionLevel(uint32 char_id, uint32 npc_id, uint32 p_race, uint32 p_class, uint32 p_deity, int32 pFaction, Mob* tnpc) -{ - if (pFaction < 0) - return GetSpecialFactionCon(tnpc); - FACTION_VALUE fac = FACTION_INDIFFERENT; - int32 tmpFactionValue; - FactionMods fmods; - - // neotokyo: few optimizations - if (GetFeigned()) - return FACTION_INDIFFERENT; - if (invisible_undead && tnpc && !tnpc->SeeInvisibleUndead()) - return FACTION_INDIFFERENT; - if (IsInvisible(tnpc)) - return FACTION_INDIFFERENT; - if (tnpc && tnpc->GetOwnerID() != 0) // pets con amiably to owner and indiff to rest - { - if (char_id == tnpc->GetOwner()->CastToClient()->CharacterID()) - return FACTION_AMIABLE; - else - return FACTION_INDIFFERENT; - } - - //First get the NPC's Primary faction - if(pFaction > 0) - { - //Get the faction data from the database - if(database.GetFactionData(&fmods, p_class, p_race, p_deity, pFaction)) - { - //Get the players current faction with pFaction - tmpFactionValue = GetCharacterFactionLevel(pFaction); - // Everhood - tack on any bonuses from Alliance type spell effects - tmpFactionValue += GetFactionBonus(pFaction); - tmpFactionValue += GetItemFactionBonus(pFaction); - //Return the faction to the client - fac = CalculateFaction(&fmods, tmpFactionValue); - } - } - else - { - return(FACTION_INDIFFERENT); - } - - // merchant fix - if (tnpc && tnpc->IsNPC() && tnpc->CastToNPC()->MerchantType && (fac == FACTION_THREATENLY || fac == FACTION_SCOWLS)) - fac = FACTION_DUBIOUS; - - if (tnpc != 0 && fac != FACTION_SCOWLS && tnpc->CastToNPC()->CheckAggro(this)) - fac = FACTION_THREATENLY; - - return fac; -} - -//o-------------------------------------------------------------- -//| Name: SetFactionLevel; rembrant, Dec. 20, 2001 -//o-------------------------------------------------------------- -//| Notes: Sets the characters faction standing with the specified NPC. -//o-------------------------------------------------------------- -void Client::SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, uint8 char_race, uint8 char_deity) -{ - int32 faction_id[MAX_NPC_FACTIONS]={ 0,0,0,0,0,0,0,0,0,0 }; - int32 npc_value[MAX_NPC_FACTIONS]={ 0,0,0,0,0,0,0,0,0,0 }; - uint8 temp[MAX_NPC_FACTIONS]={ 0,0,0,0,0,0,0,0,0,0 }; - int32 mod; - int32 t; - int32 tmpValue; - int32 current_value; - FactionMods fm; - // Get the npc faction list - if(!database.GetNPCFactionList(npc_id, faction_id, npc_value, temp)) - return; - for(int i = 0;iitembonuses.HeroicCHA) { - int faction_mod = itembonuses.HeroicCHA / 5; - // If our result isn't truncated, then just do that - if(npc_value[i] * faction_mod / 100 != 0) - npc_value[i] += npc_value[i] * faction_mod / 100; - // If our result is truncated, then double a mob's value every once and a while to equal what they would have got - else { - if(MakeRandomInt(0, 100) < faction_mod) - npc_value[i] *= 2; - } - } - //figure out their modifier - mod = fm.base + fm.class_mod + fm.race_mod + fm.deity_mod; - if(mod > MAX_FACTION) - mod = MAX_FACTION; - else if(mod < MIN_FACTION) - mod = MIN_FACTION; - - // Calculate the faction - if(npc_value[i] != 0) { - tmpValue = current_value + mod + npc_value[i]; - - int16 FactionModPct = spellbonuses.FactionModPct + itembonuses.FactionModPct + aabonuses.FactionModPct; - tmpValue += (tmpValue * FactionModPct) / 100; - - // Make sure faction hits don't go to GMs... - if (m_pp.gm==1 && (tmpValue < current_value)) { - tmpValue = current_value; - } - - // Make sure we dont go over the min/max faction limits - if(tmpValue >= MAX_FACTION) - { - t = MAX_FACTION - mod; - if(current_value == t) { - //do nothing, it is already maxed out - } else if(!(database.SetCharacterFactionLevel(char_id, faction_id[i], t, temp[i], factionvalues))) - { - return; - } - } - else if(tmpValue <= MIN_FACTION) - { - t = MIN_FACTION - mod; - if(current_value == t) { - //do nothing, it is already maxed out - } else if(!(database.SetCharacterFactionLevel(char_id, faction_id[i], t, temp[i], factionvalues))) - { - return; - } - } - else - { - if(!(database.SetCharacterFactionLevel(char_id, faction_id[i], current_value + npc_value[i], temp[i], factionvalues))) - { - return; - } - } - if(tmpValue <= MIN_FACTION) - tmpValue = MIN_FACTION; - - SendFactionMessage(npc_value[i], faction_id[i], tmpValue, temp[i]); - } - } - } - return; -} - -void Client::SetFactionLevel2(uint32 char_id, int32 faction_id, uint8 char_class, uint8 char_race, uint8 char_deity, int32 value, uint8 temp) -{ - int32 current_value; - //Get the npc faction list - if(faction_id > 0 && value != 0) { - //Get the faction modifiers - current_value = GetCharacterFactionLevel(faction_id) + value; - if(!(database.SetCharacterFactionLevel(char_id, faction_id, current_value, temp, factionvalues))) - return; - - SendFactionMessage(value, faction_id, current_value, temp); - } - return; -} - -int32 Client::GetCharacterFactionLevel(int32 faction_id) -{ - if (faction_id <= 0) - return 0; - faction_map::iterator res; - res = factionvalues.find(faction_id); - if(res == factionvalues.end()) - return(0); - return(res->second); -} - -// returns the character's faction level, adjusted for racial, class, and deity modifiers -int32 Client::GetModCharacterFactionLevel(int32 faction_id) { - int32 Modded = GetCharacterFactionLevel(faction_id); - FactionMods fm; - if(database.GetFactionData(&fm,GetClass(),GetRace(),GetDeity(),faction_id)) - Modded += fm.base + fm.class_mod + fm.race_mod + fm.deity_mod; - if (Modded > MAX_FACTION) - Modded = MAX_FACTION; - - return Modded; -} - -bool Client::HatedByClass(uint32 p_race, uint32 p_class, uint32 p_deity, int32 pFaction) -{ - - bool Result = false; - - int32 tmpFactionValue; - FactionMods fmods; - - //First get the NPC's Primary faction - if(pFaction > 0) - { - //Get the faction data from the database - if(database.GetFactionData(&fmods, p_class, p_race, p_deity, pFaction)) - { - tmpFactionValue = GetCharacterFactionLevel(pFaction); - tmpFactionValue += GetFactionBonus(pFaction); - tmpFactionValue += GetItemFactionBonus(pFaction); - CalculateFaction(&fmods, tmpFactionValue); - if(fmods.class_mod < fmods.race_mod) - Result = true; - } - } - return Result; -} - -//o-------------------------------------------------------------- -//| Name: SendFactionMessage -//o-------------------------------------------------------------- -//| Purpose: Send faction change message to client -//o-------------------------------------------------------------- -void Client::SendFactionMessage(int32 tmpvalue, int32 faction_id, int32 totalvalue, uint8 temp) -{ - char name[50]; - - // default to Faction# if we couldn't get the name from the ID - if (database.GetFactionName(faction_id, name, sizeof(name)) == false) - snprintf(name, sizeof(name),"Faction%i",faction_id); - - if (tmpvalue == 0 || temp == 1 || temp == 2) - return; - else if (totalvalue >= MAX_FACTION) - Message_StringID(0, FACTION_BEST, name); - else if (tmpvalue > 0 && totalvalue < MAX_FACTION) - Message_StringID(0, FACTION_BETTER, name); - else if (tmpvalue < 0 && totalvalue > MIN_FACTION) - Message_StringID(0, FACTION_WORSE, name); - else if (totalvalue <= MIN_FACTION) - Message_StringID(0, FACTION_WORST, name); - - return; -} - -void Client::LoadAccountFlags() -{ - accountflags.clear(); - - std::string query = StringFormat("SELECT p_flag, p_value FROM account_flags WHERE p_accid = '%d'", account_id); - auto results = database.QueryDatabase(query); - if (!results.Success()) { - std::cerr << "Error in LoadAccountFlags query '" << query << "' " << results.ErrorMessage() << std::endl; - return; - } - - for (auto row = results.begin(); row != results.end(); ++row) { - std::string fname(row[0]); - std::string fval(row[1]); - accountflags[fname] = fval; - } - -} - -void Client::SetAccountFlag(std::string flag, std::string val) -{ - std::string query = StringFormat("REPLACE INTO account_flags (p_accid, p_flag, p_value) " - "VALUES( '%d', '%s', '%s')", account_id, flag.c_str(), val.c_str()); - auto results = database.QueryDatabase(query); - if(!results.Success()) - std::cerr << "Error in SetAccountFlags query '" << query << "' " << results.ErrorMessage() << std::endl; - - accountflags[flag] = val; -} - -std::string Client::GetAccountFlag(std::string flag) -{ - return(accountflags[flag]); -} - -void Client::TickItemCheck() -{ - int i; - - if(zone->tick_items.empty()) { return; } - - //Scan equip slots for items - for(i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; i++) - { - TryItemTick(i); - } - //Scan main inventory + cursor - for(i = EmuConstants::GENERAL_BEGIN; i <= MainCursor; i++) - { - TryItemTick(i); - } - //Scan bags - for(i = EmuConstants::GENERAL_BAGS_BEGIN; i <= EmuConstants::CURSOR_BAG_END; i++) - { - TryItemTick(i); - } -} - -void Client::TryItemTick(int slot) -{ - int iid = 0; - const ItemInst* inst = m_inv[slot]; - if(inst == 0) { return; } - - iid = inst->GetID(); - - if(zone->tick_items.count(iid) > 0) - { - if( GetLevel() >= zone->tick_items[iid].level && MakeRandomInt(0, 100) >= (100 - zone->tick_items[iid].chance) && (zone->tick_items[iid].bagslot || slot <= EmuConstants::EQUIPMENT_END) ) - { - ItemInst* e_inst = (ItemInst*)inst; - parse->EventItem(EVENT_ITEM_TICK, this, e_inst, nullptr, "", slot); - } - } - - //Only look at augs in main inventory - if(slot > EmuConstants::EQUIPMENT_END) { return; } - - for (int x = AUG_BEGIN; x < EmuConstants::ITEM_COMMON_SIZE; ++x) - { - ItemInst * a_inst = inst->GetAugment(x); - if(!a_inst) { continue; } - - iid = a_inst->GetID(); - - if(zone->tick_items.count(iid) > 0) - { - if( GetLevel() >= zone->tick_items[iid].level && MakeRandomInt(0, 100) >= (100 - zone->tick_items[iid].chance) ) - { - ItemInst* e_inst = (ItemInst*)a_inst; - parse->EventItem(EVENT_ITEM_TICK, this, e_inst, nullptr, "", slot); - } - } - } -} - -void Client::ItemTimerCheck() -{ - int i; - for(i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; i++) - { - TryItemTimer(i); - } - - for(i = EmuConstants::GENERAL_BAGS_BEGIN; i <= MainCursor; i++) - { - TryItemTimer(i); - } - - for(i = EmuConstants::GENERAL_BAGS_BEGIN; i <= EmuConstants::CURSOR_BAG_END; i++) - { - TryItemTimer(i); - } -} - -void Client::TryItemTimer(int slot) -{ - ItemInst* inst = m_inv.GetItem(slot); - if(!inst) { - return; - } - - auto item_timers = inst->GetTimers(); - auto it_iter = item_timers.begin(); - while(it_iter != item_timers.end()) { - if(it_iter->second.Check()) { - parse->EventItem(EVENT_TIMER, this, inst, nullptr, it_iter->first, 0); - } - ++it_iter; - } - - if(slot > EmuConstants::EQUIPMENT_END) { - return; - } - - for (int x = AUG_BEGIN; x < EmuConstants::ITEM_COMMON_SIZE; ++x) - { - ItemInst * a_inst = inst->GetAugment(x); - if(!a_inst) { - continue; - } - - auto item_timers = a_inst->GetTimers(); - auto it_iter = item_timers.begin(); - while(it_iter != item_timers.end()) { - if(it_iter->second.Check()) { - parse->EventItem(EVENT_TIMER, this, a_inst, nullptr, it_iter->first, 0); - } - ++it_iter; - } - } -} - -void Client::RefundAA() { - int cur = 0; - bool refunded = false; - - for(int x = 0; x < aaHighestID; x++) { - cur = GetAA(x); - if(cur > 0){ - SendAA_Struct* curaa = zone->FindAA(x); - if(cur){ - SetAA(x, 0); - for(int j = 0; j < cur; j++) { - m_pp.aapoints += curaa->cost + (curaa->cost_inc * j); - refunded = true; - } - } - else - { - m_pp.aapoints += cur; - SetAA(x, 0); - refunded = true; - } - } - } - - if(refunded) { - Save(); - Kick(); - } -} - -void Client::IncrementAA(int aa_id) { - SendAA_Struct* aa2 = zone->FindAA(aa_id); - - if(aa2 == nullptr) - return; - - if(GetAA(aa_id) == aa2->max_level) - return; - - SetAA(aa_id, GetAA(aa_id) + 1); - - Save(); - - SendAA(aa_id); - SendAATable(); - SendAAStats(); - CalcBonuses(); -} - -void Client::SendItemScale(ItemInst *inst) { - int slot = m_inv.GetSlotByItemInst(inst); - if(slot != -1) { - inst->ScaleItem(); - SendItemPacket(slot, inst, ItemPacketCharmUpdate); - CalcBonuses(); - } -} - -void Client::AddRespawnOption(std::string option_name, uint32 zoneid, float x, float y, float z, float heading, bool initial_selection, int8 position) -{ - //If respawn window is already open, any changes would create an inconsistency with the client - if (IsHoveringForRespawn()) { return; } - - if (zoneid == 0) - zoneid = zone->GetZoneID(); - - //Create respawn option - RespawnOption res_opt; - res_opt.name = option_name; - res_opt.zoneid = zoneid; - res_opt.x = x; - res_opt.y = y; - res_opt.z = z; - res_opt.heading = heading; - - if (position == -1 || position >= respawn_options.size()) - { - //No position specified, or specified beyond the end, simply append - respawn_options.push_back(res_opt); - //Make this option the initial selection for the window if desired - if (initial_selection) - initial_respawn_selection = static_cast(respawn_options.size()) - 1; - } - else if (position == 0) - { - respawn_options.push_front(res_opt); - if (initial_selection) - initial_respawn_selection = 0; - } - else - { - //Insert new option between existing options - std::list::iterator itr; - uint8 pos = 0; - for (itr = respawn_options.begin(); itr != respawn_options.end(); ++itr) - { - if (pos++ == position) - { - respawn_options.insert(itr,res_opt); - //Make this option the initial selection for the window if desired - if (initial_selection) - initial_respawn_selection = pos; - return; - } - } - } -} - -bool Client::RemoveRespawnOption(std::string option_name) -{ - //If respawn window is already open, any changes would create an inconsistency with the client - if (IsHoveringForRespawn() || respawn_options.empty()) { return false; } - - bool had = false; - RespawnOption* opt; - std::list::iterator itr; - for (itr = respawn_options.begin(); itr != respawn_options.end(); ++itr) - { - opt = &(*itr); - if (opt->name.compare(option_name) == 0) - { - itr = respawn_options.erase(itr); - had = true; - //could be more with the same name, so keep going... - } - } - return had; -} - -bool Client::RemoveRespawnOption(uint8 position) -{ - //If respawn window is already open, any changes would create an inconsistency with the client - if (IsHoveringForRespawn() || respawn_options.empty()) { return false; } - - //Easy cases first... - if (position == 0) - { - respawn_options.pop_front(); - return true; - } - else if (position == (respawn_options.size() - 1)) - { - respawn_options.pop_back(); - return true; - } - - std::list::iterator itr; - uint8 pos = 0; - for (itr = respawn_options.begin(); itr != respawn_options.end(); ++itr) - { - if (pos++ == position) - { - respawn_options.erase(itr); - return true; - } - } - return false; -} - -void Client::SetHunger(int32 in_hunger) -{ - EQApplicationPacket *outapp; - outapp = new EQApplicationPacket(OP_Stamina, sizeof(Stamina_Struct)); - Stamina_Struct* sta = (Stamina_Struct*)outapp->pBuffer; - sta->food = in_hunger; - sta->water = m_pp.thirst_level > 6000 ? 6000 : m_pp.thirst_level; - - m_pp.hunger_level = in_hunger; - - QueuePacket(outapp); - safe_delete(outapp); -} - -void Client::SetThirst(int32 in_thirst) -{ - EQApplicationPacket *outapp; - outapp = new EQApplicationPacket(OP_Stamina, sizeof(Stamina_Struct)); - Stamina_Struct* sta = (Stamina_Struct*)outapp->pBuffer; - sta->food = m_pp.hunger_level > 6000 ? 6000 : m_pp.hunger_level; - sta->water = in_thirst; - - m_pp.thirst_level = in_thirst; - - QueuePacket(outapp); - safe_delete(outapp); -} - -void Client::SetConsumption(int32 in_hunger, int32 in_thirst) -{ - EQApplicationPacket *outapp; - outapp = new EQApplicationPacket(OP_Stamina, sizeof(Stamina_Struct)); - Stamina_Struct* sta = (Stamina_Struct*)outapp->pBuffer; - sta->food = in_hunger; - sta->water = in_thirst; - - m_pp.hunger_level = in_hunger; - m_pp.thirst_level = in_thirst; - - QueuePacket(outapp); - safe_delete(outapp); -} - -void Client::Consume(const Item_Struct *item, uint8 type, int16 slot, bool auto_consume) -{ - if(!item) { return; } - - uint16 cons_mod = 180; - - int16 metabolism_bonus = spellbonuses.Metabolism + itembonuses.Metabolism + aabonuses.Metabolism; - - if (metabolism_bonus) - cons_mod = cons_mod * metabolism_bonus * RuleI(Character, ConsumptionMultiplier) / 10000; - else - cons_mod = cons_mod * RuleI(Character, ConsumptionMultiplier) / 100; - - if(type == ItemTypeFood) - { - int hchange = item->CastTime * cons_mod; - hchange = mod_food_value(item, hchange); - - if(hchange < 0) { return; } - - m_pp.hunger_level += hchange; - DeleteItemInInventory(slot, 1, false); - - if(!auto_consume) //no message if the client consumed for us - entity_list.MessageClose_StringID(this, true, 50, 0, EATING_MESSAGE, GetName(), item->Name); - -#if EQDEBUG >= 5 - LogFile->write(EQEMuLog::Debug, "Eating from slot:%i", (int)slot); -#endif - } - else - { - int tchange = item->CastTime * cons_mod; - tchange = mod_drink_value(item, tchange); - - if(tchange < 0) { return; } - - m_pp.thirst_level += tchange; - DeleteItemInInventory(slot, 1, false); - - if(!auto_consume) //no message if the client consumed for us - entity_list.MessageClose_StringID(this, true, 50, 0, DRINKING_MESSAGE, GetName(), item->Name); - -#if EQDEBUG >= 5 - LogFile->write(EQEMuLog::Debug, "Drinking from slot:%i", (int)slot); -#endif - } -} - -void Client::SendMarqueeMessage(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, std::string msg) -{ - if(duration == 0 || msg.length() == 0) { - return; - } - - EQApplicationPacket outapp(OP_Marquee, sizeof(ClientMarqueeMessage_Struct) + msg.length()); - ClientMarqueeMessage_Struct *cms = (ClientMarqueeMessage_Struct*)outapp.pBuffer; - - cms->type = type; - cms->unk04 = 10; - cms->priority = priority; - cms->fade_in_time = fade_in; - cms->fade_out_time = fade_out; - cms->duration = duration; - strcpy(cms->msg, msg.c_str()); - - QueuePacket(&outapp); -} - -void Client::PlayMP3(const char* fname) -{ - std::string filename = fname; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_PlayMP3, filename.length() + 1); - PlayMP3_Struct* buf = (PlayMP3_Struct*)outapp->pBuffer; - strncpy(buf->filename, fname, filename.length()); - QueuePacket(outapp); - safe_delete(outapp); -} - -void Client::ExpeditionSay(const char *str, int expID) { - - std::string query = StringFormat("SELECT `player_name` FROM " - "`cust_inst_players` WHERE " - "`inst_id` = %i", expID); - auto results = database.QueryDatabase(query); - if (!results.Success()) - return; - - this->Message(14, "You say to the expedition, '%s'", str); - - for (auto row = results.begin(); row != results.end(); ++row) { - const char* charName = row[0]; - if(strcmp(charName, this->GetCleanName()) != 0) - worldserver.SendEmoteMessage(charName, 0, 0, 14, "%s says to the expedition, '%s'", this->GetCleanName(), str); - } - -} From b2aa3262a94f2732f6081a015fce4b28159ff7f9 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sat, 6 Sep 2014 12:56:35 -0700 Subject: [PATCH 095/127] Update client.cpp fixed bug with BEGIN_GENERAL to MainCursor being skipped before since it was starting at GENERAL_BAGS_BEGIN --- zone/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/client.cpp b/zone/client.cpp index 1aabccce8..d99e44199 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -7924,7 +7924,7 @@ void Client::ItemTimerCheck() TryItemTimer(i); } - for(i = EmuConstants::GENERAL_BAGS_BEGIN; i <= MainCursor; i++) + for(i = EmuConstants::GENERAL_BEGIN; i <= MainCursor; i++) { TryItemTimer(i); } From 616e13acac944aecd18bb2be172b283eead4dc19 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sun, 7 Sep 2014 03:43:34 -0400 Subject: [PATCH 096/127] Calc fix for spell power distance mod effect. --- zone/spell_effects.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index b10c436f2..20bef74aa 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -202,7 +202,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) effect_value = GetMaxHP(); if (GetSpellPowerDistanceMod()) - effect_value = effect_value*(GetSpellPowerDistanceMod()/100); + effect_value = effect_value*GetSpellPowerDistanceMod()/100; #ifdef SPELL_EFFECT_SPAM effect_desc[0] = 0; From b392d1680892d90fe83c85ed2319f1e724f622d6 Mon Sep 17 00:00:00 2001 From: akkadius Date: Sun, 7 Sep 2014 05:43:37 -0500 Subject: [PATCH 097/127] Fixed ROF Augment item dupe with not checking for available slots properly and adding items to the virtual instance --- changelog.txt | 3 +++ common/item.cpp | 10 ++++++++++ common/item.h | 1 + zone/client_packet.cpp | 8 ++++---- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/changelog.txt b/changelog.txt index 23640f7e5..233f26b5e 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 09/07/2014 == +Akkadius: Fixed ROF Augment item dupe with not checking for available slots properly and adding items to the virtual instance + == 09/06/2014 == Uleat: Tweaked 'Smart' trading code to return main slots before sub slots in stackable and free space search processes. (If enough people ask for it, I'll add an optional rule to allow 'bag packing' - the original implementation behavior) diff --git a/common/item.cpp b/common/item.cpp index 127f85614..513ddb23f 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -1580,6 +1580,16 @@ int8 ItemInst::AvailableAugmentSlot(int32 augtype) const return (i < EmuConstants::ITEM_COMMON_SIZE) ? i : INVALID_INDEX; } +bool ItemInst::IsAugmentSlotAvailable(int32 augtype, uint8 slot) const { + if (m_item->ItemClass != ItemClassCommon || !m_item) + return false; + + if ((!GetItem(slot) && m_item->AugSlotVisible[slot]) && augtype == -1 || (m_item->AugSlotType[slot] && ((1 << (m_item->AugSlotType[slot] - 1)) & augtype))) { + return true; + } + return false; +} + // Retrieve item inside container ItemInst* ItemInst::GetItem(uint8 index) const { diff --git a/common/item.h b/common/item.h index f279bd2aa..c24c708b1 100644 --- a/common/item.h +++ b/common/item.h @@ -274,6 +274,7 @@ public: inline bool IsAugmentable() const { return m_item->AugSlotType[0]!=0 || m_item->AugSlotType[1]!=0 || m_item->AugSlotType[2]!=0 || m_item->AugSlotType[3]!=0 || m_item->AugSlotType[4]!=0; } bool AvailableWearSlot(uint32 aug_wear_slots) const; int8 AvailableAugmentSlot(int32 augtype) const; + bool IsAugmentSlotAvailable(int32 augtype, uint8 slot) const; inline int32 GetAugmentType() const { return m_item->AugType; } inline bool IsExpendable() const { return ((m_item->Click.Type == ET_Expendable ) || (m_item->ItemType == ItemTypePotion)); } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index fc77e0c82..9d7c9e01d 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -6307,12 +6307,12 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) tobe_auged = user_inv.GetItem(slot_id); auged_with = user_inv.GetItem(MainCursor); - if(tobe_auged && auged_with) + if (tobe_auged && auged_with) { - if (((slot=tobe_auged->AvailableAugmentSlot(auged_with->GetAugmentType()))!=-1) && + if (((tobe_auged->IsAugmentSlotAvailable(auged_with->GetAugmentType(), in_augment->augment_index)) != -1) && (tobe_auged->AvailableWearSlot(auged_with->GetItem()->Slots))) { - tobe_auged->PutAugment(slot, *auged_with); + tobe_auged->PutAugment(in_augment->augment_index, *auged_with); ItemInst *aug = tobe_auged->GetAugment(in_augment->augment_index); if(aug) { @@ -6325,7 +6325,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) } else { - Message(13, "Error: Could not find augmentation at index %i. Aborting."); + Message(13, "Error: Could not find augmentation at index %i. Aborting.", in_augment->augment_index); return; } From a3b54e5cae0a7bbf820cc656be03bc08322a41fd Mon Sep 17 00:00:00 2001 From: KimLS Date: Sun, 7 Sep 2014 22:41:42 -0700 Subject: [PATCH 098/127] Fix for forage crash --- common/database.cpp | 2 +- zone/forage.cpp | 16 ++++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index d1845b82e..88f01a676 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -319,7 +319,7 @@ bool Database::DeleteAccount(const char* name) { } bool Database::SetLocalPassword(uint32 accid, const char* password) { - std::string query = StringFormat("UPDATE account SET password=MD5('%s') where id=%i;", password, accid); + std::string query = StringFormat("UPDATE account SET password=MD5('%s') where id=%i;", EscapeString(password).c_str(), accid); auto results = QueryDatabase(query); diff --git a/zone/forage.cpp b/zone/forage.cpp index 4a39d508d..d1008031a 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -356,9 +356,11 @@ void Client::GoFish() inst = m_inv.GetItem(MainCursor); } - std::vector args; - args.push_back(inst); - parse->EventPlayer(EVENT_FISH_SUCCESS, this, "", inst->GetID(), &args); + if(inst) { + std::vector args; + args.push_back(inst); + parse->EventPlayer(EVENT_FISH_SUCCESS, this, "", inst->GetID(), &args); + } } } else @@ -470,9 +472,11 @@ void Client::ForageItem(bool guarantee) { inst = m_inv.GetItem(MainCursor); } - std::vector args; - args.push_back(inst); - parse->EventPlayer(EVENT_FORAGE_SUCCESS, this, "", inst->GetID(), &args); + if(inst) { + std::vector args; + args.push_back(inst); + parse->EventPlayer(EVENT_FORAGE_SUCCESS, this, "", inst->GetID(), &args); + } } int ChanceSecondForage = aabonuses.ForageAdditionalItems + itembonuses.ForageAdditionalItems + spellbonuses.ForageAdditionalItems; From 579294fbf0ef375e5eb84d746bd01228aff34459 Mon Sep 17 00:00:00 2001 From: KimLS Date: Mon, 8 Sep 2014 03:04:22 -0700 Subject: [PATCH 099/127] Fixed many bugs with partial resist calculations, targets with higher resist should have a more natural curve when it comes to resisting spells --- zone/spells.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 357fafbd4..b54b0b66c 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -4501,13 +4501,12 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use } else { - resist_chance -= roll; if(resist_chance < 1) { resist_chance = 1; } - int partial_modifier = ((150 * (roll - resist_chance)) / resist_chance); + int partial_modifier = ((150 * (resist_chance - roll)) / resist_chance); if(IsNPC()) { @@ -4535,17 +4534,16 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use } } - if(partial_modifier < 0) + if(partial_modifier <= 0) + { + return 100; + } + else if(partial_modifier >= 100) { return 0; } - if(partial_modifier > 100) - { - return 100; - } - - return partial_modifier; + return (100.0f - partial_modifier); } } } From 7f7f99cbe39d1284150fb315ba164f55d70bbff2 Mon Sep 17 00:00:00 2001 From: KimLS Date: Mon, 8 Sep 2014 16:45:20 -0700 Subject: [PATCH 100/127] BestZ will now adjust for model size when used to adjust movement z --- common/ruletypes.h | 4 ---- zone/waypoints.cpp | 6 ++++++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index 73d538f8a..c61590ac4 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -212,10 +212,6 @@ RULE_REAL ( Map, FixPathingZMaxDeltaMoving, 20 ) //at runtime while pathing: max RULE_REAL ( Map, FixPathingZMaxDeltaWaypoint, 20 ) //at runtime at each waypoint: max change in Z to allow the BestZ code to apply. RULE_REAL ( Map, FixPathingZMaxDeltaSendTo, 20 ) //at runtime in SendTo: max change in Z to allow the BestZ code to apply. RULE_REAL ( Map, FixPathingZMaxDeltaLoading, 45 ) //while loading each waypoint: max change in Z to allow the BestZ code to apply. -RULE_BOOL ( Map, UseClosestZ, false) // Move mobs to the nearest Z above or below, rather than just the nearest below. - // Only set UseClosestZ true if all your .map files generated from EQGs were created - // with azone2. - // RULE_INT ( Map, FindBestZHeightAdjust, 1) // Adds this to the current Z before seeking the best Z position RULE_CATEGORY_END() diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 580b9c51c..f1a3dce18 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -568,6 +568,8 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, b Map::Vertex dest(x_pos, y_pos, z_pos); float newz = zone->zonemap->FindBestZ(dest, nullptr); + float sz = GetSize(); + newz += sz >= 0.0f ? sz / 2.0f : 0.0f; mlog(AI__WAYPOINTS, "BestZ returned %4.3f at %4.3f, %4.3f, %4.3f", newz,x_pos,y_pos,z_pos); @@ -697,6 +699,8 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, b Map::Vertex dest(x_pos, y_pos, z_pos); float newz = zone->zonemap->FindBestZ(dest, nullptr); + float sz = GetSize(); + newz += sz >= 0.0f ? sz / 2.0f : 0.0f; mlog(AI__WAYPOINTS, "BestZ returned %4.3f at %4.3f, %4.3f, %4.3f", newz,x_pos,y_pos,z_pos); @@ -822,6 +826,8 @@ bool Mob::CalculateNewPosition(float x, float y, float z, float speed, bool chec Map::Vertex dest(x_pos, y_pos, z_pos); float newz = zone->zonemap->FindBestZ(dest, nullptr); + float sz = GetSize(); + newz += sz >= 0.0f ? sz / 2.0f : 0.0f; mlog(AI__WAYPOINTS, "BestZ returned %4.3f at %4.3f, %4.3f, %4.3f", newz,x_pos,y_pos,z_pos); From 80242bd2505460f292251985a960e4d0fbe9d1d5 Mon Sep 17 00:00:00 2001 From: KimLS Date: Mon, 8 Sep 2014 17:02:37 -0700 Subject: [PATCH 101/127] Strange crash hack/workaround that occured on peq --- zone/groups.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/zone/groups.cpp b/zone/groups.cpp index 5c34cf359..c73b8f093 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -561,6 +561,18 @@ bool Group::DelMember(Mob* oldmember,bool ignoresender) } } + /* This may seem pointless but the case above does not cover the following situation: + * Group has Leader a, member b, member c + * b and c are out of zone + * a disconnects/quits + * b or c zone back in and disconnects/quits + * a is still "leader" from GetLeader()'s perspective and will crash the zone when we DelMember(b) + * Ultimately we should think up a better solution to this. + */ + if(oldmember == GetLeader()) { + SetLeader(nullptr); + } + ServerPacket* pack = new ServerPacket(ServerOP_GroupLeave, sizeof(ServerGroupLeave_Struct)); ServerGroupLeave_Struct* gl = (ServerGroupLeave_Struct*)pack->pBuffer; gl->gid = GetID(); From 506b3ca4a0d65ef325361dcb48561eba51b1a955 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 8 Sep 2014 21:43:25 -0400 Subject: [PATCH 102/127] Fix slow calculation Full details: http://www.eqemulator.org/forums/showthread.php?t=38734 --- changelog.txt | 4 ++++ zone/mob.cpp | 6 ++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/changelog.txt b/changelog.txt index 233f26b5e..f61ed4255 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 09/08/2014 == +demonstar55: Fix slow calc + see: http://www.eqemulator.org/forums/showthread.php?t=38734 + == 09/07/2014 == Akkadius: Fixed ROF Augment item dupe with not checking for available slots properly and adding items to the virtual instance diff --git a/zone/mob.cpp b/zone/mob.cpp index e3a23efc6..2b38e4714 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1941,10 +1941,8 @@ void Mob::Kill() { void Mob::SetAttackTimer() { float PermaHaste; - if(GetHaste() > 0) - PermaHaste = 1 / (1 + (float)GetHaste()/100); - else if(GetHaste() < 0) - PermaHaste = 1 * (1 - (float)GetHaste()/100); + if (GetHaste()) + PermaHaste = 1 / (1 + (float)GetHaste() / 100); else PermaHaste = 1.0f; From f16beddf6e1b82cac0151a5794eb26c95fae253d Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 9 Sep 2014 15:32:02 -0400 Subject: [PATCH 103/127] Increase NPC bash/kick delay by 3 (8 total by default) --- changelog.txt | 4 ++++ zone/special_attacks.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/changelog.txt b/changelog.txt index f61ed4255..1e3dc3638 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 09/09/2014 == +demonstar55: Incrase Mob kick/bash timer by 3 + see: http://www.eqemulator.org/forums/showthread.php?t=38734 + == 09/08/2014 == demonstar55: Fix slow calc see: http://www.eqemulator.org/forums/showthread.php?t=38734 diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 0431eb9b1..470bec07c 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -1464,7 +1464,7 @@ void NPC::DoClassAttacks(Mob *target) { } } - reuse = KickReuseTime * 1000; + reuse = (KickReuseTime + 3) * 1000; DoSpecialAttackDamage(target, SkillKick, dmg, 1, -1, reuse); did_attack = true; } @@ -1484,7 +1484,7 @@ void NPC::DoClassAttacks(Mob *target) { } } - reuse = BashReuseTime * 1000; + reuse = (BashReuseTime + 3) * 1000; DoSpecialAttackDamage(target, SkillBash, dmg, 1, -1, reuse); did_attack = true; } @@ -1537,7 +1537,7 @@ void NPC::DoClassAttacks(Mob *target) { } } - reuse = KickReuseTime * 1000; + reuse = (KickReuseTime + 3) * 1000; DoSpecialAttackDamage(target, SkillKick, dmg, 1, -1, reuse); did_attack = true; } @@ -1562,7 +1562,7 @@ void NPC::DoClassAttacks(Mob *target) { } } - reuse = BashReuseTime * 1000; + reuse = (BashReuseTime + 3) * 1000; DoSpecialAttackDamage(target, SkillBash, dmg, 1, -1, reuse); did_attack = true; } From 6c3d5c713c39e5458a913c9d16c8670f2cd61dc2 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 9 Sep 2014 15:34:30 -0400 Subject: [PATCH 104/127] Fix slow effect on NPC special attack reuse timers --- changelog.txt | 2 ++ zone/special_attacks.cpp | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/changelog.txt b/changelog.txt index 1e3dc3638..5a8442a7b 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,6 +3,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) == 09/09/2014 == demonstar55: Incrase Mob kick/bash timer by 3 see: http://www.eqemulator.org/forums/showthread.php?t=38734 +demonstar55: Fix slow effect on NPC special attack reuse timers + see: http://www.eqemulator.org/forums/showthread.php?t=38734 == 09/08/2014 == demonstar55: Fix slow calc diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 470bec07c..904dc41b3 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -1413,10 +1413,8 @@ void NPC::DoClassAttacks(Mob *target) { return; float HasteModifier = 0; - if(GetHaste() > 0) + if (GetHaste()) HasteModifier = 10000 / (100 + GetHaste()); - else if(GetHaste() < 0) - HasteModifier = (100 - GetHaste()); else HasteModifier = 100; From 2fa31799f655e5b827cd170df3ae1fcc97a854eb Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 9 Sep 2014 17:02:05 -0400 Subject: [PATCH 105/127] Port slow fixes to bots --- changelog.txt | 1 + zone/bot.cpp | 12 ++++-------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/changelog.txt b/changelog.txt index 5a8442a7b..649e3968f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -5,6 +5,7 @@ demonstar55: Incrase Mob kick/bash timer by 3 see: http://www.eqemulator.org/forums/showthread.php?t=38734 demonstar55: Fix slow effect on NPC special attack reuse timers see: http://www.eqemulator.org/forums/showthread.php?t=38734 +demonstar55: Slow fixes to bots! == 09/08/2014 == demonstar55: Fix slow calc diff --git a/zone/bot.cpp b/zone/bot.cpp index 9d7dc508f..d001a0b88 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -8350,12 +8350,10 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { return; float HasteModifier = 0; - if(GetHaste() >= 0){ + if (GetHaste()) HasteModifier = 10000 / (100 + GetHaste()); - } - else { - HasteModifier = (100 - GetHaste()); - } + else + HasteModifier = 100; int32 dmg = 0; uint16 skill_to_use = -1; @@ -8981,10 +8979,8 @@ int32 Bot::CalcMaxMana() { void Bot::SetAttackTimer() { float PermaHaste; - if(GetHaste() > 0) + if (GetHaste()) PermaHaste = 1 / (1 + (float)GetHaste()/100); - else if(GetHaste() < 0) - PermaHaste = 1 * (1 - (float)GetHaste()/100); else PermaHaste = 1.0f; From fa1e33783a70bd649b7e8339aceb696695103fa9 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 9 Sep 2014 22:13:30 -0400 Subject: [PATCH 106/127] Split Mob::SetAttackTimer into Client and NPC methods This was the easiest way to NPCs delay settings to be sane in the database. The functions are cleaner since there is no specific logic to change behavior depending on if they're a client or not. --- zone/attack.cpp | 142 +++++++++++++++++++++++++++++++++++++++++++++ zone/client.cpp | 16 +++++ zone/client.h | 8 ++- zone/mob.cpp | 151 ------------------------------------------------ zone/mob.h | 1 + zone/npc.h | 16 ++--- 6 files changed, 172 insertions(+), 162 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 5abba347b..e4aa80225 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -4803,3 +4803,145 @@ void Mob::CommonBreakInvisible() hidden = false; improved_hidden = false; } + +void Mob::SetAttackTimer() +{ + attack_timer.SetAtTrigger(4000, true); +} + +void Client::SetAttackTimer() +{ + float PermaHaste = GetPermaHaste() * 100.0f; + + //default value for attack timer in case they have + //an invalid weapon equipped: + attack_timer.SetAtTrigger(4000, true); + + Timer *TimerToUse = nullptr; + const Item_Struct *PrimaryWeapon = nullptr; + + for (int i = MainRange; i <= MainSecondary; i++) { + //pick a timer + if (i == MainPrimary) + TimerToUse = &attack_timer; + else if (i == MainRange) + TimerToUse = &ranged_timer; + else if (i == MainSecondary) + TimerToUse = &attack_dw_timer; + else //invalid slot (hands will always hit this) + continue; + + const Item_Struct *ItemToUse = nullptr; + + //find our item + ItemInst *ci = GetInv().GetItem(i); + if (ci) + ItemToUse = ci->GetItem(); + + //special offhand stuff + if (i == MainSecondary) { + //if we have a 2H weapon in our main hand, no dual + if (PrimaryWeapon != nullptr) { + if (PrimaryWeapon->ItemClass == ItemClassCommon + && (PrimaryWeapon->ItemType == ItemType2HSlash + || PrimaryWeapon->ItemType == ItemType2HBlunt + || PrimaryWeapon->ItemType == ItemType2HPiercing)) { + attack_dw_timer.Disable(); + continue; + } + } + + //if we cant dual wield, skip it + if (!CanThisClassDualWield()) { + attack_dw_timer.Disable(); + continue; + } + } + + //see if we have a valid weapon + if (ItemToUse != nullptr) { + //check type and damage/delay + if (ItemToUse->ItemClass != ItemClassCommon + || ItemToUse->Damage == 0 + || ItemToUse->Delay == 0) { + //no weapon + ItemToUse = nullptr; + } + // Check to see if skill is valid + else if ((ItemToUse->ItemType > ItemTypeLargeThrowing) && + (ItemToUse->ItemType != ItemTypeMartial) && + (ItemToUse->ItemType != ItemType2HPiercing)) { + //no weapon + ItemToUse = nullptr; + } + } + + int16 DelayMod = std::max(itembonuses.HundredHands + spellbonuses.HundredHands, -99); + int speed = 0; + + //if we have no weapon.. + if (ItemToUse == nullptr) { + //above checks ensure ranged weapons do not fall into here + // Work out if we're a monk + if ((GetClass() == MONK) || (GetClass() == BEASTLORD)) + speed = static_cast((GetMonkHandToHandDelay() * (100 + DelayMod) / 100) * PermaHaste); + else + speed = static_cast((36 * (100 + DelayMod) / 100) * PermaHaste); + } else { + //we have a weapon, use its delay + // Convert weapon delay to timer resolution (milliseconds) + //delay * 100 + speed = static_cast((ItemToUse->Delay * (100 + DelayMod) / 100) * PermaHaste); + if (ItemToUse->ItemType == ItemTypeBow || ItemToUse->ItemType == ItemTypeLargeThrowing) { + float quiver_haste = GetQuiverHaste(); + if (quiver_haste > 0) + speed *= quiver_haste; + } + } + TimerToUse->SetAtTrigger(std::max(RuleI(Combat, MinHastedDelay), speed), true); + + if (i == MainPrimary) + PrimaryWeapon = ItemToUse; + } +} + +void NPC::SetAttackTimer() +{ + float PermaHaste = GetPermaHaste(); + + //default value for attack timer in case they have + //an invalid weapon equipped: + attack_timer.SetAtTrigger(4000, true); + + Timer *TimerToUse = nullptr; + + for (int i = MainRange; i <= MainSecondary; i++) { + //pick a timer + if (i == MainPrimary) + TimerToUse = &attack_timer; + else if (i == MainRange) + TimerToUse = &ranged_timer; + else if (i == MainSecondary) + TimerToUse = &attack_dw_timer; + else //invalid slot (hands will always hit this) + continue; + + //special offhand stuff + if (i == MainSecondary) { + //NPCs get it for free at 13 + if(GetLevel() < 13) { + attack_dw_timer.Disable(); + continue; + } + } + + int16 DelayMod = std::max(itembonuses.HundredHands + spellbonuses.HundredHands, -99); + + // Technically NPCs should do some logic for weapons, but the effect is minimal + // What they do is take the lower of their set delay and the weapon's + // ex. Mob's delay set to 20, weapon set to 19, delay 19 + // Mob's delay set to 20, weapon set to 21, delay 20 + int speed = static_cast((36 * (100 + DelayMod) / 100) * (100.0f + attack_speed) * PermaHaste); + TimerToUse->SetAtTrigger(std::max(RuleI(Combat, MinHastedDelay), speed), true); + } +} diff --git a/zone/client.cpp b/zone/client.cpp index 8340dde9f..90f26ff18 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -8346,3 +8346,19 @@ void Client::ShowNumHits() return; } +float Client::GetQuiverHaste() +{ + float quiver_haste = 0; + for (int r = EmuConstants::GENERAL_BEGIN; r <= EmuConstants::GENERAL_END; r++) { + const ItemInst *pi = GetInv().GetItem(r); + if (!pi) + continue; + if (pi->IsType(ItemClassContainer) && pi->GetItem()->BagType == BagTypeQuiver) { + float temp_wr = (pi->GetItem()->BagWR / RuleI(Combat, QuiverWRHasteDiv)); + quiver_haste = std::max(temp_wr, quiver_haste); + } + } + if (quiver_haste > 0) + quiver_haste = 1.0f / (1.0f + static_cast(quiver_haste) / 100.0f); + return quiver_haste; +} diff --git a/zone/client.h b/zone/client.h index 9d6de336a..697e4e2d3 100644 --- a/zone/client.h +++ b/zone/client.h @@ -222,6 +222,8 @@ public: virtual Group* GetGroup() { return entity_list.GetGroupByClient(this); } virtual inline bool IsBerserk() { return berserk; } virtual int32 GetMeleeMitDmg(Mob *attacker, int32 damage, int32 minhit, float mit_rating, float atk_rating); + virtual void SetAttackTimer(); + float GetQuiverHaste(); void AI_Init(); void AI_Start(uint32 iMoveDelay = 0); @@ -1194,9 +1196,9 @@ public: int32 mod_client_xp(int32 in_exp, NPC *npc); uint32 mod_client_xp_for_level(uint32 xp, uint16 check_level); int mod_client_haste_cap(int cap); - int mod_consume(Item_Struct *item, ItemUseTypes type, int change); - int mod_food_value(const Item_Struct *item, int change); - int mod_drink_value(const Item_Struct *item, int change); + int mod_consume(Item_Struct *item, ItemUseTypes type, int change); + int mod_food_value(const Item_Struct *item, int change); + int mod_drink_value(const Item_Struct *item, int change); void SetEngagedRaidTarget(bool value) { EngagedRaidTarget = value; } bool GetEngagedRaidTarget() const { return EngagedRaidTarget; } diff --git a/zone/mob.cpp b/zone/mob.cpp index 2b38e4714..73c3ec068 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1939,157 +1939,6 @@ void Mob::Kill() { Death(this, 0, SPELL_UNKNOWN, SkillHandtoHand); } -void Mob::SetAttackTimer() { - float PermaHaste; - if (GetHaste()) - PermaHaste = 1 / (1 + (float)GetHaste() / 100); - else - PermaHaste = 1.0f; - - //default value for attack timer in case they have - //an invalid weapon equipped: - attack_timer.SetAtTrigger(4000, true); - - Timer* TimerToUse = nullptr; - const Item_Struct* PrimaryWeapon = nullptr; - - for (int i=MainRange; i<=MainSecondary; i++) { - - //pick a timer - if (i == MainPrimary) - TimerToUse = &attack_timer; - else if (i == MainRange) - TimerToUse = &ranged_timer; - else if(i == MainSecondary) - TimerToUse = &attack_dw_timer; - else //invalid slot (hands will always hit this) - continue; - - const Item_Struct* ItemToUse = nullptr; - - //find our item - if (IsClient()) { - ItemInst* ci = CastToClient()->GetInv().GetItem(i); - if (ci) - ItemToUse = ci->GetItem(); - } else if(IsNPC()) - { - //The code before here was fundementally flawed because equipment[] - //isn't the same as PC inventory and also: - //NPCs don't use weapon speed to dictate how fast they hit anyway. - ItemToUse = nullptr; - } - - //special offhand stuff - if(i == MainSecondary) { - //if we have a 2H weapon in our main hand, no dual - if(PrimaryWeapon != nullptr) { - if( PrimaryWeapon->ItemClass == ItemClassCommon - && (PrimaryWeapon->ItemType == ItemType2HSlash - || PrimaryWeapon->ItemType == ItemType2HBlunt - || PrimaryWeapon->ItemType == ItemType2HPiercing)) { - attack_dw_timer.Disable(); - continue; - } - } - - //clients must have the skill to use it... - if(IsClient()) { - //if we cant dual wield, skip it - if (!CanThisClassDualWield()) { - attack_dw_timer.Disable(); - continue; - } - } else { - //NPCs get it for free at 13 - if(GetLevel() < 13) { - attack_dw_timer.Disable(); - continue; - } - } - } - - //see if we have a valid weapon - if(ItemToUse != nullptr) { - //check type and damage/delay - if(ItemToUse->ItemClass != ItemClassCommon - || ItemToUse->Damage == 0 - || ItemToUse->Delay == 0) { - //no weapon - ItemToUse = nullptr; - } - // Check to see if skill is valid - else if((ItemToUse->ItemType > ItemTypeLargeThrowing) && (ItemToUse->ItemType != ItemTypeMartial) && (ItemToUse->ItemType != ItemType2HPiercing)) { - //no weapon - ItemToUse = nullptr; - } - } - - int16 DelayMod = itembonuses.HundredHands + spellbonuses.HundredHands; - if (DelayMod < -99) - DelayMod = -99; - - //if we have no weapon.. - if (ItemToUse == nullptr) { - //above checks ensure ranged weapons do not fall into here - // Work out if we're a monk - if ((GetClass() == MONK) || (GetClass() == BEASTLORD)) { - //we are a monk, use special delay - int speed = (int)( (GetMonkHandToHandDelay()*(100+DelayMod)/100)*(100.0f+attack_speed)*PermaHaste); - // 1200 seemed too much, with delay 10 weapons available - if(speed < RuleI(Combat, MinHastedDelay)) //lower bound - speed = RuleI(Combat, MinHastedDelay); - TimerToUse->SetAtTrigger(speed, true); // Hand to hand, delay based on level or epic - } else { - //not a monk... using fist, regular delay - int speed = (int)((36 *(100+DelayMod)/100)*(100.0f+attack_speed)*PermaHaste); - if(speed < RuleI(Combat, MinHastedDelay) && IsClient()) //lower bound - speed = RuleI(Combat, MinHastedDelay); - TimerToUse->SetAtTrigger(speed, true); // Hand to hand, non-monk 2/36 - } - } else { - //we have a weapon, use its delay - // Convert weapon delay to timer resolution (milliseconds) - //delay * 100 - int speed = (int)((ItemToUse->Delay*(100+DelayMod)/100)*(100.0f+attack_speed)*PermaHaste); - if(speed < RuleI(Combat, MinHastedDelay)) - speed = RuleI(Combat, MinHastedDelay); - - if(ItemToUse && (ItemToUse->ItemType == ItemTypeBow || ItemToUse->ItemType == ItemTypeLargeThrowing)) - { - if(IsClient()) - { - float max_quiver = 0; - for(int r = EmuConstants::GENERAL_BEGIN; r <= EmuConstants::GENERAL_END; r++) - { - const ItemInst *pi = CastToClient()->GetInv().GetItem(r); - if(!pi) - continue; - if(pi->IsType(ItemClassContainer) && pi->GetItem()->BagType == BagTypeQuiver) - { - float temp_wr = ( pi->GetItem()->BagWR / RuleI(Combat, QuiverWRHasteDiv) ); - if(temp_wr > max_quiver) - { - max_quiver = temp_wr; - } - } - } - if(max_quiver > 0) - { - float quiver_haste = 1 / (1 + max_quiver / 100); - speed *= quiver_haste; - } - } - } - TimerToUse->SetAtTrigger(speed, true); - } - - if(i == MainPrimary) - PrimaryWeapon = ItemToUse; - } - -} - bool Mob::CanThisClassDualWield(void) const { if(!IsClient()) { return(GetSkill(SkillDualWield) > 0); diff --git a/zone/mob.h b/zone/mob.h index 028f0497f..16c45ce1f 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -684,6 +684,7 @@ public: inline bool GetInvul(void) { return invulnerable; } inline void SetExtraHaste(int Haste) { ExtraHaste = Haste; } virtual int GetHaste(); + inline float GetPermaHaste() { return GetHaste() ? 1.0f / (1.0f + static_cast(GetHaste()) / 100.0f) : 1.0f; } uint8 GetWeaponDamageBonus(const Item_Struct* Weapon); uint16 GetDamageTable(SkillUseTypes skillinuse); diff --git a/zone/npc.h b/zone/npc.h index 5b28260d4..b23522bee 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -134,7 +134,6 @@ public: void CalcNPCRegen(); void CalcNPCDamage(); - int32 GetActSpellDamage(uint16 spell_id, int32 value, Mob* target = nullptr); int32 GetActSpellHealing(uint16 spell_id, int32 value, Mob* target = nullptr); inline void SetSpellFocusDMG(int32 NewSpellFocusDMG) {SpellFocusDMG = NewSpellFocusDMG;} @@ -158,6 +157,7 @@ public: virtual void InitializeBuffSlots(); virtual void UninitializeBuffSlots(); + virtual void SetAttackTimer(); virtual void RangedAttack(Mob* other); virtual void ThrowingAttack(Mob* other) { } int32 GetNumberOfAttacks() const { return attack_count; } @@ -388,16 +388,16 @@ public: inline void SetHealScale(float amt) { healscale = amt; } inline float GetHealScale() { return healscale; } - uint32 GetSpawnKillCount(); - int GetScore(); - void SetMerchantProbability(uint8 amt) { probability = amt; } + uint32 GetSpawnKillCount(); + int GetScore(); + void SetMerchantProbability(uint8 amt) { probability = amt; } uint8 GetMerchantProbability() { return probability; } - void mod_prespawn(Spawn2 *sp); - int mod_npc_damage(int damage, SkillUseTypes skillinuse, int hand, const Item_Struct* weapon, Mob* other); + void mod_prespawn(Spawn2 *sp); + int mod_npc_damage(int damage, SkillUseTypes skillinuse, int hand, const Item_Struct* weapon, Mob* other); void mod_npc_killed_merit(Mob* c); void mod_npc_killed(Mob* oos); - void AISpellsList(Client *c); - + void AISpellsList(Client *c); + bool IsRaidTarget() const { return raid_target; }; protected: From ed4e762f03b704eb07e8371dcca41500e9e4482f Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 9 Sep 2014 22:42:54 -0400 Subject: [PATCH 107/127] Change NPCs to have their attack delay set in DB This gives us a much more straight forward way of setting mob attack delay with respect to live. The attack_delay column is in 10ths of seconds, just like weapons are The attack_speed is left for references for now. --- utils/sql/git/required/2014_09_09_attack_delay.sql | 3 +++ zone/attack.cpp | 4 ++-- zone/mob.cpp | 5 +++-- zone/mob.h | 1 + zone/npc.cpp | 1 + zone/zonedb.cpp | 4 +++- zone/zonedump.h | 1 + 7 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 utils/sql/git/required/2014_09_09_attack_delay.sql diff --git a/utils/sql/git/required/2014_09_09_attack_delay.sql b/utils/sql/git/required/2014_09_09_attack_delay.sql new file mode 100644 index 000000000..87efa043a --- /dev/null +++ b/utils/sql/git/required/2014_09_09_attack_delay.sql @@ -0,0 +1,3 @@ +ALTER TABLE `npc_types` ADD `attack_delay` TINYINT(3) UNSIGNED DEFAULT '30' NOT NULL AFTER `attack_speed`; +UPDATE `npc_types` SET `attack_delay` = 36 + 36 * (`attack_speed` / 100); +UPDATE `npc_types` SET `attack_delay` = 30 WHERE `attack_speed` = 0; diff --git a/zone/attack.cpp b/zone/attack.cpp index e4aa80225..a694351cb 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -4907,7 +4907,7 @@ void Client::SetAttackTimer() void NPC::SetAttackTimer() { - float PermaHaste = GetPermaHaste(); + float PermaHaste = GetPermaHaste() * 100.0f; //default value for attack timer in case they have //an invalid weapon equipped: @@ -4941,7 +4941,7 @@ void NPC::SetAttackTimer() // What they do is take the lower of their set delay and the weapon's // ex. Mob's delay set to 20, weapon set to 19, delay 19 // Mob's delay set to 20, weapon set to 21, delay 20 - int speed = static_cast((36 * (100 + DelayMod) / 100) * (100.0f + attack_speed) * PermaHaste); + int speed = static_cast((attack_delay * (100 + DelayMod) / 100) * PermaHaste); TimerToUse->SetAtTrigger(std::max(RuleI(Combat, MinHastedDelay), speed), true); } } diff --git a/zone/mob.cpp b/zone/mob.cpp index 73c3ec068..fdce628c4 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -174,8 +174,9 @@ Mob::Mob(const char* in_name, drakkin_heritage = in_drakkin_heritage; drakkin_tattoo = in_drakkin_tattoo; drakkin_details = in_drakkin_details; - attack_speed= 0; - slow_mitigation= 0; + attack_speed = 0; + attack_delay = 0; + slow_mitigation = 0; findable = false; trackable = true; has_shieldequiped = false; diff --git a/zone/mob.h b/zone/mob.h index 16c45ce1f..b1c40c72f 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -1053,6 +1053,7 @@ protected: Timer attack_dw_timer; Timer ranged_timer; float attack_speed; //% increase/decrease in attack speed (not haste) + int8 attack_delay; //delay between attacks in 10ths of seconds float slow_mitigation; // Allows for a slow mitigation (100 = 100%, 50% = 50%) Timer tic_timer; Timer mana_timer; diff --git a/zone/npc.cpp b/zone/npc.cpp index 151852a2b..8804c488b 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -248,6 +248,7 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, float x, float y, float z, float delaytimer = false; combat_event = false; attack_speed = d->attack_speed; + attack_delay = d->attack_delay; slow_mitigation = d->slow_mitigation; EntityList::RemoveNumbers(name); diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 787e3a94e..9bf5cb9d3 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1045,6 +1045,7 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { "npc_types.adventure_template_id," "npc_types.trap_template," "npc_types.attack_speed," + "npc_types.attack_delay," "npc_types.STR," "npc_types.STA," "npc_types.DEX," @@ -1148,6 +1149,7 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { tmpNPCType->adventure_template = atoi(row[r++]); tmpNPCType->trap_template = atoi(row[r++]); tmpNPCType->attack_speed = atof(row[r++]); + tmpNPCType->attack_delay = atoi(row[r++]); tmpNPCType->STR = atoi(row[r++]); tmpNPCType->STA = atoi(row[r++]); tmpNPCType->DEX = atoi(row[r++]); @@ -3233,4 +3235,4 @@ void ZoneDatabase::StoreCharacterLookup(uint32 char_id) { " FROM `character_` " " WHERE `id` = %i ", char_id); QueryDatabase(c_lookup); -} \ No newline at end of file +} diff --git a/zone/zonedump.h b/zone/zonedump.h index 0d2bcb1d2..a96d276cd 100644 --- a/zone/zonedump.h +++ b/zone/zonedump.h @@ -111,6 +111,7 @@ struct NPCType uint8 spawn_limit; //only this many may be in zone at a time (0=no limit) uint8 mount_color; //only used by horse class float attack_speed; //%+- on attack delay of the mob. + uint8 attack_delay; //delay between attacks in 10ths of a second int accuracy_rating; //10 = 1% accuracy int avoidance_rating; //10 = 1% avoidance bool findable; //can be found with find command From 881f937a35b76412bcfc0c505941a56e8bcfc901 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 9 Sep 2014 22:50:50 -0400 Subject: [PATCH 108/127] Change scale of GetPermaHaste() --- zone/attack.cpp | 4 ++-- zone/mob.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index a694351cb..62d9f8de9 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -4811,7 +4811,7 @@ void Mob::SetAttackTimer() void Client::SetAttackTimer() { - float PermaHaste = GetPermaHaste() * 100.0f; + float PermaHaste = GetPermaHaste(); //default value for attack timer in case they have //an invalid weapon equipped: @@ -4907,7 +4907,7 @@ void Client::SetAttackTimer() void NPC::SetAttackTimer() { - float PermaHaste = GetPermaHaste() * 100.0f; + float PermaHaste = GetPermaHaste(); //default value for attack timer in case they have //an invalid weapon equipped: diff --git a/zone/mob.h b/zone/mob.h index b1c40c72f..1f1d257f9 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -684,7 +684,7 @@ public: inline bool GetInvul(void) { return invulnerable; } inline void SetExtraHaste(int Haste) { ExtraHaste = Haste; } virtual int GetHaste(); - inline float GetPermaHaste() { return GetHaste() ? 1.0f / (1.0f + static_cast(GetHaste()) / 100.0f) : 1.0f; } + inline float GetPermaHaste() { return GetHaste() ? 100.0f / (1.0f + static_cast(GetHaste()) / 100.0f) : 100.0f; } uint8 GetWeaponDamageBonus(const Item_Struct* Weapon); uint16 GetDamageTable(SkillUseTypes skillinuse); From ed4d954ba8237567aa812fe5e328538ebfbd0cf4 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 10 Sep 2014 00:05:00 -0400 Subject: [PATCH 109/127] Added attackdelay to #npcedit Also changelog! --- changelog.txt | 3 +++ zone/command.cpp | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/changelog.txt b/changelog.txt index 649e3968f..0b964c528 100644 --- a/changelog.txt +++ b/changelog.txt @@ -6,6 +6,9 @@ demonstar55: Incrase Mob kick/bash timer by 3 demonstar55: Fix slow effect on NPC special attack reuse timers see: http://www.eqemulator.org/forums/showthread.php?t=38734 demonstar55: Slow fixes to bots! +demonstar55: Revamped how NPC attack rate is set + SQL: 2014_09_09_attack_delay.sql +demonstar55: Added attackdelay to #npcedit == 09/08/2014 == demonstar55: Fix slow calc diff --git a/zone/command.cpp b/zone/command.cpp index aa7e13760..61ddf72d3 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -7159,6 +7159,15 @@ void command_npcedit(Client *c, const Seperator *sep) c->LogSQL(query); safe_delete_array(query); } + else if ( strcasecmp( sep->arg[1], "Attackdelay" ) == 0 ) + { + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + c->Message(15,"NPCID %u now has attack_delay set to %f",c->GetTarget()->CastToNPC()->GetNPCTypeID(),atof(sep->arg[2])); + database.RunQuery(query, MakeAnyLenString(&query, "update npc_types set attack_delay=%f where id=%i",atof(sep->argplus[2]),c->GetTarget()->CastToNPC()->GetNPCTypeID()), errbuf); + c->LogSQL(query); + safe_delete_array(query); + } else if ( strcasecmp( sep->arg[1], "findable" ) == 0 ) { char errbuf[MYSQL_ERRMSG_SIZE]; From 1420987c4c72e568e4326cd3867ff6bd66275f36 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 10 Sep 2014 00:07:16 -0400 Subject: [PATCH 110/127] Fix copy paste error --- zone/command.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/zone/command.cpp b/zone/command.cpp index 61ddf72d3..cf180f2bd 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -6658,6 +6658,7 @@ void command_npcedit(Client *c, const Seperator *sep) c->Message(0, "#npcedit qglobal - Sets an NPC's quest global flag"); c->Message(0, "#npcedit limit - Sets an NPC's spawn limit counter"); c->Message(0, "#npcedit Attackspeed - Sets an NPC's attack speed modifier"); + c->Message(0, "#npcedit Attackdelay - Sets an NPC's attack delay"); c->Message(0, "#npcedit findable - Sets an NPC's findable flag"); c->Message(0, "#npcedit wep1 - Sets an NPC's primary weapon model"); c->Message(0, "#npcedit wep2 - Sets an NPC's secondary weapon model"); @@ -7163,8 +7164,8 @@ void command_npcedit(Client *c, const Seperator *sep) { char errbuf[MYSQL_ERRMSG_SIZE]; char *query = 0; - c->Message(15,"NPCID %u now has attack_delay set to %f",c->GetTarget()->CastToNPC()->GetNPCTypeID(),atof(sep->arg[2])); - database.RunQuery(query, MakeAnyLenString(&query, "update npc_types set attack_delay=%f where id=%i",atof(sep->argplus[2]),c->GetTarget()->CastToNPC()->GetNPCTypeID()), errbuf); + c->Message(15,"NPCID %u now has attack_delay set to %i",c->GetTarget()->CastToNPC()->GetNPCTypeID(),atoi(sep->arg[2])); + database.RunQuery(query, MakeAnyLenString(&query, "update npc_types set attack_delay=%i where id=%i",atoi(sep->argplus[2]),c->GetTarget()->CastToNPC()->GetNPCTypeID()), errbuf); c->LogSQL(query); safe_delete_array(query); } From 9e243a2426738e1fbd801c49faa3b681ff3b2d94 Mon Sep 17 00:00:00 2001 From: KimLS Date: Wed, 10 Sep 2014 22:33:30 -0700 Subject: [PATCH 111/127] bestz will no longer scale off of model size, also it adjusts up less extremely in general. Fixed super duper attack speed on command spawned npcs --- zone/npc.cpp | 2 ++ zone/waypoints.cpp | 12 +++--------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/zone/npc.cpp b/zone/npc.cpp index 8804c488b..a4ecaec3a 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -936,6 +936,8 @@ NPC* NPC::SpawnNPC(const char* spawncommand, float in_x, float in_y, float in_z, npc_type->WIS = 150; npc_type->CHA = 150; + npc_type->attack_delay = 30; + npc_type->prim_melee_type = 28; npc_type->sec_melee_type = 28; diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index f1a3dce18..5f2b0899f 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -567,9 +567,7 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, b { Map::Vertex dest(x_pos, y_pos, z_pos); - float newz = zone->zonemap->FindBestZ(dest, nullptr); - float sz = GetSize(); - newz += sz >= 0.0f ? sz / 2.0f : 0.0f; + float newz = zone->zonemap->FindBestZ(dest, nullptr) + 2.0f; mlog(AI__WAYPOINTS, "BestZ returned %4.3f at %4.3f, %4.3f, %4.3f", newz,x_pos,y_pos,z_pos); @@ -698,9 +696,7 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, b { Map::Vertex dest(x_pos, y_pos, z_pos); - float newz = zone->zonemap->FindBestZ(dest, nullptr); - float sz = GetSize(); - newz += sz >= 0.0f ? sz / 2.0f : 0.0f; + float newz = zone->zonemap->FindBestZ(dest, nullptr); + 2.0f; mlog(AI__WAYPOINTS, "BestZ returned %4.3f at %4.3f, %4.3f, %4.3f", newz,x_pos,y_pos,z_pos); @@ -825,9 +821,7 @@ bool Mob::CalculateNewPosition(float x, float y, float z, float speed, bool chec { Map::Vertex dest(x_pos, y_pos, z_pos); - float newz = zone->zonemap->FindBestZ(dest, nullptr); - float sz = GetSize(); - newz += sz >= 0.0f ? sz / 2.0f : 0.0f; + float newz = zone->zonemap->FindBestZ(dest, nullptr) + 2.0f; mlog(AI__WAYPOINTS, "BestZ returned %4.3f at %4.3f, %4.3f, %4.3f", newz,x_pos,y_pos,z_pos); From c94ceb5b1db988b4eb0cb4b6055418028d470589 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 11 Sep 2014 16:55:58 -0400 Subject: [PATCH 112/127] Revert "LoadFactionValues_result converted to MySQLRequestResult" This reverts commit 2e847815943ec146d95983cb3282f8a03655a129. --- zone/zonedb.cpp | 8 ++++---- zone/zonedb.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index d9be0cad8..263e34a29 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -2350,11 +2350,11 @@ bool ZoneDatabase::LoadFactionValues(uint32 char_id, faction_map& val_list) { return LoadFactionValues_result(std::move(results), val_list); } -bool ZoneDatabase::LoadFactionValues_result(MySQLRequestResult results, faction_map & val_list) { - - for (auto row = results.begin(); row != results.begin(); ++row) +bool ZoneDatabase::LoadFactionValues_result(MYSQL_RES* result, faction_map & val_list) { + MYSQL_ROW row; + while((row = mysql_fetch_row(result))) { val_list[atoi(row[0])] = atoi(row[1]); - + } return true; } diff --git a/zone/zonedb.h b/zone/zonedb.h index 8755c4a92..78d09ba2a 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -303,7 +303,7 @@ public: bool SetCharacterFactionLevel(uint32 char_id, int32 faction_id, int32 value, uint8 temp, faction_map &val_list); // rembrant, needed for factions Dec, 16 2001 bool LoadFactionData(); bool LoadFactionValues(uint32 char_id, faction_map & val_list); - bool LoadFactionValues_result(MySQLRequestResult result, faction_map & val_list); + bool LoadFactionValues_result(MYSQL_RES* result, faction_map & val_list); /* * AAs From 6bc4ecf390f45c1d18ede826af0dd9cd0df9aac1 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 11 Sep 2014 16:56:15 -0400 Subject: [PATCH 113/127] Revert "LoadFactionValues converted to QueryDatabase" This reverts commit 2df823d2dbb96ac159f14243070834b5927b33d2. --- zone/zonedb.cpp | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 263e34a29..d789cbdeb 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -2336,18 +2336,21 @@ bool ZoneDatabase::GetFactionData(FactionMods* fm, uint32 class_mod, uint32 race return true; } -bool ZoneDatabase::LoadFactionValues(uint32 char_id, faction_map& val_list) { - - std::string query = StringFormat("SELECT faction_id,current_value " - "FROM faction_values " - "WHERE char_id = %i", char_id); - auto results = QueryDatabase(query); - if (!results.Success()) { - std::cerr << "Error in LoadFactionValues query '" << query << "' " << results.ErrorMessage() << std::endl; - return false; - } - - return LoadFactionValues_result(std::move(results), val_list); +bool ZoneDatabase::LoadFactionValues(uint32 char_id, faction_map & val_list) { + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + if (RunQuery(query, MakeAnyLenString(&query, "SELECT faction_id,current_value FROM faction_values WHERE char_id = %i",char_id), errbuf, &result)) { + safe_delete_array(query); + bool ret = LoadFactionValues_result(result, val_list); + mysql_free_result(result); + return ret; + } + else { + std::cerr << "Error in LoadFactionValues query '" << query << "' " << errbuf << std::endl; + safe_delete_array(query); + } + return false; } bool ZoneDatabase::LoadFactionValues_result(MYSQL_RES* result, faction_map & val_list) { From c6a7d5a96c31053376f1fa18ed97aff4a64fa932 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 11 Sep 2014 16:57:00 -0400 Subject: [PATCH 114/127] Revert "GetAccountInfoForLogin_result converted to MySQLRequestResult" This reverts commit 8369570b507242323badaf46613768d0231df1e3. Conflicts: zone/zonedb.h --- zone/zonedb.cpp | 57 +++++++++++++++++++++++-------------------------- zone/zonedb.h | 2 +- 2 files changed, 28 insertions(+), 31 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index d789cbdeb..93b910579 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -348,40 +348,37 @@ void ZoneDatabase::UpdateBug(PetitionBug_Struct* bug){ } -bool ZoneDatabase::GetAccountInfoForLogin_result(MySQLRequestResult results, int16* admin, char* account_name, uint32* lsaccountid, uint8* gmspeed, bool* revoked,bool* gmhideme, uint32* account_creation) { +bool ZoneDatabase::GetAccountInfoForLogin_result(MYSQL_RES* result, int16* admin, char* account_name, uint32* lsaccountid, uint8* gmspeed, bool* revoked,bool* gmhideme, uint32* account_creation) { + MYSQL_ROW row; + if (mysql_num_rows(result) == 1) { + row = mysql_fetch_row(result); + if (admin) + *admin = atoi(row[0]); + if (account_name) + strcpy(account_name, row[1]); + if (lsaccountid) { - if (results.RowCount() != 1) - return false; + if (row[2]) + *lsaccountid = atoi(row[2]); + else + *lsaccountid = 0; - auto row = results.begin(); - if (admin) - *admin = atoi(row[0]); - - if (account_name) - strcpy(account_name, row[1]); - - if (lsaccountid) { - if (row[2]) - *lsaccountid = atoi(row[2]); - else - *lsaccountid = 0; - } - - if (gmspeed) - *gmspeed = atoi(row[3]); - - if (revoked) - *revoked = atoi(row[4]); - - if(gmhideme) - *gmhideme = atoi(row[5]); - - if(account_creation) - *account_creation = atoul(row[6]); - - return true; + } + if (gmspeed) + *gmspeed = atoi(row[3]); + if (revoked) + *revoked = atoi(row[4]); + if(gmhideme) + *gmhideme = atoi(row[5]); + if(account_creation) + *account_creation = atoul(row[6]); + return true; + } + else { + return false; + } } diff --git a/zone/zonedb.h b/zone/zonedb.h index 78d09ba2a..2e9aed0ac 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -247,7 +247,7 @@ public: * General Character Related Stuff */ void StoreCharacterLookup(uint32 char_id); - bool GetAccountInfoForLogin_result(MySQLRequestResult results, int16* admin = 0, char* account_name = 0, + bool GetAccountInfoForLogin_result(MYSQL_RES* result, int16* admin = 0, char* account_name = 0, uint32* lsaccountid = 0, uint8* gmspeed = 0, bool* revoked = 0, bool* gmhideme = nullptr, uint32* account_creation = 0); bool GetCharacterInfoForLogin_result(MYSQL_RES* result, uint32* character_id = 0, char* current_zone = 0, From bd5cdf502ea12d7a17d3bdc4391ab1a9c77771ae Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 11 Sep 2014 18:24:40 -0400 Subject: [PATCH 115/127] Fix ZoneDatabase::GetZoneCFG errors --- zone/zonedb.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 93b910579..8bc4467a4 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -136,30 +136,30 @@ bool ZoneDatabase::GetZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct zone_data->fog_maxclip[index]=atof(row[5 + index * 5]); } - zone_data->fog_density = atof(row[22]); - zone_data->sky=atoi(row[23]); - zone_data->zone_exp_multiplier=atof(row[24]); - zone_data->safe_x=atof(row[25]); - zone_data->safe_y=atof(row[26]); - zone_data->safe_z=atof(row[27]); - zone_data->underworld=atof(row[28]); - zone_data->minclip=atof(row[29]); - zone_data->maxclip=atof(row[30]); - zone_data->time_type=atoi(row[31]); + zone_data->fog_density = atof(row[21]); + zone_data->sky=atoi(row[22]); + zone_data->zone_exp_multiplier=atof(row[23]); + zone_data->safe_x=atof(row[24]); + zone_data->safe_y=atof(row[25]); + zone_data->safe_z=atof(row[26]); + zone_data->underworld=atof(row[27]); + zone_data->minclip=atof(row[28]); + zone_data->maxclip=atof(row[29]); + zone_data->time_type=atoi(row[30]); //not in the DB yet: zone_data->gravity = 0.4; allow_mercs = true; int bindable = 0; - bindable = atoi(row[32]); + bindable = atoi(row[31]); can_bind = bindable == 0? false: true; is_city = bindable == 2? true: false; - can_combat = atoi(row[33]) == 0? false: true; - can_levitate = atoi(row[34]) == 0? false: true; - can_castoutdoor = atoi(row[35]) == 0? false: true; - is_hotzone = atoi(row[36]) == 0? false: true; + can_combat = atoi(row[32]) == 0? false: true; + can_levitate = atoi(row[33]) == 0? false: true; + can_castoutdoor = atoi(row[34]) == 0? false: true; + is_hotzone = atoi(row[35]) == 0? false: true; ruleset = atoi(row[36]); From 95969ce67b857f36fae4ea1180e7c7400f49c887 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 11 Sep 2014 18:28:25 -0400 Subject: [PATCH 116/127] Fix ZoneDatabase::GetZoneCFG for real --- zone/zonedb.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 8bc4467a4..481cac591 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -178,10 +178,10 @@ bool ZoneDatabase::GetZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct zone_data->rain_duration[index]=atoi(row[44 + index]); for(index = 0; index < 4; index++) - zone_data->snow_chance[index]=atoi(row[49 + index]); + zone_data->snow_chance[index]=atoi(row[48 + index]); for(index = 0; index < 4; index++) - zone_data->snow_duration[index]=atof(row[53 + index]); + zone_data->snow_duration[index]=atof(row[52 + index]); return true; } From 873d343529155b03b070c8e8b4bf5244a0f26b0e Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 12 Sep 2014 11:57:09 -0400 Subject: [PATCH 117/127] Fix ZoneDatabase::GetNPCType nuking attack_delay changes --- zone/zonedb.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 481cac591..fd93fc01e 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -922,8 +922,8 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { "npc_types.texture, npc_types.helmtexture, npc_types.size, " "npc_types.loottable_id, npc_types.merchant_id, npc_types.alt_currency_id, " "npc_types.adventure_template_id, npc_types.trap_template, npc_types.attack_speed, " - "npc_types.STR, npc_types.STA, npc_types.DEX, npc_types.AGI, npc_types._INT, " - "npc_types.WIS, npc_types.CHA, npc_types.MR, npc_types.CR, npc_types.DR, " + "npc_types.attack_delay, npc_types.STR, npc_types.STA, npc_types.DEX, npc_types.AGI, " + "npc_types._INT, npc_types.WIS, npc_types.CHA, npc_types.MR, npc_types.CR, npc_types.DR, " "npc_types.FR, npc_types.PR, npc_types.Corrup, npc_types.PhR," "npc_types.mindmg, npc_types.maxdmg, npc_types.attack_count, npc_types.special_abilities," "npc_types.npc_spells_id, npc_types.npc_spells_effects_id, npc_types.d_meele_texture1," @@ -976,6 +976,7 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { tmpNPCType->adventure_template = atoi(row[14]); tmpNPCType->trap_template = atoi(row[15]); tmpNPCType->attack_speed = atof(row[16]); + tmpNPCType->attack_delay = atoi(row[17]); tmpNPCType->STR = atoi(row[17]); tmpNPCType->STA = atoi(row[18]); tmpNPCType->DEX = atoi(row[19]); From d51241720a6f5b47036749be40cdf633dca5895e Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 12 Sep 2014 13:10:03 -0400 Subject: [PATCH 118/127] Fix attack_delay for real --- zone/zonedb.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index fd93fc01e..034c54dcc 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -922,8 +922,8 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { "npc_types.texture, npc_types.helmtexture, npc_types.size, " "npc_types.loottable_id, npc_types.merchant_id, npc_types.alt_currency_id, " "npc_types.adventure_template_id, npc_types.trap_template, npc_types.attack_speed, " - "npc_types.attack_delay, npc_types.STR, npc_types.STA, npc_types.DEX, npc_types.AGI, " - "npc_types._INT, npc_types.WIS, npc_types.CHA, npc_types.MR, npc_types.CR, npc_types.DR, " + "npc_types.STR, npc_types.STA, npc_types.DEX, npc_types.AGI, npc_types._INT, " + "npc_types.WIS, npc_types.CHA, npc_types.MR, npc_types.CR, npc_types.DR, " "npc_types.FR, npc_types.PR, npc_types.Corrup, npc_types.PhR," "npc_types.mindmg, npc_types.maxdmg, npc_types.attack_count, npc_types.special_abilities," "npc_types.npc_spells_id, npc_types.npc_spells_effects_id, npc_types.d_meele_texture1," @@ -942,7 +942,7 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { "npc_types.Avoidance, npc_types.slow_mitigation, npc_types.maxlevel, npc_types.scalerate, " "npc_types.private_corpse, npc_types.unique_spawn_by_name, npc_types.underwater, " "npc_types.emoteid, npc_types.spellscale, npc_types.healscale, npc_types.no_target_hotkey," - "npc_types.raid_target FROM npc_types WHERE id = %d", id); + "npc_types.raid_target, npc_types.attack_delay FROM npc_types WHERE id = %d", id); auto results = QueryDatabase(query); if (!results.Success()) { @@ -976,7 +976,6 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { tmpNPCType->adventure_template = atoi(row[14]); tmpNPCType->trap_template = atoi(row[15]); tmpNPCType->attack_speed = atof(row[16]); - tmpNPCType->attack_delay = atoi(row[17]); tmpNPCType->STR = atoi(row[17]); tmpNPCType->STA = atoi(row[18]); tmpNPCType->DEX = atoi(row[19]); @@ -1100,6 +1099,7 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { tmpNPCType->healscale = atoi(row[86]); tmpNPCType->no_target_hotkey = atoi(row[87]) == 1 ? true: false; tmpNPCType->raid_target = atoi(row[88]) == 0 ? false: true; + tmpNPCType->attack_delay = atoi(row[89]); // If NPC with duplicate NPC id already in table, // free item we attempted to add. From 4c959159c2958d91a8bb9af809a662a0c29930e6 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 13 Sep 2014 03:20:43 -0400 Subject: [PATCH 119/127] Fix rogues not starting with Thieves' Cant --- changelog.txt | 3 +++ world/client.cpp | 13 +++++++++++++ world/client.h | 1 + 3 files changed, 17 insertions(+) diff --git a/changelog.txt b/changelog.txt index 0b964c528..dcde86713 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 09/13/2014 == +demonstar55: Fix rogues not having Thieves' Cant + == 09/09/2014 == demonstar55: Incrase Mob kick/bash timer by 3 see: http://www.eqemulator.org/forums/showthread.php?t=38734 diff --git a/world/client.cpp b/world/client.cpp index fc7e525db..f34f4e3df 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -1446,6 +1446,7 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) SetRacialLanguages( &pp ); // bUsh SetRaceStartingSkills( &pp ); // bUsh SetClassStartingSkills( &pp ); // bUsh + SetClassLanguages(&pp); pp.skills[SkillSenseHeading] = 200; // Some one fucking fix this to use a field name. -Doodman //pp.unknown3596[28] = 15; // @bp: This is to enable disc usage @@ -2034,3 +2035,15 @@ void Client::SetRacialLanguages( PlayerProfile_Struct *pp ) } } +void Client::SetClassLanguages(PlayerProfile_Struct *pp) +{ + // we only need to handle one class, but custom server might want to do more + switch(pp->class_) { + case ROGUE: + pp->languages[LANG_THIEVES_CANT] = 100; + break; + default: + break; + } +} + diff --git a/world/client.h b/world/client.h index bdf1afbec..9014051ed 100644 --- a/world/client.h +++ b/world/client.h @@ -90,6 +90,7 @@ private: void SetClassStartingSkills( PlayerProfile_Struct *pp ); void SetRaceStartingSkills( PlayerProfile_Struct *pp ); void SetRacialLanguages( PlayerProfile_Struct *pp ); + void SetClassLanguages(PlayerProfile_Struct *pp); ClientListEntry* cle; Timer CLE_keepalive_timer; From 0f662bf70c59f31bbb650d9602c09e3383c2cce1 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 14 Sep 2014 15:58:08 -0400 Subject: [PATCH 120/127] Fix ZoneDatabase::LoadTraderItem not returning anything valid --- zone/zonedb.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 034c54dcc..45930991a 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -570,6 +570,7 @@ Trader_Struct* ZoneDatabase::LoadTraderItem(uint32 char_id){ loadti->Items[atoi(row[5])] = atoi(row[1]); loadti->ItemCost[atoi(row[5])] = atoi(row[4]); } + return loadti; } TraderCharges_Struct* ZoneDatabase::LoadTraderItemWithCharges(uint32 char_id){ From e256175ce692c356498f67e0a55db3da9cd90809 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 14 Sep 2014 16:00:18 -0400 Subject: [PATCH 121/127] Style nits --- zone/zonedb.cpp | 55 ++++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 45930991a..263b7ebcc 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -548,55 +548,54 @@ void ZoneDatabase::DeleteWorldContainer(uint32 parent_id, uint32 zone_id) } -Trader_Struct* ZoneDatabase::LoadTraderItem(uint32 char_id){ - +Trader_Struct* ZoneDatabase::LoadTraderItem(uint32 char_id) +{ Trader_Struct* loadti = new Trader_Struct; memset(loadti,0,sizeof(Trader_Struct)); std::string query = StringFormat("SELECT * FROM trader WHERE char_id = %i ORDER BY slot_id LIMIT 80", char_id); auto results = QueryDatabase(query); if (!results.Success()) { - _log(TRADING__CLIENT, "Failed to load trader information!\n"); - return loadti; + _log(TRADING__CLIENT, "Failed to load trader information!\n"); + return loadti; } - loadti->Code = BazaarTrader_ShowItems; - for (auto row = results.begin(); row != results.end(); ++row) { - if(atoi(row[5])>=80 || atoi(row[4])<0) { - _log(TRADING__CLIENT, "Bad Slot number when trying to load trader information!\n"); - continue; - } + loadti->Code = BazaarTrader_ShowItems; + for (auto row = results.begin(); row != results.end(); ++row) { + if (atoi(row[5]) >= 80 || atoi(row[4]) < 0) { + _log(TRADING__CLIENT, "Bad Slot number when trying to load trader information!\n"); + continue; + } loadti->Items[atoi(row[5])] = atoi(row[1]); loadti->ItemCost[atoi(row[5])] = atoi(row[4]); - } + } return loadti; } -TraderCharges_Struct* ZoneDatabase::LoadTraderItemWithCharges(uint32 char_id){ - +TraderCharges_Struct* ZoneDatabase::LoadTraderItemWithCharges(uint32 char_id) +{ TraderCharges_Struct* loadti = new TraderCharges_Struct; memset(loadti,0,sizeof(TraderCharges_Struct)); std::string query = StringFormat("SELECT * FROM trader WHERE char_id=%i ORDER BY slot_id LIMIT 80", char_id); auto results = QueryDatabase(query); - if (!results.Success()) { - _log(TRADING__CLIENT, "Failed to load trader information!\n"); - return loadti; - } + if (!results.Success()) { + _log(TRADING__CLIENT, "Failed to load trader information!\n"); + return loadti; + } - for (auto row = results.begin(); row != results.end(); ++row) { - if(atoi(row[5])>=80 || atoi(row[5])<0) { - _log(TRADING__CLIENT, "Bad Slot number when trying to load trader information!\n"); - continue; - } - - loadti->ItemID[atoi(row[5])] = atoi(row[1]); - loadti->SerialNumber[atoi(row[5])] = atoi(row[2]); - loadti->Charges[atoi(row[5])] = atoi(row[3]); - loadti->ItemCost[atoi(row[5])] = atoi(row[4]); - } + for (auto row = results.begin(); row != results.end(); ++row) { + if (atoi(row[5]) >= 80 || atoi(row[5]) < 0) { + _log(TRADING__CLIENT, "Bad Slot number when trying to load trader information!\n"); + continue; + } + loadti->ItemID[atoi(row[5])] = atoi(row[1]); + loadti->SerialNumber[atoi(row[5])] = atoi(row[2]); + loadti->Charges[atoi(row[5])] = atoi(row[3]); + loadti->ItemCost[atoi(row[5])] = atoi(row[4]); + } return loadti; } From 03485ef1e02b4d13ec3119862a244f9e6b57cc98 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Mon, 15 Sep 2014 16:05:57 -0400 Subject: [PATCH 122/127] Nimbus effects will now be reapplied after zoning. Nimbus effects will now fade when associated buff is removed. Fix for ReduceAllDamage function. --- changelog.txt | 3 +++ zone/attack.cpp | 4 ++-- zone/client_packet.cpp | 8 +++++++- zone/mob.cpp | 9 +++++++++ zone/spell_effects.cpp | 3 +++ 5 files changed, 24 insertions(+), 3 deletions(-) diff --git a/changelog.txt b/changelog.txt index dcde86713..eb89606b9 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 09/15/2014 == +Kayen: Nimbus effects will now be reapplied after zoning and will be removed when associated buff fades. + == 09/13/2014 == demonstar55: Fix rogues not having Thieves' Cant diff --git a/zone/attack.cpp b/zone/attack.cpp index 62d9f8de9..a515a08c4 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -3516,7 +3516,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons if(spell_id == SPELL_UNKNOWN) { damage = ReduceDamage(damage); mlog(COMBAT__HITS, "Melee Damage reduced to %d", damage); - ReduceAllDamage(damage); + damage = ReduceAllDamage(damage); TryTriggerThreshHold(damage, SE_TriggerMeleeThreshold, attacker); } else { int32 origdmg = damage; @@ -3529,7 +3529,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons //Kayen: Probably need to add a filter for this - Not sure if this msg is correct but there should be a message for spell negate/runes. Message(263, "%s tries to cast on YOU, but YOUR magical skin absorbs the spell.",attacker->GetCleanName()); } - ReduceAllDamage(damage); + damage = ReduceAllDamage(damage); TryTriggerThreshHold(damage, SE_TriggerSpellThreshold, attacker); } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 9d7c9e01d..261615169 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -9574,11 +9574,17 @@ void Client::CompleteConnect() { //reapply some buffs uint32 buff_count = GetMaxTotalSlots(); for (uint32 j1 = 0; j1 < buff_count; j1++) { - if (buffs[j1].spellid >(uint32)SPDAT_RECORDS) + if (!IsValidSpell(buffs[j1].spellid)) continue; const SPDat_Spell_Struct &spell = spells[buffs[j1].spellid]; + int NimbusEffect = GetNimbusEffect(buffs[j1].spellid); + if(NimbusEffect) { + if(!IsNimbusEffectActive(NimbusEffect)) + SendSpellEffect(NimbusEffect, 500, 0, 1, 3000, true); + } + for (int x1 = 0; x1 < EFFECT_COUNT; x1++) { switch (spell.effectid[x1]) { case SE_IllusionCopy: diff --git a/zone/mob.cpp b/zone/mob.cpp index fdce628c4..5e31591e4 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -4375,6 +4375,15 @@ void Mob::SpreadVirus(uint16 spell_id, uint16 casterID) void Mob::RemoveNimbusEffect(int effectid) { + if (effectid == nimbus_effect1) + nimbus_effect1 = 0; + + else if (effectid == nimbus_effect2) + nimbus_effect2 = 0; + + else if (effectid == nimbus_effect3) + nimbus_effect3 = 0; + EQApplicationPacket* outapp = new EQApplicationPacket(OP_RemoveNimbusEffect, sizeof(RemoveNimbusEffect_Struct)); RemoveNimbusEffect_Struct* rne = (RemoveNimbusEffect_Struct*)outapp->pBuffer; rne->spawnid = GetID(); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 20bef74aa..008b83a54 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -4016,6 +4016,9 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) if (!found_numhits) Numhits(false); } + + if (spells[buffs[slot].spellid].NimbusEffect > 0) + RemoveNimbusEffect(spells[buffs[slot].spellid].NimbusEffect); buffs[slot].spellid = SPELL_UNKNOWN; if(IsPet() && GetOwner() && GetOwner()->IsClient()) { From ec0989454d135669878a78c993c9d7410bd38468 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 15 Sep 2014 20:11:56 -0400 Subject: [PATCH 123/127] QGlobalCache::LoadBy to pass by reference --- zone/qglobals.cpp | 13 ++++++------- zone/qglobals.h | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/zone/qglobals.cpp b/zone/qglobals.cpp index 53f64670b..f63e13dd4 100644 --- a/zone/qglobals.cpp +++ b/zone/qglobals.cpp @@ -165,13 +165,12 @@ void QGlobalCache::LoadByGlobalContext() LoadBy(query); } -void QGlobalCache::LoadBy(const std::string query) +void QGlobalCache::LoadBy(const std::string &query) { - auto results = database.QueryDatabase(query); - if (!results.Success()) - return; - - for (auto row = results.begin(); row != results.end(); ++row) - AddGlobal(0, QGlobal(std::string(row[0]), atoi(row[1]), atoi(row[2]), atoi(row[3]), row[4], row[5]? atoi(row[5]): 0xFFFFFFFF)); + auto results = database.QueryDatabase(query); + if (!results.Success()) + return; + for (auto row = results.begin(); row != results.end(); ++row) + AddGlobal(0, QGlobal(std::string(row[0]), atoi(row[1]), atoi(row[2]), atoi(row[3]), row[4], row[5]? atoi(row[5]): 0xFFFFFFFF)); } diff --git a/zone/qglobals.h b/zone/qglobals.h index b879cba97..5f0938a20 100644 --- a/zone/qglobals.h +++ b/zone/qglobals.h @@ -42,7 +42,7 @@ public: void LoadByZoneID(uint32 zoneID); //zone void LoadByGlobalContext(); //zone protected: - void LoadBy(const std::string query); + void LoadBy(const std::string &query); std::list qGlobalBucket; }; From 11ce399e0d4a3d247d2a3d39ce8871cf17af6303 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 15 Sep 2014 20:31:45 -0400 Subject: [PATCH 124/127] Mob::ProcessSpecialAbilities pass by reference --- zone/mob.cpp | 2 +- zone/mob.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index 5e31591e4..b7f32bf94 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -4924,7 +4924,7 @@ void Mob::ClearSpecialAbilities() { } } -void Mob::ProcessSpecialAbilities(const std::string str) { +void Mob::ProcessSpecialAbilities(const std::string &str) { ClearSpecialAbilities(); std::vector sp = SplitString(str, '^'); diff --git a/zone/mob.h b/zone/mob.h index 1f1d257f9..07459eab9 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -843,7 +843,7 @@ public: void StopSpecialAbilityTimer(int ability); Timer *GetSpecialAbilityTimer(int ability); void ClearSpecialAbilities(); - void ProcessSpecialAbilities(const std::string str); + void ProcessSpecialAbilities(const std::string &str); Shielders_Struct shielder[MAX_SHIELDERS]; Trade* trade; From 85e1518856ca08d63060a25b81f4787be3da5ebb Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 16 Sep 2014 18:35:49 -0400 Subject: [PATCH 125/127] Implement spell formula 137 This is only used in the BER AA Desperation --- changelog.txt | 3 +++ zone/spell_effects.cpp | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/changelog.txt b/changelog.txt index eb89606b9..c852b2096 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 09/16/2014 == +demonstar55: Implement spell formula 137 (BER AA Desperation) + == 09/15/2014 == Kayen: Nimbus effects will now be reapplied after zoning and will be removed when associated buff fades. diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 008b83a54..3af80aacc 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -3166,6 +3166,10 @@ snare has both of them negative, yet their range should work the same: result = MakeRandomInt(ubase, abs(max)); break; + case 137: // used in berserker AA desperation + result = ubase - (ubase * (GetHPRatio() / 100.0f)); + break; + //these are used in stacking effects... formula unknown case 201: case 203: From 364ed921cedd6afbb8847c4cab5f544befdd051a Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 16 Sep 2014 22:57:15 -0400 Subject: [PATCH 126/127] Fix for LoadBuffs() server crash --- changelog.txt | 1 + zone/zonedb.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/changelog.txt b/changelog.txt index c852b2096..e629bee6c 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2,6 +2,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 09/16/2014 == demonstar55: Implement spell formula 137 (BER AA Desperation) +Uleat (NateDog): Fix for LoadBuffs() crash when a spell with a non-persistent Illusion effect was loaded. == 09/15/2014 == Kayen: Nimbus effects will now be reapplied after zoning and will be removed when associated buff fades. diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 263b7ebcc..4369d00cf 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -2066,6 +2066,7 @@ void ZoneDatabase::LoadBuffs(Client *client) { break; buffs[index].spellid = SPELL_UNKNOWN; + break; } } } From 86c1420f6edbb6f422ba325597bfe1bc415f0527 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 17 Sep 2014 00:01:32 -0400 Subject: [PATCH 127/127] Fix some effect value calcs and implement more Derived from the client --- changelog.txt | 1 + zone/spell_effects.cpp | 119 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 110 insertions(+), 10 deletions(-) diff --git a/changelog.txt b/changelog.txt index e629bee6c..a006c9a50 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,6 +3,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) == 09/16/2014 == demonstar55: Implement spell formula 137 (BER AA Desperation) Uleat (NateDog): Fix for LoadBuffs() crash when a spell with a non-persistent Illusion effect was loaded. +demonstar55: Fix some effect calcs + implement more (derived from the client) == 09/15/2014 == Kayen: Nimbus effects will now be reapplied after zoning and will be removed when associated buff fades. diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 3af80aacc..f0bc8498b 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -3127,26 +3127,42 @@ snare has both of them negative, yet their range should work the same: case 110: // confirmed 2/6/04 //is there a reason we dont use updownsign here??? - result = ubase + (caster_level / 5); break; + result = ubase + (caster_level / 6); + break; case 111: - result = updownsign * (ubase + 6 * (caster_level - GetMinLevel(spell_id))); break; + result = updownsign * (ubase + 6 * (caster_level - 16)); + break; case 112: - result = updownsign * (ubase + 8 * (caster_level - GetMinLevel(spell_id))); break; + result = updownsign * (ubase + 8 * (caster_level - 24)); + break; case 113: - result = updownsign * (ubase + 10 * (caster_level - GetMinLevel(spell_id))); break; + result = updownsign * (ubase + 10 * (caster_level - 34)); + break; case 114: - result = updownsign * (ubase + 15 * (caster_level - GetMinLevel(spell_id))); break; + result = updownsign * (ubase + 15 * (caster_level - 44)); + break; - //these formula were updated according to lucy 10/16/04 case 115: // this is only in symbol of transal - result = ubase + 6 * (caster_level - GetMinLevel(spell_id)); break; + result = ubase; + if (caster_level > 15) + result += 7 * (caster_level - 15); + break; case 116: // this is only in symbol of ryltan - result = ubase + 8 * (caster_level - GetMinLevel(spell_id)); break; + result = ubase; + if (caster_level > 24) + result += 10 * (caster_level - 24); + break; case 117: // this is only in symbol of pinzarn - result = ubase + 12 * (caster_level - GetMinLevel(spell_id)); break; + result = ubase; + if (caster_level > 34) + result += 13 * (caster_level - 34); + break; case 118: // used in naltron and a few others - result = ubase + 20 * (caster_level - GetMinLevel(spell_id)); break; + result = ubase; + if (caster_level > 44) + result += 20 * (caster_level - 44); + break; case 119: // confirmed 2/6/04 result = ubase + (caster_level / 8); break; @@ -3166,10 +3182,93 @@ snare has both of them negative, yet their range should work the same: result = MakeRandomInt(ubase, abs(max)); break; + case 124: // check sign + result = ubase; + if (caster_level > 50) + result += caster_level - 50; + break; + + case 125: // check sign + result = ubase; + if (caster_level > 50) + result += 2 * (caster_level - 50); + break; + + case 126: // check sign + result = ubase; + if (caster_level > 50) + result += 3 * (caster_level - 50); + break; + + case 127: // check sign + result = ubase; + if (caster_level > 50) + result += 4 * (caster_level - 50); + break; + + case 128: // check sign + result = ubase; + if (caster_level > 50) + result += 5 * (caster_level - 50); + break; + + case 129: // check sign + result = ubase; + if (caster_level > 50) + result += 10 * (caster_level - 50); + break; + + case 130: // check sign + result = ubase; + if (caster_level > 50) + result += 15 * (caster_level - 50); + break; + + case 131: // check sign + result = ubase; + if (caster_level > 50) + result += 20 * (caster_level - 50); + break; + + case 132: // check sign + result = ubase; + if (caster_level > 50) + result += 25 * (caster_level - 50); + break; + case 137: // used in berserker AA desperation result = ubase - (ubase * (GetHPRatio() / 100.0f)); break; + case 138: { // unused on live? + int maxhps = GetMaxHP() / 2; + if (GetHP() <= maxhps) + result = -(ubase * GetHP() / maxhps); + else + result = -ubase; + break; + } + + case 139: // check sign + result = ubase + (caster_level > 30 ? (caster_level - 30) / 2 : 0); + break; + + case 140: // check sign + result = ubase + (caster_level > 30 ? caster_level - 30 : 0); + break; + + case 141: // check sign + result = ubase + (caster_level > 30 ? (3 * caster_level - 90) / 2 : 0); + break; + + case 142: // check sign + result = ubase + (caster_level > 30 ? 2 * caster_level - 60 : 0); + break; + + case 143: // check sign + result = ubase + (3 * caster_level / 4); + break; + //these are used in stacking effects... formula unknown case 201: case 203: