Core/Battlegrounds: Moved AreaSpiritHealer resurrection handling to respective npc flags (#28508)
* UNIT_NPC_FLAG_AREA_SPIRIT_HEALER * UNIT_NPC_FLAG_2_AREA_SPIRIT_HEALER_INDIVIDUAL
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
UPDATE `creature_template_addon` SET `auras`='9036 9617' WHERE `entry`=13117; -- 13117 (Horde Spirit Guide) - Ghost, Ghost Visual
|
||||
UPDATE `creature_template_addon` SET `auras`='9036 9617' WHERE `entry`=13116; -- 13116 (Alliance Spirit Guide) - Ghost, Ghost Visual
|
||||
UPDATE `creature_template` SET `ScriptName`='', `AIName`='' WHERE `entry` IN (13116, 13117, 88238, 88239); -- BGs
|
||||
|
||||
-- allow the graveyard teleporters to see dead players
|
||||
UPDATE `creature_template` SET `flags_extra` = `flags_extra`|0x00000400 WHERE `entry` IN (26350, 26351);
|
||||
|
||||
-- Graveyard Teleport
|
||||
DELETE FROM `serverside_spell_effect` WHERE `SpellID` = 46893;
|
||||
INSERT INTO `serverside_spell_effect` (`SpellID`, `EffectIndex`, `DifficultyID`, `Effect`, `EffectAura`, `EffectAmplitude`, `EffectAttributes`, `EffectAuraPeriod`, `EffectBonusCoefficient`, `EffectChainAmplitude`, `EffectChainTargets`, `EffectItemType`, `EffectMechanic`, `EffectPointsPerResource`, `EffectPosFacing`, `EffectRealPointsPerLevel`, `EffectTriggerSpell`, `BonusCoefficientFromAP`, `PvpMultiplier`, `Coefficient`, `Variance`, `ResourceCoefficient`, `GroupSizeBasePointsCoefficient`, `EffectBasePoints`, `EffectMiscValue1`, `EffectMiscValue2`, `EffectRadiusIndex1`, `EffectRadiusIndex2`, `EffectSpellClassMask1`, `EffectSpellClassMask2`, `EffectSpellClassMask3`, `EffectSpellClassMask4`, `ImplicitTarget1`, `ImplicitTarget2`) VALUES
|
||||
(46893, 0, 0, 120, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 22, 30);
|
||||
|
||||
DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_gen_spirit_heal_aoe', 'spell_gen_spirit_heal_personal', 'spell_gen_spirit_heal_channel', 'spell_gen_waiting_to_resurrect');
|
||||
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
|
||||
(22012, 'spell_gen_spirit_heal_aoe'),
|
||||
(156758, 'spell_gen_spirit_heal_personal'),
|
||||
(22011, 'spell_gen_spirit_heal_channel'),
|
||||
(2584, 'spell_gen_waiting_to_resurrect');
|
||||
|
||||
DELETE FROM `creature_template_addon` WHERE `entry` IN (26350, 26351);
|
||||
INSERT INTO `creature_template_addon` (`entry`, `path_id`, `mount`, `StandState`, `AnimTier`, `VisFlags`, `SheathState`, `PvPFlags`, `emote`, `aiAnimKit`, `movementAnimKit`, `meleeAnimKit`, `visibilityDistanceType`, `auras`) VALUES
|
||||
(26350, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, '8149'), -- 26350 (Alliance Graveyard Teleporter) - Super Invis
|
||||
(26351, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, '8149'); -- 26351 (Horde Graveyard Teleporter) - Super Invis
|
||||
|
||||
UPDATE `creature_template` SET `ScriptName`='', `AIName`='SmartAI' WHERE `entry` IN(26350, 26351);
|
||||
DELETE FROM `smart_scripts` WHERE `entryorguid` IN(26350, 26351) AND `source_type`=0;
|
||||
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param_string`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
|
||||
(26350,0,0,0,11,0,100,0,0,0,0,0,0,'',11,46893,0,0,0,0,0,1,0,0,0,0,0,0,0,0,'Alliance Graveyard Teleporter - On spawn - Cast "Graveyard Teleport"'),
|
||||
(26351,0,0,0,11,0,100,0,0,0,0,0,0,'',11,46893,0,0,0,0,0,1,0,0,0,0,0,0,0,0,'Horde Graveyard Teleporter - On spawn - Cast "Graveyard Teleport"');
|
||||
@@ -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);*/
|
||||
|
||||
if (Creature* spiritHealer = m_Bf->GetCreature(m_SpiritGuide[team]))
|
||||
spiritHealer->SummonGraveyardTeleporter();
|
||||
|
||||
m_ControlTeam = team;
|
||||
// Teleport to other graveyard, player witch were on this graveyard
|
||||
RelocateDeadPlayers();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool BfGraveyard::HasNpc(ObjectGuid guid)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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*/)
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
//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();
|
||||
*/
|
||||
// skip if player does not want to live
|
||||
if (!playerTarget->CanAcceptAreaSpiritHealFrom(caster))
|
||||
return;
|
||||
|
||||
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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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") { }
|
||||
npc_tb_spirit_guide(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
struct npc_tb_spirit_guideAI : public ScriptedAI
|
||||
bool OnGossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
|
||||
{
|
||||
player->PlayerTalkClass->SendCloseGossip();
|
||||
|
||||
uint32 areaId = 0;
|
||||
switch (gossipListId)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
if (WorldSafeLocsEntry const* safeLoc = sObjectMgr->GetWorldSafeLoc(areaId))
|
||||
player->TeleportTo(safeLoc->Loc);
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user