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; 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); BfGraveyard const* graveyard = GetGraveyardById(graveyardId);
if (!graveyard) if (!graveyard)
return; return;
@@ -591,19 +595,30 @@ void BattlefieldWG::RelocateDeadPlayers(uint8 graveyardId, TeamId newOwner)
if (!capturedLoc) if (!capturedLoc)
return; 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 // Only the team that just lost it. The other team could never have released here, since
// revived in place on the now-inaccessible captured platform. // RepopAtGraveyard picks a graveyard their own team holds, so they are passers-by.
if (player->GetTeamId() == newOwner || !player->HasAura(SPELL_WAITING_FOR_RESURRECT)) if (player->GetTeamId() != losingTeam)
return; 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) if (player->GetDistance2d(capturedLoc->x, capturedLoc->y) > 50.0f)
return; return;
if (GraveyardStruct const* safeLoc = GetClosestGraveyard(player)) GraveyardStruct const* safeLoc = GetClosestGraveyard(player);
player->TeleportTo(safeLoc->Map, safeLoc->x, safeLoc->y, safeLoc->z, player->GetOrientation()); 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; uint8 GetSpiritGraveyardId(uint32 areaId) const;
uint32 GetAreaByGraveyardId(uint8 gId) const; uint32 GetAreaByGraveyardId(uint8 gId) const;
// Teleport ghosts waiting at a just-captured graveyard to their team's nearest controlled one. // Move ghosts off a graveyard their team just lost, and queue them to resurrect at the new one.
void RelocateDeadPlayers(uint8 graveyardId, TeamId newOwner); void RelocateDeadPlayers(uint8 graveyardId, TeamId losingTeam);
uint32 GetData(uint32 data) const override; uint32 GetData(uint32 data) const override;
@@ -1427,6 +1427,8 @@ struct WGWorkshop
void GiveControlTo(TeamId team, bool init /* for first call in setup*/) void GiveControlTo(TeamId team, bool init /* for first call in setup*/)
{ {
TeamId const previousControl = teamControl;
switch (team) switch (team)
{ {
case TEAM_NEUTRAL: case TEAM_NEUTRAL:
@@ -1473,10 +1475,10 @@ struct WGWorkshop
bf->UpdateCounterVehicle(false); bf->UpdateCounterVehicle(false);
bf->CapturePointTaken(bf->GetAreaByGraveyardId(workshopId)); bf->CapturePointTaken(bf->GetAreaByGraveyardId(workshopId));
// Workshop graveyard share the workshop id; repop ghosts that lost it. // Workshop graveyard share the workshop id. Ghosts of the team that just lost it can no
// Only on an actual capture, not while the workshop is merely contested (neutral). // longer see a spirit guide here, so move them to a graveyard they can still use.
if (IsCapturable() && teamControl != TEAM_NEUTRAL) if (IsCapturable())
bf->RelocateDeadPlayers(workshopId, teamControl); bf->RelocateDeadPlayers(workshopId, previousControl);
} }
} }