From 46f0d4033a1bce6202b3853d8dfa3d9741a061fd Mon Sep 17 00:00:00 2001 From: blinkysc <37940565+blinkysc@users.noreply.github.com> Date: Fri, 29 May 2026 09:22:01 -0500 Subject: [PATCH] fix(Core/Combat): drop dangling current victim on phase change crash (#26020) Co-authored-by: blinkysc --- src/server/game/Entities/Unit/Unit.cpp | 20 ------------------- .../server/game/Combat/ThreatManagerTest.cpp | 6 +++++- 2 files changed, 5 insertions(+), 21 deletions(-) diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index d02ed9d536..fa19728a86 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -15321,30 +15321,10 @@ void Unit::SetPhaseMask(uint32 newPhaseMask, bool update) if (!sScriptMgr->CanSetPhaseMask(this, newPhaseMask, update)) return; - - // Phase-related threat updates are done AFTER the phase change below } WorldObject::SetPhaseMask(newPhaseMask, false); - // Now update threat online states with the new phase mask applied - if (IsCreature() || (IsPlayer() && !ToPlayer()->IsGameMaster() && !ToPlayer()->GetSession()->PlayerLogout())) - { - // Update online state for units that have me on their threat list - for (auto const& pair : GetThreatMgr().GetThreatenedByMeList()) - { - if (ThreatReference* ref = pair.second) - ref->UpdateOffline(); - } - - // Update online state for units on my threat list - if (!IsPlayer()) - { - for (ThreatReference* ref : GetThreatMgr().GetModifiableThreatList()) - ref->UpdateOffline(); - } - } - if (!IsInWorld()) { return; diff --git a/src/test/server/game/Combat/ThreatManagerTest.cpp b/src/test/server/game/Combat/ThreatManagerTest.cpp index af4e48aaf2..b7e9867ecc 100644 --- a/src/test/server/game/Combat/ThreatManagerTest.cpp +++ b/src/test/server/game/Combat/ThreatManagerTest.cpp @@ -734,7 +734,7 @@ TEST_F(ThreatManagerIntegrationTest, } // ============================================================================ -// Phase Change + Threat Offline State Tests (SetPhaseMask order fix) +// Phase Change + Threat Offline State Tests // ============================================================================ TEST_F(ThreatManagerIntegrationTest, @@ -748,6 +748,10 @@ TEST_F(ThreatManagerIntegrationTest, // Move B to a different phase _creatureB->SetPhase(2); + // Online state is refreshed lazily on the next threat update tick (matches + // TrinityCore - SetPhaseMask itself does not touch threat) + _creatureA->TestGetThreatMgr().Update(ThreatManager::THREAT_UPDATE_INTERVAL); + // B should now be offline on A's threat list (different phases) // The list is not empty if we include offline, but empty if we don't EXPECT_TRUE(_creatureA->TestGetThreatMgr().IsThreatenedBy(_creatureB, true)); // includeOffline