From 8362ae1635508d116add7c95528561c7bd79068c Mon Sep 17 00:00:00 2001 From: EricksOliveira Date: Tue, 15 Sep 2026 01:37:15 -0300 Subject: [PATCH] fix(Core/Battlefield): resurrect ghosts when a Wintergrasp workshop is contested (#27264) Co-authored-by: Claude Opus 5 --- .../game/Battlefield/Zones/BattlefieldWG.cpp | 31 ++++++++++++++----- .../game/Battlefield/Zones/BattlefieldWG.h | 14 +++++---- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp index 4ec8f9a3b9..9dbd46d141 100644 --- a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp +++ b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp @@ -581,8 +581,12 @@ uint32 BattlefieldWG::GetAreaByGraveyardId(uint8 gId) const return 0; } -void BattlefieldWG::RelocateDeadPlayers(uint8 graveyardId, TeamId newOwner) +void BattlefieldWG::RelocateDeadPlayers(uint8 graveyardId, TeamId losingTeam) { + // Nobody could use the graveyard before the change, so nobody is left waiting on it. + if (losingTeam == TEAM_NEUTRAL) + return; + BfGraveyard const* graveyard = GetGraveyardById(graveyardId); if (!graveyard) return; @@ -591,19 +595,30 @@ void BattlefieldWG::RelocateDeadPlayers(uint8 graveyardId, TeamId newOwner) if (!capturedLoc) return; - ForEachPlayerInZone([this, capturedLoc, newOwner](Player* player) + ForEachPlayerInZone([this, capturedLoc, losingTeam](Player* player) { - // Only players of the losing team waiting to resurrect; they would otherwise be - // revived in place on the now-inaccessible captured platform. - if (player->GetTeamId() == newOwner || !player->HasAura(SPELL_WAITING_FOR_RESURRECT)) + // Only the team that just lost it. The other team could never have released here, since + // RepopAtGraveyard picks a graveyard their own team holds, so they are passers-by. + if (player->GetTeamId() != losingTeam) return; - // Restrict to ghosts actually waiting at the captured graveyard, not elsewhere in the zone. + // Ghosts only. Skips the living, and corpses that RepopAtGraveyard will send to a + // graveyard their team holds once they release. + if (!player->HasPlayerFlag(PLAYER_FLAGS_GHOST)) + return; + + // Only ghosts waiting at this graveyard, not elsewhere in the zone. if (player->GetDistance2d(capturedLoc->x, capturedLoc->y) > 50.0f) return; - if (GraveyardStruct const* safeLoc = GetClosestGraveyard(player)) - player->TeleportTo(safeLoc->Map, safeLoc->x, safeLoc->y, safeLoc->z, player->GetOrientation()); + GraveyardStruct const* safeLoc = GetClosestGraveyard(player); + if (!safeLoc) + return; + + player->TeleportTo(safeLoc->Map, safeLoc->x, safeLoc->y, safeLoc->z, player->GetOrientation()); + + // The spirit guides here are phased out for them now, so they can't queue themselves. + AddPlayerToResurrectQueue(ObjectGuid::Empty, player->GetGUID()); }); } diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.h b/src/server/game/Battlefield/Zones/BattlefieldWG.h index 8d163424b7..72b956354e 100644 --- a/src/server/game/Battlefield/Zones/BattlefieldWG.h +++ b/src/server/game/Battlefield/Zones/BattlefieldWG.h @@ -400,8 +400,8 @@ public: uint8 GetSpiritGraveyardId(uint32 areaId) const; uint32 GetAreaByGraveyardId(uint8 gId) const; - // Teleport ghosts waiting at a just-captured graveyard to their team's nearest controlled one. - void RelocateDeadPlayers(uint8 graveyardId, TeamId newOwner); + // Move ghosts off a graveyard their team just lost, and queue them to resurrect at the new one. + void RelocateDeadPlayers(uint8 graveyardId, TeamId losingTeam); uint32 GetData(uint32 data) const override; @@ -1427,6 +1427,8 @@ struct WGWorkshop void GiveControlTo(TeamId team, bool init /* for first call in setup*/) { + TeamId const previousControl = teamControl; + switch (team) { case TEAM_NEUTRAL: @@ -1473,10 +1475,10 @@ struct WGWorkshop bf->UpdateCounterVehicle(false); bf->CapturePointTaken(bf->GetAreaByGraveyardId(workshopId)); - // Workshop graveyard share the workshop id; repop ghosts that lost it. - // Only on an actual capture, not while the workshop is merely contested (neutral). - if (IsCapturable() && teamControl != TEAM_NEUTRAL) - bf->RelocateDeadPlayers(workshopId, teamControl); + // Workshop graveyard share the workshop id. Ghosts of the team that just lost it can no + // longer see a spirit guide here, so move them to a graveyard they can still use. + if (IsCapturable()) + bf->RelocateDeadPlayers(workshopId, previousControl); } }