From 7a4347dbacc530a4e93daff8ce0b826971e94ef9 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Fri, 13 Mar 2026 05:02:58 -0700 Subject: [PATCH] fix: clear lastInteractedGoGuid_ on cast failure, cancel, and world reset If a gather cast was interrupted by SMSG_SPELL_FAILURE (e.g. player took damage during mining), lastInteractedGoGuid_ was left set. A subsequent timed cast completion would then fire CMSG_LOOT for the stale node even though the gather never completed. Clear lastInteractedGoGuid_ in all cast-termination paths: - SMSG_SPELL_FAILURE (cast interrupted by server) - SMSG_CAST_RESULT non-zero (cast rejected before it started) - cancelCast() (player or system cancelled the cast) - World reset / logout block (state-clear boundary) --- src/game/game_handler.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/game/game_handler.cpp b/src/game/game_handler.cpp index 8ee75b9c..af089d93 100644 --- a/src/game/game_handler.cpp +++ b/src/game/game_handler.cpp @@ -2002,6 +2002,7 @@ void GameHandler::handlePacket(network::Packet& packet) { castIsChannel = false; currentCastSpellId = 0; castTimeRemaining = 0.0f; + lastInteractedGoGuid_ = 0; // Pass player's power type so result 85 says "Not enough rage/energy/etc." int playerPowerType = -1; if (auto pe = entityManager.getEntity(playerGuid)) { @@ -3012,10 +3013,12 @@ void GameHandler::handlePacket(network::Packet& packet) { } } if (failGuid == playerGuid || failGuid == 0) { - // Player's own cast failed + // Player's own cast failed — clear gather-node loot target so the + // next timed cast doesn't try to loot a stale interrupted gather node. casting = false; castIsChannel = false; currentCastSpellId = 0; + lastInteractedGoGuid_ = 0; if (auto* renderer = core::Application::getInstance().getRenderer()) { if (auto* ssm = renderer->getSpellSoundManager()) { ssm->stopPrecast(); @@ -7996,6 +7999,7 @@ void GameHandler::selectCharacter(uint64_t characterGuid) { castIsChannel = false; currentCastSpellId = 0; pendingGameObjectInteractGuid_ = 0; + lastInteractedGoGuid_ = 0; castTimeRemaining = 0.0f; castTimeTotal = 0.0f; playerDead_ = false; @@ -12219,6 +12223,7 @@ void GameHandler::stopCasting() { castIsChannel = false; currentCastSpellId = 0; pendingGameObjectInteractGuid_ = 0; + lastInteractedGoGuid_ = 0; castTimeRemaining = 0.0f; castTimeTotal = 0.0f; @@ -15912,6 +15917,7 @@ void GameHandler::cancelCast() { socket->send(packet); } pendingGameObjectInteractGuid_ = 0; + lastInteractedGoGuid_ = 0; casting = false; castIsChannel = false; currentCastSpellId = 0;