From f6b77f9d64edc50298655b5b0c51bd64ef49b51c Mon Sep 17 00:00:00 2001 From: Anton Popovichenko Date: Sat, 19 Aug 2023 22:27:51 +0200 Subject: [PATCH] fix(Core/Pets): Fix crash when pet tries to attack deleted object (#17034) This situation occurs when, during a fight, a pet receives a command to apply a positive spell to an ally and then resume attacking its previous target. --- src/server/game/Entities/Pet/Pet.cpp | 18 +++++++++++------- src/server/game/Entities/Pet/Pet.h | 10 +++++----- src/server/game/Handlers/PetHandler.cpp | 8 ++++++-- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index 8a29cc2af..aff237a32 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -48,7 +48,7 @@ Pet::Pet(Player* owner, PetType type) : Guardian(nullptr, owner ? owner->GetGUID m_loading(false), m_petRegenTimer(PET_FOCUS_REGEN_INTERVAL), m_tempspellTarget(nullptr), - m_tempoldTarget(nullptr), + m_tempoldTarget(), m_tempspellIsPositive(false), m_tempspell(0) { @@ -710,7 +710,11 @@ void Pet::Update(uint32 diff) if (m_tempspell) { Unit* tempspellTarget = m_tempspellTarget; - Unit* tempoldTarget = m_tempoldTarget; + Unit* tempoldTarget = nullptr; + + if (!m_tempoldTarget.IsEmpty()) + tempoldTarget = ObjectAccessor::GetUnit(*this, m_tempoldTarget); + bool tempspellIsPositive = m_tempspellIsPositive; uint32 tempspell = m_tempspell; Unit* charmer = GetCharmerOrOwner(); @@ -783,7 +787,7 @@ void Pet::Update(uint32 diff) } } - m_tempoldTarget = nullptr; + m_tempoldTarget = ObjectGuid::Empty; m_tempspellIsPositive = false; } } @@ -793,7 +797,7 @@ void Pet::Update(uint32 diff) { m_tempspell = 0; m_tempspellTarget = nullptr; - m_tempoldTarget = nullptr; + m_tempoldTarget = ObjectGuid::Empty; m_tempspellIsPositive = false; Unit* victim = charmer->GetVictim(); @@ -2414,7 +2418,7 @@ void Pet::SetDisplayId(uint32 modelId) player->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MODEL_ID); } -void Pet::CastWhenWillAvailable(uint32 spellid, Unit* spellTarget, Unit* oldTarget, bool spellIsPositive) +void Pet::CastWhenWillAvailable(uint32 spellid, Unit* spellTarget, ObjectGuid oldTarget, bool spellIsPositive) { if (!spellid) return; @@ -2426,7 +2430,7 @@ void Pet::CastWhenWillAvailable(uint32 spellid, Unit* spellTarget, Unit* oldTarg m_tempspell = spellid; m_tempspellIsPositive = spellIsPositive; - if (oldTarget) + if (!oldTarget.IsEmpty()) m_tempoldTarget = oldTarget; } @@ -2435,7 +2439,7 @@ void Pet::ClearCastWhenWillAvailable() m_tempspellIsPositive = false; m_tempspell = 0; m_tempspellTarget = nullptr; - m_tempoldTarget = nullptr; + m_tempoldTarget = ObjectGuid::Empty; } void Pet::RemoveSpellCooldown(uint32 spell_id, bool update /* = false */) diff --git a/src/server/game/Entities/Pet/Pet.h b/src/server/game/Entities/Pet/Pet.h index 329672d8c..d32f04fc6 100644 --- a/src/server/game/Entities/Pet/Pet.h +++ b/src/server/game/Entities/Pet/Pet.h @@ -96,7 +96,7 @@ public: void LearnPetPassives(); void CastPetAuras(bool current); - void CastWhenWillAvailable(uint32 spellid, Unit* spellTarget, Unit* oldTarget, bool spellIsPositive = false); + void CastWhenWillAvailable(uint32 spellid, Unit* spellTarget, ObjectGuid oldTarget, bool spellIsPositive = false); void ClearCastWhenWillAvailable(); void RemoveSpellCooldown(uint32 spell_id, bool update /* = false */); @@ -157,10 +157,10 @@ protected: std::unique_ptr m_declinedname; - Unit* m_tempspellTarget; - Unit* m_tempoldTarget; - bool m_tempspellIsPositive; - uint32 m_tempspell; + Unit* m_tempspellTarget; + ObjectGuid m_tempoldTarget; + bool m_tempspellIsPositive; + uint32 m_tempspell; private: void SaveToDB(uint32, uint8, uint32) override // override of Creature::SaveToDB - must not be called diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index f4b421369..102b2088c 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -530,7 +530,7 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe pet->SendPetAIReaction(guid1); } - pet->ToPet()->CastWhenWillAvailable(spellId, unit_target, nullptr, tempspellIsPositive); + pet->ToPet()->CastWhenWillAvailable(spellId, unit_target, ObjectGuid::Empty, tempspellIsPositive); } } else if (haspositiveeffect) @@ -566,7 +566,11 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe pet->SendPetAIReaction(guid1); } - pet->ToPet()->CastWhenWillAvailable(spellId, unit_target, victim, tmpSpellIsPositive); + ObjectGuid oldTarget = ObjectGuid::Empty; + if (victim) + oldTarget = victim->GetGUID(); + + pet->ToPet()->CastWhenWillAvailable(spellId, unit_target, oldTarget, tmpSpellIsPositive); } } }