fix(Core/Battlefield): resurrect ghosts when a Wintergrasp workshop is contested (#27264)

Co-authored-by: Claude Opus 5 <[email protected]>
This commit is contained in:
EricksOliveira
2026-09-15 01:37:15 -03:00
committed by GitHub
co-authored by Claude Opus 5
parent 658448f69a
commit 8362ae1635
2 changed files with 31 additions and 14 deletions
@@ -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());
});
}
@@ -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);
}
}