Core/Battlegrounds: Moved AreaSpiritHealer resurrection handling to respective npc flags

Port From (https://github.com/TrinityCore/TrinityCore/commit/205aba1ff3a6f1ff92a8b26af646fd25f139c697)
This commit is contained in:
hondacrx
2023-05-21 18:38:55 -04:00
parent 3e72da9f1e
commit 35961a0121
17 changed files with 248 additions and 331 deletions
@@ -62,8 +62,10 @@ namespace Framework.Constants
public const sbyte PlayerPositionArenaSlot5 = 6; public const sbyte PlayerPositionArenaSlot5 = 6;
//Spells //Spells
public const uint SpellSpiritHealChannelAoE = 22011; // used for AoE resurrections
public const uint SpellSpiritHealPlayerAura = 156758; // individual player timers for resurrection
public const uint SpellSpiritHealChannelSelf = 305122; // channel visual for individual area spirit healers
public const uint SpellWaitingForResurrect = 2584; // Waiting To Resurrect public const uint SpellWaitingForResurrect = 2584; // Waiting To Resurrect
public const uint SpellSpiritHealChannel = 22011; // Spirit Heal Channel
public const uint SpellSpiritHealChannelVisual = 3060; public const uint SpellSpiritHealChannelVisual = 3060;
public const uint SpellSpiritHeal = 22012; // Spirit Heal public const uint SpellSpiritHeal = 22012; // Spirit Heal
public const uint SpellResurrectionVisual = 24171; // Resurrection Impact Visual public const uint SpellResurrectionVisual = 24171; // Resurrection Impact Visual
@@ -81,6 +83,7 @@ namespace Framework.Constants
public const uint SpellMercenaryAlliance1 = 193863; public const uint SpellMercenaryAlliance1 = 193863;
public const uint SpellMercenaryAllianceReactions = 195843; public const uint SpellMercenaryAllianceReactions = 195843;
public const uint SpellMercenaryShapeshift = 193970; public const uint SpellMercenaryShapeshift = 193970;
public const uint SpellPetSummoned = 6962; // used after resurrection
} }
public enum BattlegroundEventFlags public enum BattlegroundEventFlags
@@ -62,6 +62,8 @@ namespace Framework.Constants
public const uint SpellExperienceEliminated = 206662; public const uint SpellExperienceEliminated = 206662;
public const uint CurrencyMaxCapAncientMana = 2000; public const uint CurrencyMaxCapAncientMana = 2000;
public const float MaxAreaSpiritHealerRange = 20.0f;
} }
public struct MoneyConstants public struct MoneyConstants
+4 -132
View File
@@ -31,8 +31,6 @@ namespace Game.BattleFields
m_uiKickDontAcceptTimer = 1000; m_uiKickDontAcceptTimer = 1000;
m_uiKickAfkPlayersTimer = 1000; m_uiKickAfkPlayersTimer = 1000;
m_LastResurectTimer = 30 * Time.InMilliseconds;
m_Map = map; m_Map = map;
m_MapId = map.GetId(); m_MapId = map.GetId();
@@ -99,7 +97,6 @@ namespace Game.BattleFields
m_PlayersWillBeKick[player.GetTeamId()].Remove(player.GetGUID()); m_PlayersWillBeKick[player.GetTeamId()].Remove(player.GetGUID());
m_players[player.GetTeamId()].Remove(player.GetGUID()); m_players[player.GetTeamId()].Remove(player.GetGUID());
SendRemoveWorldStates(player); SendRemoveWorldStates(player);
RemovePlayerFromResurrectQueue(player.GetGUID());
OnPlayerLeaveZone(player); OnPlayerLeaveZone(player);
} }
@@ -164,17 +161,6 @@ namespace Game.BattleFields
objective_changed = true; objective_changed = true;
} }
if (m_LastResurectTimer <= diff)
{
for (byte i = 0; i < m_GraveyardList.Count; i++)
if (GetGraveyardById(i) != null)
m_GraveyardList[i].Resurrect();
m_LastResurectTimer = BattlegroundConst.ResurrectionInterval;
}
else
m_LastResurectTimer -= diff;
return objective_changed; return objective_changed;
} }
@@ -597,45 +583,6 @@ namespace Game.BattleFields
return null; return null;
} }
public virtual void AddPlayerToResurrectQueue(ObjectGuid npcGuid, ObjectGuid playerGuid)
{
for (byte i = 0; i < m_GraveyardList.Count; i++)
{
if (m_GraveyardList[i] == null)
continue;
if (m_GraveyardList[i].HasNpc(npcGuid))
{
m_GraveyardList[i].AddPlayer(playerGuid);
break;
}
}
}
public void RemovePlayerFromResurrectQueue(ObjectGuid playerGuid)
{
for (byte i = 0; i < m_GraveyardList.Count; i++)
{
if (m_GraveyardList[i] == null)
continue;
if (m_GraveyardList[i].HasPlayer(playerGuid))
{
m_GraveyardList[i].RemovePlayer(playerGuid);
break;
}
}
}
public void SendAreaSpiritHealerQuery(Player player, ObjectGuid guid)
{
AreaSpiritHealerTime areaSpiritHealerTime = new();
areaSpiritHealerTime.HealerGuid = guid;
areaSpiritHealerTime.TimeLeft = m_LastResurectTimer;// resurrect every 30 seconds
player.SendPacket(areaSpiritHealerTime);
}
public Creature SpawnCreature(uint entry, Position pos) public Creature SpawnCreature(uint entry, Position pos)
{ {
if (Global.ObjectMgr.GetCreatureTemplate(entry) == null) if (Global.ObjectMgr.GetCreatureTemplate(entry) == null)
@@ -810,7 +757,6 @@ namespace Game.BattleFields
// Graveyard variables // Graveyard variables
protected List<BfGraveyard> m_GraveyardList = new(); // Vector witch contain the different GY of the battle protected List<BfGraveyard> m_GraveyardList = new(); // Vector witch contain the different GY of the battle
uint m_LastResurectTimer; // Timer for resurect player every 30 sec
protected uint m_StartGroupingTimer; // Timer for invite players in area 15 minute before start battle protected uint m_StartGroupingTimer; // Timer for invite players in area 15 minute before start battle
protected bool m_StartGrouping; // bool for know if all players in area has been invited protected bool m_StartGrouping; // bool for know if all players in area has been invited
@@ -856,58 +802,6 @@ namespace Game.BattleFields
return player.GetDistance2d(safeLoc.Loc.GetPositionX(), safeLoc.Loc.GetPositionY()); return player.GetDistance2d(safeLoc.Loc.GetPositionX(), safeLoc.Loc.GetPositionY());
} }
public void AddPlayer(ObjectGuid playerGuid)
{
if (!m_ResurrectQueue.Contains(playerGuid))
{
m_ResurrectQueue.Add(playerGuid);
Player player = Global.ObjAccessor.FindPlayer(playerGuid);
if (player)
player.CastSpell(player, BattlegroundConst.SpellWaitingForResurrect, true);
}
}
public void RemovePlayer(ObjectGuid playerGuid)
{
m_ResurrectQueue.Remove(playerGuid);
Player player = Global.ObjAccessor.FindPlayer(playerGuid);
if (player)
player.RemoveAurasDueToSpell(BattlegroundConst.SpellWaitingForResurrect);
}
public void Resurrect()
{
if (m_ResurrectQueue.Empty())
return;
foreach (var guid in m_ResurrectQueue)
{
// Get player object from his guid
Player player = Global.ObjAccessor.FindPlayer(guid);
if (!player)
continue;
// Check if the player is in world and on the good graveyard
if (player.IsInWorld)
{
Creature spirit = m_Bf.GetCreature(m_SpiritGuide[m_ControlTeam]);
if (spirit)
spirit.CastSpell(spirit, BattlegroundConst.SpellSpiritHeal, true);
}
// Resurect player
player.CastSpell(player, BattlegroundConst.SpellResurrectionVisual, true);
player.ResurrectPlayer(1.0f);
player.CastSpell(player, 6962, true);
player.CastSpell(player, BattlegroundConst.SpellSpiritHealMana, true);
player.SpawnCorpseBones(false);
}
m_ResurrectQueue.Clear();
}
// For changing graveyard control // For changing graveyard control
public void GiveControlTo(uint team) public void GiveControlTo(uint team)
{ {
@@ -918,29 +812,11 @@ namespace Game.BattleFields
if (m_SpiritGuide[team]) if (m_SpiritGuide[team])
m_SpiritGuide[team].SetVisible(true);*/ m_SpiritGuide[team].SetVisible(true);*/
Creature spiritHealer = m_Bf.GetCreature(m_SpiritGuide[team]);
if (spiritHealer != null)
spiritHealer.SummonGraveyardTeleporter();
m_ControlTeam = team; m_ControlTeam = team;
// Teleport to other graveyard, player witch were on this graveyard
RelocateDeadPlayers();
}
void RelocateDeadPlayers()
{
WorldSafeLocsEntry closestGrave = null;
foreach (var guid in m_ResurrectQueue)
{
Player player = Global.ObjAccessor.FindPlayer(guid);
if (!player)
continue;
if (closestGrave != null)
player.TeleportTo(closestGrave.Loc);
else
{
closestGrave = m_Bf.GetClosestGraveYard(player);
if (closestGrave != null)
player.TeleportTo(closestGrave.Loc);
}
}
} }
public bool HasNpc(ObjectGuid guid) public bool HasNpc(ObjectGuid guid)
@@ -955,9 +831,6 @@ namespace Game.BattleFields
return (m_SpiritGuide[TeamId.Alliance] == guid || m_SpiritGuide[TeamId.Horde] == guid); return (m_SpiritGuide[TeamId.Alliance] == guid || m_SpiritGuide[TeamId.Horde] == guid);
} }
// Check if a player is in this graveyard's ressurect queue
public bool HasPlayer(ObjectGuid guid) { return m_ResurrectQueue.Contains(guid); }
// Get the graveyard's ID. // Get the graveyard's ID.
public uint GetGraveyardId() { return m_GraveyardId; } public uint GetGraveyardId() { return m_GraveyardId; }
@@ -966,7 +839,6 @@ namespace Game.BattleFields
uint m_ControlTeam; uint m_ControlTeam;
uint m_GraveyardId; uint m_GraveyardId;
ObjectGuid[] m_SpiritGuide = new ObjectGuid[SharedConst.PvpTeamsCount]; ObjectGuid[] m_SpiritGuide = new ObjectGuid[SharedConst.PvpTeamsCount];
List<ObjectGuid> m_ResurrectQueue = new();
protected BattleField m_Bf; protected BattleField m_Bf;
} }
+2 -127
View File
@@ -117,7 +117,6 @@ namespace Game.BattleGrounds
} }
else else
{ {
_ProcessRessurect(diff);
if (Global.BattlegroundMgr.GetPrematureFinishTime() != 0 && (GetPlayersCountByTeam(Team.Alliance) < GetMinPlayersPerTeam() || GetPlayersCountByTeam(Team.Horde) < GetMinPlayersPerTeam())) if (Global.BattlegroundMgr.GetPrematureFinishTime() != 0 && (GetPlayersCountByTeam(Team.Alliance) < GetMinPlayersPerTeam() || GetPlayersCountByTeam(Team.Horde) < GetMinPlayersPerTeam()))
_ProcessProgress(diff); _ProcessProgress(diff);
else if (m_PrematureCountDown) else if (m_PrematureCountDown)
@@ -214,61 +213,6 @@ namespace Game.BattleGrounds
} }
} }
void _ProcessRessurect(uint diff)
{
// *********************************************************
// *** Battleground RESSURECTION SYSTEM ***
// *********************************************************
// this should be handled by spell system
m_LastResurrectTime += diff;
if (m_LastResurrectTime >= BattlegroundConst.ResurrectionInterval)
{
if (GetReviveQueueSize() != 0)
{
Creature sh = null;
foreach (var pair in m_ReviveQueue)
{
Player player = Global.ObjAccessor.FindPlayer(pair.Value);
if (!player)
continue;
if (!sh && player.IsInWorld)
{
sh = player.GetMap().GetCreature(pair.Key);
// only for visual effect
if (sh)
// Spirit Heal, effect 117
sh.CastSpell(sh, BattlegroundConst.SpellSpiritHeal, true);
}
// Resurrection visual
player.CastSpell(player, BattlegroundConst.SpellResurrectionVisual, true);
m_ResurrectQueue.Add(pair.Value);
}
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
{
foreach (var guid in m_ResurrectQueue)
{
Player player = Global.ObjAccessor.FindPlayer(guid);
if (!player)
continue;
player.ResurrectPlayer(1.0f);
player.CastSpell(player, 6962, true);
player.CastSpell(player, BattlegroundConst.SpellSpiritHealMana, true);
player.SpawnCorpseBones(false);
}
m_ResurrectQueue.Clear();
}
}
public virtual Team GetPrematureWinner() public virtual Team GetPrematureWinner()
{ {
Team winner = 0; Team winner = 0;
@@ -835,8 +779,6 @@ namespace Game.BattleGrounds
if (PlayerScores.ContainsKey(guid)) if (PlayerScores.ContainsKey(guid))
PlayerScores.Remove(guid); PlayerScores.Remove(guid);
RemovePlayerFromResurrectQueue(guid);
Player player = Global.ObjAccessor.FindPlayer(guid); Player player = Global.ObjAccessor.FindPlayer(guid);
if (player) if (player)
{ {
@@ -940,7 +882,6 @@ namespace Game.BattleGrounds
SetStatus(BattlegroundStatus.WaitQueue); SetStatus(BattlegroundStatus.WaitQueue);
SetElapsedTime(0); SetElapsedTime(0);
SetRemainingTime(0); SetRemainingTime(0);
SetLastResurrectTime(0);
m_Events = 0; m_Events = 0;
if (m_InvitedAlliance > 0 || m_InvitedHorde > 0) if (m_InvitedAlliance > 0 || m_InvitedHorde > 0)
@@ -960,7 +901,6 @@ namespace Game.BattleGrounds
public void StartBattleground() public void StartBattleground()
{ {
SetElapsedTime(0); SetElapsedTime(0);
SetLastResurrectTime(0);
// add BG to free slot queue // add BG to free slot queue
AddToBGFreeSlotQueue(); AddToBGFreeSlotQueue();
@@ -1313,56 +1253,6 @@ namespace Game.BattleGrounds
return true; return true;
} }
public void AddPlayerToResurrectQueue(ObjectGuid npc_guid, ObjectGuid player_guid)
{
m_ReviveQueue.Add(npc_guid, player_guid);
Player player = Global.ObjAccessor.FindPlayer(player_guid);
if (!player)
return;
player.CastSpell(player, BattlegroundConst.SpellWaitingForResurrect, true);
}
public void RemovePlayerFromResurrectQueue(ObjectGuid player_guid)
{
foreach (var pair in m_ReviveQueue.KeyValueList)
{
if (pair.Value == player_guid)
{
m_ReviveQueue.Remove(pair);
Player player = Global.ObjAccessor.FindPlayer(player_guid);
if (player)
player.RemoveAurasDueToSpell(BattlegroundConst.SpellWaitingForResurrect);
return;
}
}
}
public void RelocateDeadPlayers(ObjectGuid guideGuid)
{
// Those who are waiting to resurrect at this node are taken to the closest own node's graveyard
List<ObjectGuid> ghostList = m_ReviveQueue[guideGuid];
if (!ghostList.Empty())
{
WorldSafeLocsEntry closestGrave = null;
foreach (var guid in ghostList)
{
Player player = Global.ObjAccessor.FindPlayer(guid);
if (!player)
continue;
if (closestGrave == null)
closestGrave = GetClosestGraveYard(player);
if (closestGrave != null)
player.TeleportTo(closestGrave.Loc);
}
ghostList.Clear();
}
}
public bool AddObject(int type, uint entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint respawnTime = 0, GameObjectState goState = GameObjectState.Ready) public bool AddObject(int type, uint entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint respawnTime = 0, GameObjectState goState = GameObjectState.Ready)
{ {
Map map = FindBgMap(); Map map = FindBgMap();
@@ -1602,20 +1492,9 @@ namespace Game.BattleGrounds
{ {
uint entry = (uint)(teamIndex == TeamId.Alliance ? BattlegroundCreatures.A_SpiritGuide : BattlegroundCreatures.H_SpiritGuide); uint entry = (uint)(teamIndex == TeamId.Alliance ? BattlegroundCreatures.A_SpiritGuide : BattlegroundCreatures.H_SpiritGuide);
Creature creature = AddCreature(entry, type, x, y, z, o); if (AddCreature(entry, type, x, y, z, o) != null)
if (creature)
{
creature.SetDeathState(DeathState.Dead);
creature.AddChannelObject(creature.GetGUID());
// aura
//todo Fix display here
// creature.SetVisibleAura(0, SPELL_SPIRIT_HEAL_CHANNEL);
// casting visual effect
creature.SetChannelSpellId(BattlegroundConst.SpellSpiritHealChannel);
creature.SetChannelVisual(new SpellCastVisual(BattlegroundConst.SpellSpiritHealChannelVisual, 0));
//creature.CastSpell(creature, SPELL_SPIRIT_HEAL_CHANNEL, true);
return true; return true;
}
Log.outError(LogFilter.Battleground, $"Battleground.AddSpiritGuide: cannot create spirit guide (type: {type}, entry: {entry}) for BG (map: {GetMapId()}, instance id: {m_InstanceID})!"); Log.outError(LogFilter.Battleground, $"Battleground.AddSpiritGuide: cannot create spirit guide (type: {type}, entry: {entry}) for BG (map: {GetMapId()}, instance id: {m_InstanceID})!");
EndNow(); EndNow();
return false; return false;
@@ -1965,7 +1844,6 @@ namespace Game.BattleGrounds
public uint GetClientInstanceID() { return m_ClientInstanceID; } public uint GetClientInstanceID() { return m_ClientInstanceID; }
public uint GetElapsedTime() { return m_StartTime; } public uint GetElapsedTime() { return m_StartTime; }
public uint GetRemainingTime() { return (uint)m_EndTime; } public uint GetRemainingTime() { return (uint)m_EndTime; }
public uint GetLastResurrectTime() { return m_LastResurrectTime; }
int GetStartDelayTime() { return m_StartDelayTime; } int GetStartDelayTime() { return m_StartDelayTime; }
public ArenaTypes GetArenaType() { return m_ArenaType; } public ArenaTypes GetArenaType() { return m_ArenaType; }
@@ -1980,7 +1858,6 @@ namespace Game.BattleGrounds
public void SetClientInstanceID(uint InstanceID) { m_ClientInstanceID = InstanceID; } public void SetClientInstanceID(uint InstanceID) { m_ClientInstanceID = InstanceID; }
public void SetElapsedTime(uint Time) { m_StartTime = Time; } public void SetElapsedTime(uint Time) { m_StartTime = Time; }
public void SetRemainingTime(uint Time) { m_EndTime = (int)Time; } public void SetRemainingTime(uint Time) { m_EndTime = (int)Time; }
public void SetLastResurrectTime(uint Time) { m_LastResurrectTime = Time; }
public void SetRated(bool state) { m_IsRated = state; } public void SetRated(bool state) { m_IsRated = state; }
public void SetArenaType(ArenaTypes type) { m_ArenaType = type; } public void SetArenaType(ArenaTypes type) { m_ArenaType = type; }
public void SetWinner(PvPTeamId winnerTeamId) { _winnerTeamId = winnerTeamId; } public void SetWinner(PvPTeamId winnerTeamId) { _winnerTeamId = winnerTeamId; }
@@ -2118,7 +1995,6 @@ namespace Game.BattleGrounds
uint m_ResetStatTimer; uint m_ResetStatTimer;
uint m_ValidStartPositionTimer; uint m_ValidStartPositionTimer;
int m_EndTime; // it is set to 120000 when bg is ending and it decreases itself int m_EndTime; // it is set to 120000 when bg is ending and it decreases itself
uint m_LastResurrectTime;
ArenaTypes m_ArenaType; // 2=2v2, 3=3v3, 5=5v5 ArenaTypes 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_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 bool m_SetDeleteThis; // used for safe deletion of the bg after end / all players leave
@@ -2130,7 +2006,6 @@ namespace Game.BattleGrounds
uint m_LastPlayerPositionBroadcast; uint m_LastPlayerPositionBroadcast;
// Player lists // Player lists
List<ObjectGuid> m_ResurrectQueue = new(); // Player GUID
List<ObjectGuid> m_OfflineQueue = new(); // Player GUID List<ObjectGuid> m_OfflineQueue = new(); // 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 // 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
@@ -452,19 +452,6 @@ namespace Game.BattleGrounds
Log.outError(LogFilter.Battleground, $"BattlegroundMgr.SendToBattleground: Instance {instanceId} (bgType {bgTypeId}) not found while trying to teleport player {player.GetName()}"); Log.outError(LogFilter.Battleground, $"BattlegroundMgr.SendToBattleground: Instance {instanceId} (bgType {bgTypeId}) not found while trying to teleport player {player.GetName()}");
} }
public void SendAreaSpiritHealerQuery(Player player, Battleground bg, ObjectGuid guid)
{
uint time = 30000 - bg.GetLastResurrectTime(); // resurrect every 30 seconds
if (time == 0xFFFFFFFF)
time = 0;
AreaSpiritHealerTime areaSpiritHealerTime = new();
areaSpiritHealerTime.HealerGuid = guid;
areaSpiritHealerTime.TimeLeft = time;
player.SendPacket(areaSpiritHealerTime);
}
bool IsArenaType(BattlegroundTypeId bgTypeId) bool IsArenaType(BattlegroundTypeId bgTypeId)
{ {
return bgTypeId == BattlegroundTypeId.AA || bgTypeId == BattlegroundTypeId.BE || bgTypeId == BattlegroundTypeId.NA return bgTypeId == BattlegroundTypeId.AA || bgTypeId == BattlegroundTypeId.BE || bgTypeId == BattlegroundTypeId.NA
@@ -377,8 +377,6 @@ namespace Game.BattleGrounds.Zones
//remove bonus honor aura trigger creature when node is lost //remove bonus honor aura trigger creature when node is lost
DelCreature(node + 7);//null checks are in DelCreature! 0-6 spirit guides DelCreature(node + 7);//null checks are in DelCreature! 0-6 spirit guides
RelocateDeadPlayers(BgCreatures[node]);
DelCreature(node); DelCreature(node);
// buff object isn't despawned // buff object isn't despawned
+16
View File
@@ -427,6 +427,9 @@ namespace Game.Entities
{ {
if (IsAIEnabled() && triggerJustAppeared && m_deathState != DeathState.Dead) if (IsAIEnabled() && triggerJustAppeared && m_deathState != DeathState.Dead)
{ {
if (IsAreaSpiritHealer() && !IsAreaSpiritHealerIndividual())
CastSpell(null, BattlegroundConst.SpellSpiritHealChannelAoE, false);
if (m_respawnCompatibilityMode && VehicleKit != null) if (m_respawnCompatibilityMode && VehicleKit != null)
VehicleKit.Reset(); VehicleKit.Reset();
@@ -1129,6 +1132,19 @@ namespace Game.Entities
SetHomePosition(GetPosition()); SetHomePosition(GetPosition());
} }
public void SummonGraveyardTeleporter()
{
if (!IsAreaSpiritHealer())
return;
uint npcEntry = GetFaction() == (uint)FactionTemplates.AllianceGeneric ? 26350 : 26351u;
// maybe NPC is summoned with these spells:
// ID - 24237 Summon Alliance Graveyard Teleporter (SERVERSIDE)
// ID - 46894 Summon Horde Graveyard Teleporter (SERVERSIDE)
SummonCreature(npcEntry, GetPosition(), TempSummonType.TimedDespawn, TimeSpan.FromSeconds(1), 0, 0);
}
public bool HasFlag(CreatureStaticFlags flag) { return _staticFlags.HasFlag(flag); } public bool HasFlag(CreatureStaticFlags flag) { return _staticFlags.HasFlag(flag); }
public bool HasFlag(CreatureStaticFlags2 flag) { return _staticFlags.HasFlag(flag); } public bool HasFlag(CreatureStaticFlags2 flag) { return _staticFlags.HasFlag(flag); }
public bool HasFlag(CreatureStaticFlags3 flag) { return _staticFlags.HasFlag(flag); } public bool HasFlag(CreatureStaticFlags3 flag) { return _staticFlags.HasFlag(flag); }
@@ -55,6 +55,7 @@ namespace Game.Entities
long m_lastHonorUpdateTime; long m_lastHonorUpdateTime;
uint m_contestedPvPTimer; uint m_contestedPvPTimer;
bool _usePvpItemLevels; bool _usePvpItemLevels;
ObjectGuid _areaSpiritHealerGUID;
//Groups/Raids //Groups/Raids
GroupReference m_group = new(); GroupReference m_group = new();
+40
View File
@@ -3938,6 +3938,8 @@ namespace Game.Entities
public void ResurrectPlayer(float restore_percent, bool applySickness = false) public void ResurrectPlayer(float restore_percent, bool applySickness = false)
{ {
SetAreaSpiritHealer(null);
DeathReleaseLoc packet = new(); DeathReleaseLoc packet = new();
packet.MapID = -1; packet.MapID = -1;
SendPacket(packet); SendPacket(packet);
@@ -4021,6 +4023,44 @@ namespace Game.Entities
} }
} }
ObjectGuid GetSpiritHealerGUID() { return _areaSpiritHealerGUID; }
public bool CanAcceptAreaSpiritHealFrom(Unit spiritHealer) { return spiritHealer.GetGUID() == _areaSpiritHealerGUID; }
public void SetAreaSpiritHealer(Creature creature)
{
if (!creature)
{
_areaSpiritHealerGUID = ObjectGuid.Empty;
RemoveAurasDueToSpell(BattlegroundConst.SpellWaitingForResurrect);
return;
}
if (!creature.IsAreaSpiritHealer())
return;
_areaSpiritHealerGUID = creature.GetGUID();
CastSpell(null, BattlegroundConst.SpellWaitingForResurrect);
}
public void SendAreaSpiritHealerTime(Unit spiritHealer)
{
int timeLeft = 0;
Spell spell = spiritHealer.GetCurrentSpell(CurrentSpellTypes.Channeled);
if (spell != null)
timeLeft = spell.GetTimer();
SendAreaSpiritHealerTime(spiritHealer.GetGUID(), timeLeft);
}
public void SendAreaSpiritHealerTime(ObjectGuid spiritHealerGUID, int timeLeft)
{
AreaSpiritHealerTime areaSpiritHealerTime = new();
areaSpiritHealerTime.HealerGuid = spiritHealerGUID;
areaSpiritHealerTime.TimeLeft = (uint)timeLeft;
SendPacket(areaSpiritHealerTime);
}
public void KillPlayer() public void KillPlayer()
{ {
if (IsFlying() && GetTransport() == null) if (IsFlying() && GetTransport() == null)
+4
View File
@@ -466,6 +466,9 @@ namespace Game.Entities
if (IsInWorld) if (IsInWorld)
{ {
if (IsAreaSpiritHealer())
ToCreature()?.SummonGraveyardTeleporter();
m_duringRemoveFromWorld = true; m_duringRemoveFromWorld = true;
UnitAI ai = GetAI(); UnitAI ai = GetAI();
if (ai != null) if (ai != null)
@@ -847,6 +850,7 @@ namespace Game.Entities
NPCFlags.AreaSpiritHealer | NPCFlags.TabardDesigner | NPCFlags.Auctioneer); NPCFlags.AreaSpiritHealer | NPCFlags.TabardDesigner | NPCFlags.Auctioneer);
} }
public bool IsSpiritService() { return HasNpcFlag(NPCFlags.SpiritHealer | NPCFlags.AreaSpiritHealer); } public bool IsSpiritService() { return HasNpcFlag(NPCFlags.SpiritHealer | NPCFlags.AreaSpiritHealer); }
public bool IsAreaSpiritHealerIndividual() { return HasNpcFlag2(NPCFlags2.AreaSpiritHealerIndividual); }
public bool IsCritter() { return GetCreatureType() == CreatureType.Critter; } public bool IsCritter() { return GetCreatureType() == CreatureType.Critter; }
public bool IsInFlight() { return HasUnitState(UnitState.InFlight); } public bool IsInFlight() { return HasUnitState(UnitState.InFlight); }
+33 -18
View File
@@ -10,6 +10,7 @@ using Game.Entities;
using Game.Groups; using Game.Groups;
using Game.Networking; using Game.Networking;
using Game.Networking.Packets; using Game.Networking.Packets;
using Game.Spells;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@@ -618,39 +619,53 @@ namespace Game
[WorldPacketHandler(ClientOpcodes.AreaSpiritHealerQuery)] [WorldPacketHandler(ClientOpcodes.AreaSpiritHealerQuery)]
void HandleAreaSpiritHealerQuery(AreaSpiritHealerQuery areaSpiritHealerQuery) void HandleAreaSpiritHealerQuery(AreaSpiritHealerQuery areaSpiritHealerQuery)
{ {
Creature unit = ObjectAccessor.GetCreature(GetPlayer(), areaSpiritHealerQuery.HealerGuid); Player player = GetPlayer();
if (!unit) Creature spiritHealer = ObjectAccessor.GetCreature(player, areaSpiritHealerQuery.HealerGuid);
if (spiritHealer == null)
return; return;
if (!unit.IsSpiritService()) // it's not spirit service if (!spiritHealer.IsAreaSpiritHealer())
return; return;
Battleground bg = GetPlayer().GetBattleground(); if (_player.GetExactDist(spiritHealer) > PlayerConst.MaxAreaSpiritHealerRange)
if (bg != null) return;
Global.BattlegroundMgr.SendAreaSpiritHealerQuery(GetPlayer(), bg, areaSpiritHealerQuery.HealerGuid);
BattleField bf = Global.BattleFieldMgr.GetBattlefieldToZoneId(GetPlayer().GetMap(), GetPlayer().GetZoneId()); if (spiritHealer.IsAreaSpiritHealerIndividual())
if (bf != null) {
bf.SendAreaSpiritHealerQuery(GetPlayer(), areaSpiritHealerQuery.HealerGuid); Aura aura = player.GetAura(BattlegroundConst.SpellSpiritHealPlayerAura);
if (aura != null)
{
player.SendAreaSpiritHealerTime(spiritHealer.GetGUID(), aura.GetDuration());
}
else
{
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(BattlegroundConst.SpellSpiritHealPlayerAura, Difficulty.None);
if (spellInfo != null)
{
spiritHealer.CastSpell(player, BattlegroundConst.SpellSpiritHealPlayerAura);
player.SendAreaSpiritHealerTime(spiritHealer.GetGUID(), spellInfo.GetDuration());
spiritHealer.CastSpell(null, BattlegroundConst.SpellSpiritHealChannelSelf);
}
}
}
else
_player.SendAreaSpiritHealerTime(spiritHealer);
} }
[WorldPacketHandler(ClientOpcodes.AreaSpiritHealerQueue)] [WorldPacketHandler(ClientOpcodes.AreaSpiritHealerQueue)]
void HandleAreaSpiritHealerQueue(AreaSpiritHealerQueue areaSpiritHealerQueue) void HandleAreaSpiritHealerQueue(AreaSpiritHealerQueue areaSpiritHealerQueue)
{ {
Creature unit = ObjectAccessor.GetCreature(GetPlayer(), areaSpiritHealerQueue.HealerGuid); Creature spiritHealer = ObjectAccessor.GetCreature(GetPlayer(), areaSpiritHealerQueue.HealerGuid);
if (!unit) if (spiritHealer == null)
return; return;
if (!unit.IsSpiritService()) // it's not spirit service if (!spiritHealer.IsAreaSpiritHealer())
return; return;
Battleground bg = GetPlayer().GetBattleground(); if (_player.GetExactDist(spiritHealer) > PlayerConst.MaxAreaSpiritHealerRange)
if (bg) return;
bg.AddPlayerToResurrectQueue(areaSpiritHealerQueue.HealerGuid, GetPlayer().GetGUID());
BattleField bf = Global.BattleFieldMgr.GetBattlefieldToZoneId(GetPlayer().GetMap(), GetPlayer().GetZoneId()); _player.SetAreaSpiritHealer(spiritHealer);
if (bf != null)
bf.AddPlayerToResurrectQueue(areaSpiritHealerQueue.HealerGuid, GetPlayer().GetGUID());
} }
[WorldPacketHandler(ClientOpcodes.HearthAndResurrect)] [WorldPacketHandler(ClientOpcodes.HearthAndResurrect)]
+2 -8
View File
@@ -138,16 +138,10 @@ namespace Game
unit.PauseMovement(pause); unit.PauseMovement(pause);
unit.SetHomePosition(unit.GetPosition()); unit.SetHomePosition(unit.GetPosition());
// If spiritguide, no need for gossip menu, just put player into resurrect queue
if (unit.IsAreaSpiritHealer()) if (unit.IsAreaSpiritHealer())
{ {
Battleground bg = GetPlayer().GetBattleground(); _player.SetAreaSpiritHealer(unit);
if (bg) _player.SendAreaSpiritHealerTime(unit);
{
bg.AddPlayerToResurrectQueue(unit.GetGUID(), GetPlayer().GetGUID());
Global.BattlegroundMgr.SendAreaSpiritHealerQuery(GetPlayer(), bg, unit.GetGUID());
return;
}
} }
_player.PlayerTalkClass.ClearMenus(); _player.PlayerTalkClass.ClearMenus();
-12
View File
@@ -4317,18 +4317,6 @@ namespace Game.Spells
case SpellFamilyNames.Generic: case SpellFamilyNames.Generic:
switch (GetId()) switch (GetId())
{ {
case 2584: // Waiting to Resurrect
// Waiting to resurrect spell cancel, we must remove player from resurrect queue
if (target.IsTypeId(TypeId.Player))
{
Battleground bg = target.ToPlayer().GetBattleground();
if (bg)
bg.RemovePlayerFromResurrectQueue(target.GetGUID());
BattleField bf = Global.BattleFieldMgr.GetBattlefieldToZoneId(target.GetMap(), target.GetZoneId());
if (bf != null)
bf.RemovePlayerFromResurrectQueue(target.GetGUID());
}
break;
case 36730: // Flame Strike case 36730: // Flame Strike
target.CastSpell(target, 36731, new CastSpellExtraArgs(this)); target.CastSpell(target, 36731, new CastSpellExtraArgs(this));
break; break;
+2
View File
@@ -7960,6 +7960,8 @@ namespace Game.Spells
public SpellInfo GetTriggeredByAuraSpell() { return m_triggeredByAuraSpell; } public SpellInfo GetTriggeredByAuraSpell() { return m_triggeredByAuraSpell; }
public int GetTimer() { return m_timer; }
public static implicit operator bool(Spell spell) public static implicit operator bool(Spell spell)
{ {
return spell != null; return spell != null;
+20 -4
View File
@@ -4221,14 +4221,30 @@ namespace Game.Spells
Log.outDebug(LogFilter.Spells, "WORLD: SkillEFFECT"); Log.outDebug(LogFilter.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 EffectSpiritHeal() void EffectSpiritHeal()
{ {
Unit caster = GetCaster().ToUnit();
if (effectHandleMode == SpellEffectHandleMode.Hit)
caster.CastSpell(null, BattlegroundConst.SpellResurrectionVisual, true);
if (effectHandleMode != SpellEffectHandleMode.HitTarget) if (effectHandleMode != SpellEffectHandleMode.HitTarget)
return; return;
Player playerTarget = unitTarget.ToPlayer();
if (playerTarget != null)
{
if (!playerTarget.IsInWorld)
return;
// skip if player does not want to live
if (!playerTarget.CanAcceptAreaSpiritHealFrom(caster))
return;
playerTarget.ResurrectPlayer(1.0f);
playerTarget.CastSpell(playerTarget, BattlegroundConst.SpellPetSummoned, true);
playerTarget.CastSpell(playerTarget, BattlegroundConst.SpellSpiritHealMana, true);
playerTarget.SpawnCorpseBones(false);
}
} }
// remove insignia spell effect // remove insignia spell effect
-2
View File
@@ -902,8 +902,6 @@ namespace Game.Spells
case 34976: // Netherstorm Flag case 34976: // Netherstorm Flag
return map_id == 566 && player != null && player.InBattleground() ? SpellCastResult.SpellCastOk : SpellCastResult.RequiresArea; return map_id == 566 && player != null && player.InBattleground() ? SpellCastResult.SpellCastOk : SpellCastResult.RequiresArea;
case 2584: // Waiting to Resurrect case 2584: // Waiting to Resurrect
case 22011: // Spirit Heal Channel
case 22012: // Spirit Heal
case 42792: // Recently Dropped Flag case 42792: // Recently Dropped Flag
case 43681: // Inactive case 43681: // Inactive
case 44535: // Spirit Heal (mana) case 44535: // Spirit Heal (mana)
+118 -12
View File
@@ -1937,7 +1937,7 @@ namespace Scripts.Spells.Generic
OnEffectRemove.Add(new EffectApplyHandler(OnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real)); OnEffectRemove.Add(new EffectApplyHandler(OnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real));
} }
} }
// 35357 - Spawn Feign Death // 35357 - Spawn Feign Death
[Script] // 51329 - Feign Death [Script] // 51329 - Feign Death
class spell_gen_feign_death_no_dyn_flag : AuraScript class spell_gen_feign_death_no_dyn_flag : AuraScript
@@ -5010,17 +5010,17 @@ namespace Scripts.Spells.Generic
} }
} }
// 2825 - Bloodlust // 2825 - Bloodlust
// 32182 - Heroism // 32182 - Heroism
// 80353 - Time Warp // 80353 - Time Warp
// 264667 - Primal Rage // 264667 - Primal Rage
// 390386 - Fury of the Aspects // 390386 - Fury of the Aspects
// 146555 - Drums of Rage // 146555 - Drums of Rage
// 178207 - Drums of Fury // 178207 - Drums of Fury
// 230935 - Drums of the Mountain // 230935 - Drums of the Mountain
// 256740 - Drums of the Maelstrom // 256740 - Drums of the Maelstrom
// 309658 - Drums of Deathly Ferocity // 309658 - Drums of Deathly Ferocity
// 381301 - Feral Hide Drums // 381301 - Feral Hide Drums
[Script("spell_sha_bloodlust", SpellIds.ShamanSated)] [Script("spell_sha_bloodlust", SpellIds.ShamanSated)]
[Script("spell_sha_heroism", SpellIds.ShamanExhaustion)] [Script("spell_sha_heroism", SpellIds.ShamanExhaustion)]
[Script("spell_mage_time_warp", SpellIds.MageTemporalDisplacement)] [Script("spell_mage_time_warp", SpellIds.MageTemporalDisplacement)]
@@ -5071,6 +5071,112 @@ namespace Scripts.Spells.Generic
} }
} }
// AoE resurrections by spirit guides
[Script] // 22012 - Spirit Heal
class spell_gen_spirit_heal_aoe : SpellScript
{
void FilterTargets(List<WorldObject> targets)
{
Unit caster = GetCaster();
targets.RemoveAll(target =>
{
Player playerTarget = target.ToPlayer();
if (playerTarget != null)
return !playerTarget.CanAcceptAreaSpiritHealFrom(caster);
return true;
});
}
public override void Register()
{
OnObjectAreaTargetSelect.Add(new ObjectAreaTargetSelectHandler(FilterTargets, 0, Targets.UnitDestAreaAlly));
}
}
// Personal resurrections in battlegrounds
[Script] // 156758 - Spirit Heal
class spell_gen_spirit_heal_personal : AuraScript
{
uint SPELL_SPIRIT_HEAL_EFFECT = 156763;
void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode)
{
if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire)
return;
Player targetPlayer = GetTarget().ToPlayer();
if (targetPlayer == null)
return;
Unit caster = GetCaster();
if (caster == null)
return;
if (targetPlayer.CanAcceptAreaSpiritHealFrom(caster))
caster.CastSpell(targetPlayer, SPELL_SPIRIT_HEAL_EFFECT);
}
public override void Register()
{
AfterEffectRemove.Add(new EffectApplyHandler(OnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real));
}
}
class RecastSpiritHealChannelEvent : BasicEvent
{
Unit _caster;
public RecastSpiritHealChannelEvent(Unit caster)
{
_caster = caster;
}
public override bool Execute(ulong e_time, uint p_time)
{
if (_caster.GetChannelSpellId() == 0)
_caster.CastSpell(null, BattlegroundConst.SpellSpiritHealChannelAoE, false);
return true;
}
}
[Script] // 22011 - Spirit Heal Channel
class spell_gen_spirit_heal_channel : AuraScript
{
void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode)
{
if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire)
return;
Unit target = GetTarget();
target.m_Events.AddEventAtOffset(new RecastSpiritHealChannelEvent(target), TimeSpan.FromSeconds(1));
}
public override void Register()
{
AfterEffectRemove.Add(new EffectApplyHandler(OnRemove, 0, AuraType.PeriodicTriggerSpell, AuraEffectHandleModes.Real));
}
}
[Script] // 2584 - Waiting to Resurrect
class spell_gen_waiting_to_resurrect : AuraScript
{
void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode)
{
Player targetPlayer = GetTarget().ToPlayer();
if (targetPlayer == null)
return;
targetPlayer.SetAreaSpiritHealer(null);
}
public override void Register()
{
AfterEffectRemove.Add(new EffectApplyHandler(OnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real));
}
}
// 40307 - Stasis Field // 40307 - Stasis Field
class StasisFieldSearcher : ICheck<Unit> class StasisFieldSearcher : ICheck<Unit>
{ {