From 7dcd12fb9dd13a3b33a97618877ee7bba3155608 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 27 Jan 2015 19:32:49 -0500 Subject: [PATCH 01/11] clang-modernize use-nullptr on zone/mob_ai.cpp --- zone/mob_ai.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 59ee8825b..ea2bdc3d5 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -424,12 +424,12 @@ bool EntityList::AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float void Mob::AI_Init() { pAIControlled = false; - AIthink_timer = 0; - AIwalking_timer = 0; - AImovement_timer = 0; - AItarget_check_timer = 0; + AIthink_timer = nullptr; + AIwalking_timer = nullptr; + AImovement_timer = nullptr; + AItarget_check_timer = nullptr; AIfeignremember_timer = nullptr; - AIscanarea_timer = 0; + AIscanarea_timer = nullptr; minLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMin); maxLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMax); @@ -444,7 +444,7 @@ void Mob::AI_Init() { void NPC::AI_Init() { Mob::AI_Init(); - AIautocastspell_timer = 0; + AIautocastspell_timer = nullptr; casting_spell_AIindex = static_cast(AIspells.size()); roambox_max_x = 0; @@ -2657,7 +2657,7 @@ DBnpcspells_Struct* ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID) { npc_spells_cache = new DBnpcspells_Struct*[npc_spells_maxid+1]; npc_spells_loadtried = new bool[npc_spells_maxid+1]; for (uint32 i=0; i<=npc_spells_maxid; i++) { - npc_spells_cache[i] = 0; + npc_spells_cache[i] = nullptr; 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_loadtried = new bool[npc_spellseffects_maxid + 1]; for (uint32 i = 0; i <= npc_spellseffects_maxid; i++) { - npc_spellseffects_cache[i] = 0; + npc_spellseffects_cache[i] = nullptr; npc_spellseffects_loadtried[i] = false; } } From a12011ca1e96e304ce1a6e6b1a815610a1bd4f98 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 27 Jan 2015 19:53:13 -0500 Subject: [PATCH 02/11] Fix some bugs with starting AI in mercs The vtable ptr is that of the current constructor the code is in ... --- zone/client.cpp | 2 ++ zone/merc.cpp | 2 -- zone/mob_ai.cpp | 12 ++++++------ zone/npc.cpp | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index 0175503ed..504164273 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -305,6 +305,8 @@ Client::Client(EQStreamInterface* ieqs) active_light = innate_light; spell_light = equip_light = NOT_USED; + + AI_Init(); } Client::~Client() { diff --git a/zone/merc.cpp b/zone/merc.cpp index 89da59df4..01b4fbee7 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -75,7 +75,6 @@ Merc::Merc(const NPCType* d, float x, float y, float z, float heading) SetMana(GetMaxMana()); SetEndurance(GetMaxEndurance()); - AI_Init(); AI_Start(); } @@ -1737,7 +1736,6 @@ void Merc::AI_Process() { } void Merc::AI_Start(int32 iMoveDelay) { - NPC::AI_Start(iMoveDelay); if (!pAIControlled) return; diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index ea2bdc3d5..e6b3c514d 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -422,7 +422,8 @@ bool EntityList::AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float return false; } -void Mob::AI_Init() { +void Mob::AI_Init() +{ pAIControlled = false; AIthink_timer = nullptr; AIwalking_timer = nullptr; @@ -441,9 +442,8 @@ void Mob::AI_Init() { pDontCureMeBefore = 0; } -void NPC::AI_Init() { - Mob::AI_Init(); - +void NPC::AI_Init() +{ AIautocastspell_timer = nullptr; casting_spell_AIindex = static_cast(AIspells.size()); @@ -458,8 +458,8 @@ void NPC::AI_Init() { roambox_delay = 2500; } -void Client::AI_Init() { - Mob::AI_Init(); +void Client::AI_Init() +{ minLastFightingDelayMoving = CLIENT_LD_TIMEOUT; maxLastFightingDelayMoving = CLIENT_LD_TIMEOUT; } diff --git a/zone/npc.cpp b/zone/npc.cpp index b9c465195..1375559a5 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -250,8 +250,8 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, const glm::vec4& position, int if npc_aggro = d->npc_aggro; - if(!IsMerc()) - AI_Start(); + AI_Init(); + AI_Start(); d_melee_texture1 = d->d_melee_texture1; d_melee_texture2 = d->d_melee_texture2; From 0f196cc9956fec80f05fee1be5eedaf9d7cb841e Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 27 Jan 2015 19:46:31 -0600 Subject: [PATCH 03/11] Fix for ZoneDatabase::SaveCharacterCorpse where a corpse was empty and two individual corpses would be created --- zone/zonedb.cpp | 56 +++++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index d50a72473..b4d35a3bb 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -3413,38 +3413,40 @@ 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) { /* Dump Basic Corpse Data */ - std::string query = StringFormat("INSERT INTO `character_corpses` " - "SET `charname` = '%s', `zone_id` = %u, `instance_id` = %u, `charid` = %d," - "`x` = %1.1f, `y` = %1.1f, `z` = %1.1f, `heading` = %1.1f," - "`time_of_death` = NOW(), `is_buried` = 0, `is_locked` = %d," - "`exp` = %u, `size` = %f, `level` = %u, `race` = %u, `gender` = %u," - "`class` = %u, `deity` = %u, `texture` = %u, `helm_texture` = %u," - "`copper` = %u, `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); + std::string query = StringFormat( + "INSERT INTO `character_corpses` " + "SET `charname` = '%s', `zone_id` = %u, `instance_id` = %u, `charid` = %d," + "`x` = %1.1f, `y` = %1.1f, `z` = %1.1f, `heading` = %1.1f," + "`time_of_death` = NOW(), `is_buried` = 0, `is_locked` = %d," + "`exp` = %u, `size` = %f, `level` = %u, `race` = %u, `gender` = %u," + "`class` = %u, `deity` = %u, `texture` = %u, `helm_texture` = %u," + "`copper` = %u, `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); uint32 last_insert_id = results.LastInsertedID(); + std::string corpse_items_query; /* Dump Items from Inventory */ uint8 first_entry = 0; for (unsigned int i = 0; i < dbpc->itemcount; i++) { if (first_entry != 1){ - query = StringFormat("REPLACE INTO `character_corpse_items` \n" + corpse_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" " VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n", last_insert_id, @@ -3462,7 +3464,7 @@ uint32 ZoneDatabase::SaveCharacterCorpse(uint32 charid, const char* charname, ui first_entry = 1; } 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, dbpc->items[i].equip_slot, dbpc->items[i].item_id, @@ -3477,7 +3479,7 @@ uint32 ZoneDatabase::SaveCharacterCorpse(uint32 charid, const char* charname, ui ); } } - auto sc_results = QueryDatabase(query); + QueryDatabase(corpse_items_query); return last_insert_id; } From 2211a63fe7f5756d1177eb7e29228184402b6cec Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 27 Jan 2015 20:24:43 -0600 Subject: [PATCH 04/11] Some minor format changes to SaveCharacterCorpse --- zone/zonedb.cpp | 112 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 88 insertions(+), 24 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index b4d35a3bb..362155016 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -3415,29 +3415,91 @@ uint32 ZoneDatabase::SaveCharacterCorpse(uint32 charid, const char* charname, ui /* Dump Basic Corpse Data */ std::string query = StringFormat( "INSERT INTO `character_corpses` " - "SET `charname` = '%s', `zone_id` = %u, `instance_id` = %u, `charid` = %d," - "`x` = %1.1f, `y` = %1.1f, `z` = %1.1f, `heading` = %1.1f," - "`time_of_death` = NOW(), `is_buried` = 0, `is_locked` = %d," - "`exp` = %u, `size` = %f, `level` = %u, `race` = %u, `gender` = %u," - "`class` = %u, `deity` = %u, `texture` = %u, `helm_texture` = %u," - "`copper` = %u, `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); + "SET `charname` = '%s', " + "`zone_id` = %u, " + "`instance_id` = %u, " + "`charid` = %d, " + "`x` = %1.1f, " + "`y` = %1.1f, " + "`z` = %1.1f, " + "`heading` = %1.1f, " + "`time_of_death` = NOW(), " + "`is_buried` = 0, " + "`is_locked` = %d, " + "`exp` = %u, " + "`size` = %f, " + "`level` = %u, " + "`race` = %u, " + "`gender` = %u, " + "`class` = %u, " + "`deity` = %u, " + "`texture` = %u, " + "`helm_texture` = %u, " + "`copper` = %u, " + "`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); uint32 last_insert_id = results.LastInsertedID(); @@ -3479,7 +3541,9 @@ uint32 ZoneDatabase::SaveCharacterCorpse(uint32 charid, const char* charname, ui ); } } - QueryDatabase(corpse_items_query); + if (!corpse_items_query.empty()) + QueryDatabase(corpse_items_query); + return last_insert_id; } From 99164fe3f9425f3c841a9bead5d6eb52f2973490 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 27 Jan 2015 21:28:38 -0500 Subject: [PATCH 05/11] Switch AI timers to smart pointers --- zone/mob.h | 17 +++++++++-------- zone/mob_ai.cpp | 44 ++++++++++++++++++++++---------------------- zone/npc.h | 4 ++-- 3 files changed, 33 insertions(+), 32 deletions(-) diff --git a/zone/mob.h b/zone/mob.h index e2d25a952..00b1ea416 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -25,6 +25,7 @@ #include "position.h" #include #include +#include char* strn0cpy(char* dest, const char* source, uint32 size); @@ -879,8 +880,8 @@ public: virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther) { return FACTION_INDIFFERENT; } inline bool IsTrackable() const { return(trackable); } - Timer* GetAIThinkTimer() { return AIthink_timer; } - Timer* GetAIMovementTimer() { return AImovement_timer; } + const Timer* GetAIThinkTimer() { return AIthink_timer.get(); } + const Timer* GetAIMovementTimer() { return AImovement_timer.get(); } Timer GetAttackTimer() { return attack_timer; } Timer GetAttackDWTimer() { return attack_dw_timer; } inline bool IsFindable() { return findable; } @@ -1170,14 +1171,14 @@ protected: uint32 maxLastFightingDelayMoving; float pAggroRange; float pAssistRange; - Timer* AIthink_timer; - Timer* AImovement_timer; - Timer* AItarget_check_timer; + std::unique_ptr AIthink_timer; + std::unique_ptr AImovement_timer; + std::unique_ptr AItarget_check_timer; bool movetimercompleted; bool permarooted; - Timer* AIscanarea_timer; - Timer* AIwalking_timer; - Timer* AIfeignremember_timer; + std::unique_ptr AIscanarea_timer; + std::unique_ptr AIwalking_timer; + std::unique_ptr AIfeignremember_timer; uint32 pLastFightingDelayMoving; HateList hate_list; std::set feign_memory_list; diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index e6b3c514d..371a8e523 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -425,12 +425,12 @@ bool EntityList::AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float void Mob::AI_Init() { pAIControlled = false; - AIthink_timer = nullptr; - AIwalking_timer = nullptr; - AImovement_timer = nullptr; - AItarget_check_timer = nullptr; - AIfeignremember_timer = nullptr; - AIscanarea_timer = nullptr; + AIthink_timer.reset(nullptr); + AIwalking_timer.reset(nullptr); + AImovement_timer.reset(nullptr); + AItarget_check_timer.reset(nullptr); + AIfeignremember_timer.reset(nullptr); + AIscanarea_timer.reset(nullptr); minLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMin); maxLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMax); @@ -444,7 +444,7 @@ void Mob::AI_Init() void NPC::AI_Init() { - AIautocastspell_timer = nullptr; + AIautocastspell_timer.reset(nullptr); casting_spell_AIindex = static_cast(AIspells.size()); roambox_max_x = 0; @@ -474,13 +474,13 @@ void Mob::AI_Start(uint32 iMoveDelay) { pLastFightingDelayMoving = 0; pAIControlled = true; - AIthink_timer = new Timer(AIthink_duration); + AIthink_timer = std::unique_ptr(new Timer(AIthink_duration)); AIthink_timer->Trigger(); - AIwalking_timer = new Timer(0); - AImovement_timer = new Timer(AImovement_duration); - AItarget_check_timer = new Timer(AItarget_check_duration); - AIfeignremember_timer = new Timer(AIfeignremember_delay); - AIscanarea_timer = new Timer(AIscanarea_delay); + AIwalking_timer = std::unique_ptr(new Timer(0)); + AImovement_timer = std::unique_ptr(new Timer(AImovement_duration)); + AItarget_check_timer = std::unique_ptr(new Timer(AItarget_check_duration)); + AIfeignremember_timer = std::unique_ptr(new Timer(AIfeignremember_delay)); + AIscanarea_timer = std::unique_ptr(new Timer(AIscanarea_delay)); #ifdef REVERSE_AGGRO if(IsNPC() && !CastToNPC()->WillAggroNPCs()) AIscanarea_timer->Disable(); @@ -516,10 +516,10 @@ void NPC::AI_Start(uint32 iMoveDelay) { return; if (AIspells.size() == 0) { - AIautocastspell_timer = new Timer(1000); + AIautocastspell_timer = std::unique_ptr(new Timer(1000)); AIautocastspell_timer->Disable(); } else { - AIautocastspell_timer = new Timer(750); + AIautocastspell_timer = std::unique_ptr(new Timer(750)); AIautocastspell_timer->Start(RandomTimer(0, 15000), false); } @@ -540,19 +540,19 @@ void Mob::AI_Stop() { pAIControlled = false; - safe_delete(AIthink_timer); - safe_delete(AIwalking_timer); - safe_delete(AImovement_timer); - safe_delete(AItarget_check_timer); - safe_delete(AIscanarea_timer); - safe_delete(AIfeignremember_timer); + AIthink_timer.reset(nullptr); + AIwalking_timer.reset(nullptr); + AImovement_timer.reset(nullptr); + AItarget_check_timer.reset(nullptr); + AIscanarea_timer.reset(nullptr); + AIfeignremember_timer.reset(nullptr); hate_list.WipeHateList(); } void NPC::AI_Stop() { Waypoints.clear(); - safe_delete(AIautocastspell_timer); + AIautocastspell_timer.reset(nullptr); } void Client::AI_Stop() { diff --git a/zone/npc.h b/zone/npc.h index e38aa85aa..6cb31ed87 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -436,7 +436,7 @@ protected: uint32 npc_spells_id; uint8 casting_spell_AIindex; - Timer* AIautocastspell_timer; + std::unique_ptr AIautocastspell_timer; uint32* pDontCastBefore_casting_spell; std::vector AIspells; bool HasAISpell; @@ -444,7 +444,7 @@ protected: virtual bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0); AISpellsVar_Struct AISpellVar; int16 GetFocusEffect(focusType type, uint16 spell_id); - + uint32 npc_spells_effects_id; std::vector AIspellsEffects; bool HasAISpellEffects; From 5f545df31215bbf855e7c9f433aec9a242fb7194 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 27 Jan 2015 21:48:11 -0500 Subject: [PATCH 06/11] Remove const --- zone/mob.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/mob.h b/zone/mob.h index 00b1ea416..3c4c241da 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -880,8 +880,8 @@ public: virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther) { return FACTION_INDIFFERENT; } inline bool IsTrackable() const { return(trackable); } - const Timer* GetAIThinkTimer() { return AIthink_timer.get(); } - const Timer* GetAIMovementTimer() { return AImovement_timer.get(); } + Timer* GetAIThinkTimer() { return AIthink_timer.get(); } + Timer* GetAIMovementTimer() { return AImovement_timer.get(); } Timer GetAttackTimer() { return attack_timer; } Timer GetAttackDWTimer() { return attack_dw_timer; } inline bool IsFindable() { return findable; } From 61e9160d47c12fa415258aec1d98d2bd7e26273d Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 28 Jan 2015 00:05:29 -0600 Subject: [PATCH 07/11] Update eqemu_update.pl to download patch_UF.conf instead of patch_Underfoot.conf --- utils/scripts/eqemu_update.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index 21ef05b73..04c5367b3 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -325,7 +325,7 @@ sub OpCodes_Fetch{ 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"], 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"], 8 => ["Rain of Fear 2", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_RoF2.conf"], ); From 0c934272c004095b09b9b47c48fcce76a82a8721 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 28 Jan 2015 20:00:03 -0600 Subject: [PATCH 08/11] 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 --- changelog.txt | 13 ++++++++ common/eqemu_logsys.h | 4 ++- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + .../2015_01_28_quest_debug_log_category.sql | 1 + zone/embparser_api.cpp | 33 +++++++++++++++++++ 6 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 utils/sql/git/required/2015_01_28_quest_debug_log_category.sql diff --git a/changelog.txt b/changelog.txt index ac7459a20..ea5816bde 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,18 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 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 == Trevius: Removed "Mercenary Debug:" from the Mercenary Log entries. Trevius: Resolved duplicate "You have no Mercenaries" messages when zoning without owning a Mercenary. diff --git a/common/eqemu_logsys.h b/common/eqemu_logsys.h index 491ded3c6..1bd63d5b5 100644 --- a/common/eqemu_logsys.h +++ b/common/eqemu_logsys.h @@ -77,6 +77,7 @@ namespace Logs{ MySQLError, MySQLQuery, Mercenaries, + QuestDebug, MaxCategoryID /* Don't Remove this*/ }; @@ -120,6 +121,7 @@ namespace Logs{ "MySQL Error", "MySQL Query", "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 */ 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 */ /* diff --git a/common/version.h b/common/version.h index 624418df5..33d089998 100644 --- a/common/version.h +++ b/common/version.h @@ -30,7 +30,7 @@ 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 9070 #define COMPILE_DATE __DATE__ #define COMPILE_TIME __TIME__ #ifndef WIN32 diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index e76c74852..4a49c09c9 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -323,6 +323,7 @@ 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| 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| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2015_01_28_quest_debug_log_category.sql b/utils/sql/git/required/2015_01_28_quest_debug_log_category.sql new file mode 100644 index 000000000..0f4f22807 --- /dev/null +++ b/utils/sql/git/required/2015_01_28_quest_debug_log_category.sql @@ -0,0 +1 @@ +INSERT INTO `logsys_categories` (`log_category_id`, `log_category_description`, `log_to_gmsay`) VALUES ('38', 'Quest Debug', '1') \ No newline at end of file diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index 7a6989c10..8b49f01b2 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -23,6 +23,7 @@ #include "../common/global_define.h" #include "../common/misc_functions.h" +#include "../common/eqemu_logsys.h" #include "embparser.h" #include "embxs.h" @@ -3493,6 +3494,37 @@ XS(XS__crosszonesignalnpcbynpctypeid) 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 quest package's XSUBs @@ -3579,6 +3611,7 @@ EXTERN_C XS(boot_quest) newXS(strcpy(buf, "crosszonesignalclientbycharid"), XS__crosszonesignalclientbycharid, file); newXS(strcpy(buf, "crosszonesignalclientbyname"), XS__crosszonesignalclientbyname, 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, "depop"), XS__depop, file); newXS(strcpy(buf, "depop_withtimer"), XS__depop_withtimer, file); From 5d465a4d49ebc33868de41a68a7fab153141fd26 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 28 Jan 2015 22:47:43 -0600 Subject: [PATCH 09/11] UCS Crash Fix --- ucs/database.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ucs/database.cpp b/ucs/database.cpp index 75be71377..b80b4fb78 100644 --- a/ucs/database.cpp +++ b/ucs/database.cpp @@ -195,7 +195,7 @@ bool Database::VerifyMailKey(std::string characterName, int IPAddress, std::stri else 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); } From 30dbe34f78c8f21726ca4f768bfb34e2e786589e Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Wed, 28 Jan 2015 23:53:52 -0500 Subject: [PATCH 10/11] Fix for range procs --- zone/special_attacks.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 4998150bd..f0dc413e1 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -857,7 +857,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite if (IsClient()){ _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; _Ammo = CastToClient()->m_inv[AmmoSlot]; @@ -996,7 +996,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite } 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 if(RangeWeapon && other && !other->HasDied()) From 0aba2d578ac43e37d6c191cf8cb18a2f1417d058 Mon Sep 17 00:00:00 2001 From: Trevius Date: Thu, 29 Jan 2015 23:04:41 -0600 Subject: [PATCH 11/11] Added more information to Mercenary Logging. Added potential fix for Mercenaries that fail to unsuspend. Added a new "statscale" field to the merc_stats table that can be used to quickly balance Mercenary Stats based on Level. The new "statscale" field now combines with the Mercs::ScaleRate rule value (default 100 percent for both). --- changelog.txt | 6 + common/database.cpp | 2 +- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + .../2015_01_29_merc_stats_table_update.sql | 1 + zone/client.cpp | 6 +- zone/client_packet.cpp | 20 +- zone/exp.cpp | 3 +- zone/merc.cpp | 278 +++++++++++++----- zone/merc.h | 4 +- zone/zonedb.cpp | 7 +- 11 files changed, 242 insertions(+), 88 deletions(-) create mode 100644 utils/sql/git/required/2015_01_29_merc_stats_table_update.sql diff --git a/changelog.txt b/changelog.txt index ea5816bde..38cc5f7ce 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,11 @@ 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) diff --git a/common/database.cpp b/common/database.cpp index 43a08f394..98639c6af 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1991,7 +1991,7 @@ void Database::SetRaidGroupLeaderInfo(uint32 gid, uint32 rid) if (results.RowsAffected() != 0) 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); results = QueryDatabase(query); diff --git a/common/version.h b/common/version.h index 33d089998..925292555 100644 --- a/common/version.h +++ b/common/version.h @@ -30,7 +30,7 @@ Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9070 +#define CURRENT_BINARY_DATABASE_VERSION 9071 #define COMPILE_DATE __DATE__ #define COMPILE_TIME __TIME__ #ifndef WIN32 diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 4a49c09c9..90a67a789 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -324,6 +324,7 @@ 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| 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: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2015_01_29_merc_stats_table_update.sql b/utils/sql/git/required/2015_01_29_merc_stats_table_update.sql new file mode 100644 index 000000000..9c149b825 --- /dev/null +++ b/utils/sql/git/required/2015_01_29_merc_stats_table_update.sql @@ -0,0 +1 @@ +ALTER TABLE `merc_stats` ADD `statscale` int( 11 ) NOT NULL DEFAULT '100' AFTER `runspeed`; \ No newline at end of file diff --git a/zone/client.cpp b/zone/client.cpp index 504164273..ecc7d7ca7 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -7277,7 +7277,7 @@ void Client::SendMercPersonalInfo() stancecount += zone->merc_stance_list[GetMercInfo().MercTemplateID].size(); 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); return; } @@ -7371,13 +7371,13 @@ void Client::SendMercPersonalInfo() return; } } - Log.Out(Logs::General, Logs::Mercenaries, "SendMercPersonalInfo Send Successful"); + Log.Out(Logs::General, Logs::Mercenaries, "SendMercPersonalInfo Send Successful for %s.", GetName()); SendMercMerchantResponsePacket(0); } 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()); } } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 4d2d0606c..2059c262f 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -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) 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)) return; @@ -9349,7 +9349,7 @@ void Client::Handle_OP_MercenaryCommand(const EQApplicationPacket *app) merc->SetStance(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 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 if (merchant_id == 0) { @@ -9380,12 +9380,12 @@ void Client::Handle_OP_MercenaryDataRequest(const EQApplicationPacket *app) //send info about your current merc(s) if (GetMercInfo().mercid) { - Log.Out(Logs::General, Logs::Mercenaries, "SendMercPersonalInfo Request"); + Log.Out(Logs::General, Logs::Mercenaries, "SendMercPersonalInfo Request for %s.", GetName()); SendMercPersonalInfo(); } 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; } - 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()) { @@ -9524,7 +9524,7 @@ void Client::Handle_OP_MercenaryDismiss(const EQApplicationPacket *app) 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... DismissMerc(GetMercInfo().mercid); @@ -9549,7 +9549,7 @@ void Client::Handle_OP_MercenaryHire(const EQApplicationPacket *app) uint32 merc_unk1 = mmrq->MercUnk01; 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; SetHoTT(0); @@ -9615,7 +9615,7 @@ void Client::Handle_OP_MercenarySuspendRequest(const EQApplicationPacket *app) SuspendMercenary_Struct* sm = (SuspendMercenary_Struct*)app->pBuffer; 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)) return; @@ -9635,7 +9635,7 @@ void Client::Handle_OP_MercenaryTimerRequest(const EQApplicationPacket *app) 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)) { return; diff --git a/zone/exp.cpp b/zone/exp.cpp index 7eb2189df..7e878206a 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -506,8 +506,7 @@ void Client::SetLevel(uint8 set_level, bool command) SetMana(CalcMaxMana()); UpdateWho(); - if(GetMerc()) - UpdateMercLevel(); + UpdateMercLevel(); Save(); } diff --git a/zone/merc.cpp b/zone/merc.cpp index 01b4fbee7..86225e6ab 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -2242,7 +2242,7 @@ bool Merc::AICastSpell(int8 iChance, int32 iSpellTypes) { if(CheckAETaunt()) { //get AE taunt 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()) { @@ -4770,7 +4770,7 @@ Merc* Merc::LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id, { merc->SetMercData( merc_template->MercTemplateID ); database.LoadMercEquipment(merc); - merc->UpdateMercStats(c); + merc->UpdateMercStats(c, true); if(updateFromDB) { @@ -4808,6 +4808,7 @@ Merc* Merc::LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id, merc->LoadMercSpells(); } + Log.Out(Logs::General, Logs::Mercenaries, "LoadMerc Successful for %s (%s).", merc->GetName(), c->GetName()); return merc; } } @@ -4836,50 +4837,183 @@ void Merc::UpdateMercInfo(Client *c) { c->GetMercInfo().drakkinDetails = drakkin_details; } -void Merc::UpdateMercStats(Client *c) { - if(c->GetMercInfo().MercTemplateID >0) +void Merc::UpdateMercStats(Client *c, bool setmax) { + 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()); if (npc_type) { - max_hp = (npc_type->max_hp * npc_type->scalerate) / 100; - base_hp = (npc_type->max_hp * npc_type->scalerate) / 100; - max_mana = (npc_type->Mana * npc_type->scalerate) / 100; - base_mana = (npc_type->Mana * npc_type->scalerate) / 100; - hp_regen = (npc_type->hp_regen * npc_type->scalerate) / 100; - mana_regen = (npc_type->mana_regen * npc_type->scalerate) / 100; + max_hp = npc_type->max_hp; + base_hp = npc_type->max_hp; + max_mana = npc_type->Mana; + base_mana = npc_type->Mana; + max_end = npc_type->max_hp; // Hack since Endurance does not exist for NPCType yet + 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; - 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_speed = npc_type->attack_speed; spellscale = npc_type->spellscale; healscale = npc_type->healscale; CalcBonuses(); - - CalcMaxEndurance(); CalcMaxHP(); 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() { // Copied from Bot Code: uint32 itemID = NO_ITEM; @@ -4937,7 +5071,7 @@ bool Merc::Spawn(Client *owner) { SendPosition(); - Log.Out(Logs::General, Logs::Mercenaries, "Spawn Mercenary."); + Log.Out(Logs::General, Logs::Mercenaries, "Spawn Mercenary %s.", GetName()); //UpdateMercAppearance(); @@ -5083,7 +5217,8 @@ void Client::SendMercResponsePackets(uint32 ResponseType) SendMercMerchantResponsePacket(3); 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() @@ -5124,7 +5259,7 @@ void Client::UpdateMercTimer() 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 //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)); @@ -5177,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; } @@ -5250,7 +5385,7 @@ bool Client::CheckCanSpawnMerc(uint32 template_id) { return false; } - Log.Out(Logs::General, Logs::Mercenaries, "CheckCanSpawnMerc True."); + Log.Out(Logs::General, Logs::Mercenaries, "CheckCanSpawnMerc True for %s.", GetName()); return true; } @@ -5272,7 +5407,7 @@ bool Client::CheckCanUnsuspendMerc() { return false; } - Log.Out(Logs::General, Logs::Mercenaries, "CheckCanUnsuspendMerc True."); + Log.Out(Logs::General, Logs::Mercenaries, "CheckCanUnsuspendMerc True for %s.", GetName()); return true; } @@ -5287,7 +5422,7 @@ void Client::CheckMercSuspendTimer() { GetMercInfo().SuspendedTime = 0; SendMercResponsePackets(0); SendMercSuspendResponsePacket(GetMercInfo().SuspendedTime); - Log.Out(Logs::General, Logs::Mercenaries, "CheckMercSuspendTimer Ready."); + Log.Out(Logs::General, Logs::Mercenaries, "CheckMercSuspendTimer Ready for %s.", GetName()); } } } @@ -5300,7 +5435,7 @@ void Client::SuspendMercCommand() { { 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; } @@ -5310,13 +5445,13 @@ void Client::SuspendMercCommand() { if(merc) { 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 { //merc failed to spawn 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 @@ -5326,10 +5461,11 @@ void Client::SuspendMercCommand() { if(CurrentMerc && GetMercID()) { CurrentMerc->Suspend(); - Log.Out(Logs::General, Logs::Mercenaries, "SuspendMercCommand Successful Suspend."); + Log.Out(Logs::General, Logs::Mercenaries, "SuspendMercCommand Successful Suspend for %s.", GetName()); } else { + // Reset Merc Suspend State GetMercInfo().IsSuspended = true; //GetMercInfo().SuspendedTime = time(nullptr) + RuleI(Mercs, SuspendIntervalS); //GetMercInfo().MercTimerRemaining = GetMercTimer()->GetRemainingTime(); @@ -5337,9 +5473,15 @@ void Client::SuspendMercCommand() { GetMercTimer()->Disable(); SendMercSuspendResponsePacket(GetMercInfo().SuspendedTime); 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()); + } } @@ -5371,7 +5513,7 @@ void Client::SpawnMercOnZone() { { 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 { @@ -5387,7 +5529,7 @@ void Client::SpawnMercOnZone() { // Send Mercenary Status/Timer packet SendMercTimer(GetMerc()); - Log.Out(Logs::General, Logs::Mercenaries, "SpawnMercOnZone Suspended Merc."); + Log.Out(Logs::General, Logs::Mercenaries, "SpawnMercOnZone Suspended Merc for %s.", GetName()); } } else @@ -5395,6 +5537,7 @@ void Client::SpawnMercOnZone() { // No Merc Hired // RoF+ displays a message from the following packet, which seems useless //SendClearMercInfo(); + Log.Out(Logs::General, Logs::Mercenaries, "SpawnMercOnZone Failed to load Merc Info from the Database for %s.", GetName()); } } @@ -5408,17 +5551,17 @@ void Client::SendMercTimer(Merc* merc) { if (!merc) { 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()) { 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 { 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()); } } @@ -5440,7 +5583,7 @@ void Client::SpawnMerc(Merc* merc, bool setMaxStats) { merc->Unsuspend(setMaxStats); merc->SetStance(GetMercInfo().Stance); - Log.Out(Logs::General, Logs::Mercenaries, "SpawnMerc Success."); + Log.Out(Logs::General, Logs::Mercenaries, "SpawnMerc Success for %s.", GetName()); return; @@ -5469,7 +5612,7 @@ bool Merc::Suspend() { // Start the timer to send the packet that refreshes the Unsuspend Button 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; } @@ -5555,12 +5698,12 @@ bool Client::DismissMerc(uint32 MercID) { bool Dismissed = true; 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; } else { - Log.Out(Logs::General, Logs::Mercenaries, "Dismiss Successful."); + Log.Out(Logs::General, Logs::Mercenaries, "Dismiss Successful for %s.", GetName()); } if (GetMerc()) @@ -5717,13 +5860,13 @@ bool Merc::MercJoinClientGroup() { database.SetGroupLeaderName(g->GetID(), mercOwner->GetName()); database.RefreshGroupFromDB(mercOwner); 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 { g->DisbandGroup(); 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()); } } @@ -5733,12 +5876,12 @@ bool Merc::MercJoinClientGroup() { database.RefreshGroupFromDB(mercOwner); // Update members that are out of zone 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 { 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()); } } @@ -5789,7 +5932,7 @@ Merc* Client::GetMerc() { 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); } @@ -5797,14 +5940,14 @@ Merc* Client::GetMerc() { if(tmp == nullptr) { 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); } if(tmp->GetOwnerID() != GetID()) { 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); } @@ -5822,7 +5965,7 @@ uint8 Client::GetNumMercs() { 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; } @@ -5863,7 +6006,7 @@ void Client::SetMerc(Merc* newmerc) { GetMercInfo().Gender = 0; GetMercInfo().State = 0; 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 { @@ -5880,7 +6023,7 @@ void Client::SetMerc(Merc* newmerc) { GetMercInfo().Gender = newmerc->GetGender(); GetMercInfo().State = newmerc->IsSuspended() ? MERC_STATE_SUSPENDED : MERC_STATE_NORMAL; 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()); } } @@ -5888,7 +6031,8 @@ void Client::UpdateMercLevel() { Merc* merc = GetMerc(); if (merc) { - merc->UpdateMercStats(this); + merc->UpdateMercStats(this, false); + merc->SendAppearancePacket(AT_WhoLevel, GetLevel(), true, true); } } @@ -5900,7 +6044,7 @@ void Client::SendMercMerchantResponsePacket(int32 response_type) { MercenaryMerchantResponse_Struct* mmr = (MercenaryMerchantResponse_Struct*)outapp->pBuffer; mmr->ResponseType = response_type; // send specified response type 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()); } } @@ -5909,7 +6053,7 @@ void Client::SendMercenaryUnknownPacket(uint8 type) { EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenaryUnknown1, 1); outapp->WriteUInt8(type); 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()); } @@ -5918,7 +6062,7 @@ void Client::SendMercenaryUnsuspendPacket(uint8 type) { EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenaryUnsuspendResponse, 1); outapp->WriteUInt8(type); 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()); } @@ -5928,7 +6072,7 @@ void Client::SendMercSuspendResponsePacket(uint32 suspended_time) { 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 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()); } @@ -5943,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->MercUnk01 = unk01; // Seen 180000 - 3 minutes in ms - Used for the unsuspend button refresh timer 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()); } @@ -5954,7 +6098,7 @@ void Client::SendMercAssignPacket(uint32 entityID, uint32 unk01, uint32 unk02) { mas->MercUnk01 = unk01; mas->MercUnk02 = unk02; 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() { diff --git a/zone/merc.h b/zone/merc.h index 31433a060..82136c15d 100644 --- a/zone/merc.h +++ b/zone/merc.h @@ -137,7 +137,7 @@ public: virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho); static Merc* LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id, bool updateFromDB = false); void UpdateMercInfo(Client *c); - void UpdateMercStats(Client *c); + void UpdateMercStats(Client *c, bool setmax = false); void UpdateMercAppearance(); virtual void UpdateEquipLightValue(); void AddItem(uint8 slot, uint32 item_id); @@ -189,6 +189,7 @@ public: bool TryHide(); // stat functions + virtual void ScaleStats(int scalepercent, bool setmax = false); virtual void CalcBonuses(); int32 GetEndurance() const {return cur_end;} //This gets our current endurance inline virtual int32 GetAC() const { return AC; } @@ -347,6 +348,7 @@ private: // Private "base stats" Members int32 base_mana; + int32 base_end; int32 _baseAC; uint32 _baseSTR; uint32 _baseSTA; diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 362155016..7f80c7b6f 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1996,6 +1996,7 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client "m_stats.AC, " "m_stats.ATK, " "m_stats.Accuracy, " + "m_stats.statscale, " "m_stats.spellscale, " "m_stats.healscale " "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->ATK = atoi(row[41]); tmpNPCType->accuracy_rating = atoi(row[42]); - tmpNPCType->scalerate = RuleI(Mercs, ScaleRate); - tmpNPCType->spellscale = atoi(row[43]); - tmpNPCType->healscale = atoi(row[44]); + tmpNPCType->scalerate = atoi(row[43]); + tmpNPCType->spellscale = atoi(row[44]); + tmpNPCType->healscale = atoi(row[45]); // If Merc with duplicate NPC id already in table, // free item we attempted to add.