From 0a9c55f308d3ef7e1ae34a5f3d2cb9b8f53900fb Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Wed, 27 May 2026 22:44:54 -0300 Subject: [PATCH] feat(Core/Wintergrasp): aura-driven resurrect queue (#26002) Co-authored-by: Balrok Co-authored-by: Xfurry Co-authored-by: Claude Opus 4.7 (1M context) --- src/server/game/Battlefield/Battlefield.cpp | 101 ++---------------- src/server/game/Battlefield/Battlefield.h | 16 +-- .../game/Battlefield/Zones/BattlefieldWG.cpp | 36 ++++++- .../game/Spells/Auras/SpellAuraEffects.cpp | 5 +- .../scripts/Northrend/zone_wintergrasp.cpp | 12 ++- 5 files changed, 53 insertions(+), 117 deletions(-) diff --git a/src/server/game/Battlefield/Battlefield.cpp b/src/server/game/Battlefield/Battlefield.cpp index 379351bda4..c4b6d46c3c 100644 --- a/src/server/game/Battlefield/Battlefield.cpp +++ b/src/server/game/Battlefield/Battlefield.cpp @@ -629,34 +629,22 @@ GraveyardStruct const* Battlefield::GetClosestGraveyard(Player* player) return nullptr; } -void Battlefield::AddPlayerToResurrectQueue(ObjectGuid npcGuid, ObjectGuid playerGuid) +void Battlefield::AddPlayerToResurrectQueue(ObjectGuid /*npcGuid*/, ObjectGuid playerGuid) { - for (BfGraveyard* gy : GraveyardList) - { - if (!gy) - continue; + Player* player = ObjectAccessor::FindPlayer(playerGuid); + if (!player) + return; - if (gy->HasNpc(npcGuid)) - { - gy->AddPlayer(playerGuid); - break; - } - } + player->CastSpell(player, SPELL_WAITING_FOR_RESURRECT, true); } void Battlefield::RemovePlayerFromResurrectQueue(ObjectGuid playerGuid) { - for (BfGraveyard* gy : GraveyardList) - { - if (!gy) - continue; + Player* player = ObjectAccessor::FindPlayer(playerGuid); + if (!player) + return; - if (gy->HasPlayer(playerGuid)) - { - gy->RemovePlayer(playerGuid); - break; - } - } + player->RemoveAurasDueToSpell(SPELL_WAITING_FOR_RESURRECT); } void Battlefield::SendAreaSpiritHealerQueryOpcode(Player* player, ObjectGuid const& guid) @@ -702,80 +690,9 @@ float BfGraveyard::GetDistance(Player* player) return player->GetDistance2d(safeLoc->x, safeLoc->y); } -void BfGraveyard::AddPlayer(ObjectGuid playerGuid) -{ - if (!ResurrectQueue.count(playerGuid)) - { - ResurrectQueue.insert(playerGuid); - - if (Player* player = ObjectAccessor::FindPlayer(playerGuid)) - player->CastSpell(player, SPELL_WAITING_FOR_RESURRECT, true); - } -} - -void BfGraveyard::RemovePlayer(ObjectGuid playerGuid) -{ - ResurrectQueue.erase(ResurrectQueue.find(playerGuid)); - - if (Player* player = ObjectAccessor::FindPlayer(playerGuid)) - player->RemoveAurasDueToSpell(SPELL_WAITING_FOR_RESURRECT); -} - -void BfGraveyard::Resurrect() -{ - if (ResurrectQueue.empty()) - return; - - for (ObjectGuid const& guid : ResurrectQueue) - { - // Get player object from his guid - Player* player = ObjectAccessor::FindPlayer(guid); - if (!player) - continue; - - // Check if the player is in world and on the good graveyard - if (player->IsInWorld()) - if (Unit* spirit = ObjectAccessor::GetCreature(*player, SpiritGuide[ControlTeam])) - spirit->CastSpell(spirit, SPELL_SPIRIT_HEAL, true); - - // Resurrect player - player->CastSpell(player, SPELL_RESURRECTION_VISUAL, true); - player->ResurrectPlayer(1.0f); - player->CastSpell(player, 6962, true); - player->CastSpell(player, SPELL_SPIRIT_HEAL_MANA, true); - - player->SpawnCorpseBones(false); - } - - ResurrectQueue.clear(); -} - -// For changing graveyard control void BfGraveyard::GiveControlTo(TeamId team) { ControlTeam = team; - // Teleport to other graveyard, players which were on this graveyard - RelocateDeadPlayers(); -} - -void BfGraveyard::RelocateDeadPlayers() -{ - GraveyardStruct const* closestGrave = nullptr; - for (ObjectGuid const& guid : ResurrectQueue) - { - Player* player = ObjectAccessor::FindPlayer(guid); - if (!player) - continue; - - if (closestGrave) - player->TeleportTo(player->GetMapId(), closestGrave->x, closestGrave->y, closestGrave->z, player->GetOrientation()); - else - { - closestGrave = Bf->GetClosestGraveyard(player); - if (closestGrave) - player->TeleportTo(player->GetMapId(), closestGrave->x, closestGrave->y, closestGrave->z, player->GetOrientation()); - } - } } Creature* Battlefield::SpawnCreature(uint32 entry, Position pos, TeamId teamId) diff --git a/src/server/game/Battlefield/Battlefield.h b/src/server/game/Battlefield/Battlefield.h index c9e0119a31..c7cd9a9fee 100644 --- a/src/server/game/Battlefield/Battlefield.h +++ b/src/server/game/Battlefield/Battlefield.h @@ -169,18 +169,6 @@ public: // Set spirit service for the graveyard void SetSpirit(Creature* spirit, TeamId team); - // Add a player to the graveyard - void AddPlayer(ObjectGuid playerGuid); - - // Remove a player from the graveyard - void RemovePlayer(ObjectGuid playerGuid); - - // Resurrect players - void Resurrect(); - - // Move players waiting to that graveyard on the nearest one - void RelocateDeadPlayers(); - // Check if this graveyard has a spirit guide bool HasNpc(ObjectGuid guid) { @@ -190,8 +178,7 @@ public: return (SpiritGuide[0] == guid || SpiritGuide[1] == guid); } - // Check if a player is in this graveyard's resurrect queue - bool HasPlayer(ObjectGuid guid) const { return ResurrectQueue.find(guid) != ResurrectQueue.end(); } + ObjectGuid GetSpiritGuide(TeamId team) const { return SpiritGuide[team]; } // Get the graveyard's ID. uint32 GetGraveyardId() const { return GraveyardId; } @@ -200,7 +187,6 @@ protected: TeamId ControlTeam; uint32 GraveyardId; ObjectGuid SpiritGuide[2]; - GuidUnorderedSet ResurrectQueue; Battlefield* Bf; }; diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp index 49533cafa1..e1be38223f 100644 --- a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp +++ b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp @@ -193,9 +193,39 @@ bool BattlefieldWG::SetupBattlefield() _scheduler.Schedule(Milliseconds(RESURRECTION_INTERVAL), BATTLEFIELD_TIMER_GROUP_RESURRECT, [this](TaskContext context) { - for (BfGraveyard* gy : GraveyardList) - if (gy) - gy->Resurrect(); + ForEachPlayerInZone([this](Player* player) + { + if (!player->HasAura(SPELL_WAITING_FOR_RESURRECT)) + return; + + TeamId team = player->GetTeamId(); + Unit* closestSpirit = nullptr; + float closestDist = -1.0f; + for (BfGraveyard* gy : GraveyardList) + { + if (!gy) + continue; + Unit* spirit = ObjectAccessor::GetCreature(*player, gy->GetSpiritGuide(team)); + if (!spirit) + continue; + float dist = player->GetDistance(spirit); + if (closestDist < 0.0f || dist < closestDist) + { + closestDist = dist; + closestSpirit = spirit; + } + } + + if (closestSpirit) + closestSpirit->CastSpell(closestSpirit, SPELL_SPIRIT_HEAL, true); + + player->CastSpell(player, SPELL_RESURRECTION_VISUAL, true); + player->ResurrectPlayer(1.0f); + player->CastSpell(player, 6962, true); + player->CastSpell(player, SPELL_SPIRIT_HEAL_MANA, true); + player->SpawnCorpseBones(false); + player->RemoveAurasDueToSpell(SPELL_WAITING_FOR_RESURRECT); + }); context.Repeat(); }); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 4817aa222d..a77315c0f3 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -5344,13 +5344,10 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool { case 2584: // Waiting to Resurrect // Waiting to resurrect spell cancel, we must remove player from resurrect queue + // bf branch omitted: it would cascade back into this handler. if (target->IsPlayer()) - { if (Battleground* bg = target->ToPlayer()->GetBattleground()) bg->RemovePlayerFromResurrectQueue(target->ToPlayer()); - if (Battlefield* bf = sBattlefieldMgr->GetBattlefieldToZoneId(target->GetZoneId())) - bf->RemovePlayerFromResurrectQueue(target->GetGUID()); - } break; case 43681: // Inactive { diff --git a/src/server/scripts/Northrend/zone_wintergrasp.cpp b/src/server/scripts/Northrend/zone_wintergrasp.cpp index dd7b2a568d..6c2317fb5c 100644 --- a/src/server/scripts/Northrend/zone_wintergrasp.cpp +++ b/src/server/scripts/Northrend/zone_wintergrasp.cpp @@ -215,13 +215,19 @@ public: bool OnGossipHello(Player* player, Creature* creature) override { - if (creature->IsQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - Battlefield* wintergrasp = sBattlefieldMgr->GetBattlefieldByBattleId(BATTLEFIELD_BATTLEID_WG); if (!wintergrasp) return true; + if (!player->IsAlive()) + { + wintergrasp->SendAreaSpiritHealerQueryOpcode(player, creature->GetGUID()); + player->CastSpell(player, SPELL_WAITING_FOR_RESURRECT, true); + } + + if (creature->IsQuestGiver()) + player->PrepareQuestMenu(creature->GetGUID()); + GraveyardVect graveyard = wintergrasp->GetGraveyardVector(); for (uint8 i = 0; i < graveyard.size(); i++) if (graveyard[i]->GetControlTeamId() == player->GetTeamId())