From f6aaf9df6915b76d4f02c2fabe4ea7e4233df6fb Mon Sep 17 00:00:00 2001 From: hondacrx Date: Sat, 2 Mar 2024 21:57:41 -0500 Subject: [PATCH] Core/Battlegrounds: Implement Arathi Basin from Battle for Azeroth Port From (https://github.com/TrinityCore/TrinityCore/commit/cc08aa8e249c5cd33f6b09a766cf6131c42566b9) --- Source/Game/BattleGrounds/BattleGround.cs | 2 +- .../Game/BattleGrounds/BattleGroundManager.cs | 1 + .../Game/BattleGrounds/Zones/ArathiBasin.cs | 1058 +++++++---------- 3 files changed, 401 insertions(+), 660 deletions(-) diff --git a/Source/Game/BattleGrounds/BattleGround.cs b/Source/Game/BattleGrounds/BattleGround.cs index 5fa34e7ac..5e055ac34 100644 --- a/Source/Game/BattleGrounds/BattleGround.cs +++ b/Source/Game/BattleGrounds/BattleGround.cs @@ -1851,7 +1851,7 @@ namespace Game.BattleGrounds uint GetPlayersSize() { return (uint)m_Players.Count; } uint GetPlayerScoresSize() { return (uint)PlayerScores.Count; } - BattlegroundMap FindBgMap() { return m_Map; } + public BattlegroundMap FindBgMap() { return m_Map; } Group GetBgRaid(Team team) { return m_BgRaids[GetTeamIndexByTeamId(team)]; } diff --git a/Source/Game/BattleGrounds/BattleGroundManager.cs b/Source/Game/BattleGrounds/BattleGroundManager.cs index e62dd2cde..84ba05d5b 100644 --- a/Source/Game/BattleGrounds/BattleGroundManager.cs +++ b/Source/Game/BattleGrounds/BattleGroundManager.cs @@ -5,6 +5,7 @@ using Framework.Constants; using Framework.Database; using Game.BattleGrounds.Zones; using Game.BattleGrounds.Zones.AlteracValley; +using Game.BattleGrounds.Zones.ArathisBasin; using Game.BattleGrounds.Zones.EyeofStorm; using Game.DataStorage; using Game.Entities; diff --git a/Source/Game/BattleGrounds/Zones/ArathiBasin.cs b/Source/Game/BattleGrounds/Zones/ArathiBasin.cs index 035d72bd3..6f5f6fac2 100644 --- a/Source/Game/BattleGrounds/Zones/ArathiBasin.cs +++ b/Source/Game/BattleGrounds/Zones/ArathiBasin.cs @@ -3,33 +3,33 @@ using Framework.Constants; using Game.Entities; -using Game.Networking.Packets; +using Game.Maps; using System; using System.Collections.Generic; -namespace Game.BattleGrounds.Zones +namespace Game.BattleGrounds.Zones.ArathisBasin { class BgArathiBasin : Battleground { + TimeTracker _pointsTimer; + uint[] m_HonorScoreTics = new uint[SharedConst.PvpTeamsCount]; + uint[] m_ReputationScoreTics = new uint[SharedConst.PvpTeamsCount]; + bool m_IsInformedNearVictory; + uint m_HonorTics; + uint m_ReputationTics; + + List _gameobjectsToRemoveOnMatchStart = new(); + List _creaturesToRemoveOnMatchStart = new(); + List _doors = new(); + List _capturePoints = new(); + public BgArathiBasin(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) { m_IsInformedNearVictory = false; - BgObjects = new ObjectGuid[ABObjectTypes.Max]; - BgCreatures = new ObjectGuid[ABBattlegroundNodes.AllCount + 5];//+5 for aura triggers - - for (byte i = 0; i < ABBattlegroundNodes.DynamicNodesCount; ++i) - { - m_Nodes[i] = 0; - m_prevNodes[i] = 0; - m_NodeTimers[i] = 0; - m_BannerTimers[i].timer = 0; - m_BannerTimers[i].type = 0; - m_BannerTimers[i].teamIndex = 0; - } + _pointsTimer = new TimeTracker(MiscConst.TickInterval); for (byte i = 0; i < SharedConst.PvpTeamsCount; ++i) { - m_lastTick[i] = 0; m_HonorScoreTics[i] = 0; m_ReputationScoreTics[i] = 0; } @@ -42,75 +42,23 @@ namespace Game.BattleGrounds.Zones { if (GetStatus() == BattlegroundStatus.InProgress) { - int[] team_points = { 0, 0 }; - - for (byte node = 0; node < ABBattlegroundNodes.DynamicNodesCount; ++node) + // Accumulate points + _pointsTimer.Update(diff); + if (_pointsTimer.Passed()) { - // 3 sec delay to spawn new banner instead previous despawned one - if (m_BannerTimers[node].timer != 0) - { - if (m_BannerTimers[node].timer > diff) - m_BannerTimers[node].timer -= diff; - else - { - m_BannerTimers[node].timer = 0; - _CreateBanner(node, (ABNodeStatus)m_BannerTimers[node].type, m_BannerTimers[node].teamIndex, false); - } - } + _pointsTimer.Reset(MiscConst.TickInterval); - // 1-minute to occupy a node from contested state - if (m_NodeTimers[node] != 0) - { - if (m_NodeTimers[node] > diff) - m_NodeTimers[node] -= diff; - else - { - m_NodeTimers[node] = 0; - // Change from contested to occupied ! - int teamIndex = (int)m_Nodes[node] - 1; - m_prevNodes[node] = m_Nodes[node]; - m_Nodes[node] += 2; - // burn current contested banner - _DelBanner(node, ABNodeStatus.Contested, (byte)teamIndex); - // create new occupied banner - _CreateBanner(node, ABNodeStatus.Occupied, teamIndex, true); - _SendNodeUpdate(node); - _NodeOccupied(node, (teamIndex == BatttleGroundTeamId.Alliance) ? Team.Alliance : Team.Horde); - // Message to chatlog - - if (teamIndex == 0) - { - SendBroadcastText(ABBattlegroundBroadcastTexts.ABNodes[node].TextAllianceTaken, ChatMsg.BgSystemAlliance); - PlaySoundToAll(SoundCapturedAlliance); - } - else - { - SendBroadcastText(ABBattlegroundBroadcastTexts.ABNodes[node].TextHordeTaken, ChatMsg.BgSystemHorde); - PlaySoundToAll(SoundCapturedHorde); - } - } - } + _CalculateTeamNodes(out var ally, out var horde); + int[] points = [ally, horde]; for (int team = 0; team < SharedConst.PvpTeamsCount; ++team) - if (m_Nodes[node] == team + ABNodeStatus.Occupied) - ++team_points[team]; - } - - // Accumulate points - for (int team = 0; team < SharedConst.PvpTeamsCount; ++team) - { - int points = team_points[team]; - if (points == 0) - continue; - - m_lastTick[team] += diff; - - if (m_lastTick[team] > TickIntervals[points]) { - m_lastTick[team] -= TickIntervals[points]; - m_TeamScores[team] += TickPoints[points]; - m_HonorScoreTics[team] += TickPoints[points]; - m_ReputationScoreTics[team] += TickPoints[points]; + if (points[team] == 0) + continue; + + m_TeamScores[team] += MiscConst.TickPoints[points[team]]; + m_HonorScoreTics[team] += MiscConst.TickPoints[points[team]]; + m_ReputationScoreTics[team] += MiscConst.TickPoints[points[team]]; if (m_ReputationScoreTics[team] >= m_ReputationTics) { @@ -128,356 +76,92 @@ namespace Game.BattleGrounds.Zones m_HonorScoreTics[team] -= m_HonorTics; } - if (!m_IsInformedNearVictory && m_TeamScores[team] > WarningNearVictoryScore) + if (!m_IsInformedNearVictory && m_TeamScores[team] > MiscConst.WarningNearVictoryScore) { if (team == BatttleGroundTeamId.Alliance) { - SendBroadcastText(ABBattlegroundBroadcastTexts.AllianceNearVictory, ChatMsg.BgSystemNeutral); - PlaySoundToAll(SoundNearVictoryAlliance); + SendBroadcastText((uint)ABBattlegroundBroadcastTexts.AllianceNearVictory, ChatMsg.BgSystemNeutral); + PlaySoundToAll((uint)SoundIds.NearVictoryAlliance); } else { - SendBroadcastText(ABBattlegroundBroadcastTexts.HordeNearVictory, ChatMsg.BgSystemNeutral); - PlaySoundToAll(SoundNearVictoryHorde); + SendBroadcastText((uint)ABBattlegroundBroadcastTexts.HordeNearVictory, ChatMsg.BgSystemNeutral); + PlaySoundToAll((uint)SoundIds.NearVictoryHorde); } m_IsInformedNearVictory = true; } - if (m_TeamScores[team] > MaxTeamScore) - m_TeamScores[team] = MaxTeamScore; + if (m_TeamScores[team] > MiscConst.MaxTeamScore) + m_TeamScores[team] = MiscConst.MaxTeamScore; if (team == BatttleGroundTeamId.Alliance) - UpdateWorldState(ABWorldStates.ResourcesAlly, (int)m_TeamScores[team]); + UpdateWorldState(WorldStateIds.ResourcesAlly, (int)m_TeamScores[team]); else - UpdateWorldState(ABWorldStates.ResourcesHorde, (int)m_TeamScores[team]); + UpdateWorldState(WorldStateIds.ResourcesHorde, (int)m_TeamScores[team]); // update achievement flags // we increased m_TeamScores[team] so we just need to check if it is 500 more than other teams resources int otherTeam = (team + 1) % SharedConst.PvpTeamsCount; if (m_TeamScores[team] > m_TeamScores[otherTeam] + 500) { if (team == BatttleGroundTeamId.Alliance) - UpdateWorldState(ABWorldStates.Had500DisadvantageHorde, 1); + UpdateWorldState(WorldStateIds.Had500DisadvantageHorde, 1); else - UpdateWorldState(ABWorldStates.Had500DisadvantageAlliance, 1); + UpdateWorldState(WorldStateIds.Had500DisadvantageAlliance, 1); } } + + UpdateWorldState(WorldStateIds.OccupiedBasesAlly, ally); + UpdateWorldState(WorldStateIds.OccupiedBasesHorde, horde); } // Test win condition - if (m_TeamScores[BatttleGroundTeamId.Alliance] >= MaxTeamScore) + if (m_TeamScores[BatttleGroundTeamId.Alliance] >= MiscConst.MaxTeamScore) EndBattleground(Team.Alliance); - else if (m_TeamScores[BatttleGroundTeamId.Horde] >= MaxTeamScore) + else if (m_TeamScores[BatttleGroundTeamId.Horde] >= MiscConst.MaxTeamScore) EndBattleground(Team.Horde); } } - public override void StartingEventCloseDoors() - { - // despawn banners, auras and buffs - for (int obj = ABObjectTypes.BannerNeutral; obj < ABBattlegroundNodes.DynamicNodesCount * 8; ++obj) - SpawnBGObject(obj, BattlegroundConst.RespawnOneDay); - for (int i = 0; i < ABBattlegroundNodes.DynamicNodesCount * 3; ++i) - SpawnBGObject(ABObjectTypes.SpeedbuffStables + i, BattlegroundConst.RespawnOneDay); - - // Starting doors - DoorClose(ABObjectTypes.GateA); - DoorClose(ABObjectTypes.GateH); - SpawnBGObject(ABObjectTypes.GateA, BattlegroundConst.RespawnImmediately); - SpawnBGObject(ABObjectTypes.GateH, BattlegroundConst.RespawnImmediately); - - // Starting base spirit guides - _NodeOccupied(ABBattlegroundNodes.SpiritAliance, Team.Alliance); - _NodeOccupied(ABBattlegroundNodes.SpiritHorde, Team.Horde); - } - public override void StartingEventOpenDoors() { - // spawn neutral banners - for (int banner = ABObjectTypes.BannerNeutral, i = 0; i < 5; banner += 8, ++i) - SpawnBGObject(banner, BattlegroundConst.RespawnImmediately); - for (int i = 0; i < ABBattlegroundNodes.DynamicNodesCount; ++i) - { - //randomly select buff to spawn - int buff = RandomHelper.IRand(0, 2); - SpawnBGObject(ABObjectTypes.SpeedbuffStables + buff + i * 3, BattlegroundConst.RespawnImmediately); - } - DoorOpen(ABObjectTypes.GateA); - DoorOpen(ABObjectTypes.GateH); - // Achievement: Let's Get This Done - TriggerGameEvent(EventStartBattle); + TriggerGameEvent((uint)ABEventIds.StartBattle); } - void _CreateBanner(byte node, ABNodeStatus type, int teamIndex, bool delay) + void _CalculateTeamNodes(out int alliance, out int horde) { - // Just put it into the queue - if (delay) + alliance = 0; + horde = 0; + + BattlegroundMap map = FindBgMap(); + if (map != null) { - m_BannerTimers[node].timer = 2000; - m_BannerTimers[node].type = (byte)type; - m_BannerTimers[node].teamIndex = (byte)teamIndex; - return; - } - - int obj = node * 8 + (byte)type + teamIndex; - - SpawnBGObject(obj, BattlegroundConst.RespawnImmediately); - - // handle aura with banner - if (type == 0) - return; - obj = node * 8 + ((type == ABNodeStatus.Occupied) ? (5 + teamIndex) : 7); - SpawnBGObject(obj, BattlegroundConst.RespawnImmediately); - } - - void _DelBanner(byte node, ABNodeStatus type, byte teamIndex) - { - int obj = node * 8 + (byte)type + teamIndex; - SpawnBGObject(obj, BattlegroundConst.RespawnOneDay); - - // handle aura with banner - if (type == 0) - return; - obj = node * 8 + ((type == ABNodeStatus.Occupied) ? (5 + teamIndex) : 7); - SpawnBGObject(obj, BattlegroundConst.RespawnOneDay); - } - - void _SendNodeUpdate(byte node) - { - // Send node owner state update to refresh map icons on client - int[] idPlusArray = { 0, 2, 3, 0, 1 }; - int[] statePlusArray = { 0, 2, 0, 2, 0 }; - - if (m_prevNodes[node] != 0) - UpdateWorldState(NodeStates[node] + idPlusArray[(int)m_prevNodes[node]], 0); - else - UpdateWorldState(NodeIcons[node], 0); - - UpdateWorldState(NodeStates[node] + idPlusArray[(byte)m_Nodes[node]], 1); - - switch (node) - { - case ABBattlegroundNodes.NodeStables: - UpdateWorldState(ABWorldStates.StablesIconNew, (int)m_Nodes[node] + statePlusArray[(int)m_Nodes[node]]); - UpdateWorldState(ABWorldStates.StablesHordeControlState, m_Nodes[node] == ABNodeStatus.HordeOccupied ? 2 : (m_Nodes[node] == ABNodeStatus.HordeContested ? 1 : 0)); - UpdateWorldState(ABWorldStates.StablesAllianceControlState, m_Nodes[node] == ABNodeStatus.AllyOccupied ? 2 : (m_Nodes[node] == ABNodeStatus.AllyContested ? 1 : 0)); - break; - case ABBattlegroundNodes.NodeBlacksmith: - UpdateWorldState(ABWorldStates.BlacksmithIconNew, (int)m_Nodes[node] + statePlusArray[(int)m_Nodes[node]]); - UpdateWorldState(ABWorldStates.BlacksmithHordeControlState, m_Nodes[node] == ABNodeStatus.HordeOccupied ? 2 : (m_Nodes[node] == ABNodeStatus.HordeContested ? 1 : 0)); - UpdateWorldState(ABWorldStates.BlacksmithAllianceControlState, m_Nodes[node] == ABNodeStatus.AllyOccupied ? 2 : (m_Nodes[node] == ABNodeStatus.AllyContested ? 1 : 0)); - break; - case ABBattlegroundNodes.NodeFarm: - UpdateWorldState(ABWorldStates.FarmIconNew, (int)m_Nodes[node] + statePlusArray[(int)m_Nodes[node]]); - UpdateWorldState(ABWorldStates.FarmHordeControlState, m_Nodes[node] == ABNodeStatus.HordeOccupied ? 2 : (m_Nodes[node] == ABNodeStatus.HordeContested ? 1 : 0)); - UpdateWorldState(ABWorldStates.FarmAllianceControlState, m_Nodes[node] == ABNodeStatus.AllyOccupied ? 2 : (m_Nodes[node] == ABNodeStatus.AllyContested ? 1 : 0)); - break; - case ABBattlegroundNodes.NodeLumberMill: - UpdateWorldState(ABWorldStates.LumberMillIconNew, (int)m_Nodes[node] + statePlusArray[(int)m_Nodes[node]]); - UpdateWorldState(ABWorldStates.LumberMillHordeControlState, m_Nodes[node] == ABNodeStatus.HordeOccupied ? 2 : (m_Nodes[node] == ABNodeStatus.HordeContested ? 1 : 0)); - UpdateWorldState(ABWorldStates.LumberMillAllianceControlState, m_Nodes[node] == ABNodeStatus.AllyOccupied ? 2 : (m_Nodes[node] == ABNodeStatus.AllyContested ? 1 : 0)); - break; - case ABBattlegroundNodes.NodeGoldMine: - UpdateWorldState(ABWorldStates.GoldMineIconNew, (int)m_Nodes[node] + statePlusArray[(int)m_Nodes[node]]); - UpdateWorldState(ABWorldStates.GoldMineHordeControlState, m_Nodes[node] == ABNodeStatus.HordeOccupied ? 2 : (m_Nodes[node] == ABNodeStatus.HordeContested ? 1 : 0)); - UpdateWorldState(ABWorldStates.GoldMineAllianceControlState, m_Nodes[node] == ABNodeStatus.AllyOccupied ? 2 : (m_Nodes[node] == ABNodeStatus.AllyContested ? 1 : 0)); - break; - default: - break; - } - - // How many bases each team owns - byte ally = 0, horde = 0; - for (byte i = 0; i < ABBattlegroundNodes.DynamicNodesCount; ++i) - if (m_Nodes[i] == ABNodeStatus.AllyOccupied) - ++ally; - else if (m_Nodes[i] == ABNodeStatus.HordeOccupied) - ++horde; - - UpdateWorldState(ABWorldStates.OccupiedBasesAlly, ally); - UpdateWorldState(ABWorldStates.OccupiedBasesHorde, horde); - } - - void _NodeOccupied(byte node, Team team) - { - if (!AddSpiritGuide(node, SpiritGuidePos[node], GetTeamIndexByTeamId(team))) - Log.outError(LogFilter.Battleground, "Failed to spawn spirit guide! point: {0}, team: {1}, ", node, team); - - if (node >= ABBattlegroundNodes.DynamicNodesCount)//only dynamic nodes, no start points - return; - - byte capturedNodes = 0; - for (byte i = 0; i < ABBattlegroundNodes.DynamicNodesCount; ++i) - if (m_Nodes[i] == ABNodeStatus.Occupied + GetTeamIndexByTeamId(team) && m_NodeTimers[i] == 0) - ++capturedNodes; - - if (capturedNodes >= 5) - CastSpellOnTeam(BattlegroundConst.AbQuestReward5Bases, team); - if (capturedNodes >= 4) - CastSpellOnTeam(BattlegroundConst.AbQuestReward4Bases, team); - - Creature trigger = !BgCreatures[node + 7].IsEmpty() ? GetBGCreature(node + 7u) : null; // 0-6 spirit guides - if (trigger == null) - trigger = AddCreature(SharedConst.WorldTrigger, node + 7u, NodePositions[node], GetTeamIndexByTeamId(team)); - - //add bonus honor aura trigger creature when node is accupied - //cast bonus aura (+50% honor in 25yards) - //aura should only apply to players who have accupied the node, set correct faction for trigger - if (trigger != null) - { - trigger.SetFaction(team == Team.Alliance ? 84u : 83u); - trigger.CastSpell(trigger, BattlegroundConst.SpellHonorableDefender25y, false); - } - } - - void _NodeDeOccupied(byte node) - { - //only dynamic nodes, no start points - if (node >= ABBattlegroundNodes.DynamicNodesCount) - return; - - //remove bonus honor aura trigger creature when node is lost - DelCreature(node + 7u);//null checks are in DelCreature! 0-6 spirit guides - - DelCreature(node); - - // buff object isn't despawned - } - - //Invoked if a player used a banner as a gameobject - public override void EventPlayerClickedOnFlag(Player source, GameObject target_obj) - { - if (GetStatus() != BattlegroundStatus.InProgress) - return; - - byte node = ABBattlegroundNodes.NodeStables; - GameObject obj = GetBgMap().GetGameObject(BgObjects[node * 8 + 7]); - while ((node < ABBattlegroundNodes.DynamicNodesCount) && ((obj == null) || (!source.IsWithinDistInMap(obj, 10)))) - { - ++node; - obj = GetBgMap().GetGameObject(BgObjects[node * 8 + ABObjectTypes.AuraContested]); - } - - if (node == ABBattlegroundNodes.DynamicNodesCount) - { - // this means our player isn't close to any of banners - maybe cheater ?? - return; - } - - int teamIndex = GetTeamIndexByTeamId(GetPlayerTeam(source.GetGUID())); - - // Check if player really could use this banner, not cheated - if (!(m_Nodes[node] == 0 || teamIndex == (int)m_Nodes[node] % 2)) - return; - - source.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.PvPActive); - uint sound; - // If node is neutral, change to contested - if (m_Nodes[node] == ABNodeStatus.Neutral) - { - UpdatePvpStat(source, (uint)ArathiBasinPvpStats.BasesAssaulted, 1); - m_prevNodes[node] = m_Nodes[node]; - m_Nodes[node] = (ABNodeStatus)(teamIndex + 1); - // burn current neutral banner - _DelBanner(node, ABNodeStatus.Neutral, 0); - // create new contested banner - _CreateBanner(node, ABNodeStatus.Contested, (byte)teamIndex, true); - _SendNodeUpdate(node); - m_NodeTimers[node] = FlagCapturingTime; - - // FIXME: team and node names not localized - if (teamIndex == BatttleGroundTeamId.Alliance) - SendBroadcastText(ABBattlegroundBroadcastTexts.ABNodes[node].TextAllianceClaims, ChatMsg.BgSystemAlliance, source); - else - SendBroadcastText(ABBattlegroundBroadcastTexts.ABNodes[node].TextHordeClaims, ChatMsg.BgSystemHorde, source); - - sound = SoundClaimed; - } - // If node is contested - else if ((m_Nodes[node] == ABNodeStatus.AllyContested) || (m_Nodes[node] == ABNodeStatus.HordeContested)) - { - // If last state is NOT occupied, change node to enemy-contested - if (m_prevNodes[node] < ABNodeStatus.Occupied) + foreach (ObjectGuid guid in _capturePoints) { - UpdatePvpStat(source, (uint)ArathiBasinPvpStats.BasesAssaulted, 1); - m_prevNodes[node] = m_Nodes[node]; - m_Nodes[node] = (ABNodeStatus.Contested + teamIndex); - // burn current contested banner - _DelBanner(node, ABNodeStatus.Contested, (byte)teamIndex); - // create new contested banner - _CreateBanner(node, ABNodeStatus.Contested, (byte)teamIndex, true); - _SendNodeUpdate(node); - m_NodeTimers[node] = FlagCapturingTime; - - if (teamIndex == BatttleGroundTeamId.Alliance) - SendBroadcastText(ABBattlegroundBroadcastTexts.ABNodes[node].TextAllianceAssaulted, ChatMsg.BgSystemAlliance, source); - else - SendBroadcastText(ABBattlegroundBroadcastTexts.ABNodes[node].TextHordeAssaulted, ChatMsg.BgSystemHorde, source); + GameObject capturePoint = map.GetGameObject(guid); + if (capturePoint != null) + { + int wsValue = map.GetWorldStateValue((int)capturePoint.GetGoInfo().CapturePoint.worldState1); + switch ((BattlegroundCapturePointState)wsValue) + { + case BattlegroundCapturePointState.AllianceCaptured: + ++alliance; + break; + case BattlegroundCapturePointState.HordeCaptured: + ++horde; + break; + default: + break; + } + } } - // If contested, change back to occupied - else - { - UpdatePvpStat(source, (uint)ArathiBasinPvpStats.BasesDefended, 1); - m_prevNodes[node] = m_Nodes[node]; - m_Nodes[node] = (ABNodeStatus.Occupied + teamIndex); - // burn current contested banner - _DelBanner(node, ABNodeStatus.Contested, (byte)teamIndex); - // create new occupied banner - _CreateBanner(node, ABNodeStatus.Occupied, (byte)teamIndex, true); - _SendNodeUpdate(node); - m_NodeTimers[node] = 0; - _NodeOccupied(node, (teamIndex == BatttleGroundTeamId.Alliance) ? Team.Alliance : Team.Horde); - - if (teamIndex == BatttleGroundTeamId.Alliance) - SendBroadcastText(ABBattlegroundBroadcastTexts.ABNodes[node].TextAllianceDefended, ChatMsg.BgSystemAlliance, source); - else - SendBroadcastText(ABBattlegroundBroadcastTexts.ABNodes[node].TextHordeDefended, ChatMsg.BgSystemHorde, source); - } - sound = (teamIndex == BatttleGroundTeamId.Alliance) ? SoundAssaultedAlliance : SoundAssaultedHorde; } - // If node is occupied, change to enemy-contested - else - { - UpdatePvpStat(source, (uint)ArathiBasinPvpStats.BasesAssaulted, 1); - m_prevNodes[node] = m_Nodes[node]; - m_Nodes[node] = (ABNodeStatus.Contested + teamIndex); - // burn current occupied banner - _DelBanner(node, ABNodeStatus.Occupied, (byte)teamIndex); - // create new contested banner - _CreateBanner(node, ABNodeStatus.Contested, (byte)teamIndex, true); - _SendNodeUpdate(node); - _NodeDeOccupied(node); - m_NodeTimers[node] = FlagCapturingTime; - - if (teamIndex == BatttleGroundTeamId.Alliance) - SendBroadcastText(ABBattlegroundBroadcastTexts.ABNodes[node].TextAllianceAssaulted, ChatMsg.BgSystemAlliance, source); - else - SendBroadcastText(ABBattlegroundBroadcastTexts.ABNodes[node].TextHordeAssaulted, ChatMsg.BgSystemHorde, source); - - sound = (teamIndex == BatttleGroundTeamId.Alliance) ? SoundAssaultedAlliance : SoundAssaultedHorde; - } - - // If node is occupied again, send "X has taken the Y" msg. - if (m_Nodes[node] >= ABNodeStatus.Occupied) - { - // FIXME: team and node names not localized - if (teamIndex == BatttleGroundTeamId.Alliance) - SendBroadcastText(ABBattlegroundBroadcastTexts.ABNodes[node].TextAllianceTaken, ChatMsg.BgSystemAlliance); - else - SendBroadcastText(ABBattlegroundBroadcastTexts.ABNodes[node].TextHordeTaken, ChatMsg.BgSystemHorde); - } - PlaySoundToAll(sound); } public override Team GetPrematureWinner() { // How many bases each team owns - byte ally = 0, horde = 0; - for (byte i = 0; i < ABBattlegroundNodes.DynamicNodesCount; ++i) - if (m_Nodes[i] == ABNodeStatus.AllyOccupied) - ++ally; - else if (m_Nodes[i] == ABNodeStatus.HordeOccupied) - ++horde; + _CalculateTeamNodes(out var ally, out var horde); if (ally > horde) return Team.Alliance; @@ -488,49 +172,261 @@ namespace Game.BattleGrounds.Zones return base.GetPrematureWinner(); } + public override void ProcessEvent(WorldObject source, uint eventId, WorldObject invoker) + { + Player player = invoker.ToPlayer(); + + switch ((ABEventIds)eventId) + { + case ABEventIds.StartBattle: + { + foreach (ObjectGuid guid in _creaturesToRemoveOnMatchStart) + { + Creature creature = GetBgMap().GetCreature(guid); + if (creature != null) + creature.DespawnOrUnsummon(); + } + + foreach (ObjectGuid guid in _gameobjectsToRemoveOnMatchStart) + { + GameObject gameObject = GetBgMap().GetGameObject(guid); + if (gameObject != null) + gameObject.DespawnOrUnsummon(); + } + + foreach (ObjectGuid guid in _doors) + { + GameObject gameObject = GetBgMap().GetGameObject(guid); + if (gameObject != null) + { + gameObject.UseDoorOrButton(); + gameObject.DespawnOrUnsummon(TimeSpan.FromSeconds(3)); + } + } + break; + } + case ABEventIds.ContestedBlacksmithAlliance: + UpdateWorldState(WorldStateIds.BlacksmithAllianceControlState, 1); + UpdateWorldState(WorldStateIds.BlacksmithHordeControlState, 0); + PlaySoundToAll((uint)SoundIds.NodeAssaultedAlliance); + if (player != null) + UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesAssaulted, 1); + break; + case ABEventIds.DefendedBlacksmithAlliance: + UpdateWorldState(WorldStateIds.BlacksmithAllianceControlState, 2); + UpdateWorldState(WorldStateIds.BlacksmithHordeControlState, 0); + PlaySoundToAll((uint)SoundIds.NodeCapturedAlliance); + if (player != null) + UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesDefended, 1); + break; + case ABEventIds.CaptureBlacksmithAlliance: + UpdateWorldState(WorldStateIds.BlacksmithAllianceControlState, 2); + PlaySoundToAll((uint)SoundIds.NodeCapturedAlliance); + break; + case ABEventIds.ContestedBlacksmithHorde: + UpdateWorldState(WorldStateIds.BlacksmithAllianceControlState, 0); + UpdateWorldState(WorldStateIds.BlacksmithHordeControlState, 1); + PlaySoundToAll((uint)SoundIds.NodeAssaultedHorde); + if (player != null) + UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesAssaulted, 1); + break; + case ABEventIds.DefendedBlacksmithHorde: + UpdateWorldState(WorldStateIds.BlacksmithAllianceControlState, 0); + UpdateWorldState(WorldStateIds.BlacksmithHordeControlState, 2); + PlaySoundToAll((uint)SoundIds.NodeCapturedHorde); + if (player != null) + UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesDefended, 1); + break; + case ABEventIds.CaptureBlacksmithHorde: + UpdateWorldState(WorldStateIds.BlacksmithHordeControlState, 2); + PlaySoundToAll((uint)SoundIds.NodeCapturedHorde); + break; + case ABEventIds.ContestedFarmAlliance: + UpdateWorldState(WorldStateIds.FarmAllianceControlState, 1); + UpdateWorldState(WorldStateIds.FarmHordeControlState, 0); + PlaySoundToAll((uint)SoundIds.NodeAssaultedAlliance); + if (player != null) + UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesAssaulted, 1); + break; + case ABEventIds.DefendedFarmAlliance: + UpdateWorldState(WorldStateIds.FarmAllianceControlState, 2); + UpdateWorldState(WorldStateIds.FarmHordeControlState, 0); + PlaySoundToAll((uint)SoundIds.NodeCapturedAlliance); + if (player != null) + UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesDefended, 1); + break; + case ABEventIds.CaptureFarmAlliance: + UpdateWorldState(WorldStateIds.FarmAllianceControlState, 2); + PlaySoundToAll((uint)SoundIds.NodeCapturedAlliance); + break; + case ABEventIds.ContestedFarmHorde: + UpdateWorldState(WorldStateIds.FarmAllianceControlState, 0); + UpdateWorldState(WorldStateIds.FarmHordeControlState, 1); + PlaySoundToAll((uint)SoundIds.NodeAssaultedHorde); + if (player != null) + UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesAssaulted, 1); + break; + case ABEventIds.DefendedFarmHorde: + UpdateWorldState(WorldStateIds.FarmAllianceControlState, 0); + UpdateWorldState(WorldStateIds.FarmHordeControlState, 2); + PlaySoundToAll((uint)SoundIds.NodeCapturedHorde); + if (player != null) + UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesDefended, 1); + break; + case ABEventIds.CaptureFarmHorde: + UpdateWorldState(WorldStateIds.FarmHordeControlState, 2); + PlaySoundToAll((uint)SoundIds.NodeCapturedHorde); + break; + case ABEventIds.ContestedGoldMineAlliance: + UpdateWorldState(WorldStateIds.GoldMineAllianceControlState, 1); + UpdateWorldState(WorldStateIds.GoldMineHordeControlState, 0); + PlaySoundToAll((uint)SoundIds.NodeAssaultedAlliance); + if (player != null) + UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesAssaulted, 1); + break; + case ABEventIds.DefendedGoldMineAlliance: + UpdateWorldState(WorldStateIds.GoldMineAllianceControlState, 2); + UpdateWorldState(WorldStateIds.GoldMineHordeControlState, 0); + PlaySoundToAll((uint)SoundIds.NodeCapturedAlliance); + if (player != null) + UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesDefended, 1); + break; + case ABEventIds.CaptureGoldMineAlliance: + UpdateWorldState(WorldStateIds.GoldMineAllianceControlState, 2); + PlaySoundToAll((uint)SoundIds.NodeCapturedAlliance); + break; + case ABEventIds.ContestedGoldMineHorde: + UpdateWorldState(WorldStateIds.GoldMineAllianceControlState, 0); + UpdateWorldState(WorldStateIds.GoldMineHordeControlState, 1); + PlaySoundToAll((uint)SoundIds.NodeAssaultedHorde); + if (player != null) + UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesAssaulted, 1); + break; + case ABEventIds.DefendedGoldMineHorde: + UpdateWorldState(WorldStateIds.GoldMineAllianceControlState, 0); + UpdateWorldState(WorldStateIds.GoldMineHordeControlState, 2); + PlaySoundToAll((uint)SoundIds.NodeCapturedHorde); + if (player != null) + UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesDefended, 1); + break; + case ABEventIds.CaptureGoldMineHorde: + UpdateWorldState(WorldStateIds.GoldMineHordeControlState, 2); + PlaySoundToAll((uint)SoundIds.NodeCapturedHorde); + break; + case ABEventIds.ContestedLumberMillAlliance: + UpdateWorldState(WorldStateIds.LumberMillAllianceControlState, 1); + UpdateWorldState(WorldStateIds.LumberMillHordeControlState, 0); + PlaySoundToAll((uint)SoundIds.NodeAssaultedAlliance); + if (player != null) + UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesAssaulted, 1); + break; + case ABEventIds.DefendedLumberMillAlliance: + UpdateWorldState(WorldStateIds.LumberMillAllianceControlState, 2); + UpdateWorldState(WorldStateIds.LumberMillHordeControlState, 0); + PlaySoundToAll((uint)SoundIds.NodeCapturedAlliance); + if (player != null) + UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesDefended, 1); + break; + case ABEventIds.CaptureLumberMillAlliance: + UpdateWorldState(WorldStateIds.LumberMillAllianceControlState, 2); + PlaySoundToAll((uint)SoundIds.NodeCapturedAlliance); + break; + case ABEventIds.ContestedLumberMillHorde: + UpdateWorldState(WorldStateIds.LumberMillAllianceControlState, 0); + UpdateWorldState(WorldStateIds.LumberMillHordeControlState, 1); + PlaySoundToAll((uint)SoundIds.NodeAssaultedHorde); + if (player != null) + UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesAssaulted, 1); + break; + case ABEventIds.DefendedLumberMillHorde: + UpdateWorldState(WorldStateIds.LumberMillAllianceControlState, 0); + UpdateWorldState(WorldStateIds.LumberMillHordeControlState, 2); + PlaySoundToAll((uint)SoundIds.NodeCapturedHorde); + if (player != null) + UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesDefended, 1); + break; + case ABEventIds.CaptureLumberMillHorde: + UpdateWorldState(WorldStateIds.LumberMillHordeControlState, 2); + PlaySoundToAll((uint)SoundIds.NodeCapturedHorde); + break; + case ABEventIds.ContestedStablesAlliance: + UpdateWorldState(WorldStateIds.StablesAllianceControlState, 1); + UpdateWorldState(WorldStateIds.StablesHordeControlState, 0); + PlaySoundToAll((uint)SoundIds.NodeAssaultedAlliance); + if (player != null) + UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesAssaulted, 1); + break; + case ABEventIds.DefendedStablesAlliance: + UpdateWorldState(WorldStateIds.StablesAllianceControlState, 2); + UpdateWorldState(WorldStateIds.StablesHordeControlState, 0); + PlaySoundToAll((uint)SoundIds.NodeCapturedAlliance); + if (player != null) + UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesDefended, 1); + break; + case ABEventIds.CaptureStablesAlliance: + UpdateWorldState(WorldStateIds.StablesAllianceControlState, 2); + PlaySoundToAll((uint)SoundIds.NodeCapturedAlliance); + break; + case ABEventIds.ContestedStablesHorde: + UpdateWorldState(WorldStateIds.StablesAllianceControlState, 0); + UpdateWorldState(WorldStateIds.StablesHordeControlState, 1); + PlaySoundToAll((uint)SoundIds.NodeAssaultedHorde); + if (player != null) + UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesAssaulted, 1); + break; + case ABEventIds.DefendedStablesHorde: + UpdateWorldState(WorldStateIds.StablesAllianceControlState, 0); + UpdateWorldState(WorldStateIds.StablesHordeControlState, 2); + PlaySoundToAll((uint)SoundIds.NodeCapturedHorde); + if (player != null) + UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesDefended, 1); + break; + case ABEventIds.CaptureStablesHorde: + UpdateWorldState(WorldStateIds.StablesHordeControlState, 2); + PlaySoundToAll((uint)SoundIds.NodeCapturedHorde); + break; + default: + Log.outWarn(LogFilter.Battleground, $"BattlegroundAB::ProcessEvent: Unhandled event {eventId}."); + break; + } + } + + public override void OnCreatureCreate(Creature creature) + { + switch ((CreatureIds)creature.GetEntry()) + { + case CreatureIds.TheBlackBride: + case CreatureIds.RadulfLeder: + _creaturesToRemoveOnMatchStart.Add(creature.GetGUID()); + break; + default: + break; + } + } + + public override void OnGameObjectCreate(GameObject gameObject) + { + if (gameObject.GetGoInfo().type == GameObjectTypes.CapturePoint) + _capturePoints.Add(gameObject.GetGUID()); + + switch ((GameobjectIds)gameObject.GetEntry()) + { + case GameobjectIds.GhostGate: + _gameobjectsToRemoveOnMatchStart.Add(gameObject.GetGUID()); + break; + case GameobjectIds.AllianceDoor: + case GameobjectIds.HordeDoor: + _doors.Add(gameObject.GetGUID()); + break; + default: + break; + } + } + public override bool SetupBattleground() { - bool result = true; - for (int i = 0; i < ABBattlegroundNodes.DynamicNodesCount; ++i) - { - result &= AddObject(ABObjectTypes.BannerNeutral + 8 * i, (uint)(NodeObjectId.Banner0 + i), NodePositions[i], 0, 0, (float)Math.Sin(NodePositions[i].GetOrientation() / 2), (float)Math.Cos(NodePositions[i].GetOrientation() / 2), BattlegroundConst.RespawnOneDay); - result &= AddObject(ABObjectTypes.BannerContA + 8 * i, ABObjectIds.BannerContA, NodePositions[i], 0, 0, (float)Math.Sin(NodePositions[i].GetOrientation() / 2), (float)Math.Cos(NodePositions[i].GetOrientation() / 2), BattlegroundConst.RespawnOneDay); - result &= AddObject(ABObjectTypes.BannerContH + 8 * i, ABObjectIds.BannerContH, NodePositions[i], 0, 0, (float)Math.Sin(NodePositions[i].GetOrientation() / 2), (float)Math.Cos(NodePositions[i].GetOrientation() / 2), BattlegroundConst.RespawnOneDay); - result &= AddObject(ABObjectTypes.BannerAlly + 8 * i, ABObjectIds.BannerA, NodePositions[i], 0, 0, (float)Math.Sin(NodePositions[i].GetOrientation() / 2), (float)Math.Cos(NodePositions[i].GetOrientation() / 2), BattlegroundConst.RespawnOneDay); - result &= AddObject(ABObjectTypes.BannerHorde + 8 * i, ABObjectIds.BannerH, NodePositions[i], 0, 0, (float)Math.Sin(NodePositions[i].GetOrientation() / 2), (float)Math.Cos(NodePositions[i].GetOrientation() / 2), BattlegroundConst.RespawnOneDay); - result &= AddObject(ABObjectTypes.AuraAlly + 8 * i, ABObjectIds.AuraA, NodePositions[i], 0, 0, (float)Math.Sin(NodePositions[i].GetOrientation() / 2), (float)Math.Cos(NodePositions[i].GetOrientation() / 2), BattlegroundConst.RespawnOneDay); - result &= AddObject(ABObjectTypes.AuraHorde + 8 * i, ABObjectIds.AuraH, NodePositions[i], 0, 0, (float)Math.Sin(NodePositions[i].GetOrientation() / 2), (float)Math.Cos(NodePositions[i].GetOrientation() / 2), BattlegroundConst.RespawnOneDay); - result &= AddObject(ABObjectTypes.AuraContested + 8 * i, ABObjectIds.AuraC, NodePositions[i], 0, 0, (float)Math.Sin(NodePositions[i].GetOrientation() / 2), (float)Math.Cos(NodePositions[i].GetOrientation() / 2), BattlegroundConst.RespawnOneDay); - if (!result) - { - Log.outError(LogFilter.Sql, "BatteGroundAB: Failed to spawn some object Battleground not created!"); - return false; - } - } - - result &= AddObject(ABObjectTypes.GateA, ABObjectIds.GateA, DoorPositions[0][0], DoorPositions[0][1], DoorPositions[0][2], DoorPositions[0][3], DoorPositions[0][4], DoorPositions[0][5], DoorPositions[0][6], DoorPositions[0][7], BattlegroundConst.RespawnImmediately); - result &= AddObject(ABObjectTypes.GateH, ABObjectIds.GateH, DoorPositions[1][0], DoorPositions[1][1], DoorPositions[1][2], DoorPositions[1][3], DoorPositions[1][4], DoorPositions[1][5], DoorPositions[1][6], DoorPositions[1][7], BattlegroundConst.RespawnImmediately); - if (!result) - { - Log.outError(LogFilter.Sql, "BatteGroundAB: Failed to spawn door object Battleground not created!"); - return false; - } - - //buffs - for (int i = 0; i < ABBattlegroundNodes.DynamicNodesCount; ++i) - { - result &= AddObject(ABObjectTypes.SpeedbuffStables + 3 * i, Buff_Entries[0], BuffPositions[i][0], BuffPositions[i][1], BuffPositions[i][2], BuffPositions[i][3], 0, 0, (float)Math.Sin(BuffPositions[i][3] / 2), (float)Math.Cos(BuffPositions[i][3] / 2), BattlegroundConst.RespawnOneDay); - result &= AddObject(ABObjectTypes.SpeedbuffStables + 3 * i + 1, Buff_Entries[1], BuffPositions[i][0], BuffPositions[i][1], BuffPositions[i][2], BuffPositions[i][3], 0, 0, (float)Math.Sin(BuffPositions[i][3] / 2), (float)Math.Cos(BuffPositions[i][3] / 2), BattlegroundConst.RespawnOneDay); - result &= AddObject(ABObjectTypes.SpeedbuffStables + 3 * i + 2, Buff_Entries[2], BuffPositions[i][0], BuffPositions[i][1], BuffPositions[i][2], BuffPositions[i][3], 0, 0, (float)Math.Sin(BuffPositions[i][3] / 2), (float)Math.Cos(BuffPositions[i][3] / 2), BattlegroundConst.RespawnOneDay); - if (!result) - { - Log.outError(LogFilter.Sql, "BatteGroundAB: Failed to spawn buff object!"); - return false; - } - } - - UpdateWorldState(ABWorldStates.ResourcesMax, MaxTeamScore); - UpdateWorldState(ABWorldStates.ResourcesWarning, WarningNearVictoryScore); + UpdateWorldState(WorldStateIds.ResourcesMax, MiscConst.MaxTeamScore); + UpdateWorldState(WorldStateIds.ResourcesWarning, MiscConst.WarningNearVictoryScore); return true; } @@ -543,23 +439,21 @@ namespace Game.BattleGrounds.Zones for (var i = 0; i < SharedConst.PvpTeamsCount; ++i) { m_TeamScores[i] = 0; - m_lastTick[i] = 0; m_HonorScoreTics[i] = 0; m_ReputationScoreTics[i] = 0; } + _pointsTimer.Reset(MiscConst.TickInterval); + m_IsInformedNearVictory = false; bool isBGWeekend = Global.BattlegroundMgr.IsBGWeekend(GetTypeID()); - m_HonorTics = (isBGWeekend) ? ABBGWeekendHonorTicks : NotABBGWeekendHonorTicks; - m_ReputationTics = (isBGWeekend) ? ABBGWeekendReputationTicks : NotABBGWeekendReputationTicks; + m_HonorTics = isBGWeekend ? MiscConst.ABBGWeekendHonorTicks : MiscConst.NotABBGWeekendHonorTicks; + m_ReputationTics = isBGWeekend ? MiscConst.ABBGWeekendReputationTicks : MiscConst.NotABBGWeekendReputationTicks; - for (byte i = 0; i < ABBattlegroundNodes.DynamicNodesCount; ++i) - { - m_Nodes[i] = 0; - m_prevNodes[i] = 0; - m_NodeTimers[i] = 0; - m_BannerTimers[i].timer = 0; - } + _creaturesToRemoveOnMatchStart.Clear(); + _gameobjectsToRemoveOnMatchStart.Clear(); + _doors.Clear(); + _capturePoints.Clear(); } public override void EndBattleground(Team winner) @@ -578,149 +472,75 @@ namespace Game.BattleGrounds.Zones public override WorldSafeLocsEntry GetClosestGraveyard(Player player) { - int teamIndex = GetTeamIndexByTeamId(GetPlayerTeam(player.GetGUID())); - - // Is there any occupied node for this team? - List nodes = new(); - for (byte i = 0; i < ABBattlegroundNodes.DynamicNodesCount; ++i) - if (m_Nodes[i] == ABNodeStatus.Occupied + teamIndex) - nodes.Add(i); - - WorldSafeLocsEntry good_entry = null; - // If so, select the closest node to place ghost on - if (!nodes.Empty()) - { - float plr_x = player.GetPositionX(); - float plr_y = player.GetPositionY(); - - float mindist = 999999.0f; - for (byte i = 0; i < nodes.Count; ++i) - { - WorldSafeLocsEntry entry = Global.ObjectMgr.GetWorldSafeLoc(GraveyardIds[nodes[i]]); - if (entry == null) - continue; - float dist = (entry.Loc.GetPositionX() - plr_x) * (entry.Loc.GetPositionX() - plr_x) + (entry.Loc.GetPositionY() - plr_y) * (entry.Loc.GetPositionY() - plr_y); - if (mindist > dist) - { - mindist = dist; - good_entry = entry; - } - } - nodes.Clear(); - } - // If not, place ghost on starting location - if (good_entry == null) - good_entry = Global.ObjectMgr.GetWorldSafeLoc(GraveyardIds[teamIndex + 5]); - - return good_entry; + return Global.ObjectMgr.GetClosestGraveyard(player.GetWorldLocation(), player.GetTeam(), player); } public override WorldSafeLocsEntry GetExploitTeleportLocation(Team team) { - return Global.ObjectMgr.GetWorldSafeLoc(team == Team.Alliance ? ExploitTeleportLocationAlliance : ExploitTeleportLocationHorde); + return Global.ObjectMgr.GetWorldSafeLoc(team == Team.Alliance ? MiscConst.ExploitTeleportLocationAlliance : MiscConst.ExploitTeleportLocationHorde); } + } - /// - /// Nodes info: - /// 0: neutral - /// 1: ally contested - /// 2: horde contested - /// 3: ally occupied - /// 4: horde occupied - /// - ABNodeStatus[] m_Nodes = new ABNodeStatus[ABBattlegroundNodes.DynamicNodesCount]; - ABNodeStatus[] m_prevNodes = new ABNodeStatus[ABBattlegroundNodes.DynamicNodesCount]; - BannerTimer[] m_BannerTimers = new BannerTimer[ABBattlegroundNodes.DynamicNodesCount]; - uint[] m_NodeTimers = new uint[ABBattlegroundNodes.DynamicNodesCount]; - uint[] m_lastTick = new uint[SharedConst.PvpTeamsCount]; - uint[] m_HonorScoreTics = new uint[SharedConst.PvpTeamsCount]; - uint[] m_ReputationScoreTics = new uint[SharedConst.PvpTeamsCount]; - bool m_IsInformedNearVictory; - uint m_HonorTics; - uint m_ReputationTics; - - //Const + #region Constants + struct MiscConst + { public const uint NotABBGWeekendHonorTicks = 260; public const uint ABBGWeekendHonorTicks = 160; public const uint NotABBGWeekendReputationTicks = 160; public const uint ABBGWeekendReputationTicks = 120; - public const int EventStartBattle = 9158;// Achievement: Let's Get This Done - - public const int SoundClaimed = 8192; - public const int SoundCapturedAlliance = 8173; - public const int SoundCapturedHorde = 8213; - public const uint SoundAssaultedAlliance = 8212; - public const uint SoundAssaultedHorde = 8174; - public const int SoundNearVictoryAlliance = 8456; - public const int SoundNearVictoryHorde = 8457; - - public const int FlagCapturingTime = 60000; - public const int WarningNearVictoryScore = 1400; public const int MaxTeamScore = 1500; public const uint ExploitTeleportLocationAlliance = 3705; public const uint ExploitTeleportLocationHorde = 3706; - public static Position[] NodePositions = - { - new Position(1166.785f, 1200.132f, -56.70859f, 0.9075713f), // stables - new Position(977.0156f, 1046.616f, -44.80923f, -2.600541f), // blacksmith - new Position(806.1821f, 874.2723f, -55.99371f, -2.303835f), // farm - new Position(856.1419f, 1148.902f, 11.18469f, -2.303835f), // lumber mill - new Position(1146.923f, 848.1782f, -110.917f, -0.7330382f) // gold mine - }; - - // x, y, z, o, rot0, rot1, rot2, rot3 - public static float[][] DoorPositions = - { - new float[] {1284.597f, 1281.167f, -15.97792f, 0.7068594f, 0.012957f, -0.060288f, 0.344959f, 0.93659f }, - new float[] {708.0903f, 708.4479f, -17.8342f, -2.391099f, 0.050291f, 0.015127f, 0.929217f, -0.365784f} - }; - // Tick intervals and given points: case 0, 1, 2, 3, 4, 5 captured nodes - public static uint[] TickIntervals = { 0, 12000, 9000, 6000, 3000, 1000 }; + public static TimeSpan TickInterval = TimeSpan.FromSeconds(2); public static uint[] TickPoints = { 0, 10, 10, 10, 10, 30 }; - - // WorldSafeLocs ids for 5 nodes, and for ally, and horde starting location - public static uint[] GraveyardIds = { 895, 894, 893, 897, 896, 898, 899 }; - - // x, y, z, o - public static float[][] BuffPositions = - { - new float[] {1185.566f, 1184.629f, -56.36329f, 2.303831f }, // stables - new float[] {990.1131f, 1008.73f, -42.60328f, 0.8203033f }, // blacksmith - new float[] {818.0089f, 842.3543f, -56.54062f, 3.176533f }, // farm - new float[] {808.8463f, 1185.417f, 11.92161f, 5.619962f }, // lumber mill - new float[] {1147.091f, 816.8362f, -98.39896f, 6.056293f } // gold mine - }; - - public static Position[] SpiritGuidePos = - { - new Position(1200.03f, 1171.09f, -56.47f, 5.15f), // stables - new Position(1017.43f, 960.61f, -42.95f, 4.88f), // blacksmith - new Position(833.00f, 793.00f, -57.25f, 5.27f), // farm - new Position(775.17f, 1206.40f, 15.79f, 1.90f), // lumber mill - new Position(1207.48f, 787.00f, -83.36f, 5.51f), // gold mine - new Position(1354.05f, 1275.48f, -11.30f, 4.77f), // alliance starting base - new Position(714.61f, 646.15f, -10.87f, 4.34f) // horde starting base - }; - - public static int[] NodeStates = { 1767, 1782, 1772, 1792, 1787 }; - - public static int[] NodeIcons = { 1842, 1846, 1845, 1844, 1843 }; } - struct BannerTimer + enum ABEventIds { - public uint timer; - public byte type; - public byte teamIndex; + StartBattle = 9158, // Achievement: Let'S Get This Done + + ContestedStablesHorde = 28523, + CaptureStablesHorde = 28527, + DefendedStablesHorde = 28525, + ContestedStablesAlliance = 28522, + CaptureStablesAlliance = 28526, + DefendedStablesAlliance = 28524, + + ContestedBlacksmithHorde = 8876, + CaptureBlacksmithHorde = 8773, + DefendedBlacksmithHorde = 8770, + ContestedBlacksmithAlliance = 8874, + CaptureBlacksmithAlliance = 8769, + DefendedBlacksmithAlliance = 8774, + + ContestedFarmHorde = 39398, + CaptureFarmHorde = 39399, + DefendedFarmHorde = 39400, + ContestedFarmAlliance = 39401, + CaptureFarmAlliance = 39402, + DefendedFarmAlliance = 39403, + + ContestedGoldMineHorde = 39404, + CaptureGoldMineHorde = 39405, + DefendedGoldMineHorde = 39406, + ContestedGoldMineAlliance = 39407, + CaptureGoldMineAlliance = 39408, + DefendedGoldMineAlliance = 39409, + + ContestedLumberMillHorde = 39387, + CaptureLumberMillHorde = 39388, + DefendedLumberMillHorde = 39389, + ContestedLumberMillAlliance = 39390, + CaptureLumberMillAlliance = 39391, + DefendedLumberMillAlliance = 39392 } - #region Consts - struct ABWorldStates + struct WorldStateIds { public const int OccupiedBasesHorde = 1778; public const int OccupiedBasesAlly = 1779; @@ -776,63 +596,24 @@ namespace Game.BattleGrounds.Zones public const int StablesAllianceControlState = 17322; } - // Note: code uses that these IDs follow each other - struct NodeObjectId - { - public const uint Banner0 = 180087; // Stables Banner - public const uint Banner1 = 180088; // Blacksmith Banner - public const uint Banner2 = 180089; // Farm Banner - public const uint Banner3 = 180090; // Lumber Mill Banner - public const uint Banner4 = 180091; // Gold Mine Banner - } - - struct ABObjectTypes - { - // for all 5 node points 8*5=40 objects - public const int BannerNeutral = 0; - public const int BannerContA = 1; - public const int BannerContH = 2; - public const int BannerAlly = 3; - public const int BannerHorde = 4; - public const int AuraAlly = 5; - public const int AuraHorde = 6; - public const int AuraContested = 7; - //Gates - public const int GateA = 40; - public const int GateH = 41; - //Buffs - public const int SpeedbuffStables = 42; - public const int RegenbuffStables = 43; - public const int BerserkbuffStables = 44; - public const int SpeedbuffBlacksmith = 45; - public const int RegenbuffBlacksmith = 46; - public const int BerserkbuffBlacksmith = 47; - public const int SpeedbuffFarm = 48; - public const int RegenbuffFarm = 49; - public const int BerserkbuffFarm = 50; - public const int SpeedbuffLumberMill = 51; - public const int RegenbuffLumberMill = 52; - public const int BerserkbuffLumberMill = 53; - public const int SpeedbuffGoldMine = 54; - public const int RegenbuffGoldMine = 55; - public const int BerserkbuffGoldMine = 56; - public const int Max = 57; - } - // Object id templates from DB - struct ABObjectIds + enum GameobjectIds { - public const uint BannerA = 180058; - public const uint BannerContA = 180059; - public const uint BannerH = 180060; - public const uint BannerContH = 180061; + CapturePointStables = 227420, + CapturePointBlacksmith = 227522, + CapturePointFarm = 227536, + CapturePointGoldMine = 227538, + CapturePointLumberMill = 227544, - public const uint AuraA = 180100; - public const uint AuraH = 180101; - public const uint AuraC = 180102; + GhostGate = 180322, + AllianceDoor = 322273, + HordeDoor = 322274 + } - public const uint GateA = 180255; - public const uint GateH = 180256; + enum CreatureIds + { + TheBlackBride = 150501, + RadulfLeder = 150505 } struct ABBattlegroundNodes @@ -851,62 +632,21 @@ namespace Game.BattleGrounds.Zones public const int AllCount = 7; // All Nodes (Dynamic And Static) } - struct ABBattlegroundBroadcastTexts + enum ABBattlegroundBroadcastTexts { - public const uint AllianceNearVictory = 10598; - public const uint HordeNearVictory = 10599; - - public static ABNodeInfo[] ABNodes = - { - new ABNodeInfo(ABBattlegroundNodes.NodeStables, 10199, 10200, 10203, 10204, 10201, 10202, 10286, 10287), - new ABNodeInfo(ABBattlegroundNodes.NodeBlacksmith, 10211, 10212, 10213, 10214, 10215, 10216, 10290, 10291), - new ABNodeInfo(ABBattlegroundNodes.NodeFarm, 10217, 10218, 10219, 10220, 10221, 10222, 10288, 10289), - new ABNodeInfo(ABBattlegroundNodes.NodeLumberMill, 10224, 10225, 10226, 10227, 10228, 10229, 10284, 10285), - new ABNodeInfo(ABBattlegroundNodes.NodeGoldMine, 10230, 10231, 10232, 10233, 10234, 10235, 10282, 10283) - }; + AllianceNearVictory = 10598, + HordeNearVictory = 10599 } - struct ABNodeInfo + enum SoundIds { - public ABNodeInfo(uint nodeId, uint textAllianceAssaulted, uint textHordeAssaulted, uint textAllianceTaken, uint textHordeTaken, uint textAllianceDefended, uint textHordeDefended, uint textAllianceClaims, uint textHordeClaims) - { - NodeId = nodeId; - TextAllianceAssaulted = textAllianceAssaulted; - TextHordeAssaulted = textHordeAssaulted; - TextAllianceTaken = textAllianceTaken; - TextHordeTaken = textHordeTaken; - TextAllianceDefended = textAllianceDefended; - TextHordeDefended = textHordeDefended; - TextAllianceClaims = textAllianceClaims; - TextHordeClaims = textHordeClaims; - } - - public uint NodeId; - public uint TextAllianceAssaulted; - public uint TextHordeAssaulted; - public uint TextAllianceTaken; - public uint TextHordeTaken; - public uint TextAllianceDefended; - public uint TextHordeDefended; - public uint TextAllianceClaims; - public uint TextHordeClaims; - } - - enum ABNodeStatus - { - Neutral = 0, - Contested = 1, - AllyContested = 1, - HordeContested = 2, - Occupied = 3, - AllyOccupied = 3, - HordeOccupied = 4 - } - - enum ABObjectives - { - AssaultBase = 122, - DefendBase = 123 + NodeClaimed = 8192, + NodeCapturedAlliance = 8173, + NodeCapturedHorde = 8213, + NodeAssaultedAlliance = 8212, + NodeAssaultedHorde = 8174, + NearVictoryAlliance = 8456, + NearVictoryHorde = 8457 } enum ArathiBasinPvpStats