mirror of
https://github.com/liyunfan1223/azerothcore-wotlk.git
synced 2026-08-09 00:08:01 +00:00
feat(Core/Wintergrasp): aura-driven resurrect queue (#26002)
Co-authored-by: Balrok <balrok@getmangos.com> Co-authored-by: Xfurry <xfurry.cmangos@outlook.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -629,34 +629,22 @@ GraveyardStruct const* Battlefield::GetClosestGraveyard(Player* player)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Battlefield::AddPlayerToResurrectQueue(ObjectGuid npcGuid, ObjectGuid playerGuid)
|
void Battlefield::AddPlayerToResurrectQueue(ObjectGuid /*npcGuid*/, ObjectGuid playerGuid)
|
||||||
{
|
{
|
||||||
for (BfGraveyard* gy : GraveyardList)
|
Player* player = ObjectAccessor::FindPlayer(playerGuid);
|
||||||
{
|
if (!player)
|
||||||
if (!gy)
|
return;
|
||||||
continue;
|
|
||||||
|
|
||||||
if (gy->HasNpc(npcGuid))
|
player->CastSpell(player, SPELL_WAITING_FOR_RESURRECT, true);
|
||||||
{
|
|
||||||
gy->AddPlayer(playerGuid);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Battlefield::RemovePlayerFromResurrectQueue(ObjectGuid playerGuid)
|
void Battlefield::RemovePlayerFromResurrectQueue(ObjectGuid playerGuid)
|
||||||
{
|
{
|
||||||
for (BfGraveyard* gy : GraveyardList)
|
Player* player = ObjectAccessor::FindPlayer(playerGuid);
|
||||||
{
|
if (!player)
|
||||||
if (!gy)
|
return;
|
||||||
continue;
|
|
||||||
|
|
||||||
if (gy->HasPlayer(playerGuid))
|
player->RemoveAurasDueToSpell(SPELL_WAITING_FOR_RESURRECT);
|
||||||
{
|
|
||||||
gy->RemovePlayer(playerGuid);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Battlefield::SendAreaSpiritHealerQueryOpcode(Player* player, ObjectGuid const& guid)
|
void Battlefield::SendAreaSpiritHealerQueryOpcode(Player* player, ObjectGuid const& guid)
|
||||||
@@ -702,80 +690,9 @@ float BfGraveyard::GetDistance(Player* player)
|
|||||||
return player->GetDistance2d(safeLoc->x, safeLoc->y);
|
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)
|
void BfGraveyard::GiveControlTo(TeamId team)
|
||||||
{
|
{
|
||||||
ControlTeam = 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)
|
Creature* Battlefield::SpawnCreature(uint32 entry, Position pos, TeamId teamId)
|
||||||
|
|||||||
@@ -169,18 +169,6 @@ public:
|
|||||||
// Set spirit service for the graveyard
|
// Set spirit service for the graveyard
|
||||||
void SetSpirit(Creature* spirit, TeamId team);
|
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
|
// Check if this graveyard has a spirit guide
|
||||||
bool HasNpc(ObjectGuid guid)
|
bool HasNpc(ObjectGuid guid)
|
||||||
{
|
{
|
||||||
@@ -190,8 +178,7 @@ public:
|
|||||||
return (SpiritGuide[0] == guid || SpiritGuide[1] == guid);
|
return (SpiritGuide[0] == guid || SpiritGuide[1] == guid);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if a player is in this graveyard's resurrect queue
|
ObjectGuid GetSpiritGuide(TeamId team) const { return SpiritGuide[team]; }
|
||||||
bool HasPlayer(ObjectGuid guid) const { return ResurrectQueue.find(guid) != ResurrectQueue.end(); }
|
|
||||||
|
|
||||||
// Get the graveyard's ID.
|
// Get the graveyard's ID.
|
||||||
uint32 GetGraveyardId() const { return GraveyardId; }
|
uint32 GetGraveyardId() const { return GraveyardId; }
|
||||||
@@ -200,7 +187,6 @@ protected:
|
|||||||
TeamId ControlTeam;
|
TeamId ControlTeam;
|
||||||
uint32 GraveyardId;
|
uint32 GraveyardId;
|
||||||
ObjectGuid SpiritGuide[2];
|
ObjectGuid SpiritGuide[2];
|
||||||
GuidUnorderedSet ResurrectQueue;
|
|
||||||
Battlefield* Bf;
|
Battlefield* Bf;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -193,9 +193,39 @@ bool BattlefieldWG::SetupBattlefield()
|
|||||||
_scheduler.Schedule(Milliseconds(RESURRECTION_INTERVAL),
|
_scheduler.Schedule(Milliseconds(RESURRECTION_INTERVAL),
|
||||||
BATTLEFIELD_TIMER_GROUP_RESURRECT, [this](TaskContext context)
|
BATTLEFIELD_TIMER_GROUP_RESURRECT, [this](TaskContext context)
|
||||||
{
|
{
|
||||||
for (BfGraveyard* gy : GraveyardList)
|
ForEachPlayerInZone([this](Player* player)
|
||||||
if (gy)
|
{
|
||||||
gy->Resurrect();
|
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();
|
context.Repeat();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -5344,13 +5344,10 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
|
|||||||
{
|
{
|
||||||
case 2584: // Waiting to Resurrect
|
case 2584: // Waiting to Resurrect
|
||||||
// Waiting to resurrect spell cancel, we must remove player from resurrect queue
|
// 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 (target->IsPlayer())
|
||||||
{
|
|
||||||
if (Battleground* bg = target->ToPlayer()->GetBattleground())
|
if (Battleground* bg = target->ToPlayer()->GetBattleground())
|
||||||
bg->RemovePlayerFromResurrectQueue(target->ToPlayer());
|
bg->RemovePlayerFromResurrectQueue(target->ToPlayer());
|
||||||
if (Battlefield* bf = sBattlefieldMgr->GetBattlefieldToZoneId(target->GetZoneId()))
|
|
||||||
bf->RemovePlayerFromResurrectQueue(target->GetGUID());
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 43681: // Inactive
|
case 43681: // Inactive
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -215,13 +215,19 @@ public:
|
|||||||
|
|
||||||
bool OnGossipHello(Player* player, Creature* creature) override
|
bool OnGossipHello(Player* player, Creature* creature) override
|
||||||
{
|
{
|
||||||
if (creature->IsQuestGiver())
|
|
||||||
player->PrepareQuestMenu(creature->GetGUID());
|
|
||||||
|
|
||||||
Battlefield* wintergrasp = sBattlefieldMgr->GetBattlefieldByBattleId(BATTLEFIELD_BATTLEID_WG);
|
Battlefield* wintergrasp = sBattlefieldMgr->GetBattlefieldByBattleId(BATTLEFIELD_BATTLEID_WG);
|
||||||
if (!wintergrasp)
|
if (!wintergrasp)
|
||||||
return true;
|
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();
|
GraveyardVect graveyard = wintergrasp->GetGraveyardVector();
|
||||||
for (uint8 i = 0; i < graveyard.size(); i++)
|
for (uint8 i = 0; i < graveyard.size(); i++)
|
||||||
if (graveyard[i]->GetControlTeamId() == player->GetTeamId())
|
if (graveyard[i]->GetControlTeamId() == player->GetTeamId())
|
||||||
|
|||||||
Reference in New Issue
Block a user