From 6d52f191087c2d26723710960a4b608bd30705e0 Mon Sep 17 00:00:00 2001 From: Emagi Date: Fri, 30 May 2025 11:03:36 -0400 Subject: [PATCH] Additional changes made to remove use of spell pointer in recast timer unlock spell logic, assure we have no crash in this area --- source/WorldServer/Player.cpp | 20 ++++++++++++++++++++ source/WorldServer/Player.h | 1 + source/WorldServer/SpellProcess.cpp | 13 ++++++++++--- source/WorldServer/SpellProcess.h | 2 ++ 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/source/WorldServer/Player.cpp b/source/WorldServer/Player.cpp index 45d8f71..d203c53 100644 --- a/source/WorldServer/Player.cpp +++ b/source/WorldServer/Player.cpp @@ -2751,6 +2751,26 @@ void Player::UnlockSpell(Spell* spell) { MSpellsBook.releasewritelock(__FUNCTION__, __LINE__); } + +void Player::UnlockSpell(int32 spell_id, int32 linked_timer_id) { + vector::iterator itr; + SpellBookEntry* spell2; + MSpellsBook.writelock(__FUNCTION__, __LINE__); + for (itr = spells.begin(); itr != spells.end(); itr++) { + spell2 = *itr; + if (spell2->spell_id == spell_id || (linked_timer_id > 0 && linked_timer_id == spell2->timer)) + { + spell2->in_use = false; + spell2->recast_available = 0; + if(all_spells_locked) + spell2->in_remiss = true; + else + AddSpellStatus(spell2, SPELL_STATUS_LOCK, false); + } + } + MSpellsBook.releasewritelock(__FUNCTION__, __LINE__); +} + void Player::LockTSSpells() { vector::iterator itr; diff --git a/source/WorldServer/Player.h b/source/WorldServer/Player.h index 97beb80..4a1d03f 100644 --- a/source/WorldServer/Player.h +++ b/source/WorldServer/Player.h @@ -967,6 +967,7 @@ public: /// Unlocks the given spell as well as all spells with shared timers void UnlockSpell(Spell* spell); + void UnlockSpell(int32 spell_id, int32 linked_timer_id); /// Locks all ts spells and unlocks all normal spells void LockTSSpells(); diff --git a/source/WorldServer/SpellProcess.cpp b/source/WorldServer/SpellProcess.cpp index eda495c..335b825 100644 --- a/source/WorldServer/SpellProcess.cpp +++ b/source/WorldServer/SpellProcess.cpp @@ -242,8 +242,8 @@ void SpellProcess::Process(){ recast_timer = itr->value; if(recast_timer->timer->Check(false)){ MaintainedEffects* effect = 0; - if(recast_timer->caster && (!(effect = recast_timer->caster->GetMaintainedSpell(recast_timer->spell_id)) || !effect->spell->spell->GetSpellData()->duration_until_cancel)) - UnlockSpell(recast_timer->client, recast_timer->spell); + if(recast_timer->caster && !recast_timer->stay_locked && (!(effect = recast_timer->caster->GetMaintainedSpell(recast_timer->spell_id)) || !effect->spell->spell->GetSpellData()->duration_until_cancel)) + UnlockSpell(recast_timer->client, recast_timer->spell_id, recast_timer->linked_timer); safe_delete(recast_timer->timer); recast_timers.Remove(recast_timer, true); } @@ -357,7 +357,7 @@ void SpellProcess::CheckRecast(Spell* spell, Entity* caster, float timer_overrid timer->type_group_spell_id = spell->GetSpellData()->type_group_spell_id; timer->linked_timer = spell->GetSpellData()->linked_timer; timer->spell_id = spell->GetSpellID(); - + timer->stay_locked = spell->GetStayLocked(); recast_timers.Add(timer); } if(caster->IsPlayer()){ @@ -791,6 +791,13 @@ void SpellProcess::UnlockSpell(Client* client, Spell* spell){ } } +void SpellProcess::UnlockSpell(Client* client, int32 spell_id, int32 link_timer_id){ + if(client && client->GetPlayer() && spell_id) { + client->GetPlayer()->UnlockSpell(spell_id, link_timer_id); + SendSpellBookUpdate(client); + } +} + bool SpellProcess::CheckPower(LuaSpell* spell){ int16 req = 0; if(spell->caster){ diff --git a/source/WorldServer/SpellProcess.h b/source/WorldServer/SpellProcess.h index 34e5785..b421a06 100644 --- a/source/WorldServer/SpellProcess.h +++ b/source/WorldServer/SpellProcess.h @@ -149,6 +149,7 @@ struct RecastTimer{ int32 spell_id; int32 linked_timer; int32 type_group_spell_id; + bool stay_locked; }; /// Handles all spell casts for a zone, only 1 SpellProcess per zone @@ -259,6 +260,7 @@ public: /// The client to unlock the spell for /// The spell to unlock void UnlockSpell(Client* client, Spell* spell); + void UnlockSpell(Client* client, int32 spell_id, int32 link_timer_id); /// Remove the given spell for the given caster from the SpellProcess /// The spawn to remove the spell for