Core/Battlegrounds: Implement Arathi Basin from Battle for Azeroth (#28369)

Co-authored-by: ModoX <[email protected]>
This commit is contained in:
Jeremy
2023-07-05 23:52:22 +02:00
committed by GitHub
co-authored by ModoX
parent d70d1d24a5
commit cc08aa8e24
5 changed files with 3492 additions and 607 deletions
File diff suppressed because it is too large Load Diff
@@ -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)
alliance = 0;
horde = 0;
if (BattlegroundMap* map = FindBgMap())
{
m_BannerTimers[node].timer = 2000;
m_BannerTimers[node].type = type;
m_BannerTimers[node].teamIndex = teamIndex;
return;
}
uint8 obj = node*8 + type + teamIndex;
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)
{
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)
for (ObjectGuid const& guid : _capturePoints)
{
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 (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;
}
}
}
// If contested, change back to occupied
else
{
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);
}
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();
}
void BattlegroundAB::ProcessEvent(WorldObject* /*source*/, uint32 eventId, WorldObject* invoker)
{
switch (eventId)
{
case AB_EVENT_START_BATTLE:
{
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;
}
}
void BattlegroundAB::OnCreatureCreate(Creature* creature)
{
switch (creature->GetEntry())
{
case BG_AB_NPC_THE_BLACK_BRIDE:
case BG_AB_NPC_RADULF_LEDER:
_creaturesToRemoveOnMatchStart.push_back(creature->GetGUID());
break;
default:
break;
}
}
void BattlegroundAB::OnGameObjectCreate(GameObject* gameObject)
{
if (gameObject->GetGOInfo()->type == GAMEOBJECT_TYPE_CAPTURE_POINT)
_capturePoints.push_back(gameObject->GetGUID());
switch (gameObject->GetEntry())
{
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()
{
for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
{
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))
{
TC_LOG_ERROR("sql.sql", "BatteGroundAB: Failed to spawn some object Battleground not created!");
return false;
}
}
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))
{
TC_LOG_ERROR("sql.sql", "BatteGroundAB: Failed to spawn door object Battleground not created!");
return false;
}
//buffs
for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
{
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!");
}
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)
@@ -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_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_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_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] =
enum BG_AB_Events
{
{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
};
AB_EVENT_START_BATTLE = 9158, // Achievement: Let's Get This Done
// x, y, z, o, rot0, rot1, rot2, rot3
const float BG_AB_DoorPositions[2][8] =
{
{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_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] =
enum BG_AB_Graveyards
{
{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
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
};
Position const BG_AB_SpiritGuidePos[BG_AB_ALL_NODES_COUNT] =
const uint32 BG_AB_GraveyardIds[BG_AB_ALL_NODES_COUNT] =
{
{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
};
struct BG_AB_BannerTimer
{
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);
void _CalculateTeamNodes(uint8& alliance, uint8& horde);
/* 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];
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
@@ -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);
}
@@ -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();