diff options
author | Jeremy <Golrag@users.noreply.github.com> | 2023-07-05 23:52:22 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-07-05 23:52:22 +0200 |
commit | cc08aa8e249c5cd33f6b09a766cf6131c42566b9 (patch) | |
tree | ad5197150562f40cebb6a9bb4ef187c73e0e2592 /src | |
parent | d70d1d24a52816d6fb8f657afc609c15aeff4fea (diff) |
Core/Battlegrounds: Implement Arathi Basin from Battle for Azeroth (#28369)
Co-authored-by: ModoX <moardox@gmail.com>
Diffstat (limited to 'src')
4 files changed, 449 insertions, 600 deletions
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp index 045238009d0..adec4dcdca8 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp @@ -30,22 +30,12 @@ BattlegroundAB::BattlegroundAB(BattlegroundTemplate const* battlegroundTemplate) { m_IsInformedNearVictory = false; m_BuffChange = true; - BgObjects.resize(BG_AB_OBJECT_MAX); - BgCreatures.resize(BG_AB_ALL_NODES_COUNT + 5);//+5 for aura triggers - - for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++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; - } + BgObjects.resize(0); + BgCreatures.resize(0); + m_lastTick = 0; for (uint8 i = 0; i < PVP_TEAMS_COUNT; ++i) { - m_lastTick[i] = 0; m_HonorScoreTics[i] = 0; m_ReputationScoreTics[i] = 0; } @@ -60,75 +50,24 @@ void BattlegroundAB::PostUpdateImpl(uint32 diff) { if (GetStatus() == STATUS_IN_PROGRESS) { - int team_points[PVP_TEAMS_COUNT] = { 0, 0 }; - - for (int node = 0; node < BG_AB_DYNAMIC_NODES_COUNT; ++node) - { - // 3 sec delay to spawn new banner instead previous despawned one - if (m_BannerTimers[node].timer) - { - if (m_BannerTimers[node].timer > diff) - m_BannerTimers[node].timer -= diff; - else - { - m_BannerTimers[node].timer = 0; - _CreateBanner(node, m_BannerTimers[node].type, m_BannerTimers[node].teamIndex, false); - } - } - - // 1-minute to occupy a node from contested state - if (m_NodeTimers[node]) - { - if (m_NodeTimers[node] > diff) - m_NodeTimers[node] -= diff; - else - { - m_NodeTimers[node] = 0; - // Change from contested to occupied ! - uint8 teamIndex = m_Nodes[node]-1; - m_prevNodes[node] = m_Nodes[node]; - m_Nodes[node] += 2; - // burn current contested banner - _DelBanner(node, BG_AB_NODE_TYPE_CONTESTED, teamIndex); - // create new occupied banner - _CreateBanner(node, BG_AB_NODE_TYPE_OCCUPIED, teamIndex, true); - _SendNodeUpdate(node); - _NodeOccupied(node, (teamIndex == TEAM_ALLIANCE) ? ALLIANCE : HORDE); - // Message to chatlog - - if (teamIndex == TEAM_ALLIANCE) - { - SendBroadcastText(ABNodes[node].TextAllianceTaken, CHAT_MSG_BG_SYSTEM_ALLIANCE); - PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_ALLIANCE); - } - else - { - SendBroadcastText(ABNodes[node].TextHordeTaken, CHAT_MSG_BG_SYSTEM_HORDE); - PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_HORDE); - } - } - } - - for (int team = 0; team < PVP_TEAMS_COUNT; ++team) - if (m_Nodes[node] == team + BG_AB_NODE_TYPE_OCCUPIED) - ++team_points[team]; - } - // Accumulate points - for (int team = 0; team < PVP_TEAMS_COUNT; ++team) + m_lastTick += diff; + if (m_lastTick > BG_AB_TickInterval) { - int points = team_points[team]; - if (!points) - continue; + m_lastTick -= BG_AB_TickInterval; - m_lastTick[team] += diff; + uint8 ally = 0, horde = 0; + _CalculateTeamNodes(ally, horde); + uint8 points[PVP_TEAMS_COUNT] = { ally, horde }; - if (m_lastTick[team] > BG_AB_TickIntervals[points]) + for (uint8 team = 0; team < PVP_TEAMS_COUNT; ++team) { - m_lastTick[team] -= BG_AB_TickIntervals[points]; - m_TeamScores[team] += BG_AB_TickPoints[points]; - m_HonorScoreTics[team] += BG_AB_TickPoints[points]; - m_ReputationScoreTics[team] += BG_AB_TickPoints[points]; + if (!points[team]) + continue; + + m_TeamScores[team] += BG_AB_TickPoints[points[team]]; + m_HonorScoreTics[team] += BG_AB_TickPoints[points[team]]; + m_ReputationScoreTics[team] += BG_AB_TickPoints[points[team]]; if (m_ReputationScoreTics[team] >= m_ReputationTics) { @@ -175,6 +114,9 @@ void BattlegroundAB::PostUpdateImpl(uint32 diff) UpdateWorldState(BG_AB_WS_HAD_500_DISADVANTAGE_ALLIANCE, 1); } } + + UpdateWorldState(BG_AB_WS_OCCUPIED_BASES_ALLY, ally); + UpdateWorldState(BG_AB_WS_OCCUPIED_BASES_HORDE, horde); } // Test win condition @@ -185,39 +127,8 @@ void BattlegroundAB::PostUpdateImpl(uint32 diff) } } -void BattlegroundAB::StartingEventCloseDoors() -{ - // despawn banners, auras and buffs - for (int obj = BG_AB_OBJECT_BANNER_NEUTRAL; obj < BG_AB_DYNAMIC_NODES_COUNT * 8; ++obj) - SpawnBGObject(obj, RESPAWN_ONE_DAY); - for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT * 3; ++i) - SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + i, RESPAWN_ONE_DAY); - - // Starting doors - DoorClose(BG_AB_OBJECT_GATE_A); - DoorClose(BG_AB_OBJECT_GATE_H); - SpawnBGObject(BG_AB_OBJECT_GATE_A, RESPAWN_IMMEDIATELY); - SpawnBGObject(BG_AB_OBJECT_GATE_H, RESPAWN_IMMEDIATELY); - - // Starting base spirit guides - _NodeOccupied(BG_AB_SPIRIT_ALIANCE, ALLIANCE); - _NodeOccupied(BG_AB_SPIRIT_HORDE, HORDE); -} - void BattlegroundAB::StartingEventOpenDoors() { - // spawn neutral banners - for (int banner = BG_AB_OBJECT_BANNER_NEUTRAL, i = 0; i < 5; banner += 8, ++i) - SpawnBGObject(banner, RESPAWN_IMMEDIATELY); - for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) - { - //randomly select buff to spawn - uint8 buff = urand(0, 2); - SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + buff + i * 3, RESPAWN_IMMEDIATELY); - } - DoorOpen(BG_AB_OBJECT_GATE_A); - DoorOpen(BG_AB_OBJECT_GATE_H); - // Achievement: Let's Get This Done TriggerGameEvent(AB_EVENT_START_BATTLE); } @@ -260,276 +171,39 @@ void BattlegroundAB::HandleAreaTrigger(Player* player, uint32 trigger, bool ente } } -/* type: 0-neutral, 1-contested, 3-occupied - teamIndex: 0-ally, 1-horde */ -void BattlegroundAB::_CreateBanner(uint8 node, uint8 type, uint8 teamIndex, bool delay) +void BattlegroundAB::_CalculateTeamNodes(uint8& alliance, uint8& horde) { - // Just put it into the queue - if (delay) - { - m_BannerTimers[node].timer = 2000; - m_BannerTimers[node].type = type; - m_BannerTimers[node].teamIndex = teamIndex; - return; - } - - uint8 obj = node*8 + type + teamIndex; + alliance = 0; + horde = 0; - SpawnBGObject(obj, RESPAWN_IMMEDIATELY); - - // handle aura with banner - if (!type) - return; - obj = node * 8 + ((type == BG_AB_NODE_TYPE_OCCUPIED) ? (5 + teamIndex) : 7); - SpawnBGObject(obj, RESPAWN_IMMEDIATELY); -} - -void BattlegroundAB::_DelBanner(uint8 node, uint8 type, uint8 teamIndex) -{ - uint8 obj = node*8 + type + teamIndex; - SpawnBGObject(obj, RESPAWN_ONE_DAY); - - // handle aura with banner - if (!type) - return; - obj = node * 8 + ((type == BG_AB_NODE_TYPE_OCCUPIED) ? (5 + teamIndex) : 7); - SpawnBGObject(obj, RESPAWN_ONE_DAY); -} - -void BattlegroundAB::_SendNodeUpdate(uint8 node) -{ - // Send node owner state update to refresh map icons on client - constexpr int32 idPlusArray[] = {0, 2, 3, 0, 1}; - constexpr int32 statePlusArray[] = {0, 2, 0, 2, 0}; - - if (m_prevNodes[node]) - UpdateWorldState(BG_AB_OP_NODESTATES[node] + idPlusArray[m_prevNodes[node]], 0); - else - UpdateWorldState(BG_AB_OP_NODEICONS[node], 0); - - UpdateWorldState(BG_AB_OP_NODESTATES[node] + idPlusArray[m_Nodes[node]], 1); - - switch (node) - { - case BG_AB_NODE_STABLES: - UpdateWorldState(BG_AB_WS_STABLES_ICON_NEW, m_Nodes[node] + statePlusArray[m_Nodes[node]]); - UpdateWorldState(BG_AB_WS_STABLES_HORDE_CONTROL_STATE, m_Nodes[node] == BG_AB_NODE_STATUS_HORDE_OCCUPIED ? 2 : (m_Nodes[node] == BG_AB_NODE_STATUS_HORDE_CONTESTED ? 1 : 0)); - UpdateWorldState(BG_AB_WS_STABLES_ALLIANCE_CONTROL_STATE, m_Nodes[node] == BG_AB_NODE_STATUS_ALLY_OCCUPIED ? 2 : (m_Nodes[node] == BG_AB_NODE_STATUS_ALLY_CONTESTED ? 1 : 0)); - break; - case BG_AB_NODE_BLACKSMITH: - UpdateWorldState(BG_AB_WS_BLACKSMITH_ICON_NEW, m_Nodes[node] + statePlusArray[m_Nodes[node]]); - UpdateWorldState(BG_AB_WS_BLACKSMITH_HORDE_CONTROL_STATE, m_Nodes[node] == BG_AB_NODE_STATUS_HORDE_OCCUPIED ? 2 : (m_Nodes[node] == BG_AB_NODE_STATUS_HORDE_CONTESTED ? 1 : 0)); - UpdateWorldState(BG_AB_WS_BLACKSMITH_ALLIANCE_CONTROL_STATE, m_Nodes[node] == BG_AB_NODE_STATUS_ALLY_OCCUPIED ? 2 : (m_Nodes[node] == BG_AB_NODE_STATUS_ALLY_CONTESTED ? 1 : 0)); - break; - case BG_AB_NODE_FARM: - UpdateWorldState(BG_AB_WS_FARM_ICON_NEW, m_Nodes[node] + statePlusArray[m_Nodes[node]]); - UpdateWorldState(BG_AB_WS_FARM_HORDE_CONTROL_STATE, m_Nodes[node] == BG_AB_NODE_STATUS_HORDE_OCCUPIED ? 2 : (m_Nodes[node] == BG_AB_NODE_STATUS_HORDE_CONTESTED ? 1 : 0)); - UpdateWorldState(BG_AB_WS_FARM_ALLIANCE_CONTROL_STATE, m_Nodes[node] == BG_AB_NODE_STATUS_ALLY_OCCUPIED ? 2 : (m_Nodes[node] == BG_AB_NODE_STATUS_ALLY_CONTESTED ? 1 : 0)); - break; - case BG_AB_NODE_LUMBER_MILL: - UpdateWorldState(BG_AB_WS_LUMBER_MILL_ICON_NEW, m_Nodes[node] + statePlusArray[m_Nodes[node]]); - UpdateWorldState(BG_AB_WS_LUMBER_MILL_HORDE_CONTROL_STATE, m_Nodes[node] == BG_AB_NODE_STATUS_HORDE_OCCUPIED ? 2 : (m_Nodes[node] == BG_AB_NODE_STATUS_HORDE_CONTESTED ? 1 : 0)); - UpdateWorldState(BG_AB_WS_LUMBER_MILL_ALLIANCE_CONTROL_STATE, m_Nodes[node] == BG_AB_NODE_STATUS_ALLY_OCCUPIED ? 2 : (m_Nodes[node] == BG_AB_NODE_STATUS_ALLY_CONTESTED ? 1 : 0)); - break; - case BG_AB_NODE_GOLD_MINE: - UpdateWorldState(BG_AB_WS_GOLD_MINE_ICON_NEW, m_Nodes[node] + statePlusArray[m_Nodes[node]]); - UpdateWorldState(BG_AB_WS_GOLD_MINE_HORDE_CONTROL_STATE, m_Nodes[node] == BG_AB_NODE_STATUS_HORDE_OCCUPIED ? 2 : (m_Nodes[node] == BG_AB_NODE_STATUS_HORDE_CONTESTED ? 1 : 0)); - UpdateWorldState(BG_AB_WS_GOLD_MINE_ALLIANCE_CONTROL_STATE, m_Nodes[node] == BG_AB_NODE_STATUS_ALLY_OCCUPIED ? 2 : (m_Nodes[node] == BG_AB_NODE_STATUS_ALLY_CONTESTED ? 1 : 0)); - break; - default: - break; - } - - // How many bases each team owns - uint8 ally = 0, horde = 0; - for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) - if (m_Nodes[i] == BG_AB_NODE_STATUS_ALLY_OCCUPIED) - ++ally; - else if (m_Nodes[i] == BG_AB_NODE_STATUS_HORDE_OCCUPIED) - ++horde; - - UpdateWorldState(BG_AB_WS_OCCUPIED_BASES_ALLY, ally); - UpdateWorldState(BG_AB_WS_OCCUPIED_BASES_HORDE, horde); -} - -void BattlegroundAB::_NodeOccupied(uint8 node, Team team) -{ - if (!AddSpiritGuide(node, BG_AB_SpiritGuidePos[node], GetTeamIndexByTeamId(team))) - TC_LOG_ERROR("bg.battleground", "Failed to spawn spirit guide! point: {}, team: {}, ", node, team); - - if (node >= BG_AB_DYNAMIC_NODES_COUNT)//only dynamic nodes, no start points - return; - - uint8 capturedNodes = 0; - for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) - if (m_Nodes[i] == uint8(GetTeamIndexByTeamId(team)) + BG_AB_NODE_TYPE_OCCUPIED && !m_NodeTimers[i]) - ++capturedNodes; - - if (capturedNodes >= 5) - CastSpellOnTeam(SPELL_AB_QUEST_REWARD_5_BASES, team); - if (capturedNodes >= 4) - CastSpellOnTeam(SPELL_AB_QUEST_REWARD_4_BASES, team); - - Creature* trigger = !BgCreatures[node + 7] ? GetBGCreature(node + 7) : nullptr; // 0-6 spirit guides - if (!trigger) - trigger = AddCreature(WORLD_TRIGGER, node+7, BG_AB_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) + if (BattlegroundMap* map = FindBgMap()) { - trigger->SetFaction(team == ALLIANCE ? FACTION_ALLIANCE_GENERIC : FACTION_HORDE_GENERIC); - trigger->CastSpell(trigger, SPELL_HONORABLE_DEFENDER_25Y, false); - } -} - -void BattlegroundAB::_NodeDeOccupied(uint8 node) -{ - //only dynamic nodes, no start points - if (node >= BG_AB_DYNAMIC_NODES_COUNT) - return; - - //remove bonus honor aura trigger creature when node is lost - DelCreature(node+7);//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 */ -void BattlegroundAB::EventPlayerClickedOnFlag(Player* source, GameObject* /*target_obj*/) -{ - if (GetStatus() != STATUS_IN_PROGRESS) - return; - - uint8 node = BG_AB_NODE_STABLES; - GameObject* obj = GetBgMap()->GetGameObject(BgObjects[node*8+7]); - while ((node < BG_AB_DYNAMIC_NODES_COUNT) && ((!obj) || (!source->IsWithinDistInMap(obj, 10)))) - { - ++node; - obj = GetBgMap()->GetGameObject(BgObjects[node*8+BG_AB_OBJECT_AURA_CONTESTED]); - } - - if (node == BG_AB_DYNAMIC_NODES_COUNT) - { - // this means our player isn't close to any of banners - maybe cheater ?? - return; - } - - TeamId teamIndex = GetTeamIndexByTeamId(GetPlayerTeam(source->GetGUID())); - - // Check if player really could use this banner, not cheated - if (!(m_Nodes[node] == 0 || teamIndex == m_Nodes[node]%2)) - return; - - source->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::PvPActive); - uint32 sound = 0; - // If node is neutral, change to contested - if (m_Nodes[node] == BG_AB_NODE_TYPE_NEUTRAL) - { - UpdatePlayerScore(source, SCORE_BASES_ASSAULTED, 1); - m_prevNodes[node] = m_Nodes[node]; - m_Nodes[node] = teamIndex + 1; - // burn current neutral banner - _DelBanner(node, BG_AB_NODE_TYPE_NEUTRAL, 0); - // create new contested banner - _CreateBanner(node, BG_AB_NODE_TYPE_CONTESTED, teamIndex, true); - _SendNodeUpdate(node); - m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME; - - if (teamIndex == TEAM_ALLIANCE) - SendBroadcastText(ABNodes[node].TextAllianceClaims, CHAT_MSG_BG_SYSTEM_ALLIANCE, source); - else - SendBroadcastText(ABNodes[node].TextHordeClaims, CHAT_MSG_BG_SYSTEM_HORDE, source); - - sound = BG_AB_SOUND_NODE_CLAIMED; - } - // If node is contested - else if ((m_Nodes[node] == BG_AB_NODE_STATUS_ALLY_CONTESTED) || (m_Nodes[node] == BG_AB_NODE_STATUS_HORDE_CONTESTED)) - { - // If last state is NOT occupied, change node to enemy-contested - if (m_prevNodes[node] < BG_AB_NODE_TYPE_OCCUPIED) - { - UpdatePlayerScore(source, SCORE_BASES_ASSAULTED, 1); - m_prevNodes[node] = m_Nodes[node]; - m_Nodes[node] = uint8(teamIndex) + BG_AB_NODE_TYPE_CONTESTED; - // burn current contested banner - _DelBanner(node, BG_AB_NODE_TYPE_CONTESTED, !teamIndex); - // create new contested banner - _CreateBanner(node, BG_AB_NODE_TYPE_CONTESTED, teamIndex, true); - _SendNodeUpdate(node); - m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME; - - if (teamIndex == TEAM_ALLIANCE) - SendBroadcastText(ABNodes[node].TextAllianceAssaulted, CHAT_MSG_BG_SYSTEM_ALLIANCE, source); - else - SendBroadcastText(ABNodes[node].TextHordeAssaulted, CHAT_MSG_BG_SYSTEM_HORDE, source); - } - // If contested, change back to occupied - else + for (ObjectGuid const& guid : _capturePoints) { - UpdatePlayerScore(source, SCORE_BASES_DEFENDED, 1); - m_prevNodes[node] = m_Nodes[node]; - m_Nodes[node] = uint8(teamIndex) + BG_AB_NODE_TYPE_OCCUPIED; - // burn current contested banner - _DelBanner(node, BG_AB_NODE_TYPE_CONTESTED, !teamIndex); - // create new occupied banner - _CreateBanner(node, BG_AB_NODE_TYPE_OCCUPIED, teamIndex, true); - _SendNodeUpdate(node); - m_NodeTimers[node] = 0; - _NodeOccupied(node, (teamIndex == TEAM_ALLIANCE) ? ALLIANCE : HORDE); - - if (teamIndex == TEAM_ALLIANCE) - SendBroadcastText(ABNodes[node].TextAllianceDefended, CHAT_MSG_BG_SYSTEM_ALLIANCE, source); - else - SendBroadcastText(ABNodes[node].TextHordeDefended, CHAT_MSG_BG_SYSTEM_HORDE, source); + if (GameObject* capturePoint = map->GetGameObject(guid)) + { + int32 wsValue = map->GetWorldStateValue(capturePoint->GetGOInfo()->capturePoint.worldState1); + switch (WorldPackets::Battleground::BattlegroundCapturePointState(wsValue)) + { + case WorldPackets::Battleground::BattlegroundCapturePointState::AllianceCaptured: + ++alliance; + break; + case WorldPackets::Battleground::BattlegroundCapturePointState::HordeCaptured: + ++horde; + break; + default: + break; + } + } } - sound = (teamIndex == TEAM_ALLIANCE) ? BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE : BG_AB_SOUND_NODE_ASSAULTED_HORDE; - } - // If node is occupied, change to enemy-contested - else - { - UpdatePlayerScore(source, SCORE_BASES_ASSAULTED, 1); - m_prevNodes[node] = m_Nodes[node]; - m_Nodes[node] = uint8(teamIndex) + BG_AB_NODE_TYPE_CONTESTED; - // burn current occupied banner - _DelBanner(node, BG_AB_NODE_TYPE_OCCUPIED, !teamIndex); - // create new contested banner - _CreateBanner(node, BG_AB_NODE_TYPE_CONTESTED, teamIndex, true); - _SendNodeUpdate(node); - _NodeDeOccupied(node); - m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME; - - if (teamIndex == TEAM_ALLIANCE) - SendBroadcastText(ABNodes[node].TextAllianceAssaulted, CHAT_MSG_BG_SYSTEM_ALLIANCE, source); - else - SendBroadcastText(ABNodes[node].TextHordeAssaulted, CHAT_MSG_BG_SYSTEM_HORDE, source); - - sound = (teamIndex == TEAM_ALLIANCE) ? BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE : BG_AB_SOUND_NODE_ASSAULTED_HORDE; - } - - // If node is occupied again, send "X has taken the Y" msg. - if (m_Nodes[node] >= BG_AB_NODE_TYPE_OCCUPIED) - { - if (teamIndex == TEAM_ALLIANCE) - SendBroadcastText(ABNodes[node].TextAllianceTaken, CHAT_MSG_BG_SYSTEM_ALLIANCE); - else - SendBroadcastText(ABNodes[node].TextHordeTaken, CHAT_MSG_BG_SYSTEM_HORDE); } - PlaySoundToAll(sound); } uint32 BattlegroundAB::GetPrematureWinner() { // How many bases each team owns uint8 ally = 0, horde = 0; - for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) - if (m_Nodes[i] == BG_AB_NODE_STATUS_ALLY_OCCUPIED) - ++ally; - else if (m_Nodes[i] == BG_AB_NODE_STATUS_HORDE_OCCUPIED) - ++horde; + _CalculateTeamNodes(ally, horde); if (ally > horde) return ALLIANCE; @@ -540,40 +214,250 @@ uint32 BattlegroundAB::GetPrematureWinner() return Battleground::GetPrematureWinner(); } -bool BattlegroundAB::SetupBattleground() +void BattlegroundAB::ProcessEvent(WorldObject* /*source*/, uint32 eventId, WorldObject* invoker) { - for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) + switch (eventId) { - if (!AddObject(BG_AB_OBJECT_BANNER_NEUTRAL + 8*i, BG_AB_OBJECTID_NODE_BANNER_0 + i, BG_AB_NodePositions[i], 0, 0, std::sin(BG_AB_NodePositions[i].GetOrientation()/2), std::cos(BG_AB_NodePositions[i].GetOrientation()/2), RESPAWN_ONE_DAY) - || !AddObject(BG_AB_OBJECT_BANNER_CONT_A + 8*i, BG_AB_OBJECTID_BANNER_CONT_A, BG_AB_NodePositions[i], 0, 0, std::sin(BG_AB_NodePositions[i].GetOrientation()/2), std::cos(BG_AB_NodePositions[i].GetOrientation()/2), RESPAWN_ONE_DAY) - || !AddObject(BG_AB_OBJECT_BANNER_CONT_H + 8*i, BG_AB_OBJECTID_BANNER_CONT_H, BG_AB_NodePositions[i], 0, 0, std::sin(BG_AB_NodePositions[i].GetOrientation()/2), std::cos(BG_AB_NodePositions[i].GetOrientation()/2), RESPAWN_ONE_DAY) - || !AddObject(BG_AB_OBJECT_BANNER_ALLY + 8*i, BG_AB_OBJECTID_BANNER_A, BG_AB_NodePositions[i], 0, 0, std::sin(BG_AB_NodePositions[i].GetOrientation()/2), std::cos(BG_AB_NodePositions[i].GetOrientation()/2), RESPAWN_ONE_DAY) - || !AddObject(BG_AB_OBJECT_BANNER_HORDE + 8*i, BG_AB_OBJECTID_BANNER_H, BG_AB_NodePositions[i], 0, 0, std::sin(BG_AB_NodePositions[i].GetOrientation()/2), std::cos(BG_AB_NodePositions[i].GetOrientation()/2), RESPAWN_ONE_DAY) - || !AddObject(BG_AB_OBJECT_AURA_ALLY + 8*i, BG_AB_OBJECTID_AURA_A, BG_AB_NodePositions[i], 0, 0, std::sin(BG_AB_NodePositions[i].GetOrientation()/2), std::cos(BG_AB_NodePositions[i].GetOrientation()/2), RESPAWN_ONE_DAY) - || !AddObject(BG_AB_OBJECT_AURA_HORDE + 8*i, BG_AB_OBJECTID_AURA_H, BG_AB_NodePositions[i], 0, 0, std::sin(BG_AB_NodePositions[i].GetOrientation()/2), std::cos(BG_AB_NodePositions[i].GetOrientation()/2), RESPAWN_ONE_DAY) - || !AddObject(BG_AB_OBJECT_AURA_CONTESTED + 8*i, BG_AB_OBJECTID_AURA_C, BG_AB_NodePositions[i], 0, 0, std::sin(BG_AB_NodePositions[i].GetOrientation()/2), std::cos(BG_AB_NodePositions[i].GetOrientation()/2), RESPAWN_ONE_DAY)) + case AB_EVENT_START_BATTLE: { - TC_LOG_ERROR("sql.sql", "BatteGroundAB: Failed to spawn some object Battleground not created!"); - return false; + for (ObjectGuid const& guid : _creaturesToRemoveOnMatchStart) + if (Creature* creature = GetBgMap()->GetCreature(guid)) + creature->DespawnOrUnsummon(); + + for (ObjectGuid const& guid : _gameobjectsToRemoveOnMatchStart) + if (GameObject* gameObject = GetBgMap()->GetGameObject(guid)) + gameObject->DespawnOrUnsummon(); + + for (ObjectGuid const& guid : _doors) + { + if (GameObject* gameObject = GetBgMap()->GetGameObject(guid)) + { + gameObject->UseDoorOrButton(); + gameObject->DespawnOrUnsummon(3s); + } + } + break; } + case AB_EVENT_CONTESTED_BLACKSMITH_ALLIANCE: + UpdateWorldState(BG_AB_WS_BLACKSMITH_ALLIANCE_CONTROL_STATE, 1); + UpdateWorldState(BG_AB_WS_BLACKSMITH_HORDE_CONTROL_STATE, 0); + PlaySoundToAll(BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE); + if (Player* player = invoker->ToPlayer()) + UpdatePlayerScore(player, SCORE_BASES_ASSAULTED, 1); + break; + case AB_EVENT_DEFENDED_BLACKSMITH_ALLIANCE: + UpdateWorldState(BG_AB_WS_BLACKSMITH_ALLIANCE_CONTROL_STATE, 2); + UpdateWorldState(BG_AB_WS_BLACKSMITH_HORDE_CONTROL_STATE, 0); + PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_ALLIANCE); + if (Player* player = invoker->ToPlayer()) + UpdatePlayerScore(player, SCORE_BASES_DEFENDED, 1); + break; + case AB_EVENT_CAPTURE_BLACKSMITH_ALLIANCE: + UpdateWorldState(BG_AB_WS_BLACKSMITH_ALLIANCE_CONTROL_STATE, 2); + PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_ALLIANCE); + break; + case AB_EVENT_CONTESTED_BLACKSMITH_HORDE: + UpdateWorldState(BG_AB_WS_BLACKSMITH_ALLIANCE_CONTROL_STATE, 0); + UpdateWorldState(BG_AB_WS_BLACKSMITH_HORDE_CONTROL_STATE, 1); + PlaySoundToAll(BG_AB_SOUND_NODE_ASSAULTED_HORDE); + if (Player* player = invoker->ToPlayer()) + UpdatePlayerScore(player, SCORE_BASES_ASSAULTED, 1); + break; + case AB_EVENT_DEFENDED_BLACKSMITH_HORDE: + UpdateWorldState(BG_AB_WS_BLACKSMITH_ALLIANCE_CONTROL_STATE, 0); + UpdateWorldState(BG_AB_WS_BLACKSMITH_HORDE_CONTROL_STATE, 2); + PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_HORDE); + if (Player* player = invoker->ToPlayer()) + UpdatePlayerScore(player, SCORE_BASES_DEFENDED, 1); + break; + case AB_EVENT_CAPTURE_BLACKSMITH_HORDE: + UpdateWorldState(BG_AB_WS_BLACKSMITH_HORDE_CONTROL_STATE, 2); + PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_HORDE); + break; + case AB_EVENT_CONTESTED_FARM_ALLIANCE: + UpdateWorldState(BG_AB_WS_FARM_ALLIANCE_CONTROL_STATE, 1); + UpdateWorldState(BG_AB_WS_FARM_HORDE_CONTROL_STATE, 0); + PlaySoundToAll(BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE); + if (Player* player = invoker->ToPlayer()) + UpdatePlayerScore(player, SCORE_BASES_ASSAULTED, 1); + break; + case AB_EVENT_DEFENDED_FARM_ALLIANCE: + UpdateWorldState(BG_AB_WS_FARM_ALLIANCE_CONTROL_STATE, 2); + UpdateWorldState(BG_AB_WS_FARM_HORDE_CONTROL_STATE, 0); + PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_ALLIANCE); + if (Player* player = invoker->ToPlayer()) + UpdatePlayerScore(player, SCORE_BASES_DEFENDED, 1); + break; + case AB_EVENT_CAPTURE_FARM_ALLIANCE: + UpdateWorldState(BG_AB_WS_FARM_ALLIANCE_CONTROL_STATE, 2); + PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_ALLIANCE); + break; + case AB_EVENT_CONTESTED_FARM_HORDE: + UpdateWorldState(BG_AB_WS_FARM_ALLIANCE_CONTROL_STATE, 0); + UpdateWorldState(BG_AB_WS_FARM_HORDE_CONTROL_STATE, 1); + PlaySoundToAll(BG_AB_SOUND_NODE_ASSAULTED_HORDE); + if (Player* player = invoker->ToPlayer()) + UpdatePlayerScore(player, SCORE_BASES_ASSAULTED, 1); + break; + case AB_EVENT_DEFENDED_FARM_HORDE: + UpdateWorldState(BG_AB_WS_FARM_ALLIANCE_CONTROL_STATE, 0); + UpdateWorldState(BG_AB_WS_FARM_HORDE_CONTROL_STATE, 2); + PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_HORDE); + if (Player* player = invoker->ToPlayer()) + UpdatePlayerScore(player, SCORE_BASES_DEFENDED, 1); + break; + case AB_EVENT_CAPTURE_FARM_HORDE: + UpdateWorldState(BG_AB_WS_FARM_HORDE_CONTROL_STATE, 2); + PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_HORDE); + break; + case AB_EVENT_CONTESTED_GOLD_MINE_ALLIANCE: + UpdateWorldState(BG_AB_WS_GOLD_MINE_ALLIANCE_CONTROL_STATE, 1); + UpdateWorldState(BG_AB_WS_GOLD_MINE_HORDE_CONTROL_STATE, 0); + PlaySoundToAll(BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE); + if (Player* player = invoker->ToPlayer()) + UpdatePlayerScore(player, SCORE_BASES_ASSAULTED, 1); + break; + case AB_EVENT_DEFENDED_GOLD_MINE_ALLIANCE: + UpdateWorldState(BG_AB_WS_GOLD_MINE_ALLIANCE_CONTROL_STATE, 2); + UpdateWorldState(BG_AB_WS_GOLD_MINE_HORDE_CONTROL_STATE, 0); + PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_ALLIANCE); + if (Player* player = invoker->ToPlayer()) + UpdatePlayerScore(player, SCORE_BASES_DEFENDED, 1); + break; + case AB_EVENT_CAPTURE_GOLD_MINE_ALLIANCE: + UpdateWorldState(BG_AB_WS_GOLD_MINE_ALLIANCE_CONTROL_STATE, 2); + PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_ALLIANCE); + break; + case AB_EVENT_CONTESTED_GOLD_MINE_HORDE: + UpdateWorldState(BG_AB_WS_GOLD_MINE_ALLIANCE_CONTROL_STATE, 0); + UpdateWorldState(BG_AB_WS_GOLD_MINE_HORDE_CONTROL_STATE, 1); + PlaySoundToAll(BG_AB_SOUND_NODE_ASSAULTED_HORDE); + if (Player* player = invoker->ToPlayer()) + UpdatePlayerScore(player, SCORE_BASES_ASSAULTED, 1); + break; + case AB_EVENT_DEFENDED_GOLD_MINE_HORDE: + UpdateWorldState(BG_AB_WS_GOLD_MINE_ALLIANCE_CONTROL_STATE, 0); + UpdateWorldState(BG_AB_WS_GOLD_MINE_HORDE_CONTROL_STATE, 2); + PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_HORDE); + if (Player* player = invoker->ToPlayer()) + UpdatePlayerScore(player, SCORE_BASES_DEFENDED, 1); + break; + case AB_EVENT_CAPTURE_GOLD_MINE_HORDE: + UpdateWorldState(BG_AB_WS_GOLD_MINE_HORDE_CONTROL_STATE, 2); + PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_HORDE); + break; + case AB_EVENT_CONTESTED_LUMBER_MILL_ALLIANCE: + UpdateWorldState(BG_AB_WS_LUMBER_MILL_ALLIANCE_CONTROL_STATE, 1); + UpdateWorldState(BG_AB_WS_LUMBER_MILL_HORDE_CONTROL_STATE, 0); + PlaySoundToAll(BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE); + if (Player* player = invoker->ToPlayer()) + UpdatePlayerScore(player, SCORE_BASES_ASSAULTED, 1); + break; + case AB_EVENT_DEFENDED_LUMBER_MILL_ALLIANCE: + UpdateWorldState(BG_AB_WS_LUMBER_MILL_ALLIANCE_CONTROL_STATE, 2); + UpdateWorldState(BG_AB_WS_LUMBER_MILL_HORDE_CONTROL_STATE, 0); + PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_ALLIANCE); + if (Player* player = invoker->ToPlayer()) + UpdatePlayerScore(player, SCORE_BASES_DEFENDED, 1); + break; + case AB_EVENT_CAPTURE_LUMBER_MILL_ALLIANCE: + UpdateWorldState(BG_AB_WS_LUMBER_MILL_ALLIANCE_CONTROL_STATE, 2); + PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_ALLIANCE); + break; + case AB_EVENT_CONTESTED_LUMBER_MILL_HORDE: + UpdateWorldState(BG_AB_WS_LUMBER_MILL_ALLIANCE_CONTROL_STATE, 0); + UpdateWorldState(BG_AB_WS_LUMBER_MILL_HORDE_CONTROL_STATE, 1); + PlaySoundToAll(BG_AB_SOUND_NODE_ASSAULTED_HORDE); + if (Player* player = invoker->ToPlayer()) + UpdatePlayerScore(player, SCORE_BASES_ASSAULTED, 1); + break; + case AB_EVENT_DEFENDED_LUMBER_MILL_HORDE: + UpdateWorldState(BG_AB_WS_LUMBER_MILL_ALLIANCE_CONTROL_STATE, 0); + UpdateWorldState(BG_AB_WS_LUMBER_MILL_HORDE_CONTROL_STATE, 2); + PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_HORDE); + if (Player* player = invoker->ToPlayer()) + UpdatePlayerScore(player, SCORE_BASES_DEFENDED, 1); + break; + case AB_EVENT_CAPTURE_LUMBER_MILL_HORDE: + UpdateWorldState(BG_AB_WS_LUMBER_MILL_HORDE_CONTROL_STATE, 2); + PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_HORDE); + break; + case AB_EVENT_CONTESTED_STABLES_ALLIANCE: + UpdateWorldState(BG_AB_WS_STABLES_ALLIANCE_CONTROL_STATE, 1); + UpdateWorldState(BG_AB_WS_STABLES_HORDE_CONTROL_STATE, 0); + PlaySoundToAll(BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE); + if (Player* player = invoker->ToPlayer()) + UpdatePlayerScore(player, SCORE_BASES_ASSAULTED, 1); + break; + case AB_EVENT_DEFENDED_STABLES_ALLIANCE: + UpdateWorldState(BG_AB_WS_STABLES_ALLIANCE_CONTROL_STATE, 2); + UpdateWorldState(BG_AB_WS_STABLES_HORDE_CONTROL_STATE, 0); + PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_ALLIANCE); + if (Player* player = invoker->ToPlayer()) + UpdatePlayerScore(player, SCORE_BASES_DEFENDED, 1); + break; + case AB_EVENT_CAPTURE_STABLES_ALLIANCE: + UpdateWorldState(BG_AB_WS_STABLES_ALLIANCE_CONTROL_STATE, 2); + PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_ALLIANCE); + break; + case AB_EVENT_CONTESTED_STABLES_HORDE: + UpdateWorldState(BG_AB_WS_STABLES_ALLIANCE_CONTROL_STATE, 0); + UpdateWorldState(BG_AB_WS_STABLES_HORDE_CONTROL_STATE, 1); + PlaySoundToAll(BG_AB_SOUND_NODE_ASSAULTED_HORDE); + if (Player* player = invoker->ToPlayer()) + UpdatePlayerScore(player, SCORE_BASES_ASSAULTED, 1); + break; + case AB_EVENT_DEFENDED_STABLES_HORDE: + UpdateWorldState(BG_AB_WS_STABLES_ALLIANCE_CONTROL_STATE, 0); + UpdateWorldState(BG_AB_WS_STABLES_HORDE_CONTROL_STATE, 2); + PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_HORDE); + if (Player* player = invoker->ToPlayer()) + UpdatePlayerScore(player, SCORE_BASES_DEFENDED, 1); + break; + case AB_EVENT_CAPTURE_STABLES_HORDE: + UpdateWorldState(BG_AB_WS_STABLES_HORDE_CONTROL_STATE, 2); + PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_HORDE); + break; + default: + TC_LOG_WARN("bg.events", "BattlegroundAB::ProcessEvent: Unhandled event %u.", eventId); + break; } +} - if (!AddObject(BG_AB_OBJECT_GATE_A, BG_AB_OBJECTID_GATE_A, BG_AB_DoorPositions[0][0], BG_AB_DoorPositions[0][1], BG_AB_DoorPositions[0][2], BG_AB_DoorPositions[0][3], BG_AB_DoorPositions[0][4], BG_AB_DoorPositions[0][5], BG_AB_DoorPositions[0][6], BG_AB_DoorPositions[0][7], RESPAWN_IMMEDIATELY) - || !AddObject(BG_AB_OBJECT_GATE_H, BG_AB_OBJECTID_GATE_H, BG_AB_DoorPositions[1][0], BG_AB_DoorPositions[1][1], BG_AB_DoorPositions[1][2], BG_AB_DoorPositions[1][3], BG_AB_DoorPositions[1][4], BG_AB_DoorPositions[1][5], BG_AB_DoorPositions[1][6], BG_AB_DoorPositions[1][7], RESPAWN_IMMEDIATELY)) +void BattlegroundAB::OnCreatureCreate(Creature* creature) +{ + switch (creature->GetEntry()) { - TC_LOG_ERROR("sql.sql", "BatteGroundAB: Failed to spawn door object Battleground not created!"); - return false; + case BG_AB_NPC_THE_BLACK_BRIDE: + case BG_AB_NPC_RADULF_LEDER: + _creaturesToRemoveOnMatchStart.push_back(creature->GetGUID()); + break; + default: + break; } +} - //buffs - for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) +void BattlegroundAB::OnGameObjectCreate(GameObject* gameObject) +{ + if (gameObject->GetGOInfo()->type == GAMEOBJECT_TYPE_CAPTURE_POINT) + _capturePoints.push_back(gameObject->GetGUID()); + + switch (gameObject->GetEntry()) { - if (!AddObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + 3 * i, Buff_Entries[0], BG_AB_BuffPositions[i][0], BG_AB_BuffPositions[i][1], BG_AB_BuffPositions[i][2], BG_AB_BuffPositions[i][3], 0, 0, std::sin(BG_AB_BuffPositions[i][3]/2), std::cos(BG_AB_BuffPositions[i][3]/2), RESPAWN_ONE_DAY) - || !AddObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + 3 * i + 1, Buff_Entries[1], BG_AB_BuffPositions[i][0], BG_AB_BuffPositions[i][1], BG_AB_BuffPositions[i][2], BG_AB_BuffPositions[i][3], 0, 0, std::sin(BG_AB_BuffPositions[i][3]/2), std::cos(BG_AB_BuffPositions[i][3]/2), RESPAWN_ONE_DAY) - || !AddObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + 3 * i + 2, Buff_Entries[2], BG_AB_BuffPositions[i][0], BG_AB_BuffPositions[i][1], BG_AB_BuffPositions[i][2], BG_AB_BuffPositions[i][3], 0, 0, std::sin(BG_AB_BuffPositions[i][3]/2), std::cos(BG_AB_BuffPositions[i][3]/2), RESPAWN_ONE_DAY)) - TC_LOG_ERROR("sql.sql", "BatteGroundAB: Failed to spawn buff object!"); + case BG_AB_OBJECTID_GHOST_GATE: + _gameobjectsToRemoveOnMatchStart.push_back(gameObject->GetGUID()); + break; + case BG_AB_OBJECTID_ALLIANCE_DOOR: + case BG_AB_OBJECTID_HORDE_DOOR: + _doors.push_back(gameObject->GetGUID()); + break; + default: + break; } +} +bool BattlegroundAB::SetupBattleground() +{ UpdateWorldState(BG_AB_WS_RESOURCES_MAX, BG_AB_MAX_TEAM_SCORE); UpdateWorldState(BG_AB_WS_RESOURCES_WARNING, BG_AB_WARNING_NEAR_VICTORY_SCORE); @@ -587,8 +471,7 @@ void BattlegroundAB::Reset() m_TeamScores[TEAM_ALLIANCE] = 0; m_TeamScores[TEAM_HORDE] = 0; - m_lastTick[TEAM_ALLIANCE] = 0; - m_lastTick[TEAM_HORDE] = 0; + m_lastTick = 0; m_HonorScoreTics[TEAM_ALLIANCE] = 0; m_HonorScoreTics[TEAM_HORDE] = 0; m_ReputationScoreTics[TEAM_ALLIANCE] = 0; @@ -598,17 +481,10 @@ void BattlegroundAB::Reset() m_HonorTics = (isBGWeekend) ? BG_AB_ABBGWeekendHonorTicks : BG_AB_NotABBGWeekendHonorTicks; m_ReputationTics = (isBGWeekend) ? BG_AB_ABBGWeekendReputationTicks : BG_AB_NotABBGWeekendReputationTicks; - for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) - { - m_Nodes[i] = 0; - m_prevNodes[i] = 0; - m_NodeTimers[i] = 0; - m_BannerTimers[i].timer = 0; - } - - for (uint8 i = 0; i < BG_AB_ALL_NODES_COUNT + 5; ++i)//+5 for aura triggers - if (!BgCreatures[i].IsEmpty()) - DelCreature(i); + _creaturesToRemoveOnMatchStart.clear(); + _gameobjectsToRemoveOnMatchStart.clear(); + _doors.clear(); + _capturePoints.clear(); } void BattlegroundAB::EndBattleground(uint32 winner) @@ -627,41 +503,7 @@ void BattlegroundAB::EndBattleground(uint32 winner) WorldSafeLocsEntry const* BattlegroundAB::GetClosestGraveyard(Player* player) { - TeamId teamIndex = GetTeamIndexByTeamId(GetPlayerTeam(player->GetGUID())); - - // Is there any occupied node for this team? - std::vector<uint8> nodes; - for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) - if (m_Nodes[i] == teamIndex + 3) - nodes.push_back(i); - - WorldSafeLocsEntry const* good_entry = nullptr; - // 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 (uint8 i = 0; i < nodes.size(); ++i) - { - WorldSafeLocsEntry const* entry = sObjectMgr->GetWorldSafeLoc(BG_AB_GraveyardIds[nodes[i]]); - if (!entry) - 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) - good_entry = sObjectMgr->GetWorldSafeLoc(BG_AB_GraveyardIds[teamIndex+5]); - - return good_entry; + return sObjectMgr->GetClosestGraveyard(player->GetWorldLocation(), player->GetTeam(), player); } WorldSafeLocsEntry const* BattlegroundAB::GetExploitTeleportLocation(Team team) diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAB.h b/src/server/game/Battlegrounds/Zones/BattlegroundAB.h index 5bdf9fb159b..19c786b3614 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.h @@ -78,77 +78,29 @@ enum BG_AB_WorldStates BG_AB_WS_STABLES_ALLIANCE_CONTROL_STATE = 17322, }; -const int32 BG_AB_OP_NODESTATES[5] = {1767, 1782, 1772, 1792, 1787}; - -const int32 BG_AB_OP_NODEICONS[5] = {1842, 1846, 1845, 1844, 1843}; - -/* Note: code uses that these IDs follow each other */ -enum BG_AB_NodeObjectId -{ - BG_AB_OBJECTID_NODE_BANNER_0 = 180087, // Stables banner - BG_AB_OBJECTID_NODE_BANNER_1 = 180088, // Blacksmith banner - BG_AB_OBJECTID_NODE_BANNER_2 = 180089, // Farm banner - BG_AB_OBJECTID_NODE_BANNER_3 = 180090, // Lumber mill banner - BG_AB_OBJECTID_NODE_BANNER_4 = 180091 // Gold mine banner -}; - -enum BG_AB_ObjectType -{ - // for all 5 node points 8*5=40 objects - BG_AB_OBJECT_BANNER_NEUTRAL = 0, - BG_AB_OBJECT_BANNER_CONT_A = 1, - BG_AB_OBJECT_BANNER_CONT_H = 2, - BG_AB_OBJECT_BANNER_ALLY = 3, - BG_AB_OBJECT_BANNER_HORDE = 4, - BG_AB_OBJECT_AURA_ALLY = 5, - BG_AB_OBJECT_AURA_HORDE = 6, - BG_AB_OBJECT_AURA_CONTESTED = 7, - //gates - BG_AB_OBJECT_GATE_A = 40, - BG_AB_OBJECT_GATE_H = 41, - //buffs - BG_AB_OBJECT_SPEEDBUFF_STABLES = 42, - BG_AB_OBJECT_REGENBUFF_STABLES = 43, - BG_AB_OBJECT_BERSERKBUFF_STABLES = 44, - BG_AB_OBJECT_SPEEDBUFF_BLACKSMITH = 45, - BG_AB_OBJECT_REGENBUFF_BLACKSMITH = 46, - BG_AB_OBJECT_BERSERKBUFF_BLACKSMITH = 47, - BG_AB_OBJECT_SPEEDBUFF_FARM = 48, - BG_AB_OBJECT_REGENBUFF_FARM = 49, - BG_AB_OBJECT_BERSERKBUFF_FARM = 50, - BG_AB_OBJECT_SPEEDBUFF_LUMBER_MILL = 51, - BG_AB_OBJECT_REGENBUFF_LUMBER_MILL = 52, - BG_AB_OBJECT_BERSERKBUFF_LUMBER_MILL = 53, - BG_AB_OBJECT_SPEEDBUFF_GOLD_MINE = 54, - BG_AB_OBJECT_REGENBUFF_GOLD_MINE = 55, - BG_AB_OBJECT_BERSERKBUFF_GOLD_MINE = 56, - BG_AB_OBJECT_MAX = 57 -}; - /* Object id templates from DB */ enum BG_AB_ObjectTypes { - BG_AB_OBJECTID_BANNER_A = 180058, - BG_AB_OBJECTID_BANNER_CONT_A = 180059, - BG_AB_OBJECTID_BANNER_H = 180060, - BG_AB_OBJECTID_BANNER_CONT_H = 180061, - - BG_AB_OBJECTID_AURA_A = 180100, - BG_AB_OBJECTID_AURA_H = 180101, - BG_AB_OBJECTID_AURA_C = 180102, - - BG_AB_OBJECTID_GATE_A = 180255, - BG_AB_OBJECTID_GATE_H = 180256 + BG_AB_OBJECTID_CAPTURE_POINT_STABLES = 227420, + BG_AB_OBJECTID_CAPTURE_POINT_BLACKSMITH = 227522, + BG_AB_OBJECTID_CAPTURE_POINT_FARM = 227536, + BG_AB_OBJECTID_CAPTURE_POINT_GOLD_MINE = 227538, + BG_AB_OBJECTID_CAPTURE_POINT_LUMBER_MILL = 227544, + + BG_AB_OBJECTID_GHOST_GATE = 180322, + BG_AB_OBJECTID_ALLIANCE_DOOR = 322273, + BG_AB_OBJECTID_HORDE_DOOR = 322274 }; -enum BG_AB_Timers +enum BG_AB_Creatures { - BG_AB_FLAG_CAPTURING_TIME = 60000 + BG_AB_NPC_THE_BLACK_BRIDE = 150501, + BG_AB_NPC_RADULF_LEDER = 150505 }; enum BG_AB_Score { - BG_AB_WARNING_NEAR_VICTORY_SCORE = 1400, + BG_AB_WARNING_NEAR_VICTORY_SCORE = 1200, BG_AB_MAX_TEAM_SCORE = 1500 }; @@ -175,39 +127,6 @@ enum BG_AB_BroadcastTexts BG_AB_TEXT_HORDE_NEAR_VICTORY = 10599, }; -struct ABNodeInfo -{ - uint32 NodeId; - uint32 TextAllianceAssaulted; - uint32 TextHordeAssaulted; - uint32 TextAllianceTaken; - uint32 TextHordeTaken; - uint32 TextAllianceDefended; - uint32 TextHordeDefended; - uint32 TextAllianceClaims; - uint32 TextHordeClaims; -}; - -ABNodeInfo const ABNodes[BG_AB_DYNAMIC_NODES_COUNT] = -{ - { BG_AB_NODE_STABLES, 10199, 10200, 10203, 10204, 10201, 10202, 10286, 10287 }, - { BG_AB_NODE_BLACKSMITH, 10211, 10212, 10213, 10214, 10215, 10216, 10290, 10291 }, - { BG_AB_NODE_FARM, 10217, 10218, 10219, 10220, 10221, 10222, 10288, 10289 }, - { BG_AB_NODE_LUMBER_MILL, 10224, 10225, 10226, 10227, 10228, 10229, 10284, 10285 }, - { BG_AB_NODE_GOLD_MINE, 10230, 10231, 10232, 10233, 10234, 10235, 10282, 10283 } -}; - -enum BG_AB_NodeStatus -{ - BG_AB_NODE_TYPE_NEUTRAL = 0, - BG_AB_NODE_TYPE_CONTESTED = 1, - BG_AB_NODE_STATUS_ALLY_CONTESTED = 1, - BG_AB_NODE_STATUS_HORDE_CONTESTED = 2, - BG_AB_NODE_TYPE_OCCUPIED = 3, - BG_AB_NODE_STATUS_ALLY_OCCUPIED = 3, - BG_AB_NODE_STATUS_HORDE_OCCUPIED = 4 -}; - enum BG_AB_Sounds { BG_AB_SOUND_NODE_CLAIMED = 8192, @@ -221,14 +140,14 @@ enum BG_AB_Sounds enum BG_AB_Objectives { - AB_OBJECTIVE_ASSAULT_BASE = 122, - AB_OBJECTIVE_DEFEND_BASE = 123 + AB_OBJECTIVE_ASSAULT_BASE = 926, + AB_OBJECTIVE_DEFEND_BASE = 927 }; enum BG_AB_ExploitTeleportLocations { - AB_EXPLOIT_TELEPORT_LOCATION_ALLIANCE = 3705, - AB_EXPLOIT_TELEPORT_LOCATION_HORDE = 3706 + AB_EXPLOIT_TELEPORT_LOCATION_ALLIANCE = 7056, + AB_EXPLOIT_TELEPORT_LOCATION_HORDE = 7055 }; #define BG_AB_NotABBGWeekendHonorTicks 260 @@ -236,57 +155,71 @@ enum BG_AB_ExploitTeleportLocations #define BG_AB_NotABBGWeekendReputationTicks 160 #define BG_AB_ABBGWeekendReputationTicks 120 -#define AB_EVENT_START_BATTLE 9158 // Achievement: Let's Get This Done - -Position const BG_AB_NodePositions[BG_AB_DYNAMIC_NODES_COUNT] = -{ - {1166.785f, 1200.132f, -56.70859f, 0.9075713f}, // stables - {977.0156f, 1046.616f, -44.80923f, -2.600541f}, // blacksmith - {806.1821f, 874.2723f, -55.99371f, -2.303835f}, // farm - {856.1419f, 1148.902f, 11.18469f, -2.303835f}, // lumber mill - {1146.923f, 848.1782f, -110.917f, -0.7330382f} // gold mine -}; - -// x, y, z, o, rot0, rot1, rot2, rot3 -const float BG_AB_DoorPositions[2][8] = +enum BG_AB_Events { - {1284.597f, 1281.167f, -15.97792f, 0.7068594f, 0.012957f, -0.060288f, 0.344959f, 0.93659f}, - {708.0903f, 708.4479f, -17.8342f, -2.391099f, 0.050291f, 0.015127f, 0.929217f, -0.365784f} + AB_EVENT_START_BATTLE = 9158, // Achievement: Let's Get This Done + + AB_EVENT_CONTESTED_STABLES_HORDE = 28523, + AB_EVENT_CAPTURE_STABLES_HORDE = 28527, + AB_EVENT_DEFENDED_STABLES_HORDE = 28525, + AB_EVENT_CONTESTED_STABLES_ALLIANCE = 28522, + AB_EVENT_CAPTURE_STABLES_ALLIANCE = 28526, + AB_EVENT_DEFENDED_STABLES_ALLIANCE = 28524, + + AB_EVENT_CONTESTED_BLACKSMITH_HORDE = 8876, + AB_EVENT_CAPTURE_BLACKSMITH_HORDE = 8773, + AB_EVENT_DEFENDED_BLACKSMITH_HORDE = 8770, + AB_EVENT_CONTESTED_BLACKSMITH_ALLIANCE = 8874, + AB_EVENT_CAPTURE_BLACKSMITH_ALLIANCE = 8769, + AB_EVENT_DEFENDED_BLACKSMITH_ALLIANCE = 8774, + + AB_EVENT_CONTESTED_FARM_HORDE = 39398, + AB_EVENT_CAPTURE_FARM_HORDE = 39399, + AB_EVENT_DEFENDED_FARM_HORDE = 39400, + AB_EVENT_CONTESTED_FARM_ALLIANCE = 39401, + AB_EVENT_CAPTURE_FARM_ALLIANCE = 39402, + AB_EVENT_DEFENDED_FARM_ALLIANCE = 39403, + + AB_EVENT_CONTESTED_GOLD_MINE_HORDE = 39404, + AB_EVENT_CAPTURE_GOLD_MINE_HORDE = 39405, + AB_EVENT_DEFENDED_GOLD_MINE_HORDE = 39406, + AB_EVENT_CONTESTED_GOLD_MINE_ALLIANCE = 39407, + AB_EVENT_CAPTURE_GOLD_MINE_ALLIANCE = 39408, + AB_EVENT_DEFENDED_GOLD_MINE_ALLIANCE = 39409, + + AB_EVENT_CONTESTED_LUMBER_MILL_HORDE = 39387, + AB_EVENT_CAPTURE_LUMBER_MILL_HORDE = 39388, + AB_EVENT_DEFENDED_LUMBER_MILL_HORDE = 39389, + AB_EVENT_CONTESTED_LUMBER_MILL_ALLIANCE = 39390, + AB_EVENT_CAPTURE_LUMBER_MILL_ALLIANCE = 39391, + AB_EVENT_DEFENDED_LUMBER_MILL_ALLIANCE = 39392 }; // Tick intervals and given points: case 0, 1, 2, 3, 4, 5 captured nodes -const uint32 BG_AB_TickIntervals[6] = {0, 12000, 9000, 6000, 3000, 1000}; -const uint32 BG_AB_TickPoints[6] = {0, 10, 10, 10, 10, 30}; +const uint32 BG_AB_TickInterval = 2000; +const uint32 BG_AB_TickPoints[6] = { 0, 2, 3, 4, 7, 60 }; // WorldSafeLocs ids for 5 nodes, and for ally, and horde starting location -const uint32 BG_AB_GraveyardIds[BG_AB_ALL_NODES_COUNT] = {895, 894, 893, 897, 896, 898, 899}; - -// x, y, z, o -const float BG_AB_BuffPositions[BG_AB_DYNAMIC_NODES_COUNT][4] = -{ - {1185.566f, 1184.629f, -56.36329f, 2.303831f}, // stables - {990.1131f, 1008.73f, -42.60328f, 0.8203033f}, // blacksmith - {818.0089f, 842.3543f, -56.54062f, 3.176533f}, // farm - {808.8463f, 1185.417f, 11.92161f, 5.619962f}, // lumber mill - {1147.091f, 816.8362f, -98.39896f, 6.056293f} // gold mine -}; - -Position const BG_AB_SpiritGuidePos[BG_AB_ALL_NODES_COUNT] = +enum BG_AB_Graveyards { - {1200.03f, 1171.09f, -56.47f, 5.15f}, // stables - {1017.43f, 960.61f, -42.95f, 4.88f}, // blacksmith - {833.00f, 793.00f, -57.25f, 5.27f}, // farm - {775.17f, 1206.40f, 15.79f, 1.90f}, // lumber mill - {1207.48f, 787.00f, -83.36f, 5.51f}, // gold mine - {1354.05f, 1275.48f, -11.30f, 4.77f}, // alliance starting base - {714.61f, 646.15f, -10.87f, 4.34f} // horde starting base + AB_GRAVEYARD_ALLIANCE_BASE = 7251, + AB_GRAVEYARD_STABLES = 7252, + AB_GRAVEYARD_GOLD_MINE = 7253, + AB_GRAVEYARD_LUMBER_MILL = 7254, + AB_GRAVEYARD_HORDE_BASE = 7255, + AB_GRAVEYARD_FARM = 7256, + AB_GRAVEYARD_BLACKSMITH = 7257 }; -struct BG_AB_BannerTimer +const uint32 BG_AB_GraveyardIds[BG_AB_ALL_NODES_COUNT] = { - uint32 timer; - uint8 type; - uint8 teamIndex; + AB_GRAVEYARD_STABLES, + AB_GRAVEYARD_BLACKSMITH, + AB_GRAVEYARD_FARM, + AB_GRAVEYARD_LUMBER_MILL, + AB_GRAVEYARD_GOLD_MINE, + AB_GRAVEYARD_ALLIANCE_BASE, + AB_GRAVEYARD_HORDE_BASE }; struct BattlegroundABScore final : public BattlegroundScore @@ -334,7 +267,6 @@ class BattlegroundAB : public Battleground ~BattlegroundAB(); void AddPlayer(Player* player) override; - void StartingEventCloseDoors() override; void StartingEventOpenDoors() override; void RemovePlayer(Player* player, ObjectGuid guid, uint32 team) override; void HandleAreaTrigger(Player* source, uint32 trigger, bool entered) override; @@ -347,37 +279,27 @@ class BattlegroundAB : public Battleground /* Scorekeeping */ bool UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override; - /* Nodes occupying */ - void EventPlayerClickedOnFlag(Player* source, GameObject* target_obj) override; - uint32 GetPrematureWinner() override; + + void ProcessEvent(WorldObject* obj, uint32 eventId, WorldObject* invoker = nullptr) override; + + void OnCreatureCreate(Creature* creature) override; + void OnGameObjectCreate(GameObject* gameObject) override; private: void PostUpdateImpl(uint32 diff) override; - /* Gameobject spawning/despawning */ - void _CreateBanner(uint8 node, uint8 type, uint8 teamIndex, bool delay); - void _DelBanner(uint8 node, uint8 type, uint8 teamIndex); - void _SendNodeUpdate(uint8 node); - - /* Creature spawning/despawning */ - /// @todo working, scripted peons spawning - void _NodeOccupied(uint8 node, Team team); - void _NodeDeOccupied(uint8 node); - - /* Nodes info: - 0: neutral - 1: ally contested - 2: horde contested - 3: ally occupied - 4: horde occupied */ - uint8 m_Nodes[BG_AB_DYNAMIC_NODES_COUNT]; - uint8 m_prevNodes[BG_AB_DYNAMIC_NODES_COUNT]; - BG_AB_BannerTimer m_BannerTimers[BG_AB_DYNAMIC_NODES_COUNT]; - uint32 m_NodeTimers[BG_AB_DYNAMIC_NODES_COUNT]; - uint32 m_lastTick[PVP_TEAMS_COUNT]; + + void _CalculateTeamNodes(uint8& alliance, uint8& horde); + + uint32 m_lastTick; uint32 m_HonorScoreTics[PVP_TEAMS_COUNT]; uint32 m_ReputationScoreTics[PVP_TEAMS_COUNT]; bool m_IsInformedNearVictory; uint32 m_HonorTics; uint32 m_ReputationTics; + + GuidVector _gameobjectsToRemoveOnMatchStart; + GuidVector _creaturesToRemoveOnMatchStart; + GuidVector _doors; + GuidVector _capturePoints; }; #endif diff --git a/src/server/scripts/EasternKingdoms/ArathiBasin/arathi_basin.cpp b/src/server/scripts/EasternKingdoms/ArathiBasin/arathi_basin.cpp new file mode 100644 index 00000000000..f3d6a928d91 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ArathiBasin/arathi_basin.cpp @@ -0,0 +1,83 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "Map.h" +#include "MotionMaster.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" + +enum ArathiBasinGryphonBatRiderLeaderData +{ + PATH_GRYPHON_RIDER_LEADER = 800000059, + PATH_BAT_RIDER_LEADER = 800000058, +}; + +// 150513 - Arathor Gryphon Rider +// 150459 - Defiler Bat Rider +template<uint32 Path> +struct npc_bg_ab_gryphon_bat_rider_leader : public ScriptedAI +{ + npc_bg_ab_gryphon_bat_rider_leader(Creature* creature) : ScriptedAI(creature) { } + + void WaypointPathEnded(uint32 /*nodeId*/, uint32 pathId) override + { + if (pathId != Path) + return; + + // despawn formation group + std::list<Creature*> followers; + me->GetCreatureListWithEntryInGrid(followers, me->GetEntry()); + for (Creature* follower : followers) + follower->DespawnOrUnsummon(500ms); + + me->DespawnOrUnsummon(500ms); + } +}; + +// 261985 - Blacksmith Working +class spell_bg_ab_blacksmith_working : public AuraScript +{ + PrepareAuraScript(spell_bg_ab_blacksmith_working); + + static constexpr uint32 ITEM_BLACKSMITH_HAMMER = 5956; + + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->SetVirtualItem(0, ITEM_BLACKSMITH_HAMMER); + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Creature* creature = GetTarget()->ToCreature()) + creature->LoadEquipment(creature->GetOriginalEquipmentId()); + } + + void Register() override + { + AfterEffectApply += AuraEffectRemoveFn(spell_bg_ab_blacksmith_working::OnApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_bg_ab_blacksmith_working::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } +}; + +void AddSC_arathi_basin() +{ + new GenericCreatureScript<npc_bg_ab_gryphon_bat_rider_leader<PATH_GRYPHON_RIDER_LEADER>>("npc_bg_ab_arathor_gryphon_rider_leader"); + new GenericCreatureScript<npc_bg_ab_gryphon_bat_rider_leader<PATH_BAT_RIDER_LEADER>>("npc_bg_ab_defiler_bat_rider_leader"); + + RegisterSpellScript(spell_bg_ab_blacksmith_working); +} diff --git a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp index d300c894b33..128880dd0f8 100644 --- a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp +++ b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp @@ -21,6 +21,7 @@ void AddSC_boss_balinda(); void AddSC_boss_drekthar(); void AddSC_boss_galvangar(); void AddSC_boss_vanndar(); +void AddSC_arathi_basin(); //Arathi Basin void AddSC_boss_alizabal(); //Baradin Hold void AddSC_boss_occuthar(); void AddSC_boss_pit_lord_argaloth(); @@ -213,6 +214,7 @@ void AddEasternKingdomsScripts() AddSC_boss_drekthar(); AddSC_boss_galvangar(); AddSC_boss_vanndar(); + AddSC_arathi_basin(); //Arathi Basin AddSC_boss_alizabal(); //Baradin Hold AddSC_boss_occuthar(); AddSC_boss_pit_lord_argaloth(); |