aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Battlefield/Battlefield.cpp123
-rw-r--r--src/server/game/Battlefield/Battlefield.h21
-rw-r--r--src/server/game/Battlegrounds/Battleground.cpp130
-rw-r--r--src/server/game/Battlegrounds/Battleground.h18
-rw-r--r--src/server/game/Battlegrounds/BattlegroundMgr.cpp12
-rw-r--r--src/server/game/Battlegrounds/BattlegroundMgr.h1
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp2
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp2
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp2
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp22
-rw-r--r--src/server/game/Entities/Creature/Creature.h2
-rw-r--r--src/server/game/Entities/Player/Player.cpp35
-rw-r--r--src/server/game/Entities/Player/Player.h8
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp6
-rw-r--r--src/server/game/Entities/Unit/Unit.h1
-rw-r--r--src/server/game/Handlers/BattleGroundHandler.cpp44
-rw-r--r--src/server/game/Handlers/NPCHandler.cpp10
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp10
-rw-r--r--src/server/game/Spells/SpellEffects.cpp31
-rw-r--r--src/server/game/Spells/SpellInfo.cpp2
-rw-r--r--src/server/scripts/Battlefield/BattlefieldTB.cpp1
-rw-r--r--src/server/scripts/Battlefield/BattlefieldTB.h1
-rw-r--r--src/server/scripts/EasternKingdoms/zone_tol_barad.cpp87
-rw-r--r--src/server/scripts/Northrend/zone_wintergrasp.cpp9
-rw-r--r--src/server/scripts/Spells/spell_generic.cpp116
25 files changed, 282 insertions, 414 deletions
diff --git a/src/server/game/Battlefield/Battlefield.cpp b/src/server/game/Battlefield/Battlefield.cpp
index 3b641adcb95..7893b925bc3 100644
--- a/src/server/game/Battlefield/Battlefield.cpp
+++ b/src/server/game/Battlefield/Battlefield.cpp
@@ -56,7 +56,6 @@ Battlefield::Battlefield(Map* map)
m_uiKickAfkPlayersTimer = 1000;
- m_LastResurrectTimer = 30 * IN_MILLISECONDS;
m_StartGroupingTimer = 0;
m_StartGrouping = false;
}
@@ -122,7 +121,6 @@ void Battlefield::HandlePlayerLeaveZone(Player* player, uint32 /*zone*/)
m_PlayersWillBeKick[player->GetTeamId()].erase(player->GetGUID());
m_players[player->GetTeamId()].erase(player->GetGUID());
SendRemoveWorldStates(player);
- RemovePlayerFromResurrectQueue(player->GetGUID());
OnPlayerLeaveZone(player);
}
@@ -183,16 +181,6 @@ bool Battlefield::Update(uint32 diff)
objective_changed = true;
}
- if (m_LastResurrectTimer <= diff)
- {
- for (uint8 i = 0; i < m_GraveyardList.size(); i++)
- if (GetGraveyardById(i))
- m_GraveyardList[i]->Resurrect();
- m_LastResurrectTimer = RESURRECTION_INTERVAL;
- }
- else
- m_LastResurrectTimer -= diff;
-
return objective_changed;
}
@@ -596,44 +584,6 @@ WorldSafeLocsEntry const* Battlefield::GetClosestGraveyard(Player* player)
return nullptr;
}
-void Battlefield::AddPlayerToResurrectQueue(ObjectGuid npcGuid, ObjectGuid playerGuid)
-{
- for (uint8 i = 0; i < m_GraveyardList.size(); i++)
- {
- if (!m_GraveyardList[i])
- continue;
-
- if (m_GraveyardList[i]->HasNpc(npcGuid))
- {
- m_GraveyardList[i]->AddPlayer(playerGuid);
- break;
- }
- }
-}
-
-void Battlefield::RemovePlayerFromResurrectQueue(ObjectGuid playerGuid)
-{
- for (uint8 i = 0; i < m_GraveyardList.size(); i++)
- {
- if (!m_GraveyardList[i])
- continue;
-
- if (m_GraveyardList[i]->HasPlayer(playerGuid))
- {
- m_GraveyardList[i]->RemovePlayer(playerGuid);
- break;
- }
- }
-}
-
-void Battlefield::SendAreaSpiritHealerQueryOpcode(Player* player, ObjectGuid const& guid)
-{
- WorldPackets::Battleground::AreaSpiritHealerTime areaSpiritHealerTime;
- areaSpiritHealerTime.HealerGuid = guid;
- areaSpiritHealerTime.TimeLeft = m_LastResurrectTimer;
- player->SendDirectMessage(areaSpiritHealerTime.Write());
-}
-
// ----------------------
// - BfGraveyard Method -
// ----------------------
@@ -668,54 +618,6 @@ float BfGraveyard::GetDistance(Player* player)
return player->GetDistance2d(safeLoc->Loc.GetPositionX(), safeLoc->Loc.GetPositionY());
}
-void BfGraveyard::AddPlayer(ObjectGuid playerGuid)
-{
- if (!m_ResurrectQueue.count(playerGuid))
- {
- m_ResurrectQueue.insert(playerGuid);
-
- if (Player* player = ObjectAccessor::FindPlayer(playerGuid))
- player->CastSpell(player, SPELL_WAITING_FOR_RESURRECT, true);
- }
-}
-
-void BfGraveyard::RemovePlayer(ObjectGuid playerGuid)
-{
- m_ResurrectQueue.erase(m_ResurrectQueue.find(playerGuid));
-
- if (Player* player = ObjectAccessor::FindPlayer(playerGuid))
- player->RemoveAurasDueToSpell(SPELL_WAITING_FOR_RESURRECT);
-}
-
-void BfGraveyard::Resurrect()
-{
- if (m_ResurrectQueue.empty())
- return;
-
- for (GuidSet::const_iterator itr = m_ResurrectQueue.begin(); itr != m_ResurrectQueue.end(); ++itr)
- {
- // Get player object from his guid
- Player* player = ObjectAccessor::FindPlayer(*itr);
- if (!player)
- continue;
-
- // Check if the player is in world and on the good graveyard
- if (player->IsInWorld())
- if (Creature* spirit = m_Bf->GetCreature(m_SpiritGuide[m_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);
- }
-
- m_ResurrectQueue.clear();
-}
-
// For changing graveyard control
void BfGraveyard::GiveControlTo(TeamId team)
{
@@ -726,29 +628,10 @@ void BfGraveyard::GiveControlTo(TeamId team)
if (m_SpiritGuide[team])
m_SpiritGuide[team]->SetVisible(true);*/
- m_ControlTeam = team;
- // Teleport to other graveyard, player witch were on this graveyard
- RelocateDeadPlayers();
-}
+ if (Creature* spiritHealer = m_Bf->GetCreature(m_SpiritGuide[team]))
+ spiritHealer->SummonGraveyardTeleporter();
-void BfGraveyard::RelocateDeadPlayers()
-{
- WorldSafeLocsEntry const* closestGrave = nullptr;
- for (GuidSet::const_iterator itr = m_ResurrectQueue.begin(); itr != m_ResurrectQueue.end(); ++itr)
- {
- Player* player = ObjectAccessor::FindPlayer(*itr);
- if (!player)
- continue;
-
- if (closestGrave)
- player->TeleportTo(closestGrave->Loc);
- else
- {
- closestGrave = m_Bf->GetClosestGraveyard(player);
- if (closestGrave)
- player->TeleportTo(closestGrave->Loc);
- }
- }
+ m_ControlTeam = team;
}
bool BfGraveyard::HasNpc(ObjectGuid guid)
diff --git a/src/server/game/Battlefield/Battlefield.h b/src/server/game/Battlefield/Battlefield.h
index 5490b62ac54..fb95918d7a5 100644
--- a/src/server/game/Battlefield/Battlefield.h
+++ b/src/server/game/Battlefield/Battlefield.h
@@ -177,24 +177,9 @@ class TC_GAME_API BfGraveyard
// Set spirit service for the graveyard
void SetSpirit(Creature* spirit, TeamId team);
- // Add a player to the graveyard
- void AddPlayer(ObjectGuid player_guid);
-
- // Remove a player from the graveyard
- void RemovePlayer(ObjectGuid player_guid);
-
- // 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);
- // Check if a player is in this graveyard's resurrect queue
- bool HasPlayer(ObjectGuid guid) { return m_ResurrectQueue.find(guid) != m_ResurrectQueue.end(); }
-
// Get the graveyard's ID.
uint32 GetGraveyardId() const { return m_GraveyardId; }
@@ -202,7 +187,6 @@ class TC_GAME_API BfGraveyard
TeamId m_ControlTeam;
uint32 m_GraveyardId;
ObjectGuid m_SpiritGuide[PVP_TEAMS_COUNT];
- GuidSet m_ResurrectQueue;
Battlefield* m_Bf;
};
@@ -304,8 +288,6 @@ class TC_GAME_API Battlefield : public ZoneScript
// Find which graveyard the player must be teleported to to be resurrected by spiritguide
WorldSafeLocsEntry const* GetClosestGraveyard(Player* player);
- virtual void AddPlayerToResurrectQueue(ObjectGuid npc_guid, ObjectGuid player_guid);
- void RemovePlayerFromResurrectQueue(ObjectGuid player_guid);
void SetGraveyardNumber(uint32 number) { m_GraveyardList.resize(number); }
BfGraveyard* GetGraveyardById(uint32 id) const;
@@ -346,8 +328,6 @@ class TC_GAME_API Battlefield : public ZoneScript
/// Return if we can use mount in battlefield
bool CanFlyIn() { return !m_isActive; }
- void SendAreaSpiritHealerQueryOpcode(Player* player, ObjectGuid const& guid);
-
void StartBattle();
void EndBattle(bool endByTimer);
@@ -403,7 +383,6 @@ class TC_GAME_API Battlefield : public ZoneScript
// Graveyard variables
GraveyardVect m_GraveyardList; // Vector witch contain the different GY of the battle
- uint32 m_LastResurrectTimer; // Timer for resurrect player every 30 sec
uint32 m_StartGroupingTimer; // Timer for invite players in area 15 minute before start battle
bool m_StartGrouping; // bool for know if all players in area has been invited
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp
index ee768353eb7..198bf8f4f84 100644
--- a/src/server/game/Battlegrounds/Battleground.cpp
+++ b/src/server/game/Battlegrounds/Battleground.cpp
@@ -64,7 +64,6 @@ Battleground::Battleground(BattlegroundTemplate const* battlegroundTemplate) : _
m_Status = STATUS_NONE;
m_ClientInstanceID = 0;
m_EndTime = 0;
- m_LastResurrectTime = 0;
m_InvitedAlliance = 0;
m_InvitedHorde = 0;
m_ArenaType = 0;
@@ -195,7 +194,6 @@ void Battleground::Update(uint32 diff)
}
else
{
- _ProcessResurrect(diff);
if (sBattlegroundMgr->GetPrematureFinishTime() && (GetPlayersCountByTeam(ALLIANCE) < GetMinPlayersPerTeam() || GetPlayersCountByTeam(HORDE) < GetMinPlayersPerTeam()))
_ProcessProgress(diff);
else if (m_PrematureCountDown)
@@ -290,65 +288,6 @@ inline void Battleground::_ProcessOfflineQueue()
}
}
-inline void Battleground::_ProcessResurrect(uint32 diff)
-{
- // *********************************************************
- // *** BATTLEGROUND RESURRECTION SYSTEM ***
- // *********************************************************
- // this should be handled by spell system
- m_LastResurrectTime += diff;
- if (m_LastResurrectTime >= RESURRECTION_INTERVAL)
- {
- if (GetReviveQueueSize())
- {
- for (std::map<ObjectGuid, GuidVector>::iterator itr = m_ReviveQueue.begin(); itr != m_ReviveQueue.end(); ++itr)
- {
- Creature* sh = nullptr;
- for (GuidVector::const_iterator itr2 = (itr->second).begin(); itr2 != (itr->second).end(); ++itr2)
- {
- Player* player = ObjectAccessor::FindPlayer(*itr2);
- if (!player)
- continue;
-
- if (!sh && player->IsInWorld())
- {
- sh = player->GetMap()->GetCreature(itr->first);
- // only for visual effect
- if (sh)
- // Spirit Heal, effect 117
- sh->CastSpell(sh, SPELL_SPIRIT_HEAL, true);
- }
-
- // Resurrection visual
- player->CastSpell(player, SPELL_RESURRECTION_VISUAL, true);
- m_ResurrectQueue.push_back(*itr2);
- }
- (itr->second).clear();
- }
-
- m_ReviveQueue.clear();
- m_LastResurrectTime = 0;
- }
- else
- // queue is clear and time passed, just update last resurrection time
- m_LastResurrectTime = 0;
- }
- else if (m_LastResurrectTime > 500) // Resurrect players only half a second later, to see spirit heal effect on NPC
- {
- for (GuidVector::const_iterator itr = m_ResurrectQueue.begin(); itr != m_ResurrectQueue.end(); ++itr)
- {
- Player* player = ObjectAccessor::FindPlayer(*itr);
- if (!player)
- continue;
- player->ResurrectPlayer(1.0f);
- player->CastSpell(player, 6962, true);
- player->CastSpell(player, SPELL_SPIRIT_HEAL_MANA, true);
- player->SpawnCorpseBones(false);
- }
- m_ResurrectQueue.clear();
- }
-}
-
uint32 Battleground::GetPrematureWinner()
{
uint32 winner = 0;
@@ -894,8 +833,6 @@ void Battleground::RemovePlayerAtLeave(ObjectGuid guid, bool Transport, bool Sen
PlayerScores.erase(itr2);
}
- RemovePlayerFromResurrectQueue(guid);
-
Player* player = ObjectAccessor::FindPlayer(guid);
if (player)
@@ -1004,7 +941,6 @@ void Battleground::Reset()
SetStatus(STATUS_WAIT_QUEUE);
SetElapsedTime(0);
SetRemainingTime(0);
- SetLastResurrectTime(0);
m_Events = 0;
if (m_InvitedAlliance > 0 || m_InvitedHorde > 0)
@@ -1027,7 +963,6 @@ void Battleground::Reset()
void Battleground::StartBattleground()
{
SetElapsedTime(0);
- SetLastResurrectTime(0);
// add BG to free slot queue
AddToBGFreeSlotQueue();
@@ -1374,57 +1309,6 @@ bool Battleground::UpdatePlayerScore(Player* player, uint32 type, uint32 value,
return true;
}
-void Battleground::AddPlayerToResurrectQueue(ObjectGuid npc_guid, ObjectGuid player_guid)
-{
- m_ReviveQueue[npc_guid].push_back(player_guid);
-
- Player* player = ObjectAccessor::FindPlayer(player_guid);
- if (!player)
- return;
-
- player->CastSpell(player, SPELL_WAITING_FOR_RESURRECT, true);
-}
-
-void Battleground::RemovePlayerFromResurrectQueue(ObjectGuid player_guid)
-{
- for (std::map<ObjectGuid, GuidVector>::iterator itr = m_ReviveQueue.begin(); itr != m_ReviveQueue.end(); ++itr)
- {
- for (GuidVector::iterator itr2 = itr->second.begin(); itr2 != itr->second.end(); ++itr2)
- {
- if (*itr2 == player_guid)
- {
- itr->second.erase(itr2);
- if (Player* player = ObjectAccessor::FindPlayer(player_guid))
- player->RemoveAurasDueToSpell(SPELL_WAITING_FOR_RESURRECT);
- return;
- }
- }
- }
-}
-
-void Battleground::RelocateDeadPlayers(ObjectGuid guideGuid)
-{
- // Those who are waiting to resurrect at this node are taken to the closest own node's graveyard
- GuidVector& ghostList = m_ReviveQueue[guideGuid];
- if (!ghostList.empty())
- {
- WorldSafeLocsEntry const* closestGrave = nullptr;
- for (GuidVector::const_iterator itr = ghostList.begin(); itr != ghostList.end(); ++itr)
- {
- Player* player = ObjectAccessor::FindPlayer(*itr);
- if (!player)
- continue;
-
- if (!closestGrave)
- closestGrave = GetClosestGraveyard(player);
-
- if (closestGrave)
- player->TeleportTo(closestGrave->Loc);
- }
- ghostList.clear();
- }
-}
-
bool Battleground::AddObject(uint32 type, uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint32 /*respawnTime*/, GOState goState)
{
// If the assert is called, means that BgObjects must be resized!
@@ -1698,19 +1582,9 @@ bool Battleground::AddSpiritGuide(uint32 type, float x, float y, float z, float
{
uint32 entry = (teamId == TEAM_ALLIANCE) ? BG_CREATURE_ENTRY_A_SPIRITGUIDE : BG_CREATURE_ENTRY_H_SPIRITGUIDE;
- if (Creature* creature = AddCreature(entry, type, x, y, z, o, teamId))
- {
- creature->setDeathState(DEAD);
- creature->AddChannelObject(creature->GetGUID());
- // aura
- /// @todo Fix display here
- // creature->SetVisibleAura(0, SPELL_SPIRIT_HEAL_CHANNEL);
- // casting visual effect
- creature->SetChannelSpellId(SPELL_SPIRIT_HEAL_CHANNEL);
- creature->SetChannelVisual({ VISUAL_SPIRIT_HEAL_CHANNEL, 0 });
- //creature->CastSpell(creature, SPELL_SPIRIT_HEAL_CHANNEL, true);
+ if (AddCreature(entry, type, x, y, z, o, teamId))
return true;
- }
+
TC_LOG_ERROR("bg.battleground", "Battleground::AddSpiritGuide: cannot create spirit guide (type: {}, entry: {}) for BG (map: {}, instance id: {})!",
type, entry, GetMapId(), m_InstanceID);
EndNow();
diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h
index 5cb8976422d..bfa4cec6dbe 100644
--- a/src/server/game/Battlegrounds/Battleground.h
+++ b/src/server/game/Battlegrounds/Battleground.h
@@ -96,8 +96,10 @@ enum BattlegroundCreatures
enum BattlegroundSpells
{
+ SPELL_SPIRIT_HEAL_CHANNEL_AOE = 22011, // used for AoE resurrections
+ SPELL_SPIRIT_HEAL_PLAYER_AURA = 156758, // individual player timers for resurrection
+ SPELL_SPIRIT_HEAL_CHANNEL_SELF = 305122, // channel visual for individual area spirit healers
SPELL_WAITING_FOR_RESURRECT = 2584, // Waiting to Resurrect
- SPELL_SPIRIT_HEAL_CHANNEL = 22011, // Spirit Heal Channel
VISUAL_SPIRIT_HEAL_CHANNEL = 3060,
SPELL_SPIRIT_HEAL = 22012, // Spirit Heal
SPELL_RESURRECTION_VISUAL = 24171, // Resurrection Impact Visual
@@ -115,6 +117,7 @@ enum BattlegroundSpells
SPELL_MERCENARY_ALLIANCE_1 = 193863,
SPELL_MERCENARY_ALLIANCE_REACTIONS = 195843,
SPELL_MERCENARY_SHAPESHIFT = 193970,
+ SPELL_PET_SUMMONED = 6962 // used after resurrection
};
enum BattlegroundTimeIntervals
@@ -286,7 +289,6 @@ class TC_GAME_API Battleground : public ZoneScript
uint32 GetClientInstanceID() const { return m_ClientInstanceID; }
uint32 GetElapsedTime() const { return m_StartTime; }
uint32 GetRemainingTime() const { return m_EndTime; }
- uint32 GetLastResurrectTime() const { return m_LastResurrectTime; }
uint32 GetMaxPlayers() const;
uint32 GetMinPlayers() const;
@@ -313,7 +315,6 @@ class TC_GAME_API Battleground : public ZoneScript
void SetClientInstanceID(uint32 InstanceID) { m_ClientInstanceID = InstanceID; }
void SetElapsedTime(uint32 Time) { m_StartTime = Time; }
void SetRemainingTime(uint32 Time) { m_EndTime = Time; }
- void SetLastResurrectTime(uint32 Time) { m_LastResurrectTime = Time; }
void SetRated(bool state) { m_IsRated = state; }
void SetArenaType(uint8 type) { m_ArenaType = type; }
void SetWinner(PvPTeamId winnerTeamId) { _winnerTeamId = winnerTeamId; }
@@ -343,14 +344,6 @@ class TC_GAME_API Battleground : public ZoneScript
typedef std::map<ObjectGuid, BattlegroundScore*> BattlegroundScoreMap;
uint32 GetPlayerScoresSize() const { return uint32(PlayerScores.size()); }
- uint32 GetReviveQueueSize() const { return uint32(m_ReviveQueue.size()); }
-
- void AddPlayerToResurrectQueue(ObjectGuid npc_guid, ObjectGuid player_guid);
- void RemovePlayerFromResurrectQueue(ObjectGuid player_guid);
-
- /// Relocate all players in ReviveQueue to the closest graveyard
- void RelocateDeadPlayers(ObjectGuid guideGuid);
-
void StartBattleground();
GameObject* GetBGObject(uint32 type, bool logError = true);
@@ -543,7 +536,6 @@ class TC_GAME_API Battleground : public ZoneScript
virtual void PostUpdateImpl(uint32 /* diff */) { }
void _ProcessOfflineQueue();
- void _ProcessResurrect(uint32 diff);
void _ProcessProgress(uint32 diff);
void _ProcessLeave(uint32 diff);
void _ProcessJoin(uint32 diff);
@@ -584,7 +576,6 @@ class TC_GAME_API Battleground : public ZoneScript
uint32 m_ResetStatTimer;
uint32 m_ValidStartPositionTimer;
int32 m_EndTime; // it is set to 120000 when bg is ending and it decreases itself
- uint32 m_LastResurrectTime;
uint8 m_ArenaType; // 2=2v2, 3=3v3, 5=5v5
bool m_InBGFreeSlotQueue; // used to make sure that BG is only once inserted into the BattlegroundMgr.BGFreeSlotQueue[bgTypeId] deque
bool m_SetDeleteThis; // used for safe deletion of the bg after end / all players leave
@@ -597,7 +588,6 @@ class TC_GAME_API Battleground : public ZoneScript
uint32 m_LastPlayerPositionBroadcast;
// Player lists
- GuidVector m_ResurrectQueue; // Player GUID
std::deque<ObjectGuid> m_OfflineQueue; // Player GUID
// Invited counters are useful for player invitation to BG - do not allow, if BG is started to one faction to have 2 more players than another faction
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
index c7808947032..aa903481d75 100644
--- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
@@ -579,18 +579,6 @@ void BattlegroundMgr::SendToBattleground(Player* player, uint32 instanceId, Batt
TC_LOG_ERROR("bg.battleground", "BattlegroundMgr::SendToBattleground: Instance {} (bgType {}) not found while trying to teleport player {}", instanceId, bgTypeId, player->GetName());
}
-void BattlegroundMgr::SendAreaSpiritHealerQueryOpcode(Player* player, Battleground* bg, ObjectGuid const& guid)
-{
- uint32 time_ = 30000 - bg->GetLastResurrectTime(); // resurrect every 30 seconds
- if (time_ == uint32(-1))
- time_ = 0;
-
- WorldPackets::Battleground::AreaSpiritHealerTime areaSpiritHealerTime;
- areaSpiritHealerTime.HealerGuid = guid;
- areaSpiritHealerTime.TimeLeft = time_;
- player->SendDirectMessage(areaSpiritHealerTime.Write());
-}
-
bool BattlegroundMgr::IsArenaType(BattlegroundTypeId bgTypeId)
{
return bgTypeId == BATTLEGROUND_AA
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.h b/src/server/game/Battlegrounds/BattlegroundMgr.h
index 76ec8832ee9..8de23069e99 100644
--- a/src/server/game/Battlegrounds/BattlegroundMgr.h
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.h
@@ -96,7 +96,6 @@ class TC_GAME_API BattlegroundMgr
void BuildBattlegroundStatusActive(WorldPackets::Battleground::BattlefieldStatusActive* battlefieldStatus, Battleground* bg, Player* player, uint32 ticketId, uint32 joinTime, uint32 arenaType);
void BuildBattlegroundStatusQueued(WorldPackets::Battleground::BattlefieldStatusQueued* battlefieldStatus, Battleground* bg, Player* player, uint32 ticketId, uint32 joinTime, BattlegroundQueueTypeId queueId, uint32 avgWaitTime, uint32 arenaType, bool asGroup);
void BuildBattlegroundStatusFailed(WorldPackets::Battleground::BattlefieldStatusFailed* battlefieldStatus, BattlegroundQueueTypeId queueId, Player* pPlayer, uint32 ticketId, GroupJoinBattlegroundResult result, ObjectGuid const* errorGuid = nullptr);
- void SendAreaSpiritHealerQueryOpcode(Player* player, Battleground* bg, ObjectGuid const& guid);
/* Battlegrounds */
Battleground* GetBattleground(uint32 InstanceID, BattlegroundTypeId bgTypeId);
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp
index 112558377af..045238009d0 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp
@@ -393,8 +393,6 @@ void BattlegroundAB::_NodeDeOccupied(uint8 node)
//remove bonus honor aura trigger creature when node is lost
DelCreature(node+7);//NULL checks are in DelCreature! 0-6 spirit guides
- RelocateDeadPlayers(BgCreatures[node]);
-
DelCreature(node);
// buff object isn't despawned
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
index ee07e305e24..be75e338ed8 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
@@ -1000,8 +1000,6 @@ void BattlegroundAV::EventPlayerAssaultsPoint(Player* player, uint32 object)
//spawning/despawning of aura
SpawnBGObject(BG_AV_OBJECT_AURA_N_FIRSTAID_STATION + 3 * node, RESPAWN_IMMEDIATELY); //neutral aura spawn
SpawnBGObject(BG_AV_OBJECT_AURA_A_FIRSTAID_STATION + uint32(GetTeamIndexByTeamId(owner)) + 3 * node, RESPAWN_ONE_DAY); //teeamaura despawn
-
- RelocateDeadPlayers(BgCreatures[node]);
}
DePopulateNode(node);
}
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp
index b8c9e8ed845..78ea466b716 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp
@@ -427,8 +427,6 @@ void BattlegroundIC::EventPlayerClickedOnFlag(Player* player, GameObject* target
nodePoint[i].timer = BANNER_STATE_CHANGE_TIME; // 1 minute for last change (real faction banner)
nodePoint[i].needChange = true;
- RelocateDeadPlayers(BgCreatures[BG_IC_NPC_SPIRIT_GUIDE_1 + uint32(nodePoint[i].nodeType) - 2]);
-
// if we are here means that the point has been lost, or it is the first capture
if (nodePoint[i].nodeType != NODE_TYPE_REFINERY && nodePoint[i].nodeType != NODE_TYPE_QUARRY)
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 32690e08bff..d41b0162613 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -694,6 +694,9 @@ void Creature::Update(uint32 diff)
{
if (IsAIEnabled() && m_triggerJustAppeared && m_deathState != DEAD)
{
+ if (IsAreaSpiritHealer() && !IsAreaSpiritHealerIndividual())
+ CastSpell(nullptr, SPELL_SPIRIT_HEAL_CHANNEL_AOE, false);
+
if (m_respawnCompatibilityMode && m_vehicleKit)
m_vehicleKit->Reset();
m_triggerJustAppeared = false;
@@ -3600,3 +3603,22 @@ void Creature::SetTrainerId(Optional<uint32> trainerId)
{
_trainerId = trainerId;
}
+
+enum AreaSpiritHealerData
+{
+ NPC_ALLIANCE_GRAVEYARD_TELEPORT = 26350,
+ NPC_HORDE_GRAVEYARD_TELEPORT = 26351
+};
+
+void Creature::SummonGraveyardTeleporter()
+{
+ if (!IsAreaSpiritHealer())
+ return;
+
+ uint32 npcEntry = GetFaction() == FACTION_ALLIANCE_GENERIC ? NPC_ALLIANCE_GRAVEYARD_TELEPORT : NPC_HORDE_GRAVEYARD_TELEPORT;
+
+ // maybe NPC is summoned with these spells:
+ // ID - 24237 Summon Alliance Graveyard Teleporter (SERVERSIDE)
+ // ID - 46894 Summon Horde Graveyard Teleporter (SERVERSIDE)
+ SummonCreature(npcEntry, GetPosition(), TEMPSUMMON_TIMED_DESPAWN, 1s, 0, 0);
+}
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index a8d14a0a9b0..9f1f57904a9 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -424,6 +424,8 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
uint32 GetTrainerId() const;
void SetTrainerId(Optional<uint32> trainerId);
+ void SummonGraveyardTeleporter();
+
protected:
bool CreateFromProto(ObjectGuid::LowType guidlow, uint32 entry, CreatureData const* data = nullptr, uint32 vehId = 0);
bool InitEntry(uint32 entry, CreatureData const* data = nullptr);
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index ba8e83a5bf5..56cce2bf0a4 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -4380,6 +4380,8 @@ void Player::BuildPlayerRepop()
void Player::ResurrectPlayer(float restore_percent, bool applySickness)
{
+ SetAreaSpiritHealer(nullptr);
+
WorldPackets::Misc::DeathReleaseLoc packet;
packet.MapID = -1;
SendDirectMessage(packet.Write());
@@ -29235,6 +29237,39 @@ std::string Player::GetDebugInfo() const
return sstr.str();
}
+void Player::SetAreaSpiritHealer(Creature* creature)
+{
+ if (!creature)
+ {
+ _areaSpiritHealerGUID = ObjectGuid::Empty;
+ RemoveAurasDueToSpell(SPELL_WAITING_FOR_RESURRECT);
+ return;
+ }
+
+ if (!creature->IsAreaSpiritHealer())
+ return;
+
+ _areaSpiritHealerGUID = creature->GetGUID();
+ CastSpell(nullptr, SPELL_WAITING_FOR_RESURRECT);
+}
+
+void Player::SendAreaSpiritHealerTime(Unit* spiritHealer) const
+{
+ int32 timeLeft = 0;
+ if (Spell* spell = spiritHealer->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
+ timeLeft = spell->GetTimer();
+
+ SendAreaSpiritHealerTime(spiritHealer->GetGUID(), timeLeft);
+}
+
+void Player::SendAreaSpiritHealerTime(ObjectGuid const& spiritHealerGUID, int32 timeLeft) const
+{
+ WorldPackets::Battleground::AreaSpiritHealerTime areaSpiritHealerTime;
+ areaSpiritHealerTime.HealerGuid = spiritHealerGUID;
+ areaSpiritHealerTime.TimeLeft = timeLeft;
+ SendDirectMessage(areaSpiritHealerTime.Write());
+}
+
void Player::SendDisplayToast(uint32 entry, DisplayToastType type, bool isBonusRoll, uint32 quantity, DisplayToastMethod method, uint32 questId, Item* item /*= nullptr*/) const
{
WorldPackets::Misc::DisplayToast displayToast;
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 798925e5c85..200b343b9c6 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1121,6 +1121,7 @@ private:
uint32 constexpr PLAYER_MAX_HONOR_LEVEL = 500;
uint8 constexpr PLAYER_LEVEL_MIN_HONOR = 10;
uint32 constexpr SPELL_PVP_RULES_ENABLED = 134735;
+float constexpr MAX_AREA_SPIRIT_HEALER_RANGE = 20.0f;
enum class ZonePVPTypeOverride : uint32
{
@@ -2865,6 +2866,12 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
UF::UpdateField<UF::PlayerData, 0, TYPEID_PLAYER> m_playerData;
UF::UpdateField<UF::ActivePlayerData, 0, TYPEID_ACTIVE_PLAYER> m_activePlayerData;
+ void SetAreaSpiritHealer(Creature* creature);
+ ObjectGuid const& GetSpiritHealerGUID() const { return _areaSpiritHealerGUID; }
+ bool CanAcceptAreaSpiritHealFrom(Unit* spiritHealer) const { return spiritHealer->GetGUID() == _areaSpiritHealerGUID; }
+ void SendAreaSpiritHealerTime(Unit* spiritHealer) const;
+ void SendAreaSpiritHealerTime(ObjectGuid const& spiritHealerGUID, int32 timeLeft) const;
+
protected:
// Gamemaster whisper whitelist
GuidList WhisperList;
@@ -3217,6 +3224,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
std::unique_ptr<RestMgr> _restMgr;
bool _usePvpItemLevels;
+ ObjectGuid _areaSpiritHealerGUID;
};
TC_GAME_API void AddItemsSetItem(Player* player, Item const* item);
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 6c7491f2c2e..91247e8166a 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -9414,6 +9414,12 @@ void Unit::RemoveFromWorld()
if (IsInWorld())
{
+ if (IsAreaSpiritHealer())
+ {
+ if (Creature* creature = ToCreature())
+ creature->SummonGraveyardTeleporter();
+ }
+
m_duringRemoveFromWorld = true;
if (UnitAI* ai = GetAI())
ai->OnDespawn();
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 9875c5eab70..06f8076df6d 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -1120,6 +1120,7 @@ class TC_GAME_API Unit : public WorldObject
bool IsWildBattlePet() const { return HasNpcFlag(UNIT_NPC_FLAG_WILD_BATTLE_PET); }
bool IsServiceProvider() const;
bool IsSpiritService() const { return HasNpcFlag(UNIT_NPC_FLAG_SPIRIT_HEALER | UNIT_NPC_FLAG_AREA_SPIRIT_HEALER); }
+ bool IsAreaSpiritHealerIndividual() const { return HasNpcFlag2(UNIT_NPC_FLAG_2_AREA_SPIRIT_HEALER_INDIVIDUAL); }
bool IsCritter() const { return GetCreatureType() == CREATURE_TYPE_CRITTER; }
bool IsInFlight() const { return HasUnitState(UNIT_STATE_IN_FLIGHT); }
diff --git a/src/server/game/Handlers/BattleGroundHandler.cpp b/src/server/game/Handlers/BattleGroundHandler.cpp
index a24e97ba821..1fafa48e9a9 100644
--- a/src/server/game/Handlers/BattleGroundHandler.cpp
+++ b/src/server/game/Handlers/BattleGroundHandler.cpp
@@ -35,6 +35,9 @@
#include "Object.h"
#include "ObjectAccessor.h"
#include "Player.h"
+#include "SpellAuras.h"
+#include "SpellMgr.h"
+#include "SpellInfo.h"
#include "World.h"
void WorldSession::HandleBattlemasterHelloOpcode(WorldPackets::NPC::Hello& hello)
@@ -651,34 +654,47 @@ void WorldSession::HandleRequestPvpReward(WorldPackets::Battleground::RequestPVP
void WorldSession::HandleAreaSpiritHealerQueryOpcode(WorldPackets::Battleground::AreaSpiritHealerQuery& areaSpiritHealerQuery)
{
- Creature* unit = ObjectAccessor::GetCreature(*GetPlayer(), areaSpiritHealerQuery.HealerGuid);
- if (!unit)
+ Player* player = GetPlayer();
+ Creature* spiritHealer = ObjectAccessor::GetCreature(*player, areaSpiritHealerQuery.HealerGuid);
+ if (!spiritHealer)
return;
- if (!unit->IsSpiritService()) // it's not spirit service
+ if (!spiritHealer->IsAreaSpiritHealer())
return;
- if (Battleground* bg = _player->GetBattleground())
- sBattlegroundMgr->SendAreaSpiritHealerQueryOpcode(_player, bg, areaSpiritHealerQuery.HealerGuid);
+ if (_player->GetExactDist(spiritHealer) > MAX_AREA_SPIRIT_HEALER_RANGE)
+ return;
- if (Battlefield* bf = sBattlefieldMgr->GetBattlefieldToZoneId(_player->GetMap(), _player->GetZoneId()))
- bf->SendAreaSpiritHealerQueryOpcode(_player, areaSpiritHealerQuery.HealerGuid);
+ if (spiritHealer->IsAreaSpiritHealerIndividual())
+ {
+ if (Aura* aura = player->GetAura(SPELL_SPIRIT_HEAL_PLAYER_AURA))
+ {
+ player->SendAreaSpiritHealerTime(spiritHealer->GetGUID(), aura->GetDuration());
+ }
+ else if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_SPIRIT_HEAL_PLAYER_AURA, DIFFICULTY_NONE))
+ {
+ spiritHealer->CastSpell(player, SPELL_SPIRIT_HEAL_PLAYER_AURA);
+ player->SendAreaSpiritHealerTime(spiritHealer->GetGUID(), spellInfo->GetDuration());
+ spiritHealer->CastSpell(nullptr, SPELL_SPIRIT_HEAL_CHANNEL_SELF);
+ }
+ }
+ else
+ _player->SendAreaSpiritHealerTime(spiritHealer);
}
void WorldSession::HandleAreaSpiritHealerQueueOpcode(WorldPackets::Battleground::AreaSpiritHealerQueue& areaSpiritHealerQueue)
{
- Creature* unit = ObjectAccessor::GetCreature(*GetPlayer(), areaSpiritHealerQueue.HealerGuid);
- if (!unit)
+ Creature* spiritHealer = ObjectAccessor::GetCreature(*GetPlayer(), areaSpiritHealerQueue.HealerGuid);
+ if (!spiritHealer)
return;
- if (!unit->IsSpiritService()) // it's not spirit service
+ if (!spiritHealer->IsAreaSpiritHealer())
return;
- if (Battleground* bg = _player->GetBattleground())
- bg->AddPlayerToResurrectQueue(areaSpiritHealerQueue.HealerGuid, _player->GetGUID());
+ if (_player->GetExactDist(spiritHealer) > MAX_AREA_SPIRIT_HEALER_RANGE)
+ return;
- if (Battlefield* bf = sBattlefieldMgr->GetBattlefieldToZoneId(_player->GetMap(), _player->GetZoneId()))
- bf->AddPlayerToResurrectQueue(areaSpiritHealerQueue.HealerGuid, _player->GetGUID());
+ _player->SetAreaSpiritHealer(spiritHealer);
}
void WorldSession::HandleHearthAndResurrect(WorldPackets::Battleground::HearthAndResurrect& /*hearthAndResurrect*/)
diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp
index 5f706002ec4..c8a94c3f206 100644
--- a/src/server/game/Handlers/NPCHandler.cpp
+++ b/src/server/game/Handlers/NPCHandler.cpp
@@ -167,16 +167,10 @@ void WorldSession::HandleGossipHelloOpcode(WorldPackets::NPC::Hello& packet)
unit->PauseMovement(pause);
unit->SetHomePosition(unit->GetPosition());
- // If spiritguide, no need for gossip menu, just put player into resurrect queue
if (unit->IsAreaSpiritHealer())
{
- Battleground* bg = _player->GetBattleground();
- if (bg)
- {
- bg->AddPlayerToResurrectQueue(unit->GetGUID(), _player->GetGUID());
- sBattlegroundMgr->SendAreaSpiritHealerQueryOpcode(_player, bg, unit->GetGUID());
- return;
- }
+ _player->SetAreaSpiritHealer(unit);
+ _player->SendAreaSpiritHealerTime(unit);
}
_player->PlayerTalkClass->ClearMenus();
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 2a205b09882..8992a14462c 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -4662,16 +4662,6 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
case SPELLFAMILY_GENERIC:
switch (GetId())
{
- case 2584: // Waiting to Resurrect
- // Waiting to resurrect spell cancel, we must remove player from resurrect queue
- if (target->GetTypeId() == TYPEID_PLAYER)
- {
- if (Battleground* bg = target->ToPlayer()->GetBattleground())
- bg->RemovePlayerFromResurrectQueue(target->GetGUID());
- if (Battlefield* bf = sBattlefieldMgr->GetBattlefieldToZoneId(target->GetMap(), target->GetZoneId()))
- bf->RemovePlayerFromResurrectQueue(target->GetGUID());
- }
- break;
case 43681: // Inactive
{
if (target->GetTypeId() != TYPEID_PLAYER || aurApp->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE)
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 2dab2a3d9c5..1dbc2269e84 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -4488,26 +4488,29 @@ void Spell::EffectSkill()
TC_LOG_DEBUG("spells", "WORLD: SkillEFFECT");
}
-/* There is currently no need for this effect. We handle it in Battleground.cpp
- If we would handle the resurrection here, the spiritguide would instantly disappear as the
- player revives, and so we wouldn't see the spirit heal visual effect on the npc.
- This is why we use a half sec delay between the visual effect and the resurrection itself */
void Spell::EffectSpiritHeal()
{
+ Unit* caster = GetCaster()->ToUnit();
+ if (effectHandleMode == SPELL_EFFECT_HANDLE_HIT)
+ caster->CastSpell(nullptr, SPELL_RESURRECTION_VISUAL, true);
+
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
return;
- /*
- if (unitTarget->GetTypeId() != TYPEID_PLAYER)
- return;
- if (!unitTarget->IsInWorld())
- return;
+ if (Player* playerTarget = unitTarget->ToPlayer())
+ {
+ if (!playerTarget->IsInWorld())
+ return;
+
+ // skip if player does not want to live
+ if (!playerTarget->CanAcceptAreaSpiritHealFrom(caster))
+ return;
- //m_spellInfo->Effects[i].BasePoints; == 99 (percent?)
- //unitTarget->ToPlayer()->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA));
- unitTarget->ToPlayer()->ResurrectPlayer(1.0f);
- unitTarget->ToPlayer()->SpawnCorpseBones();
- */
+ playerTarget->ResurrectPlayer(1.0f);
+ playerTarget->CastSpell(playerTarget, SPELL_PET_SUMMONED, true);
+ playerTarget->CastSpell(playerTarget, SPELL_SPIRIT_HEAL_MANA, true);
+ playerTarget->SpawnCorpseBones(false);
+ }
}
// remove insignia spell effect
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index cf9c1fa9997..43844717a11 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -2052,8 +2052,6 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a
case 34976: // Netherstorm Flag
return map_id == 566 && player && player->InBattleground() ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA;
case 2584: // Waiting to Resurrect
- case 22011: // Spirit Heal Channel
- case 22012: // Spirit Heal
case 42792: // Recently Dropped Flag
case 43681: // Inactive
case 44535: // Spirit Heal (mana)
diff --git a/src/server/scripts/Battlefield/BattlefieldTB.cpp b/src/server/scripts/Battlefield/BattlefieldTB.cpp
index c49d92eb6bc..9d9902adbe2 100644
--- a/src/server/scripts/Battlefield/BattlefieldTB.cpp
+++ b/src/server/scripts/Battlefield/BattlefieldTB.cpp
@@ -511,7 +511,6 @@ void BattlefieldTB::OnCreatureCreate(Creature* creature)
case NPC_TB_GY_SPIRIT_EAST_SPIRE_H:
case NPC_TB_GY_SPIRIT_SOUTH_SPIRE_H:
creature->CastSpell(creature, SPELL_TB_SPIRITUAL_IMMUNITY, true);
- creature->CastSpell(creature, SPELL_TB_SPIRIT_HEAL_CHANNEL, true);
break;
default:
break;
diff --git a/src/server/scripts/Battlefield/BattlefieldTB.h b/src/server/scripts/Battlefield/BattlefieldTB.h
index ed274a2e49e..f39e39d690c 100644
--- a/src/server/scripts/Battlefield/BattlefieldTB.h
+++ b/src/server/scripts/Battlefield/BattlefieldTB.h
@@ -54,7 +54,6 @@ enum TolBaradSpells
SPELL_TB_SLOW_FALL = 88473,
SPELL_TB_VETERAN = 84655,
SPELL_TOWER_ATTACK_BONUS = 82629,
- SPELL_TB_SPIRIT_HEAL_CHANNEL = 22011, // this spell replaces m_LastResurrectTimer in Battlefield.cpp?
SPELL_TB_SPIRITUAL_IMMUNITY = 95332,
// Vehicle
diff --git a/src/server/scripts/EasternKingdoms/zone_tol_barad.cpp b/src/server/scripts/EasternKingdoms/zone_tol_barad.cpp
index d52d7f89eca..e0da4c64877 100644
--- a/src/server/scripts/EasternKingdoms/zone_tol_barad.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_tol_barad.cpp
@@ -29,8 +29,6 @@
enum TBSpiritGuide
{
- SPELL_CHANNEL_SPIRIT_HEAL = 22011,
-
GOSSIP_OPTION_ID_SLAGWORKS = 0,
GOSSIP_OPTION_ID_IRONCLAD_GARRISON = 1,
GOSSIP_OPTION_ID_WARDENS_VIGIL = 2,
@@ -39,61 +37,44 @@ enum TBSpiritGuide
GOSSIP_OPTION_ID_SOUTH_SPIRE = 5,
};
-class npc_tb_spirit_guide : public CreatureScript
+struct npc_tb_spirit_guide : public ScriptedAI
{
- public:
- npc_tb_spirit_guide() : CreatureScript("npc_tb_spirit_guide") { }
-
- struct npc_tb_spirit_guideAI : public ScriptedAI
- {
- npc_tb_spirit_guideAI(Creature* creature) : ScriptedAI(creature) { }
-
- void UpdateAI(uint32 /*diff*/) override
- {
- if (!me->HasUnitState(UNIT_STATE_CASTING))
- DoCast(me, SPELL_CHANNEL_SPIRIT_HEAL);
- }
-
- bool OnGossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
- {
- player->PlayerTalkClass->SendCloseGossip();
-
- uint32 areaId = 0;
- switch (gossipListId)
- {
- case GOSSIP_OPTION_ID_SLAGWORKS:
- areaId = TB_GY_SLAGWORKS;
- break;
- case GOSSIP_OPTION_ID_IRONCLAD_GARRISON:
- areaId = TB_GY_IRONCLAD_GARRISON;
- break;
- case GOSSIP_OPTION_ID_WARDENS_VIGIL:
- areaId = TB_GY_WARDENS_VIGIL;
- break;
- case GOSSIP_OPTION_ID_EAST_SPIRE:
- areaId = TB_GY_EAST_SPIRE;
- break;
- case GOSSIP_OPTION_ID_WEST_SPIRE:
- areaId = TB_GY_WEST_SPIRE;
- break;
- case GOSSIP_OPTION_ID_SOUTH_SPIRE:
- areaId = TB_GY_SOUTH_SPIRE;
- break;
- default:
- return true;
- }
+ npc_tb_spirit_guide(Creature* creature) : ScriptedAI(creature) { }
- if (WorldSafeLocsEntry const* safeLoc = sObjectMgr->GetWorldSafeLoc(areaId))
- player->TeleportTo(safeLoc->Loc);
-
- return false;
- }
- };
+ bool OnGossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
+ {
+ player->PlayerTalkClass->SendCloseGossip();
- CreatureAI* GetAI(Creature* creature) const override
+ uint32 areaId = 0;
+ switch (gossipListId)
{
- return new npc_tb_spirit_guideAI(creature);
+ case GOSSIP_OPTION_ID_SLAGWORKS:
+ areaId = TB_GY_SLAGWORKS;
+ break;
+ case GOSSIP_OPTION_ID_IRONCLAD_GARRISON:
+ areaId = TB_GY_IRONCLAD_GARRISON;
+ break;
+ case GOSSIP_OPTION_ID_WARDENS_VIGIL:
+ areaId = TB_GY_WARDENS_VIGIL;
+ break;
+ case GOSSIP_OPTION_ID_EAST_SPIRE:
+ areaId = TB_GY_EAST_SPIRE;
+ break;
+ case GOSSIP_OPTION_ID_WEST_SPIRE:
+ areaId = TB_GY_WEST_SPIRE;
+ break;
+ case GOSSIP_OPTION_ID_SOUTH_SPIRE:
+ areaId = TB_GY_SOUTH_SPIRE;
+ break;
+ default:
+ return true;
}
+
+ if (WorldSafeLocsEntry const* safeLoc = sObjectMgr->GetWorldSafeLoc(areaId))
+ player->TeleportTo(safeLoc->Loc);
+
+ return false;
+ }
};
// 85123 - Siege Cannon - selects random target
@@ -130,6 +111,6 @@ public:
void AddSC_tol_barad()
{
- new npc_tb_spirit_guide();
+ RegisterCreatureAI(npc_tb_spirit_guide);
new spell_siege_cannon();
}
diff --git a/src/server/scripts/Northrend/zone_wintergrasp.cpp b/src/server/scripts/Northrend/zone_wintergrasp.cpp
index e4a53d4c57f..011414865c7 100644
--- a/src/server/scripts/Northrend/zone_wintergrasp.cpp
+++ b/src/server/scripts/Northrend/zone_wintergrasp.cpp
@@ -61,9 +61,6 @@ enum Spells
SPELL_RIDE_WG_VEHICLE = 60968,
SPELL_VEHICLE_TELEPORT = 49759,
-
- // Spirit guide
- SPELL_CHANNEL_SPIRIT_HEAL = 22011,
};
enum CreatureIds
@@ -192,12 +189,6 @@ struct npc_wg_spirit_guide : public ScriptedAI
{
npc_wg_spirit_guide(Creature* creature) : ScriptedAI(creature) { }
- void UpdateAI(uint32 /*diff*/) override
- {
- if (!me->HasUnitState(UNIT_STATE_CASTING))
- DoCast(me, SPELL_CHANNEL_SPIRIT_HEAL);
- }
-
bool OnGossipHello(Player* player) override
{
if (me->IsQuestGiver())
diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp
index e5346f910bb..3176c5704fa 100644
--- a/src/server/scripts/Spells/spell_generic.cpp
+++ b/src/server/scripts/Spells/spell_generic.cpp
@@ -5415,6 +5415,118 @@ private:
uint32 _exhaustionSpellId;
};
+// AoE resurrections by spirit guides
+// 22012 - Spirit Heal
+class spell_gen_spirit_heal_aoe : public SpellScript
+{
+ PrepareSpellScript(spell_gen_spirit_heal_aoe);
+
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ Unit* caster = GetCaster();
+ targets.remove_if([caster](WorldObject* target) -> bool
+ {
+ if (Player* playerTarget = target->ToPlayer())
+ return !playerTarget->CanAcceptAreaSpiritHealFrom(caster);
+
+ return true;
+ });
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_gen_spirit_heal_aoe::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ALLY);
+ }
+};
+
+// Personal resurrections in battlegrounds
+// 156758 - Spirit Heal
+class spell_gen_spirit_heal_personal : public AuraScript
+{
+ static constexpr uint32 SPELL_SPIRIT_HEAL_EFFECT = 156763;
+
+ PrepareAuraScript(spell_gen_spirit_heal_personal);
+
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE)
+ return;
+
+ Player* targetPlayer = GetTarget()->ToPlayer();
+ if (!targetPlayer)
+ return;
+
+ Unit* caster = GetCaster();
+ if (!caster)
+ return;
+
+ if (targetPlayer->CanAcceptAreaSpiritHealFrom(caster))
+ caster->CastSpell(targetPlayer, SPELL_SPIRIT_HEAL_EFFECT);
+ }
+
+ void Register() override
+ {
+ AfterEffectRemove += AuraEffectRemoveFn(spell_gen_spirit_heal_personal::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
+};
+
+class RecastSpiritHealChannelEvent : public BasicEvent
+{
+public:
+ RecastSpiritHealChannelEvent(Unit* caster) : _caster(caster) { }
+
+ bool Execute(uint64 /*e_time*/, uint32 /*p_time*/) override
+ {
+ if (_caster->GetChannelSpellId() == 0)
+ _caster->CastSpell(nullptr, SPELL_SPIRIT_HEAL_CHANNEL_AOE, false);
+
+ return true;
+ }
+
+private:
+ Unit* _caster;
+};
+
+// 22011 - Spirit Heal Channel
+class spell_gen_spirit_heal_channel : public AuraScript
+{
+ PrepareAuraScript(spell_gen_spirit_heal_channel);
+
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE)
+ return;
+
+ Unit* target = GetTarget();
+ target->m_Events.AddEventAtOffset(new RecastSpiritHealChannelEvent(target), 1s);
+ }
+
+ void Register() override
+ {
+ AfterEffectRemove += AuraEffectRemoveFn(spell_gen_spirit_heal_channel::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
+ }
+};
+
+// 2584 - Waiting to Resurrect
+class spell_gen_waiting_to_resurrect : public AuraScript
+{
+ PrepareAuraScript(spell_gen_waiting_to_resurrect);
+
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ Player* targetPlayer = GetTarget()->ToPlayer();
+ if (!targetPlayer)
+ return;
+
+ targetPlayer->SetAreaSpiritHealer(nullptr);
+ }
+
+ void Register() override
+ {
+ AfterEffectRemove += AuraEffectRemoveFn(spell_gen_waiting_to_resurrect::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
+};
+
void AddSC_generic_spell_scripts()
{
RegisterSpellScript(spell_gen_absorb0_hitlimit1);
@@ -5584,4 +5696,8 @@ void AddSC_generic_spell_scripts()
RegisterSpellScriptWithArgs(spell_gen_bloodlust, "spell_hun_primal_rage", SPELL_HUNTER_FATIGUED);
RegisterSpellScriptWithArgs(spell_gen_bloodlust, "spell_evo_fury_of_the_aspects", SPELL_EVOKER_EXHAUSTION);
RegisterSpellScriptWithArgs(spell_gen_bloodlust, "spell_item_bloodlust_drums", SPELL_SHAMAN_EXHAUSTION);
+ RegisterSpellScript(spell_gen_spirit_heal_aoe);
+ RegisterSpellScript(spell_gen_spirit_heal_personal);
+ RegisterSpellScript(spell_gen_spirit_heal_channel);
+ RegisterSpellScript(spell_gen_waiting_to_resurrect);
}