Merge branch 'master' into eqstream_ptr

This commit is contained in:
KimLS
2015-01-29 22:13:41 -08:00
21 changed files with 435 additions and 164 deletions
+19
View File
@@ -1,5 +1,24 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50) EQEMu Changelog (Started on Sept 24, 2003 15:50)
------------------------------------------------------- -------------------------------------------------------
== 01/29/2015 ==
Trevius: Added more information to Mercenary Logging.
Trevius: Added potential fix for Mercenaries that fail to unsuspend.
Trevius: Added a new "statscale" field to the merc_stats table that can be used to quickly balance Mercenary Stats based on Level.
Trevius: The new "statscale" field now combines with the Mercs::ScaleRate rule value (default 100 percent for both).
== 01/28/2015 ==
Akkadius: Added Logs::DebugQuest category per request from Trevius (Great idea)
- Exported quest::debug(log_message, [debug_level = 1)
- Example:
quest::debug("This is a test debug message, level 1 (default)");
quest::debug("This is a test debug message, level 1", 1);
quest::debug("This is a test debug message, level 2", 2);
quest::debug("This is a test debug message, level 3", 3);
Result: http://i.imgur.com/6VoafGE.png
- Uses traditional logging system to output this category
- Required MySQL Source in Database version 9070
== 01/27/2015 == == 01/27/2015 ==
Trevius: Removed "Mercenary Debug:" from the Mercenary Log entries. Trevius: Removed "Mercenary Debug:" from the Mercenary Log entries.
Trevius: Resolved duplicate "You have no Mercenaries" messages when zoning without owning a Mercenary. Trevius: Resolved duplicate "You have no Mercenaries" messages when zoning without owning a Mercenary.
+1 -1
View File
@@ -1991,7 +1991,7 @@ void Database::SetRaidGroupLeaderInfo(uint32 gid, uint32 rid)
if (results.RowsAffected() != 0) if (results.RowsAffected() != 0)
return; return;
query = StringFormat("INSERT INTO raid_leaders(gid, rid, marknpc, leadershipaa, maintank, assist, puller, mentoree, mentor_percent) VALUES(%lu, %lu, '', '', '', '', '', '', 0)", query = StringFormat("REPLACE INTO raid_leaders(gid, rid, marknpc, leadershipaa, maintank, assist, puller, mentoree, mentor_percent) VALUES(%lu, %lu, '', '', '', '', '', '', 0)",
(unsigned long)gid, (unsigned long)rid); (unsigned long)gid, (unsigned long)rid);
results = QueryDatabase(query); results = QueryDatabase(query);
+3 -1
View File
@@ -77,6 +77,7 @@ namespace Logs{
MySQLError, MySQLError,
MySQLQuery, MySQLQuery,
Mercenaries, Mercenaries,
QuestDebug,
MaxCategoryID /* Don't Remove this*/ MaxCategoryID /* Don't Remove this*/
}; };
@@ -120,6 +121,7 @@ namespace Logs{
"MySQL Error", "MySQL Error",
"MySQL Query", "MySQL Query",
"Mercenaries", "Mercenaries",
"Quest Debug",
}; };
} }
@@ -141,7 +143,7 @@ public:
be checked against to see if that piped output is set to actually process it for the category and debug level be checked against to see if that piped output is set to actually process it for the category and debug level
*/ */
void Out(Logs::DebugLevel debug_level, uint16 log_category, std::string message, ...); void Out(Logs::DebugLevel debug_level, uint16 log_category, std::string message, ...);
void SetCurrentTimeStamp(char* time_stamp); /* Used in file logs to prepend a timestamp entry for logs */ void SetCurrentTimeStamp(char* time_stamp); /* Used in file logs to prepend a timestamp entry for logs */
void StartFileLogs(const std::string &log_name = ""); /* Used to declare the processes file log and to keep it open for later use */ void StartFileLogs(const std::string &log_name = ""); /* Used to declare the processes file log and to keep it open for later use */
/* /*
+1 -1
View File
@@ -30,7 +30,7 @@
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/ */
#define CURRENT_BINARY_DATABASE_VERSION 9069 #define CURRENT_BINARY_DATABASE_VERSION 9071
#define COMPILE_DATE __DATE__ #define COMPILE_DATE __DATE__
#define COMPILE_TIME __TIME__ #define COMPILE_TIME __TIME__
#ifndef WIN32 #ifndef WIN32
+1 -1
View File
@@ -195,7 +195,7 @@ bool Database::VerifyMailKey(std::string characterName, int IPAddress, std::stri
else else
sprintf(combinedKey, "%s", MailKey.c_str()); sprintf(combinedKey, "%s", MailKey.c_str());
Log.Out(Logs::Detail, Logs::UCS_Server, "DB key is [%s], Client key is [%s]", row[0], combinedKey); Log.Out(Logs::Detail, Logs::UCS_Server, "DB key is [%s], Client key is [%s]", (row[0] ? row[0] : ""), combinedKey);
return !strcmp(row[0], combinedKey); return !strcmp(row[0], combinedKey);
} }
+1 -1
View File
@@ -325,7 +325,7 @@ sub OpCodes_Fetch{
3 => ["Titanium", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_Titanium.conf"], 3 => ["Titanium", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_Titanium.conf"],
4 => ["Secrets of Faydwer", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_SoF.conf"], 4 => ["Secrets of Faydwer", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_SoF.conf"],
5 => ["Seeds of Destruction", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_SoD.conf"], 5 => ["Seeds of Destruction", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_SoD.conf"],
6 => ["Underfoot", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_Underfoot.conf"], 6 => ["Underfoot", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_UF.conf"],
7 => ["Rain of Fear", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_RoF.conf"], 7 => ["Rain of Fear", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_RoF.conf"],
8 => ["Rain of Fear 2", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_RoF2.conf"], 8 => ["Rain of Fear 2", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_RoF2.conf"],
); );
+2
View File
@@ -323,6 +323,8 @@
9067|2015_01_21_npc_types_update.sql|SHOW COLUMNS FROM `npc_types` LIKE 'light'|empty| 9067|2015_01_21_npc_types_update.sql|SHOW COLUMNS FROM `npc_types` LIKE 'light'|empty|
9068|2015_01_15_logsys_categories_table.sql|SHOW TABLES LIKE 'logsys_categories'|empty| 9068|2015_01_15_logsys_categories_table.sql|SHOW TABLES LIKE 'logsys_categories'|empty|
9069|2015_01_25_logsys_Mercenaries_category.sql|SELECT * FROM `logsys_categories` WHERE `log_category_description` LIKE 'Mercenaries'|empty| 9069|2015_01_25_logsys_Mercenaries_category.sql|SELECT * FROM `logsys_categories` WHERE `log_category_description` LIKE 'Mercenaries'|empty|
9070|2015_01_28_quest_debug_log_category.sql|SELECT * FROM `logsys_categories` WHERE `log_category_description` LIKE 'Quest Debug'|empty|
9071|2015_01_29_merc_stats_table_update.sql|SHOW COLUMNS FROM `merc_stats` LIKE 'statscale'|empty|
# Upgrade conditions: # Upgrade conditions:
# This won't be needed after this system is implemented, but it is used database that are not # This won't be needed after this system is implemented, but it is used database that are not
@@ -0,0 +1 @@
INSERT INTO `logsys_categories` (`log_category_id`, `log_category_description`, `log_to_gmsay`) VALUES ('38', 'Quest Debug', '1')
@@ -0,0 +1 @@
ALTER TABLE `merc_stats` ADD `statscale` int( 11 ) NOT NULL DEFAULT '100' AFTER `runspeed`;
+5 -3
View File
@@ -305,6 +305,8 @@ Client::Client(EQStreamInterface* ieqs)
active_light = innate_light; active_light = innate_light;
spell_light = equip_light = NOT_USED; spell_light = equip_light = NOT_USED;
AI_Init();
} }
Client::~Client() { Client::~Client() {
@@ -7276,7 +7278,7 @@ void Client::SendMercPersonalInfo()
stancecount += zone->merc_stance_list[GetMercInfo().MercTemplateID].size(); stancecount += zone->merc_stance_list[GetMercInfo().MercTemplateID].size();
if(stancecount > MAX_MERC_STANCES || mercCount > MAX_MERC || mercTypeCount > MAX_MERC_GRADES) if(stancecount > MAX_MERC_STANCES || mercCount > MAX_MERC || mercTypeCount > MAX_MERC_GRADES)
{ {
Log.Out(Logs::General, Logs::Mercenaries, "SendMercPersonalInfo canceled: (%i) (%i) (%i)", stancecount, mercCount, mercTypeCount); Log.Out(Logs::General, Logs::Mercenaries, "SendMercPersonalInfo canceled: (%i) (%i) (%i) for %s", stancecount, mercCount, mercTypeCount, GetName());
SendMercMerchantResponsePacket(0); SendMercMerchantResponsePacket(0);
return; return;
} }
@@ -7370,13 +7372,13 @@ void Client::SendMercPersonalInfo()
return; return;
} }
} }
Log.Out(Logs::General, Logs::Mercenaries, "SendMercPersonalInfo Send Successful"); Log.Out(Logs::General, Logs::Mercenaries, "SendMercPersonalInfo Send Successful for %s.", GetName());
SendMercMerchantResponsePacket(0); SendMercMerchantResponsePacket(0);
} }
else else
{ {
Log.Out(Logs::General, Logs::Mercenaries, "SendMercPersonalInfo Send Failed Due to no MercData for %i", GetMercInfo().MercTemplateID); Log.Out(Logs::General, Logs::Mercenaries, "SendMercPersonalInfo Send Failed Due to no MercData (%i) for %s", GetMercInfo().MercTemplateID, GetName());
} }
} }
+10 -10
View File
@@ -9315,7 +9315,7 @@ void Client::Handle_OP_MercenaryCommand(const EQApplicationPacket *app)
uint32 merc_command = mc->MercCommand; // Seen 0 (zone in with no merc or suspended), 1 (dismiss merc), 5 (normal state), 20 (unknown), 36 (zone in with merc) uint32 merc_command = mc->MercCommand; // Seen 0 (zone in with no merc or suspended), 1 (dismiss merc), 5 (normal state), 20 (unknown), 36 (zone in with merc)
int32 option = mc->Option; // Seen -1 (zone in with no merc), 0 (setting to passive stance), 1 (normal or setting to balanced stance) int32 option = mc->Option; // Seen -1 (zone in with no merc), 0 (setting to passive stance), 1 (normal or setting to balanced stance)
Log.Out(Logs::General, Logs::Mercenaries, "Command %i, Option %i received.", merc_command, option); Log.Out(Logs::General, Logs::Mercenaries, "Command %i, Option %i received from %s.", merc_command, option, GetName());
if (!RuleB(Mercs, AllowMercs)) if (!RuleB(Mercs, AllowMercs))
return; return;
@@ -9349,7 +9349,7 @@ void Client::Handle_OP_MercenaryCommand(const EQApplicationPacket *app)
merc->SetStance(mercTemplate->Stances[option]); merc->SetStance(mercTemplate->Stances[option]);
GetMercInfo().Stance = mercTemplate->Stances[option]; GetMercInfo().Stance = mercTemplate->Stances[option];
Log.Out(Logs::General, Logs::Mercenaries, "Set Stance: %u", merc->GetStance()); Log.Out(Logs::General, Logs::Mercenaries, "Set Stance: %u for %s (%s)", merc->GetStance(), merc->GetName(), GetName());
} }
} }
} }
@@ -9372,7 +9372,7 @@ void Client::Handle_OP_MercenaryDataRequest(const EQApplicationPacket *app)
uint32 merchant_id = mmsr->MercMerchantID; uint32 merchant_id = mmsr->MercMerchantID;
uint32 altCurrentType = 19; uint32 altCurrentType = 19;
Log.Out(Logs::General, Logs::Mercenaries, "Data Request for Merchant ID (%i)", merchant_id); Log.Out(Logs::General, Logs::Mercenaries, "Data Request for Merchant ID (%i) for %s.", merchant_id, GetName());
//client is requesting data about currently owned mercenary //client is requesting data about currently owned mercenary
if (merchant_id == 0) { if (merchant_id == 0) {
@@ -9380,12 +9380,12 @@ void Client::Handle_OP_MercenaryDataRequest(const EQApplicationPacket *app)
//send info about your current merc(s) //send info about your current merc(s)
if (GetMercInfo().mercid) if (GetMercInfo().mercid)
{ {
Log.Out(Logs::General, Logs::Mercenaries, "SendMercPersonalInfo Request"); Log.Out(Logs::General, Logs::Mercenaries, "SendMercPersonalInfo Request for %s.", GetName());
SendMercPersonalInfo(); SendMercPersonalInfo();
} }
else else
{ {
Log.Out(Logs::General, Logs::Mercenaries, "SendMercPersonalInfo Not Sent - MercID (%i)", GetMercInfo().mercid); Log.Out(Logs::General, Logs::Mercenaries, "SendMercPersonalInfo Not Sent - MercID (%i) for %s.", GetMercInfo().mercid, GetName());
} }
} }
@@ -9498,7 +9498,7 @@ void Client::Handle_OP_MercenaryDataUpdateRequest(const EQApplicationPacket *app
return; return;
} }
Log.Out(Logs::General, Logs::Mercenaries, "Data Update Request Received."); Log.Out(Logs::General, Logs::Mercenaries, "Data Update Request Received for %s.", GetName());
if (GetMercID()) if (GetMercID())
{ {
@@ -9524,7 +9524,7 @@ void Client::Handle_OP_MercenaryDismiss(const EQApplicationPacket *app)
Command = VARSTRUCT_DECODE_TYPE(uint8, InBuffer); Command = VARSTRUCT_DECODE_TYPE(uint8, InBuffer);
} }
Log.Out(Logs::General, Logs::Mercenaries, "Dismiss Request ( %i ) Received.", Command); Log.Out(Logs::General, Logs::Mercenaries, "Dismiss Request ( %i ) Received for %s.", Command, GetName());
// Handle the dismiss here... // Handle the dismiss here...
DismissMerc(GetMercInfo().mercid); DismissMerc(GetMercInfo().mercid);
@@ -9549,7 +9549,7 @@ void Client::Handle_OP_MercenaryHire(const EQApplicationPacket *app)
uint32 merc_unk1 = mmrq->MercUnk01; uint32 merc_unk1 = mmrq->MercUnk01;
uint32 merc_unk2 = mmrq->MercUnk02; uint32 merc_unk2 = mmrq->MercUnk02;
Log.Out(Logs::General, Logs::Mercenaries, "Template ID (%i), Merchant ID (%i), Unknown1 (%i), Unknown2 (%i)", merc_template_id, merchant_id, merc_unk1, merc_unk2); Log.Out(Logs::General, Logs::Mercenaries, "Template ID (%i), Merchant ID (%i), Unknown1 (%i), Unknown2 (%i), Client: %s", merc_template_id, merchant_id, merc_unk1, merc_unk2, GetName());
//HirePending = true; //HirePending = true;
SetHoTT(0); SetHoTT(0);
@@ -9615,7 +9615,7 @@ void Client::Handle_OP_MercenarySuspendRequest(const EQApplicationPacket *app)
SuspendMercenary_Struct* sm = (SuspendMercenary_Struct*)app->pBuffer; SuspendMercenary_Struct* sm = (SuspendMercenary_Struct*)app->pBuffer;
uint32 merc_suspend = sm->SuspendMerc; // Seen 30 for suspending or unsuspending uint32 merc_suspend = sm->SuspendMerc; // Seen 30 for suspending or unsuspending
Log.Out(Logs::General, Logs::Mercenaries, "Suspend ( %i ) received.", merc_suspend); Log.Out(Logs::General, Logs::Mercenaries, "Suspend ( %i ) received for %s.", merc_suspend, GetName());
if (!RuleB(Mercs, AllowMercs)) if (!RuleB(Mercs, AllowMercs))
return; return;
@@ -9635,7 +9635,7 @@ void Client::Handle_OP_MercenaryTimerRequest(const EQApplicationPacket *app)
return; return;
} }
Log.Out(Logs::General, Logs::Mercenaries, "Timer Request received."); Log.Out(Logs::General, Logs::Mercenaries, "Timer Request received for %s.", GetName());
if (!RuleB(Mercs, AllowMercs)) { if (!RuleB(Mercs, AllowMercs)) {
return; return;
+33
View File
@@ -23,6 +23,7 @@
#include "../common/global_define.h" #include "../common/global_define.h"
#include "../common/misc_functions.h" #include "../common/misc_functions.h"
#include "../common/eqemu_logsys.h"
#include "embparser.h" #include "embparser.h"
#include "embxs.h" #include "embxs.h"
@@ -3493,6 +3494,37 @@ XS(XS__crosszonesignalnpcbynpctypeid)
XSRETURN_EMPTY; XSRETURN_EMPTY;
} }
XS(XS__debug);
XS(XS__debug)
{
dXSARGS;
if (items != 1 && items != 2){
Perl_croak(aTHX_ "Usage: debug(message, [debug_level])");
}
else{
std::string log_message = (std::string)SvPV_nolen(ST(0));
uint8 debug_level = 1;
if (items == 2)
debug_level = (uint8)SvIV(ST(1));
if (debug_level > Logs::Detail)
return;
if (debug_level == Logs::General){
Log.Out(Logs::General, Logs::QuestDebug, log_message);
}
else if (debug_level == Logs::Moderate){
Log.Out(Logs::Moderate, Logs::QuestDebug, log_message);
}
else if (debug_level == Logs::Detail){
Log.Out(Logs::Detail, Logs::QuestDebug, log_message);
}
}
XSRETURN_EMPTY;
}
/* /*
This is the callback perl will look for to setup the This is the callback perl will look for to setup the
quest package's XSUBs quest package's XSUBs
@@ -3579,6 +3611,7 @@ EXTERN_C XS(boot_quest)
newXS(strcpy(buf, "crosszonesignalclientbycharid"), XS__crosszonesignalclientbycharid, file); newXS(strcpy(buf, "crosszonesignalclientbycharid"), XS__crosszonesignalclientbycharid, file);
newXS(strcpy(buf, "crosszonesignalclientbyname"), XS__crosszonesignalclientbyname, file); newXS(strcpy(buf, "crosszonesignalclientbyname"), XS__crosszonesignalclientbyname, file);
newXS(strcpy(buf, "crosszonesignalnpcbynpctypeid"), XS__crosszonesignalnpcbynpctypeid, file); newXS(strcpy(buf, "crosszonesignalnpcbynpctypeid"), XS__crosszonesignalnpcbynpctypeid, file);
newXS(strcpy(buf, "debug"), XS__debug, file);
newXS(strcpy(buf, "delglobal"), XS__delglobal, file); newXS(strcpy(buf, "delglobal"), XS__delglobal, file);
newXS(strcpy(buf, "depop"), XS__depop, file); newXS(strcpy(buf, "depop"), XS__depop, file);
newXS(strcpy(buf, "depop_withtimer"), XS__depop_withtimer, file); newXS(strcpy(buf, "depop_withtimer"), XS__depop_withtimer, file);
+1 -2
View File
@@ -506,8 +506,7 @@ void Client::SetLevel(uint8 set_level, bool command)
SetMana(CalcMaxMana()); SetMana(CalcMaxMana());
UpdateWho(); UpdateWho();
if(GetMerc()) UpdateMercLevel();
UpdateMercLevel();
Save(); Save();
} }
+211 -69
View File
@@ -75,7 +75,6 @@ Merc::Merc(const NPCType* d, float x, float y, float z, float heading)
SetMana(GetMaxMana()); SetMana(GetMaxMana());
SetEndurance(GetMaxEndurance()); SetEndurance(GetMaxEndurance());
AI_Init();
AI_Start(); AI_Start();
} }
@@ -1737,7 +1736,6 @@ void Merc::AI_Process() {
} }
void Merc::AI_Start(int32 iMoveDelay) { void Merc::AI_Start(int32 iMoveDelay) {
NPC::AI_Start(iMoveDelay);
if (!pAIControlled) if (!pAIControlled)
return; return;
@@ -2244,7 +2242,7 @@ bool Merc::AICastSpell(int8 iChance, int32 iSpellTypes) {
if(CheckAETaunt()) { if(CheckAETaunt()) {
//get AE taunt //get AE taunt
selectedMercSpell = GetBestMercSpellForAETaunt(this); selectedMercSpell = GetBestMercSpellForAETaunt(this);
Log.Out(Logs::General, Logs::Mercenaries, "AE Taunting"); Log.Out(Logs::General, Logs::Mercenaries, "%s AE Taunting.", GetName());
} }
if(selectedMercSpell.spellid == 0 && CheckTaunt()) { if(selectedMercSpell.spellid == 0 && CheckTaunt()) {
@@ -4772,7 +4770,7 @@ Merc* Merc::LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id,
{ {
merc->SetMercData( merc_template->MercTemplateID ); merc->SetMercData( merc_template->MercTemplateID );
database.LoadMercEquipment(merc); database.LoadMercEquipment(merc);
merc->UpdateMercStats(c); merc->UpdateMercStats(c, true);
if(updateFromDB) if(updateFromDB)
{ {
@@ -4810,6 +4808,7 @@ Merc* Merc::LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id,
merc->LoadMercSpells(); merc->LoadMercSpells();
} }
Log.Out(Logs::General, Logs::Mercenaries, "LoadMerc Successful for %s (%s).", merc->GetName(), c->GetName());
return merc; return merc;
} }
} }
@@ -4838,50 +4837,183 @@ void Merc::UpdateMercInfo(Client *c) {
c->GetMercInfo().drakkinDetails = drakkin_details; c->GetMercInfo().drakkinDetails = drakkin_details;
} }
void Merc::UpdateMercStats(Client *c) { void Merc::UpdateMercStats(Client *c, bool setmax) {
if(c->GetMercInfo().MercTemplateID >0) if(c->GetMercInfo().MercTemplateID > 0)
{ {
Log.Out(Logs::General, Logs::Mercenaries, "Updating Mercenary Stats for %s (%s).", GetName(), c->GetName());
const NPCType* npc_type = database.GetMercType( zone->GetMercTemplate(c->GetMercInfo().MercTemplateID)->MercNPCID, GetRace(), c->GetLevel()); const NPCType* npc_type = database.GetMercType( zone->GetMercTemplate(c->GetMercInfo().MercTemplateID)->MercNPCID, GetRace(), c->GetLevel());
if (npc_type) if (npc_type)
{ {
max_hp = (npc_type->max_hp * npc_type->scalerate) / 100; max_hp = npc_type->max_hp;
base_hp = (npc_type->max_hp * npc_type->scalerate) / 100; base_hp = npc_type->max_hp;
max_mana = (npc_type->Mana * npc_type->scalerate) / 100; max_mana = npc_type->Mana;
base_mana = (npc_type->Mana * npc_type->scalerate) / 100; base_mana = npc_type->Mana;
hp_regen = (npc_type->hp_regen * npc_type->scalerate) / 100; max_end = npc_type->max_hp; // Hack since Endurance does not exist for NPCType yet
mana_regen = (npc_type->mana_regen * npc_type->scalerate) / 100; base_end = npc_type->max_hp; // Hack since Endurance does not exist for NPCType yet
hp_regen = npc_type->hp_regen;
mana_regen = npc_type->mana_regen;
max_dmg = npc_type->max_dmg;
min_dmg = npc_type->min_dmg;
_baseAC = npc_type->AC;
_baseATK = npc_type->ATK;
_baseSTR = npc_type->STR;
_baseSTA = npc_type->STA;
_baseDEX = npc_type->DEX;
_baseAGI = npc_type->AGI;
_baseWIS = npc_type->WIS;
_baseINT = npc_type->INT;
_baseCHA = npc_type->CHA;
_baseATK = npc_type->ATK;
_baseMR = npc_type->MR;
_baseFR = npc_type->FR;
_baseDR = npc_type->DR;
_basePR = npc_type->PR;
_baseCR = npc_type->CR;
_baseCorrup = npc_type->Corrup;
uint32 scalepercent = (int)(npc_type->scalerate * RuleI(Mercs, ScaleRate) / 100);
ScaleStats(scalepercent, setmax);
level = npc_type->level; level = npc_type->level;
max_dmg = (npc_type->max_dmg * npc_type->scalerate) / 100;
min_dmg = (npc_type->min_dmg * npc_type->scalerate) / 100;
_baseSTR = (npc_type->STR * npc_type->scalerate) / 100;
_baseSTA = (npc_type->STA * npc_type->scalerate) / 100;
_baseDEX = (npc_type->DEX * npc_type->scalerate) / 100;
_baseAGI = (npc_type->AGI * npc_type->scalerate) / 100;
_baseWIS = (npc_type->WIS * npc_type->scalerate) / 100;
_baseINT = (npc_type->INT * npc_type->scalerate) / 100;
_baseCHA = (npc_type->CHA * npc_type->scalerate) / 100;
_baseATK = (npc_type->ATK * npc_type->scalerate) / 100;
_baseMR = (npc_type->MR * npc_type->scalerate) / 100;
_baseFR = (npc_type->FR * npc_type->scalerate) / 100;
_baseDR = (npc_type->DR * npc_type->scalerate) / 100;
_basePR = (npc_type->PR * npc_type->scalerate) / 100;
_baseCR = (npc_type->CR * npc_type->scalerate) / 100;
_baseCorrup = (npc_type->Corrup * npc_type->scalerate) / 100;
_baseAC = (npc_type->AC * npc_type->scalerate) / 100;
attack_speed = npc_type->attack_speed;
attack_count = npc_type->attack_count; attack_count = npc_type->attack_count;
attack_speed = npc_type->attack_speed;
spellscale = npc_type->spellscale; spellscale = npc_type->spellscale;
healscale = npc_type->healscale; healscale = npc_type->healscale;
CalcBonuses(); CalcBonuses();
CalcMaxEndurance();
CalcMaxHP(); CalcMaxHP();
CalcMaxMana(); CalcMaxMana();
CalcMaxEndurance();
} }
} }
} }
void Merc::ScaleStats(int scalepercent, bool setmax) {
Log.Out(Logs::General, Logs::Mercenaries, "Scaling Mercenary Stats to %d Percent for %s.", scalepercent, GetName());
if (scalepercent <= 0)
return;
float scalerate = (float)scalepercent / 100.0f;
if ((int)((float)base_hp * scalerate) > 1)
{
max_hp = (int)((float)base_hp * scalerate);
base_hp = max_hp;
if (setmax)
cur_hp = max_hp;
}
if (base_mana)
{
max_mana = (int)((float)base_mana * scalerate);
base_mana = max_mana;
if (setmax)
cur_mana = max_mana;
}
if (base_end)
{
max_end = (int)((float)base_end * scalerate);
base_end = max_end;
if (setmax)
cur_end = max_end;
}
if (_baseAC)
{
AC = (int)((float)_baseAC * scalerate);
_baseAC = AC;
}
if (_baseATK)
{
ATK = (int)((float)_baseATK * scalerate);
_baseATK = ATK;
}
if (_baseSTR)
{
STR = (int)((float)_baseSTR * scalerate);
_baseSTR = STR;
}
if (_baseSTA)
{
STA = (int)((float)_baseSTA * scalerate);
_baseSTA = STA;
}
if (_baseAGI)
{
AGI = (int)((float)_baseAGI * scalerate);
_baseAGI = AGI;
}
if (_baseDEX)
{
DEX = (int)((float)_baseDEX * scalerate);
_baseDEX = DEX;
}
if (_baseINT)
{
INT = (int)((float)_baseINT * scalerate);
_baseINT = INT;
}
if (_baseWIS)
{
WIS = (int)((float)_baseWIS * scalerate);
_baseWIS = WIS;
}
if (_baseCHA)
{
CHA = (int)((float)_baseCHA * scalerate);
_baseCHA = CHA;
}
if (_baseMR)
{
MR = (int)((float)_baseMR * scalerate);
_baseMR = MR;
}
if (_baseCR)
{
CR = (int)((float)_baseCR * scalerate);
_baseCR = CR;
}
if (_baseDR)
{
DR = (int)((float)_baseDR * scalerate);
_baseDR = DR;
}
if (_baseFR)
{
FR = (int)((float)_baseFR * scalerate);
_baseFR = FR;
}
if (_basePR)
{
PR = (int)((float)_basePR * scalerate);
_basePR = PR;
}
if (_baseCorrup)
{
Corrup = (int)((float)_baseCorrup * scalerate);
_baseCorrup = Corrup;
}
if (max_dmg)
{
max_dmg = (int)((float)max_dmg * scalerate);
}
if (min_dmg)
{
min_dmg = (int)((float)min_dmg * scalerate);
}
return;
}
void Merc::UpdateMercAppearance() { void Merc::UpdateMercAppearance() {
// Copied from Bot Code: // Copied from Bot Code:
uint32 itemID = NO_ITEM; uint32 itemID = NO_ITEM;
@@ -4939,7 +5071,7 @@ bool Merc::Spawn(Client *owner) {
SendPosition(); SendPosition();
Log.Out(Logs::General, Logs::Mercenaries, "Spawn Mercenary."); Log.Out(Logs::General, Logs::Mercenaries, "Spawn Mercenary %s.", GetName());
//UpdateMercAppearance(); //UpdateMercAppearance();
@@ -5085,7 +5217,8 @@ void Client::SendMercResponsePackets(uint32 ResponseType)
SendMercMerchantResponsePacket(3); SendMercMerchantResponsePacket(3);
break; break;
} }
Log.Out(Logs::General, Logs::Mercenaries, "SendMercResponsePackets %i.", ResponseType); Log.Out(Logs::General, Logs::Mercenaries, "SendMercResponsePackets %i for %s.", ResponseType, GetName());
} }
void Client::UpdateMercTimer() void Client::UpdateMercTimer()
@@ -5126,7 +5259,7 @@ void Client::UpdateMercTimer()
SendMercResponsePackets(16); SendMercResponsePackets(16);
} }
Log.Out(Logs::General, Logs::Mercenaries, "UpdateMercTimer Complete."); Log.Out(Logs::General, Logs::Mercenaries, "UpdateMercTimer Complete for %s.", GetName());
// Normal upkeep charge message // Normal upkeep charge message
//Message(7, "You have been charged a mercenary upkeep cost of %i plat, and %i gold and your mercenary upkeep cost timer has been reset to 15 minutes.", upkeep_plat, upkeep_gold, (int)(RuleI(Mercs, UpkeepIntervalMS) / 1000 / 60)); //Message(7, "You have been charged a mercenary upkeep cost of %i plat, and %i gold and your mercenary upkeep cost timer has been reset to 15 minutes.", upkeep_plat, upkeep_gold, (int)(RuleI(Mercs, UpkeepIntervalMS) / 1000 / 60));
@@ -5179,7 +5312,7 @@ bool Client::CheckCanHireMerc(Mob* merchant, uint32 template_id) {
} }
} }
Log.Out(Logs::General, Logs::Mercenaries, "CheckCanHireMerc True."); Log.Out(Logs::General, Logs::Mercenaries, "CheckCanHireMerc True for %s.", GetName());
return true; return true;
} }
@@ -5252,7 +5385,7 @@ bool Client::CheckCanSpawnMerc(uint32 template_id) {
return false; return false;
} }
Log.Out(Logs::General, Logs::Mercenaries, "CheckCanSpawnMerc True."); Log.Out(Logs::General, Logs::Mercenaries, "CheckCanSpawnMerc True for %s.", GetName());
return true; return true;
} }
@@ -5274,7 +5407,7 @@ bool Client::CheckCanUnsuspendMerc() {
return false; return false;
} }
Log.Out(Logs::General, Logs::Mercenaries, "CheckCanUnsuspendMerc True."); Log.Out(Logs::General, Logs::Mercenaries, "CheckCanUnsuspendMerc True for %s.", GetName());
return true; return true;
} }
@@ -5289,7 +5422,7 @@ void Client::CheckMercSuspendTimer() {
GetMercInfo().SuspendedTime = 0; GetMercInfo().SuspendedTime = 0;
SendMercResponsePackets(0); SendMercResponsePackets(0);
SendMercSuspendResponsePacket(GetMercInfo().SuspendedTime); SendMercSuspendResponsePacket(GetMercInfo().SuspendedTime);
Log.Out(Logs::General, Logs::Mercenaries, "CheckMercSuspendTimer Ready."); Log.Out(Logs::General, Logs::Mercenaries, "CheckMercSuspendTimer Ready for %s.", GetName());
} }
} }
} }
@@ -5302,7 +5435,7 @@ void Client::SuspendMercCommand() {
{ {
if(!CheckCanUnsuspendMerc()) if(!CheckCanUnsuspendMerc())
{ {
Log.Out(Logs::General, Logs::Mercenaries, "SuspendMercCommand Unable to Unsuspend."); Log.Out(Logs::General, Logs::Mercenaries, "SuspendMercCommand Unable to Unsuspend Merc for %s.", GetName());
return; return;
} }
@@ -5312,13 +5445,13 @@ void Client::SuspendMercCommand() {
if(merc) if(merc)
{ {
SpawnMerc(merc, true); SpawnMerc(merc, true);
Log.Out(Logs::General, Logs::Mercenaries, "SuspendMercCommand Successful Unsuspend."); Log.Out(Logs::General, Logs::Mercenaries, "SuspendMercCommand Successful Unsuspend for %s.", GetName());
} }
else else
{ {
//merc failed to spawn //merc failed to spawn
SendMercResponsePackets(3); SendMercResponsePackets(3);
Log.Out(Logs::General, Logs::Mercenaries, "SuspendMercCommand Failed to Spawn Merc."); Log.Out(Logs::General, Logs::Mercenaries, "SuspendMercCommand Failed to Spawn Merc for %s.", GetName());
} }
} }
else else
@@ -5328,10 +5461,11 @@ void Client::SuspendMercCommand() {
if(CurrentMerc && GetMercID()) if(CurrentMerc && GetMercID())
{ {
CurrentMerc->Suspend(); CurrentMerc->Suspend();
Log.Out(Logs::General, Logs::Mercenaries, "SuspendMercCommand Successful Suspend."); Log.Out(Logs::General, Logs::Mercenaries, "SuspendMercCommand Successful Suspend for %s.", GetName());
} }
else else
{ {
// Reset Merc Suspend State
GetMercInfo().IsSuspended = true; GetMercInfo().IsSuspended = true;
//GetMercInfo().SuspendedTime = time(nullptr) + RuleI(Mercs, SuspendIntervalS); //GetMercInfo().SuspendedTime = time(nullptr) + RuleI(Mercs, SuspendIntervalS);
//GetMercInfo().MercTimerRemaining = GetMercTimer()->GetRemainingTime(); //GetMercInfo().MercTimerRemaining = GetMercTimer()->GetRemainingTime();
@@ -5339,9 +5473,15 @@ void Client::SuspendMercCommand() {
GetMercTimer()->Disable(); GetMercTimer()->Disable();
SendMercSuspendResponsePacket(GetMercInfo().SuspendedTime); SendMercSuspendResponsePacket(GetMercInfo().SuspendedTime);
SendMercTimer(nullptr); SendMercTimer(nullptr);
Log.Out(Logs::General, Logs::Mercenaries, "SuspendMercCommand Failed to Get Merc to Suspend. Resetting Suspend State for %s.", GetName());
} }
} }
} }
else
{
SpawnMercOnZone();
Log.Out(Logs::General, Logs::Mercenaries, "SuspendMercCommand Request Failed to Load Merc for %s. Trying SpawnMercOnZone.", GetName());
}
} }
@@ -5373,7 +5513,7 @@ void Client::SpawnMercOnZone() {
{ {
SpawnMerc(merc, false); SpawnMerc(merc, false);
} }
Log.Out(Logs::General, Logs::Mercenaries, "SpawnMercOnZone Normal Merc."); Log.Out(Logs::General, Logs::Mercenaries, "SpawnMercOnZone Normal Merc for %s.", GetName());
} }
else else
{ {
@@ -5389,7 +5529,7 @@ void Client::SpawnMercOnZone() {
// Send Mercenary Status/Timer packet // Send Mercenary Status/Timer packet
SendMercTimer(GetMerc()); SendMercTimer(GetMerc());
Log.Out(Logs::General, Logs::Mercenaries, "SpawnMercOnZone Suspended Merc."); Log.Out(Logs::General, Logs::Mercenaries, "SpawnMercOnZone Suspended Merc for %s.", GetName());
} }
} }
else else
@@ -5397,6 +5537,7 @@ void Client::SpawnMercOnZone() {
// No Merc Hired // No Merc Hired
// RoF+ displays a message from the following packet, which seems useless // RoF+ displays a message from the following packet, which seems useless
//SendClearMercInfo(); //SendClearMercInfo();
Log.Out(Logs::General, Logs::Mercenaries, "SpawnMercOnZone Failed to load Merc Info from the Database for %s.", GetName());
} }
} }
@@ -5410,17 +5551,17 @@ void Client::SendMercTimer(Merc* merc) {
if (!merc) if (!merc)
{ {
SendMercTimerPacket(NO_MERC_ID, MERC_STATE_SUSPENDED, GetMercInfo().SuspendedTime, GetMercInfo().MercTimerRemaining, RuleI(Mercs, SuspendIntervalMS)); SendMercTimerPacket(NO_MERC_ID, MERC_STATE_SUSPENDED, GetMercInfo().SuspendedTime, GetMercInfo().MercTimerRemaining, RuleI(Mercs, SuspendIntervalMS));
Log.Out(Logs::General, Logs::Mercenaries, "SendMercTimer No Merc."); Log.Out(Logs::General, Logs::Mercenaries, "SendMercTimer No Merc for %s.", GetName());
} }
else if (merc->IsSuspended()) else if (merc->IsSuspended())
{ {
SendMercTimerPacket(NO_MERC_ID, MERC_STATE_SUSPENDED, GetMercInfo().SuspendedTime, GetMercInfo().MercTimerRemaining, RuleI(Mercs, SuspendIntervalMS)); SendMercTimerPacket(NO_MERC_ID, MERC_STATE_SUSPENDED, GetMercInfo().SuspendedTime, GetMercInfo().MercTimerRemaining, RuleI(Mercs, SuspendIntervalMS));
Log.Out(Logs::General, Logs::Mercenaries, "SendMercTimer Suspended Merc."); Log.Out(Logs::General, Logs::Mercenaries, "SendMercTimer Suspended Merc for %s.", GetName());
} }
else else
{ {
SendMercTimerPacket(merc->GetID(), MERC_STATE_NORMAL, NOT_SUSPENDED_TIME, GetMercInfo().MercTimerRemaining, RuleI(Mercs, SuspendIntervalMS)); SendMercTimerPacket(merc->GetID(), MERC_STATE_NORMAL, NOT_SUSPENDED_TIME, GetMercInfo().MercTimerRemaining, RuleI(Mercs, SuspendIntervalMS));
Log.Out(Logs::General, Logs::Mercenaries, "SendMercTimer Normal Merc."); Log.Out(Logs::General, Logs::Mercenaries, "SendMercTimer Normal Merc for %s.", GetName());
} }
} }
@@ -5442,7 +5583,7 @@ void Client::SpawnMerc(Merc* merc, bool setMaxStats) {
merc->Unsuspend(setMaxStats); merc->Unsuspend(setMaxStats);
merc->SetStance(GetMercInfo().Stance); merc->SetStance(GetMercInfo().Stance);
Log.Out(Logs::General, Logs::Mercenaries, "SpawnMerc Success."); Log.Out(Logs::General, Logs::Mercenaries, "SpawnMerc Success for %s.", GetName());
return; return;
@@ -5471,7 +5612,7 @@ bool Merc::Suspend() {
// Start the timer to send the packet that refreshes the Unsuspend Button // Start the timer to send the packet that refreshes the Unsuspend Button
mercOwner->GetPTimers().Start(pTimerMercSuspend, RuleI(Mercs, SuspendIntervalS)); mercOwner->GetPTimers().Start(pTimerMercSuspend, RuleI(Mercs, SuspendIntervalS));
Log.Out(Logs::General, Logs::Mercenaries, "Suspend Complete."); Log.Out(Logs::General, Logs::Mercenaries, "Suspend Complete for %s.", mercOwner->GetName());
return true; return true;
} }
@@ -5557,12 +5698,12 @@ bool Client::DismissMerc(uint32 MercID) {
bool Dismissed = true; bool Dismissed = true;
if (!database.DeleteMerc(MercID)) if (!database.DeleteMerc(MercID))
{ {
Log.Out(Logs::General, Logs::Mercenaries, "Dismiss Failed for MercID %i", MercID); Log.Out(Logs::General, Logs::Mercenaries, "Dismiss Failed Database Query for MercID: %i, Client: %s.", MercID, GetName());
Dismissed = false; Dismissed = false;
} }
else else
{ {
Log.Out(Logs::General, Logs::Mercenaries, "Dismiss Successful."); Log.Out(Logs::General, Logs::Mercenaries, "Dismiss Successful for %s.", GetName());
} }
if (GetMerc()) if (GetMerc())
@@ -5719,13 +5860,13 @@ bool Merc::MercJoinClientGroup() {
database.SetGroupLeaderName(g->GetID(), mercOwner->GetName()); database.SetGroupLeaderName(g->GetID(), mercOwner->GetName());
database.RefreshGroupFromDB(mercOwner); database.RefreshGroupFromDB(mercOwner);
g->SaveGroupLeaderAA(); g->SaveGroupLeaderAA();
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary joined new group."); Log.Out(Logs::General, Logs::Mercenaries, "Mercenary joined new group: %s (%s).", GetName(), mercOwner->GetName());
} }
else else
{ {
g->DisbandGroup(); g->DisbandGroup();
Suspend(); Suspend();
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary disbanded new group."); Log.Out(Logs::General, Logs::Mercenaries, "Mercenary disbanded new group: %s (%s).", GetName(), mercOwner->GetName());
} }
} }
@@ -5735,12 +5876,12 @@ bool Merc::MercJoinClientGroup() {
database.RefreshGroupFromDB(mercOwner); database.RefreshGroupFromDB(mercOwner);
// Update members that are out of zone // Update members that are out of zone
GetGroup()->SendGroupJoinOOZ(this); GetGroup()->SendGroupJoinOOZ(this);
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary joined existing group."); Log.Out(Logs::General, Logs::Mercenaries, "Mercenary %s joined existing group with %s.", GetName(), mercOwner->GetName());
} }
else else
{ {
Suspend(); Suspend();
Log.Out(Logs::General, Logs::Mercenaries, "Mercenary failed to join the group - Suspending"); Log.Out(Logs::General, Logs::Mercenaries, "Mercenary failed to join the group - Suspending %s for (%s).", GetName(), mercOwner->GetName());
} }
} }
@@ -5791,7 +5932,7 @@ Merc* Client::GetMerc() {
if(GetMercID() == 0) if(GetMercID() == 0)
{ {
Log.Out(Logs::Detail, Logs::Mercenaries, "GetMerc 0."); Log.Out(Logs::Detail, Logs::Mercenaries, "GetMerc - GetMercID: 0 for %s.", GetName());
return (nullptr); return (nullptr);
} }
@@ -5799,14 +5940,14 @@ Merc* Client::GetMerc() {
if(tmp == nullptr) if(tmp == nullptr)
{ {
SetMercID(0); SetMercID(0);
Log.Out(Logs::Detail, Logs::Mercenaries, "GetMerc No Merc."); Log.Out(Logs::Detail, Logs::Mercenaries, "GetMerc No Merc for %s.", GetName());
return (nullptr); return (nullptr);
} }
if(tmp->GetOwnerID() != GetID()) if(tmp->GetOwnerID() != GetID())
{ {
SetMercID(0); SetMercID(0);
Log.Out(Logs::Detail, Logs::Mercenaries, "GetMerc Owner Mismatch."); Log.Out(Logs::Detail, Logs::Mercenaries, "GetMerc Owner Mismatch - OwnerID: %d, ClientID: %d, Client: %s.", tmp->GetOwnerID(), GetID(), GetName());
return (nullptr); return (nullptr);
} }
@@ -5824,7 +5965,7 @@ uint8 Client::GetNumMercs() {
numMercs++; numMercs++;
} }
} }
Log.Out(Logs::General, Logs::Mercenaries, "GetNumMercs %i.", numMercs); Log.Out(Logs::General, Logs::Mercenaries, "GetNumMercs Number: %i for %s.", numMercs, GetName());
return numMercs; return numMercs;
} }
@@ -5865,7 +6006,7 @@ void Client::SetMerc(Merc* newmerc) {
GetMercInfo().Gender = 0; GetMercInfo().Gender = 0;
GetMercInfo().State = 0; GetMercInfo().State = 0;
memset(GetMercInfo().merc_name, 0, 64); memset(GetMercInfo().merc_name, 0, 64);
Log.Out(Logs::General, Logs::Mercenaries, "SetMerc No Merc."); Log.Out(Logs::General, Logs::Mercenaries, "SetMerc No Merc for %s.", GetName());
} }
else else
{ {
@@ -5882,7 +6023,7 @@ void Client::SetMerc(Merc* newmerc) {
GetMercInfo().Gender = newmerc->GetGender(); GetMercInfo().Gender = newmerc->GetGender();
GetMercInfo().State = newmerc->IsSuspended() ? MERC_STATE_SUSPENDED : MERC_STATE_NORMAL; GetMercInfo().State = newmerc->IsSuspended() ? MERC_STATE_SUSPENDED : MERC_STATE_NORMAL;
snprintf(GetMercInfo().merc_name, 64, "%s", newmerc->GetName()); snprintf(GetMercInfo().merc_name, 64, "%s", newmerc->GetName());
Log.Out(Logs::General, Logs::Mercenaries, "SetMerc New Merc."); Log.Out(Logs::General, Logs::Mercenaries, "SetMerc New Merc for %s.", GetName());
} }
} }
@@ -5890,7 +6031,8 @@ void Client::UpdateMercLevel() {
Merc* merc = GetMerc(); Merc* merc = GetMerc();
if (merc) if (merc)
{ {
merc->UpdateMercStats(this); merc->UpdateMercStats(this, false);
merc->SendAppearancePacket(AT_WhoLevel, GetLevel(), true, true);
} }
} }
@@ -5902,7 +6044,7 @@ void Client::SendMercMerchantResponsePacket(int32 response_type) {
MercenaryMerchantResponse_Struct* mmr = (MercenaryMerchantResponse_Struct*)outapp->pBuffer; MercenaryMerchantResponse_Struct* mmr = (MercenaryMerchantResponse_Struct*)outapp->pBuffer;
mmr->ResponseType = response_type; // send specified response type mmr->ResponseType = response_type; // send specified response type
FastQueuePacket(&outapp); FastQueuePacket(&outapp);
Log.Out(Logs::Moderate, Logs::Mercenaries, "Sent SendMercMerchantResponsePacket %i.", response_type); Log.Out(Logs::Moderate, Logs::Mercenaries, "Sent SendMercMerchantResponsePacket ResponseType: %i, Client: %s.", response_type, GetName());
} }
} }
@@ -5911,7 +6053,7 @@ void Client::SendMercenaryUnknownPacket(uint8 type) {
EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenaryUnknown1, 1); EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenaryUnknown1, 1);
outapp->WriteUInt8(type); outapp->WriteUInt8(type);
FastQueuePacket(&outapp); FastQueuePacket(&outapp);
Log.Out(Logs::Moderate, Logs::Mercenaries, "Sent SendMercenaryUnknownPacket %i.", type); Log.Out(Logs::Moderate, Logs::Mercenaries, "Sent SendMercenaryUnknownPacket Type: %i, Client: %s.", type, GetName());
} }
@@ -5920,7 +6062,7 @@ void Client::SendMercenaryUnsuspendPacket(uint8 type) {
EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenaryUnsuspendResponse, 1); EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenaryUnsuspendResponse, 1);
outapp->WriteUInt8(type); outapp->WriteUInt8(type);
FastQueuePacket(&outapp); FastQueuePacket(&outapp);
Log.Out(Logs::Moderate, Logs::Mercenaries, "Sent SendMercenaryUnsuspendPacket %i.", type); Log.Out(Logs::Moderate, Logs::Mercenaries, "Sent SendMercenaryUnsuspendPacket Type: %i, Client: %s.", type, GetName());
} }
@@ -5930,7 +6072,7 @@ void Client::SendMercSuspendResponsePacket(uint32 suspended_time) {
SuspendMercenaryResponse_Struct* smr = (SuspendMercenaryResponse_Struct*)outapp->pBuffer; SuspendMercenaryResponse_Struct* smr = (SuspendMercenaryResponse_Struct*)outapp->pBuffer;
smr->SuspendTime = suspended_time; // Seen 0 (not suspended) or c9 c2 64 4f (suspended on Sat Mar 17 11:58:49 2012) - Unix Timestamp smr->SuspendTime = suspended_time; // Seen 0 (not suspended) or c9 c2 64 4f (suspended on Sat Mar 17 11:58:49 2012) - Unix Timestamp
FastQueuePacket(&outapp); FastQueuePacket(&outapp);
Log.Out(Logs::Moderate, Logs::Mercenaries, "Sent SendMercSuspendResponsePacket %i.", suspended_time); Log.Out(Logs::Moderate, Logs::Mercenaries, "Sent SendMercSuspendResponsePacket Time: %i, Client: %s.", suspended_time, GetName());
} }
@@ -5945,7 +6087,7 @@ void Client::SendMercTimerPacket(int32 entity_id, int32 merc_state, int32 suspen
mss->UpdateInterval = update_interval; // Seen 900000 - 15 minutes in ms mss->UpdateInterval = update_interval; // Seen 900000 - 15 minutes in ms
mss->MercUnk01 = unk01; // Seen 180000 - 3 minutes in ms - Used for the unsuspend button refresh timer mss->MercUnk01 = unk01; // Seen 180000 - 3 minutes in ms - Used for the unsuspend button refresh timer
FastQueuePacket(&outapp); FastQueuePacket(&outapp);
Log.Out(Logs::Moderate, Logs::Mercenaries, "Sent SendMercTimerPacket %i, %i, %i, %i, %i.", entity_id, merc_state, suspended_time, update_interval, unk01); Log.Out(Logs::Moderate, Logs::Mercenaries, "Sent SendMercTimerPacket EndID: %i, State: %i, SuspendTime: %i, Interval: %i, Unk1: %i, Client: %s.", entity_id, merc_state, suspended_time, update_interval, unk01, GetName());
} }
@@ -5956,7 +6098,7 @@ void Client::SendMercAssignPacket(uint32 entityID, uint32 unk01, uint32 unk02) {
mas->MercUnk01 = unk01; mas->MercUnk01 = unk01;
mas->MercUnk02 = unk02; mas->MercUnk02 = unk02;
FastQueuePacket(&outapp); FastQueuePacket(&outapp);
Log.Out(Logs::Moderate, Logs::Mercenaries, "Sent SendMercAssignPacket %i, %i, %i.", entityID, unk01, unk02); Log.Out(Logs::Moderate, Logs::Mercenaries, "Sent SendMercAssignPacket EndID: %i, Unk1: %i, Unk2: %i, Client: %s.", entityID, unk01, unk02, GetName());
} }
void NPC::LoadMercTypes() { void NPC::LoadMercTypes() {
+3 -1
View File
@@ -137,7 +137,7 @@ public:
virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho); virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
static Merc* LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id, bool updateFromDB = false); static Merc* LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id, bool updateFromDB = false);
void UpdateMercInfo(Client *c); void UpdateMercInfo(Client *c);
void UpdateMercStats(Client *c); void UpdateMercStats(Client *c, bool setmax = false);
void UpdateMercAppearance(); void UpdateMercAppearance();
virtual void UpdateEquipLightValue(); virtual void UpdateEquipLightValue();
void AddItem(uint8 slot, uint32 item_id); void AddItem(uint8 slot, uint32 item_id);
@@ -189,6 +189,7 @@ public:
bool TryHide(); bool TryHide();
// stat functions // stat functions
virtual void ScaleStats(int scalepercent, bool setmax = false);
virtual void CalcBonuses(); virtual void CalcBonuses();
int32 GetEndurance() const {return cur_end;} //This gets our current endurance int32 GetEndurance() const {return cur_end;} //This gets our current endurance
inline virtual int32 GetAC() const { return AC; } inline virtual int32 GetAC() const { return AC; }
@@ -347,6 +348,7 @@ private:
// Private "base stats" Members // Private "base stats" Members
int32 base_mana; int32 base_mana;
int32 base_end;
int32 _baseAC; int32 _baseAC;
uint32 _baseSTR; uint32 _baseSTR;
uint32 _baseSTA; uint32 _baseSTA;
+9 -8
View File
@@ -25,6 +25,7 @@
#include "position.h" #include "position.h"
#include <set> #include <set>
#include <vector> #include <vector>
#include <memory>
char* strn0cpy(char* dest, const char* source, uint32 size); char* strn0cpy(char* dest, const char* source, uint32 size);
@@ -879,8 +880,8 @@ public:
virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther) { return FACTION_INDIFFERENT; } virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther) { return FACTION_INDIFFERENT; }
inline bool IsTrackable() const { return(trackable); } inline bool IsTrackable() const { return(trackable); }
Timer* GetAIThinkTimer() { return AIthink_timer; } Timer* GetAIThinkTimer() { return AIthink_timer.get(); }
Timer* GetAIMovementTimer() { return AImovement_timer; } Timer* GetAIMovementTimer() { return AImovement_timer.get(); }
Timer GetAttackTimer() { return attack_timer; } Timer GetAttackTimer() { return attack_timer; }
Timer GetAttackDWTimer() { return attack_dw_timer; } Timer GetAttackDWTimer() { return attack_dw_timer; }
inline bool IsFindable() { return findable; } inline bool IsFindable() { return findable; }
@@ -1170,14 +1171,14 @@ protected:
uint32 maxLastFightingDelayMoving; uint32 maxLastFightingDelayMoving;
float pAggroRange; float pAggroRange;
float pAssistRange; float pAssistRange;
Timer* AIthink_timer; std::unique_ptr<Timer> AIthink_timer;
Timer* AImovement_timer; std::unique_ptr<Timer> AImovement_timer;
Timer* AItarget_check_timer; std::unique_ptr<Timer> AItarget_check_timer;
bool movetimercompleted; bool movetimercompleted;
bool permarooted; bool permarooted;
Timer* AIscanarea_timer; std::unique_ptr<Timer> AIscanarea_timer;
Timer* AIwalking_timer; std::unique_ptr<Timer> AIwalking_timer;
Timer* AIfeignremember_timer; std::unique_ptr<Timer> AIfeignremember_timer;
uint32 pLastFightingDelayMoving; uint32 pLastFightingDelayMoving;
HateList hate_list; HateList hate_list;
std::set<uint32> feign_memory_list; std::set<uint32> feign_memory_list;
+30 -30
View File
@@ -422,14 +422,15 @@ bool EntityList::AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float
return false; return false;
} }
void Mob::AI_Init() { void Mob::AI_Init()
{
pAIControlled = false; pAIControlled = false;
AIthink_timer = 0; AIthink_timer.reset(nullptr);
AIwalking_timer = 0; AIwalking_timer.reset(nullptr);
AImovement_timer = 0; AImovement_timer.reset(nullptr);
AItarget_check_timer = 0; AItarget_check_timer.reset(nullptr);
AIfeignremember_timer = nullptr; AIfeignremember_timer.reset(nullptr);
AIscanarea_timer = 0; AIscanarea_timer.reset(nullptr);
minLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMin); minLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMin);
maxLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMax); maxLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMax);
@@ -441,10 +442,9 @@ void Mob::AI_Init() {
pDontCureMeBefore = 0; pDontCureMeBefore = 0;
} }
void NPC::AI_Init() { void NPC::AI_Init()
Mob::AI_Init(); {
AIautocastspell_timer.reset(nullptr);
AIautocastspell_timer = 0;
casting_spell_AIindex = static_cast<uint8>(AIspells.size()); casting_spell_AIindex = static_cast<uint8>(AIspells.size());
roambox_max_x = 0; roambox_max_x = 0;
@@ -458,8 +458,8 @@ void NPC::AI_Init() {
roambox_delay = 2500; roambox_delay = 2500;
} }
void Client::AI_Init() { void Client::AI_Init()
Mob::AI_Init(); {
minLastFightingDelayMoving = CLIENT_LD_TIMEOUT; minLastFightingDelayMoving = CLIENT_LD_TIMEOUT;
maxLastFightingDelayMoving = CLIENT_LD_TIMEOUT; maxLastFightingDelayMoving = CLIENT_LD_TIMEOUT;
} }
@@ -474,13 +474,13 @@ void Mob::AI_Start(uint32 iMoveDelay) {
pLastFightingDelayMoving = 0; pLastFightingDelayMoving = 0;
pAIControlled = true; pAIControlled = true;
AIthink_timer = new Timer(AIthink_duration); AIthink_timer = std::unique_ptr<Timer>(new Timer(AIthink_duration));
AIthink_timer->Trigger(); AIthink_timer->Trigger();
AIwalking_timer = new Timer(0); AIwalking_timer = std::unique_ptr<Timer>(new Timer(0));
AImovement_timer = new Timer(AImovement_duration); AImovement_timer = std::unique_ptr<Timer>(new Timer(AImovement_duration));
AItarget_check_timer = new Timer(AItarget_check_duration); AItarget_check_timer = std::unique_ptr<Timer>(new Timer(AItarget_check_duration));
AIfeignremember_timer = new Timer(AIfeignremember_delay); AIfeignremember_timer = std::unique_ptr<Timer>(new Timer(AIfeignremember_delay));
AIscanarea_timer = new Timer(AIscanarea_delay); AIscanarea_timer = std::unique_ptr<Timer>(new Timer(AIscanarea_delay));
#ifdef REVERSE_AGGRO #ifdef REVERSE_AGGRO
if(IsNPC() && !CastToNPC()->WillAggroNPCs()) if(IsNPC() && !CastToNPC()->WillAggroNPCs())
AIscanarea_timer->Disable(); AIscanarea_timer->Disable();
@@ -516,10 +516,10 @@ void NPC::AI_Start(uint32 iMoveDelay) {
return; return;
if (AIspells.size() == 0) { if (AIspells.size() == 0) {
AIautocastspell_timer = new Timer(1000); AIautocastspell_timer = std::unique_ptr<Timer>(new Timer(1000));
AIautocastspell_timer->Disable(); AIautocastspell_timer->Disable();
} else { } else {
AIautocastspell_timer = new Timer(750); AIautocastspell_timer = std::unique_ptr<Timer>(new Timer(750));
AIautocastspell_timer->Start(RandomTimer(0, 15000), false); AIautocastspell_timer->Start(RandomTimer(0, 15000), false);
} }
@@ -540,19 +540,19 @@ void Mob::AI_Stop() {
pAIControlled = false; pAIControlled = false;
safe_delete(AIthink_timer); AIthink_timer.reset(nullptr);
safe_delete(AIwalking_timer); AIwalking_timer.reset(nullptr);
safe_delete(AImovement_timer); AImovement_timer.reset(nullptr);
safe_delete(AItarget_check_timer); AItarget_check_timer.reset(nullptr);
safe_delete(AIscanarea_timer); AIscanarea_timer.reset(nullptr);
safe_delete(AIfeignremember_timer); AIfeignremember_timer.reset(nullptr);
hate_list.WipeHateList(); hate_list.WipeHateList();
} }
void NPC::AI_Stop() { void NPC::AI_Stop() {
Waypoints.clear(); Waypoints.clear();
safe_delete(AIautocastspell_timer); AIautocastspell_timer.reset(nullptr);
} }
void Client::AI_Stop() { void Client::AI_Stop() {
@@ -2657,7 +2657,7 @@ DBnpcspells_Struct* ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID) {
npc_spells_cache = new DBnpcspells_Struct*[npc_spells_maxid+1]; npc_spells_cache = new DBnpcspells_Struct*[npc_spells_maxid+1];
npc_spells_loadtried = new bool[npc_spells_maxid+1]; npc_spells_loadtried = new bool[npc_spells_maxid+1];
for (uint32 i=0; i<=npc_spells_maxid; i++) { for (uint32 i=0; i<=npc_spells_maxid; i++) {
npc_spells_cache[i] = 0; npc_spells_cache[i] = nullptr;
npc_spells_loadtried[i] = false; npc_spells_loadtried[i] = false;
} }
} }
@@ -2795,7 +2795,7 @@ DBnpcspellseffects_Struct *ZoneDatabase::GetNPCSpellsEffects(uint32 iDBSpellsEff
npc_spellseffects_cache = new DBnpcspellseffects_Struct *[npc_spellseffects_maxid + 1]; npc_spellseffects_cache = new DBnpcspellseffects_Struct *[npc_spellseffects_maxid + 1];
npc_spellseffects_loadtried = new bool[npc_spellseffects_maxid + 1]; npc_spellseffects_loadtried = new bool[npc_spellseffects_maxid + 1];
for (uint32 i = 0; i <= npc_spellseffects_maxid; i++) { for (uint32 i = 0; i <= npc_spellseffects_maxid; i++) {
npc_spellseffects_cache[i] = 0; npc_spellseffects_cache[i] = nullptr;
npc_spellseffects_loadtried[i] = false; npc_spellseffects_loadtried[i] = false;
} }
} }
+2 -2
View File
@@ -250,8 +250,8 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, const glm::vec4& position, int if
npc_aggro = d->npc_aggro; npc_aggro = d->npc_aggro;
if(!IsMerc()) AI_Init();
AI_Start(); AI_Start();
d_melee_texture1 = d->d_melee_texture1; d_melee_texture1 = d->d_melee_texture1;
d_melee_texture2 = d->d_melee_texture2; d_melee_texture2 = d->d_melee_texture2;
+2 -2
View File
@@ -436,7 +436,7 @@ protected:
uint32 npc_spells_id; uint32 npc_spells_id;
uint8 casting_spell_AIindex; uint8 casting_spell_AIindex;
Timer* AIautocastspell_timer; std::unique_ptr<Timer> AIautocastspell_timer;
uint32* pDontCastBefore_casting_spell; uint32* pDontCastBefore_casting_spell;
std::vector<AISpells_Struct> AIspells; std::vector<AISpells_Struct> AIspells;
bool HasAISpell; bool HasAISpell;
@@ -444,7 +444,7 @@ protected:
virtual bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0); virtual bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0);
AISpellsVar_Struct AISpellVar; AISpellsVar_Struct AISpellVar;
int16 GetFocusEffect(focusType type, uint16 spell_id); int16 GetFocusEffect(focusType type, uint16 spell_id);
uint32 npc_spells_effects_id; uint32 npc_spells_effects_id;
std::vector<AISpellsEffects_Struct> AIspellsEffects; std::vector<AISpellsEffects_Struct> AIspellsEffects;
bool HasAISpellEffects; bool HasAISpellEffects;
+2 -2
View File
@@ -857,7 +857,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite
if (IsClient()){ if (IsClient()){
_RangeWeapon = CastToClient()->m_inv[MainRange]; _RangeWeapon = CastToClient()->m_inv[MainRange];
if (_RangeWeapon && !_RangeWeapon->GetItem() && _RangeWeapon->GetItem()->ID == range_id) if (_RangeWeapon && _RangeWeapon->GetItem() && _RangeWeapon->GetItem()->ID == range_id)
RangeWeapon = _RangeWeapon; RangeWeapon = _RangeWeapon;
_Ammo = CastToClient()->m_inv[AmmoSlot]; _Ammo = CastToClient()->m_inv[AmmoSlot];
@@ -996,7 +996,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite
} }
if (LaunchProjectile) if (LaunchProjectile)
return;//Shouldn't reach this point, but just in case. return;//Shouldn't reach this point durring initial launch phase, but just in case.
//Weapon Proc //Weapon Proc
if(RangeWeapon && other && !other->HasDied()) if(RangeWeapon && other && !other->HasDied())
+97 -30
View File
@@ -1996,6 +1996,7 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client
"m_stats.AC, " "m_stats.AC, "
"m_stats.ATK, " "m_stats.ATK, "
"m_stats.Accuracy, " "m_stats.Accuracy, "
"m_stats.statscale, "
"m_stats.spellscale, " "m_stats.spellscale, "
"m_stats.healscale " "m_stats.healscale "
"FROM merc_stats m_stats " "FROM merc_stats m_stats "
@@ -2119,9 +2120,9 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client
tmpNPCType->AC = atoi(row[40]); tmpNPCType->AC = atoi(row[40]);
tmpNPCType->ATK = atoi(row[41]); tmpNPCType->ATK = atoi(row[41]);
tmpNPCType->accuracy_rating = atoi(row[42]); tmpNPCType->accuracy_rating = atoi(row[42]);
tmpNPCType->scalerate = RuleI(Mercs, ScaleRate); tmpNPCType->scalerate = atoi(row[43]);
tmpNPCType->spellscale = atoi(row[43]); tmpNPCType->spellscale = atoi(row[44]);
tmpNPCType->healscale = atoi(row[44]); tmpNPCType->healscale = atoi(row[45]);
// If Merc with duplicate NPC id already in table, // If Merc with duplicate NPC id already in table,
// free item we attempted to add. // free item we attempted to add.
@@ -3413,38 +3414,102 @@ void ZoneDatabase::MarkCorpseAsRezzed(uint32 db_id) {
uint32 ZoneDatabase::SaveCharacterCorpse(uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, PlayerCorpse_Struct* dbpc, const glm::vec4& position) { uint32 ZoneDatabase::SaveCharacterCorpse(uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, PlayerCorpse_Struct* dbpc, const glm::vec4& position) {
/* Dump Basic Corpse Data */ /* Dump Basic Corpse Data */
std::string query = StringFormat("INSERT INTO `character_corpses` " std::string query = StringFormat(
"SET `charname` = '%s', `zone_id` = %u, `instance_id` = %u, `charid` = %d," "INSERT INTO `character_corpses` "
"`x` = %1.1f, `y` = %1.1f, `z` = %1.1f, `heading` = %1.1f," "SET `charname` = '%s', "
"`time_of_death` = NOW(), `is_buried` = 0, `is_locked` = %d," "`zone_id` = %u, "
"`exp` = %u, `size` = %f, `level` = %u, `race` = %u, `gender` = %u," "`instance_id` = %u, "
"`class` = %u, `deity` = %u, `texture` = %u, `helm_texture` = %u," "`charid` = %d, "
"`copper` = %u, `silver` = %u,`gold` = %u,`platinum` = %u," "`x` = %1.1f, "
"`hair_color` = %u, `beard_color` = %u, `eye_color_1` = %u," "`y` = %1.1f, "
"`eye_color_2` = %u, `hair_style` = %u, `face` = %u," "`z` = %1.1f, "
"`beard` = %u, `drakkin_heritage` = %u, `drakkin_tattoo` = %u," "`heading` = %1.1f, "
"`drakkin_details` = %u, `wc_1` = %u, `wc_2` = %u," "`time_of_death` = NOW(), "
"`wc_3` = %u, `wc_4` = %u, `wc_5` = %u, `wc_6` = %u," "`is_buried` = 0, "
"`wc_7` = %u,`wc_8` = %u,`wc_9` = %u", "`is_locked` = %d, "
EscapeString(charname).c_str(), zoneid, instanceid, charid, "`exp` = %u, "
position.x, position.y, position.z, position.w, "`size` = %f, "
dbpc->locked, dbpc->exp, dbpc->size, dbpc->level, dbpc->race, "`level` = %u, "
dbpc->gender, dbpc->class_, dbpc->deity, dbpc->texture, "`race` = %u, "
dbpc->helmtexture, dbpc->copper, dbpc->silver, dbpc->gold, "`gender` = %u, "
dbpc->plat, dbpc->haircolor, dbpc->beardcolor, dbpc->eyecolor1, "`class` = %u, "
dbpc->eyecolor2, dbpc->hairstyle, dbpc->face, dbpc->beard, "`deity` = %u, "
dbpc->drakkin_heritage, dbpc->drakkin_tattoo, dbpc->drakkin_details, "`texture` = %u, "
dbpc->item_tint[0].color, dbpc->item_tint[1].color, dbpc->item_tint[2].color, "`helm_texture` = %u, "
dbpc->item_tint[3].color, dbpc->item_tint[4].color, dbpc->item_tint[5].color, "`copper` = %u, "
dbpc->item_tint[6].color, dbpc->item_tint[7].color, dbpc->item_tint[8].color); "`silver` = %u, "
"`gold` = %u, "
"`platinum` = %u, "
"`hair_color` = %u, "
"`beard_color` = %u, "
"`eye_color_1` = %u, "
"`eye_color_2` = %u, "
"`hair_style` = %u, "
"`face` = %u, "
"`beard` = %u, "
"`drakkin_heritage` = %u, "
"`drakkin_tattoo` = %u, "
"`drakkin_details` = %u, "
"`wc_1` = %u, "
"`wc_2` = %u, "
"`wc_3` = %u, "
"`wc_4` = %u, "
"`wc_5` = %u, "
"`wc_6` = %u, "
"`wc_7` = %u, "
"`wc_8` = %u, "
"`wc_9` = %u ",
EscapeString(charname).c_str(),
zoneid,
instanceid,
charid,
position.x,
position.y,
position.z,
position.w,
dbpc->locked,
dbpc->exp,
dbpc->size,
dbpc->level,
dbpc->race,
dbpc->gender,
dbpc->class_,
dbpc->deity,
dbpc->texture,
dbpc->helmtexture,
dbpc->copper,
dbpc->silver,
dbpc->gold,
dbpc->plat,
dbpc->haircolor,
dbpc->beardcolor,
dbpc->eyecolor1,
dbpc->eyecolor2,
dbpc->hairstyle,
dbpc->face,
dbpc->beard,
dbpc->drakkin_heritage,
dbpc->drakkin_tattoo,
dbpc->drakkin_details,
dbpc->item_tint[0].color,
dbpc->item_tint[1].color,
dbpc->item_tint[2].color,
dbpc->item_tint[3].color,
dbpc->item_tint[4].color,
dbpc->item_tint[5].color,
dbpc->item_tint[6].color,
dbpc->item_tint[7].color,
dbpc->item_tint[8].color
);
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
uint32 last_insert_id = results.LastInsertedID(); uint32 last_insert_id = results.LastInsertedID();
std::string corpse_items_query;
/* Dump Items from Inventory */ /* Dump Items from Inventory */
uint8 first_entry = 0; uint8 first_entry = 0;
for (unsigned int i = 0; i < dbpc->itemcount; i++) { for (unsigned int i = 0; i < dbpc->itemcount; i++) {
if (first_entry != 1){ if (first_entry != 1){
query = StringFormat("REPLACE INTO `character_corpse_items` \n" corpse_items_query = StringFormat("REPLACE INTO `character_corpse_items` \n"
" (corpse_id, equip_slot, item_id, charges, aug_1, aug_2, aug_3, aug_4, aug_5, aug_6, attuned) \n" " (corpse_id, equip_slot, item_id, charges, aug_1, aug_2, aug_3, aug_4, aug_5, aug_6, attuned) \n"
" VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n", " VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n",
last_insert_id, last_insert_id,
@@ -3462,7 +3527,7 @@ uint32 ZoneDatabase::SaveCharacterCorpse(uint32 charid, const char* charname, ui
first_entry = 1; first_entry = 1;
} }
else{ else{
query = query + StringFormat(", (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n", corpse_items_query = corpse_items_query + StringFormat(", (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n",
last_insert_id, last_insert_id,
dbpc->items[i].equip_slot, dbpc->items[i].equip_slot,
dbpc->items[i].item_id, dbpc->items[i].item_id,
@@ -3477,7 +3542,9 @@ uint32 ZoneDatabase::SaveCharacterCorpse(uint32 charid, const char* charname, ui
); );
} }
} }
auto sc_results = QueryDatabase(query); if (!corpse_items_query.empty())
QueryDatabase(corpse_items_query);
return last_insert_id; return last_insert_id;
} }