Core/Battlegrounds: Move to scripts (#29799)

* Introduce new BattlegroundScript class for map/bg specific scripts
* Remove all sub, zone specific, battleground classes except Arena
* Move all bg zone scripts to new BattlegroundScripts class in script folder
* Remove ZoneScript from Battleground class
* Remove some unused hooks from Battleground

(cherry picked from commit be11f42a16)
This commit is contained in:
Jeremy
2024-03-28 19:29:22 +01:00
committed by funjoker
parent aefa15ece7
commit d0d5d309bb
78 changed files with 6821 additions and 7805 deletions

View File

@@ -15,8 +15,9 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "alterac_valley.h"
#include "ScriptMgr.h"
#include "BattlegroundAV.h"
#include "Battleground.h"
#include "GameObject.h"
#include "GameObjectAI.h"
#include "Player.h"
@@ -192,10 +193,36 @@ public:
}
};
template<AlteracValleySharedActions ActionId>
class quest_alterac_valley : public QuestScript
{
public:
quest_alterac_valley(char const* scriptName) : QuestScript(scriptName) { }
void OnQuestStatusChange(Player* player, Quest const* /*quest*/, QuestStatus /*oldStatus*/, QuestStatus newStatus) override
{
if (newStatus != QUEST_STATUS_REWARDED)
return;
if (ZoneScript* zoneScript = player->FindZoneScript())
zoneScript->DoAction(ActionId, player, player);
}
};
void AddSC_alterac_valley()
{
RegisterCreatureAI(npc_av_marshal_or_warmaster);
RegisterGameObjectAI(go_av_capturable_object);
RegisterGameObjectAI(go_av_contested_object);
new at_av_exploit();
new quest_alterac_valley<ACTION_TURN_IN_SCRAPS>("quest_alterac_valley_armor_scraps");
new quest_alterac_valley<ACTION_TURN_IN_COMMANDER_1>("quest_alterac_valley_call_of_air_slidore_guse");
new quest_alterac_valley<ACTION_TURN_IN_COMMANDER_2>("quest_alterac_valley_call_of_air_vipore_jeztor");
new quest_alterac_valley<ACTION_TURN_IN_COMMANDER_3>("quest_alterac_valley_call_of_air_ichman_mulverick");
new quest_alterac_valley<ACTION_TURN_IN_BOSS_1>("quest_alterac_valley_boss_5");
new quest_alterac_valley<ACTION_TURN_IN_BOSS_2>("quest_alterac_valley_boss_1");
new quest_alterac_valley<ACTION_TURN_IN_NEAR_MINE>("quest_alterac_valley_near_mine");
new quest_alterac_valley<ACTION_TURN_IN_OTHER_MINE>("quest_alterac_valley_other_mine");
new quest_alterac_valley<ACTION_TURN_IN_RIDER_HIDE>("quest_alterac_valley_ram_harnesses");
new quest_alterac_valley<ACTION_TURN_IN_RIDER_TAME>("quest_alterac_valley_empty_stables");
}

View File

@@ -0,0 +1,39 @@
/*
* 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/>.
*/
#ifndef __ALTERAC_VALLEY_H
#define __ALTERAC_VALLEY_H
enum AlteracValleySharedActions
{
ACTION_BUFF_YELL = -30001,
ACTION_AV_INTERACT_CAPTURABLE_OBJECT = 1,
ACTION_AV_CAPTURE_CAPTURABLE_OBJECT = 2,
ACTION_TURN_IN_SCRAPS = 3,
ACTION_TURN_IN_COMMANDER_1 = 4,
ACTION_TURN_IN_COMMANDER_2 = 5,
ACTION_TURN_IN_COMMANDER_3 = 6,
ACTION_TURN_IN_BOSS_1,
ACTION_TURN_IN_BOSS_2,
ACTION_TURN_IN_NEAR_MINE,
ACTION_TURN_IN_OTHER_MINE,
ACTION_TURN_IN_RIDER_HIDE,
ACTION_TURN_IN_RIDER_TAME
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,605 @@
/*
* 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 "BattlegroundScript.h"
#include "Battleground.h"
#include "BattlegroundMgr.h"
#include "BattlegroundPackets.h"
#include "Creature.h"
#include "GameObject.h"
#include "GameTime.h"
#include "Log.h"
#include "Map.h"
#include "ScriptMgr.h"
struct battleground_arathi_basin : BattlegroundScript
{
// Tick intervals and given points: case 0, 1, 2, 3, 4, 5 captured nodes
static constexpr uint32 BG_AB_TickInterval = 2000;
static constexpr uint32 BG_AB_TickPoints[6] = { 0, 2, 3, 4, 7, 60 };
static constexpr uint32 NORMAL_HONOR_TICKS = 160;
static constexpr uint32 WEEKEND_HONOR_TICKS = 260;
static constexpr uint32 NORMAL_REPUTATION_TICKS = 120;
static constexpr uint32 WEEKEND_REPUTATION_TICKS = 160;
enum PvpStats
{
PVP_STAT_BASES_ASSAULTED = 926,
PVP_STAT_BASES_DEFENDED = 927,
};
enum Events
{
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
};
enum Sounds
{
BG_AB_SOUND_NODE_CLAIMED = 8192,
BG_AB_SOUND_NODE_CAPTURED_ALLIANCE = 8173,
BG_AB_SOUND_NODE_CAPTURED_HORDE = 8213,
BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE = 8212,
BG_AB_SOUND_NODE_ASSAULTED_HORDE = 8174,
BG_AB_SOUND_NEAR_VICTORY_ALLIANCE = 8456,
BG_AB_SOUND_NEAR_VICTORY_HORDE = 8457
};
enum BroadcastTexts
{
BG_AB_TEXT_ALLIANCE_NEAR_VICTORY = 10598,
BG_AB_TEXT_HORDE_NEAR_VICTORY = 10599,
};
enum Score
{
BG_AB_WARNING_NEAR_VICTORY_SCORE = 1200,
BG_AB_MAX_TEAM_SCORE = 1500
};
enum Creatures
{
BG_AB_NPC_THE_BLACK_BRIDE = 150501,
BG_AB_NPC_RADULF_LEDER = 150505
};
enum ObjectTypes
{
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 WorldStates
{
BG_AB_WS_OCCUPIED_BASES_HORDE = 1778,
BG_AB_WS_OCCUPIED_BASES_ALLY = 1779,
BG_AB_WS_RESOURCES_ALLY = 1776,
BG_AB_WS_RESOURCES_HORDE = 1777,
BG_AB_WS_RESOURCES_MAX = 1780,
BG_AB_WS_RESOURCES_WARNING = 1955,
BG_AB_WS_STABLE_ICON = 1842, // Stable map icon (NONE)
BG_AB_WS_STABLE_STATE_ALIENCE = 1767, // Stable map state (ALIENCE)
BG_AB_WS_STABLE_STATE_HORDE = 1768, // Stable map state (HORDE)
BG_AB_WS_STABLE_STATE_CON_ALI = 1769, // Stable map state (CON ALIENCE)
BG_AB_WS_STABLE_STATE_CON_HOR = 1770, // Stable map state (CON HORDE)
BG_AB_WS_FARM_ICON = 1845, // Farm map icon (NONE)
BG_AB_WS_FARM_STATE_ALIENCE = 1772, // Farm state (ALIENCE)
BG_AB_WS_FARM_STATE_HORDE = 1773, // Farm state (HORDE)
BG_AB_WS_FARM_STATE_CON_ALI = 1774, // Farm state (CON ALIENCE)
BG_AB_WS_FARM_STATE_CON_HOR = 1775, // Farm state (CON HORDE)
BG_AB_WS_BLACKSMITH_ICON = 1846, // Blacksmith map icon (NONE)
BG_AB_WS_BLACKSMITH_STATE_ALIENCE = 1782, // Blacksmith map state (ALIENCE)
BG_AB_WS_BLACKSMITH_STATE_HORDE = 1783, // Blacksmith map state (HORDE)
BG_AB_WS_BLACKSMITH_STATE_CON_ALI = 1784, // Blacksmith map state (CON ALIENCE)
BG_AB_WS_BLACKSMITH_STATE_CON_HOR = 1785, // Blacksmith map state (CON HORDE)
BG_AB_WS_LUMBERMILL_ICON = 1844, // Lumber Mill map icon (NONE)
BG_AB_WS_LUMBERMILL_STATE_ALIENCE = 1792, // Lumber Mill map state (ALIENCE)
BG_AB_WS_LUMBERMILL_STATE_HORDE = 1793, // Lumber Mill map state (HORDE)
BG_AB_WS_LUMBERMILL_STATE_CON_ALI = 1794, // Lumber Mill map state (CON ALIENCE)
BG_AB_WS_LUMBERMILL_STATE_CON_HOR = 1795, // Lumber Mill map state (CON HORDE)
BG_AB_WS_GOLDMINE_ICON = 1843, // Gold Mine map icon (NONE)
BG_AB_WS_GOLDMINE_STATE_ALIENCE = 1787, // Gold Mine map state (ALIENCE)
BG_AB_WS_GOLDMINE_STATE_HORDE = 1788, // Gold Mine map state (HORDE)
BG_AB_WS_GOLDMINE_STATE_CON_ALI = 1789, // Gold Mine map state (CON ALIENCE
BG_AB_WS_GOLDMINE_STATE_CON_HOR = 1790, // Gold Mine map state (CON HORDE)
BG_AB_WS_HAD_500_DISADVANTAGE_ALLIANCE = 3644,
BG_AB_WS_HAD_500_DISADVANTAGE_HORDE = 3645,
BG_AB_WS_FARM_ICON_NEW = 8808, // Farm map icon
BG_AB_WS_LUMBER_MILL_ICON_NEW = 8805, // Lumber Mill map icon
BG_AB_WS_BLACKSMITH_ICON_NEW = 8799, // Blacksmith map icon
BG_AB_WS_GOLD_MINE_ICON_NEW = 8809, // Gold Mine map icon
BG_AB_WS_STABLES_ICON_NEW = 5834, // Stable map icon
BG_AB_WS_FARM_HORDE_CONTROL_STATE = 17328,
BG_AB_WS_FARM_ALLIANCE_CONTROL_STATE = 17325,
BG_AB_WS_LUMBER_MILL_HORDE_CONTROL_STATE = 17330,
BG_AB_WS_LUMBER_MILL_ALLIANCE_CONTROL_STATE = 17326,
BG_AB_WS_BLACKSMITH_HORDE_CONTROL_STATE = 17327,
BG_AB_WS_BLACKSMITH_ALLIANCE_CONTROL_STATE = 17324,
BG_AB_WS_GOLD_MINE_HORDE_CONTROL_STATE = 17329,
BG_AB_WS_GOLD_MINE_ALLIANCE_CONTROL_STATE = 17323,
BG_AB_WS_STABLES_HORDE_CONTROL_STATE = 17331,
BG_AB_WS_STABLES_ALLIANCE_CONTROL_STATE = 17322,
};
explicit battleground_arathi_basin(BattlegroundMap* map) : BattlegroundScript(map), _lastTick(0), _isInformedNearVictory(false)
{
bool const isBGWeekend = sBattlegroundMgr->IsBGWeekend(battleground->GetTypeID());
_honorTics = (isBGWeekend) ? WEEKEND_HONOR_TICKS : NORMAL_HONOR_TICKS;
_reputationTics = (isBGWeekend) ? WEEKEND_REPUTATION_TICKS : NORMAL_REPUTATION_TICKS;
_honorScoreTics = { { 0, 0 } };
_reputationScoreTics = { { 0, 0 } };
}
void OnInit() override
{
BattlegroundScript::OnInit();
UpdateWorldState(BG_AB_WS_RESOURCES_MAX, BG_AB_MAX_TEAM_SCORE);
UpdateWorldState(BG_AB_WS_RESOURCES_WARNING, BG_AB_WARNING_NEAR_VICTORY_SCORE);
}
void OnUpdate(uint32 diff) override
{
if (battleground->GetStatus() != STATUS_IN_PROGRESS)
return;
// Accumulate points
_lastTick += diff;
if (_lastTick > BG_AB_TickInterval)
{
_lastTick -= BG_AB_TickInterval;
uint8 ally = 0, horde = 0;
_CalculateTeamNodes(ally, horde);
uint8 points[PVP_TEAMS_COUNT] = { ally, horde };
for (uint8 team = 0; team < PVP_TEAMS_COUNT; ++team)
{
if (!points[team])
continue;
battleground->AddPoint(team == TEAM_HORDE ? HORDE : ALLIANCE, BG_AB_TickPoints[points[team]]);
_honorScoreTics[team] += BG_AB_TickPoints[points[team]];
_reputationScoreTics[team] += BG_AB_TickPoints[points[team]];
if (_reputationScoreTics[team] >= _reputationTics)
{
(team == TEAM_ALLIANCE) ? battleground->RewardReputationToTeam(509, 10, ALLIANCE) : battleground->RewardReputationToTeam(510, 10, HORDE);
_reputationScoreTics[team] -= _reputationTics;
}
if (_honorScoreTics[team] >= _honorTics)
{
battleground->RewardHonorToTeam(battleground->GetBonusHonorFromKill(1), (team == TEAM_ALLIANCE) ? ALLIANCE : HORDE);
_honorScoreTics[team] -= _honorTics;
}
const uint32 teamScore = battleground->GetTeamScore(static_cast<TeamId>(team));
if (!_isInformedNearVictory && teamScore > BG_AB_WARNING_NEAR_VICTORY_SCORE)
{
if (team == TEAM_ALLIANCE)
{
battleground->SendBroadcastText(BG_AB_TEXT_ALLIANCE_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL);
battleground->PlaySoundToAll(BG_AB_SOUND_NEAR_VICTORY_ALLIANCE);
}
else
{
battleground->SendBroadcastText(BG_AB_TEXT_HORDE_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL);
battleground->PlaySoundToAll(BG_AB_SOUND_NEAR_VICTORY_HORDE);
}
_isInformedNearVictory = true;
}
if (teamScore > BG_AB_MAX_TEAM_SCORE)
battleground->SetTeamPoint(team == TEAM_HORDE ? HORDE : ALLIANCE, BG_AB_MAX_TEAM_SCORE);
if (team == TEAM_ALLIANCE)
UpdateWorldState(BG_AB_WS_RESOURCES_ALLY, teamScore);
else
UpdateWorldState(BG_AB_WS_RESOURCES_HORDE, teamScore);
// update achievement flags
// we increased m_TeamScores[team] so we just need to check if it is 500 more than other teams resources
uint8 otherTeam = (team + 1) % PVP_TEAMS_COUNT;
if (teamScore > battleground->GetTeamScore(static_cast<TeamId>(otherTeam)) + 500)
{
if (team == TEAM_ALLIANCE)
UpdateWorldState(BG_AB_WS_HAD_500_DISADVANTAGE_HORDE, 1);
else
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
if (battleground->GetTeamScore(TEAM_ALLIANCE) >= BG_AB_MAX_TEAM_SCORE && battleground->GetTeamScore(TEAM_HORDE) >= BG_AB_MAX_TEAM_SCORE)
battleground->EndBattleground(TEAM_OTHER); // draw
else if (battleground->GetTeamScore(TEAM_ALLIANCE) >= BG_AB_MAX_TEAM_SCORE)
battleground->EndBattleground(ALLIANCE);
else if (battleground->GetTeamScore(TEAM_HORDE) >= BG_AB_MAX_TEAM_SCORE)
battleground->EndBattleground(HORDE);
}
void OnStart() override
{
// Achievement: Let's Get This Done
TriggerGameEvent(AB_EVENT_START_BATTLE);
}
void _CalculateTeamNodes(uint8& alliance, uint8& horde) const
{
alliance = 0;
horde = 0;
for (ObjectGuid const& guid : _capturePoints)
{
if (GameObject const* capturePoint = battlegroundMap->GetGameObject(guid))
{
int32 const wsValue = battlegroundMap->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;
}
}
}
}
Team GetPrematureWinner() override
{
// How many bases each team owns
uint8 ally = 0, horde = 0;
_CalculateTeamNodes(ally, horde);
if (ally > horde)
return ALLIANCE;
if (horde > ally)
return HORDE;
// If the values are equal, fall back to the original result (based on number of players on each team)
return BattlegroundScript::GetPrematureWinner();
}
void ProcessEvent(WorldObject* /*source*/, uint32 eventId, WorldObject* invoker) override
{
switch (eventId)
{
case AB_EVENT_START_BATTLE:
{
for (ObjectGuid const& guid : _creaturesToRemoveOnMatchStart)
if (Creature* creature = battlegroundMap->GetCreature(guid))
creature->DespawnOrUnsummon();
for (ObjectGuid const& guid : _gameobjectsToRemoveOnMatchStart)
if (GameObject* gameObject = battlegroundMap->GetGameObject(guid))
gameObject->DespawnOrUnsummon();
for (ObjectGuid const& guid : _doors)
{
if (GameObject* gameObject = battlegroundMap->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);
battleground->PlaySoundToAll(BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE);
if (Player* player = invoker->ToPlayer())
battleground->UpdatePvpStat(player, PVP_STAT_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);
battleground->PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_ALLIANCE);
if (Player* player = invoker->ToPlayer())
battleground->UpdatePvpStat(player, PVP_STAT_BASES_DEFENDED, 1);
break;
case AB_EVENT_CAPTURE_BLACKSMITH_ALLIANCE:
UpdateWorldState(BG_AB_WS_BLACKSMITH_ALLIANCE_CONTROL_STATE, 2);
battleground->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);
battleground->PlaySoundToAll(BG_AB_SOUND_NODE_ASSAULTED_HORDE);
if (Player* player = invoker->ToPlayer())
battleground->UpdatePvpStat(player, PVP_STAT_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);
battleground->PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_HORDE);
if (Player* player = invoker->ToPlayer())
battleground->UpdatePvpStat(player, PVP_STAT_BASES_DEFENDED, 1);
break;
case AB_EVENT_CAPTURE_BLACKSMITH_HORDE:
UpdateWorldState(BG_AB_WS_BLACKSMITH_HORDE_CONTROL_STATE, 2);
battleground->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);
battleground->PlaySoundToAll(BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE);
if (Player* player = invoker->ToPlayer())
battleground->UpdatePvpStat(player, PVP_STAT_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);
battleground->PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_ALLIANCE);
if (Player* player = invoker->ToPlayer())
battleground->UpdatePvpStat(player, PVP_STAT_BASES_DEFENDED, 1);
break;
case AB_EVENT_CAPTURE_FARM_ALLIANCE:
UpdateWorldState(BG_AB_WS_FARM_ALLIANCE_CONTROL_STATE, 2);
battleground->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);
battleground->PlaySoundToAll(BG_AB_SOUND_NODE_ASSAULTED_HORDE);
if (Player* player = invoker->ToPlayer())
battleground->UpdatePvpStat(player, PVP_STAT_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);
battleground->PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_HORDE);
if (Player* player = invoker->ToPlayer())
battleground->UpdatePvpStat(player, PVP_STAT_BASES_DEFENDED, 1);
break;
case AB_EVENT_CAPTURE_FARM_HORDE:
UpdateWorldState(BG_AB_WS_FARM_HORDE_CONTROL_STATE, 2);
battleground->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);
battleground->PlaySoundToAll(BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE);
if (Player* player = invoker->ToPlayer())
battleground->UpdatePvpStat(player, PVP_STAT_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);
battleground->PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_ALLIANCE);
if (Player* player = invoker->ToPlayer())
battleground->UpdatePvpStat(player, PVP_STAT_BASES_DEFENDED, 1);
break;
case AB_EVENT_CAPTURE_GOLD_MINE_ALLIANCE:
UpdateWorldState(BG_AB_WS_GOLD_MINE_ALLIANCE_CONTROL_STATE, 2);
battleground->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);
battleground->PlaySoundToAll(BG_AB_SOUND_NODE_ASSAULTED_HORDE);
if (Player* player = invoker->ToPlayer())
battleground->UpdatePvpStat(player, PVP_STAT_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);
battleground->PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_HORDE);
if (Player* player = invoker->ToPlayer())
battleground->UpdatePvpStat(player, PVP_STAT_BASES_DEFENDED, 1);
break;
case AB_EVENT_CAPTURE_GOLD_MINE_HORDE:
UpdateWorldState(BG_AB_WS_GOLD_MINE_HORDE_CONTROL_STATE, 2);
battleground->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);
battleground->PlaySoundToAll(BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE);
if (Player* player = invoker->ToPlayer())
battleground->UpdatePvpStat(player, PVP_STAT_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);
battleground->PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_ALLIANCE);
if (Player* player = invoker->ToPlayer())
battleground->UpdatePvpStat(player, PVP_STAT_BASES_DEFENDED, 1);
break;
case AB_EVENT_CAPTURE_LUMBER_MILL_ALLIANCE:
UpdateWorldState(BG_AB_WS_LUMBER_MILL_ALLIANCE_CONTROL_STATE, 2);
battleground->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);
battleground->PlaySoundToAll(BG_AB_SOUND_NODE_ASSAULTED_HORDE);
if (Player* player = invoker->ToPlayer())
battleground->UpdatePvpStat(player, PVP_STAT_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);
battleground->PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_HORDE);
if (Player* player = invoker->ToPlayer())
battleground->UpdatePvpStat(player, PVP_STAT_BASES_DEFENDED, 1);
break;
case AB_EVENT_CAPTURE_LUMBER_MILL_HORDE:
UpdateWorldState(BG_AB_WS_LUMBER_MILL_HORDE_CONTROL_STATE, 2);
battleground->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);
battleground->PlaySoundToAll(BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE);
if (Player* player = invoker->ToPlayer())
battleground->UpdatePvpStat(player, PVP_STAT_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);
battleground->PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_ALLIANCE);
if (Player* player = invoker->ToPlayer())
battleground->UpdatePvpStat(player, PVP_STAT_BASES_DEFENDED, 1);
break;
case AB_EVENT_CAPTURE_STABLES_ALLIANCE:
UpdateWorldState(BG_AB_WS_STABLES_ALLIANCE_CONTROL_STATE, 2);
battleground->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);
battleground->PlaySoundToAll(BG_AB_SOUND_NODE_ASSAULTED_HORDE);
if (Player* player = invoker->ToPlayer())
battleground->UpdatePvpStat(player, PVP_STAT_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);
battleground->PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_HORDE);
if (Player* player = invoker->ToPlayer())
battleground->UpdatePvpStat(player, PVP_STAT_BASES_DEFENDED, 1);
break;
case AB_EVENT_CAPTURE_STABLES_HORDE:
UpdateWorldState(BG_AB_WS_STABLES_HORDE_CONTROL_STATE, 2);
battleground->PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_HORDE);
break;
default:
TC_LOG_WARN("bg.events", "BattlegroundAB::ProcessEvent: Unhandled event %u.", eventId);
break;
}
}
void OnCreatureCreate(Creature* creature) override
{
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 OnGameObjectCreate(GameObject* gameObject) override
{
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;
}
}
void OnEnd(Team winner) override
{
BattlegroundScript::OnEnd(winner);
// Win reward
if (winner == ALLIANCE)
battleground->RewardHonorToTeam(battleground->GetBonusHonorFromKill(1), ALLIANCE);
if (winner == HORDE)
battleground->RewardHonorToTeam(battleground->GetBonusHonorFromKill(1), HORDE);
// Complete map_end rewards (even if no team wins)
battleground->RewardHonorToTeam(battleground->GetBonusHonorFromKill(1), HORDE);
battleground->RewardHonorToTeam(battleground->GetBonusHonorFromKill(1), ALLIANCE);
}
private:
uint32 _lastTick;
std::array<uint32, PVP_TEAMS_COUNT> _honorScoreTics;
std::array<uint32, PVP_TEAMS_COUNT> _reputationScoreTics;
bool _isInformedNearVictory;
uint32 _honorTics;
uint32 _reputationTics;
GuidVector _gameobjectsToRemoveOnMatchStart;
GuidVector _creaturesToRemoveOnMatchStart;
GuidVector _doors;
GuidVector _capturePoints;
};
void AddSC_battleground_arathi_basin()
{
RegisterBattlegroundMapScript(battleground_arathi_basin, 2107);
}

View File

@@ -0,0 +1,35 @@
/*
* 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 "BattlegroundScript.h"
#include "ScriptMgr.h"
struct battleground_battle_for_gilneas : BattlegroundScript
{
enum PvpStats : uint32
{
BFG_OBJECTIVE_BASES_ASSAULTED = 370,
BFG_OBJECTIVE_BASES_DEFENDED = 371
};
explicit battleground_battle_for_gilneas(BattlegroundMap* map) : BattlegroundScript(map) { }
};
void AddSC_battleground_battle_for_gilneas()
{
RegisterBattlegroundMapScript(battleground_battle_for_gilneas, 761);
}

View File

@@ -0,0 +1,84 @@
/*
* 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 "Battleground.h"
#include "BattlegroundScript.h"
#include "GameObject.h"
#include "Map.h"
#include "ScriptMgr.h"
#include "TaskScheduler.h"
struct arena_blades_edge : ArenaScript
{
enum GameObjects
{
BG_BE_OBJECT_TYPE_DOOR_1 = 183971,
BG_BE_OBJECT_TYPE_DOOR_2 = 183973,
BG_BE_OBJECT_TYPE_DOOR_3 = 183970,
BG_BE_OBJECT_TYPE_DOOR_4 = 183972,
BG_BE_OBJECT_TYPE_BUFF_1 = 184663,
BG_BE_OBJECT_TYPE_BUFF_2 = 184664
};
explicit arena_blades_edge(BattlegroundMap* map) : ArenaScript(map) { }
void OnUpdate(uint32 diff) override
{
_scheduler.Update(diff);
}
void OnInit() override
{
AddDoor(BG_BE_OBJECT_TYPE_DOOR_1, 6287.277f, 282.1877f, 3.810925f, -2.260201f, 0, 0, 0.9044551f, -0.4265689f);
AddDoor(BG_BE_OBJECT_TYPE_DOOR_2, 6189.546f, 241.7099f, 3.101481f, 0.8813917f, 0, 0, 0.4265689f, 0.9044551f);
AddDoor(BG_BE_OBJECT_TYPE_DOOR_3, 6299.116f, 296.5494f, 3.308032f, 0.8813917f, 0, 0, 0.4265689f, 0.9044551f);
AddDoor(BG_BE_OBJECT_TYPE_DOOR_4, 6177.708f, 227.3481f, 3.604374f, -2.260201f, 0, 0, 0.9044551f, -0.4265689f);
}
void OnStart() override
{
for (ObjectGuid const& guid : _doorGUIDs)
{
if (GameObject* door = battlegroundMap->GetGameObject(guid))
{
door->UseDoorOrButton();
door->DespawnOrUnsummon(5s);
}
}
_scheduler.Schedule(1min, [&](TaskContext)
{
CreateObject(BG_BE_OBJECT_TYPE_BUFF_1, 6249.042f, 275.3239f, 11.22033f, -1.448624f, 0, 0, 0.6626201f, -0.7489557f);
CreateObject(BG_BE_OBJECT_TYPE_BUFF_2, 6228.26f, 249.566f, 11.21812f, -0.06981307f, 0, 0, 0.03489945f, -0.9993908f);
});
}
void AddDoor(uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, GOState goState = GO_STATE_READY)
{
if (GameObject const* go = CreateObject(entry, x, y, z, o, rotation0, rotation1, rotation2, rotation3, goState))
_doorGUIDs.emplace_back(go->GetGUID());
}
private:
GuidVector _doorGUIDs;
TaskScheduler _scheduler;
};
void AddSC_arena_blades_edge()
{
RegisterBattlegroundMapScript(arena_blades_edge, 1672);
}

View File

@@ -0,0 +1,266 @@
/*
* 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 "Battleground.h"
#include "BattlegroundScript.h"
#include "Creature.h"
#include "Duration.h"
#include "EventMap.h"
#include "GameObject.h"
#include "Map.h"
#include "ObjectAccessor.h"
#include "Player.h"
#include "ScriptMgr.h"
#include "TaskScheduler.h"
struct arena_dalaran_sewers : ArenaScript
{
enum GameObjects
{
BG_DS_OBJECT_TYPE_DOOR_1 = 192642,
BG_DS_OBJECT_TYPE_DOOR_2 = 192643,
BG_DS_OBJECT_TYPE_WATER_1 = 194395, // Collision
BG_DS_OBJECT_TYPE_WATER_2 = 191877,
BG_DS_OBJECT_TYPE_BUFF_1 = 184663,
BG_DS_OBJECT_TYPE_BUFF_2 = 184664
};
enum Events
{
BG_DS_EVENT_WATERFALL_WARNING = 1, // Water starting to fall, but no LoS Blocking nor movement blocking
BG_DS_EVENT_WATERFALL_ON = 2, // LoS and Movement blocking active
BG_DS_EVENT_WATERFALL_OFF = 3,
BG_DS_EVENT_WATERFALL_KNOCKBACK = 4,
BG_DS_EVENT_PIPE_KNOCKBACK = 5
};
enum Creatures
{
BG_DS_NPC_TYPE_WATER_SPOUT = 28567
};
enum Spells
{
BG_DS_SPELL_FLUSH = 57405, // Visual and target selector for the starting knockback from the pipe
BG_DS_SPELL_FLUSH_KNOCKBACK = 61698, // Knockback effect for previous spell (triggered, not needed to be cast)
BG_DS_SPELL_WATER_SPOUT = 58873, // Knockback effect of the central waterfall
SPELL_WARL_DEMONIC_CIRCLE = 48018 // Demonic Circle Summon
};
enum Data
{
// These values are NOT blizzlike... need the correct data!
BG_DS_PIPE_KNOCKBACK_FIRST_DELAY = 5000,
BG_DS_PIPE_KNOCKBACK_DELAY = 3000
};
// These values are NOT blizzlike... need the correct data!
static constexpr Seconds BG_DS_WATERFALL_TIMER_MIN = 30s;
static constexpr Seconds BG_DS_WATERFALL_TIMER_MAX = 60s;
static constexpr Seconds BG_DS_WATERFALL_WARNING_DURATION = 5s;
static constexpr Seconds BG_DS_WATERFALL_DURATION = 30s;
static constexpr Milliseconds BG_DS_WATERFALL_KNOCKBACK_TIMER = 1500ms;
static constexpr uint32 BG_DS_DATA_PIPE_KNOCKBACK_COUNT = 1;
static constexpr uint32 BG_DS_PIPE_KNOCKBACK_TOTAL_COUNT = 2;
explicit arena_dalaran_sewers(BattlegroundMap* map) : ArenaScript(map), _pipeKnockBackTimer(BG_DS_PIPE_KNOCKBACK_FIRST_DELAY), _pipeKnockBackCount(0) { }
void OnUpdate(uint32 diff) override
{
if (battleground->GetStatus() != STATUS_IN_PROGRESS)
return;
_events.Update(diff);
_scheduler.Update(diff);
while (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case BG_DS_EVENT_WATERFALL_WARNING:
// Add the water
if (GameObject* go = battlegroundMap->GetGameObject(_water2GUID))
go->ResetDoorOrButton();
_events.ScheduleEvent(BG_DS_EVENT_WATERFALL_ON, BG_DS_WATERFALL_WARNING_DURATION);
break;
case BG_DS_EVENT_WATERFALL_ON:
// Active collision and start knockback timer
if (GameObject* go = battlegroundMap->GetGameObject(_water1GUID))
go->ResetDoorOrButton();
_events.ScheduleEvent(BG_DS_EVENT_WATERFALL_OFF, BG_DS_WATERFALL_DURATION);
_events.ScheduleEvent(BG_DS_EVENT_WATERFALL_KNOCKBACK, BG_DS_WATERFALL_KNOCKBACK_TIMER);
break;
case BG_DS_EVENT_WATERFALL_OFF:
// Remove collision and water
if (GameObject* go = battlegroundMap->GetGameObject(_water1GUID))
go->UseDoorOrButton();
if (GameObject* go = battlegroundMap->GetGameObject(_water2GUID))
go->UseDoorOrButton();
_events.CancelEvent(BG_DS_EVENT_WATERFALL_KNOCKBACK);
_events.ScheduleEvent(BG_DS_EVENT_WATERFALL_WARNING, BG_DS_WATERFALL_TIMER_MIN, BG_DS_WATERFALL_TIMER_MAX);
break;
case BG_DS_EVENT_WATERFALL_KNOCKBACK:
// Repeat knockback while the waterfall still active
if (Creature* waterSpout = battlegroundMap->GetCreature(_waterfallCreatureGUID))
waterSpout->CastSpell(waterSpout, BG_DS_SPELL_WATER_SPOUT, true);
_events.ScheduleEvent(eventId, BG_DS_WATERFALL_KNOCKBACK_TIMER);
break;
case BG_DS_EVENT_PIPE_KNOCKBACK:
for (ObjectGuid const& guid : _pipeCreatureGUIDs)
if (Creature* waterSpout = battlegroundMap->GetCreature(guid))
waterSpout->CastSpell(waterSpout, BG_DS_SPELL_FLUSH, true);
break;
default:
break;
}
}
if (_pipeKnockBackCount < BG_DS_PIPE_KNOCKBACK_TOTAL_COUNT)
{
if (_pipeKnockBackTimer < diff)
{
for (ObjectGuid const& guid : _pipeCreatureGUIDs)
if (Creature* waterSpout = battlegroundMap->GetCreature(guid))
waterSpout->CastSpell(waterSpout, BG_DS_SPELL_FLUSH, true);
++_pipeKnockBackCount;
_pipeKnockBackTimer = BG_DS_PIPE_KNOCKBACK_DELAY;
}
else
_pipeKnockBackTimer -= diff;
}
}
void OnInit() override
{
AddObject(BG_DS_OBJECT_TYPE_DOOR_1, 1350.95f, 817.2f, 20.8096f, 3.15f, 0, 0, 0.99627f, 0.0862864f, GO_STATE_READY, _doorGUIDs);
AddObject(BG_DS_OBJECT_TYPE_DOOR_2, 1232.65f, 764.913f, 20.0729f, 6.3f, 0, 0, 0.0310211f, -0.999519f, GO_STATE_READY, _doorGUIDs);
if (GameObject const* go = CreateObject(BG_DS_OBJECT_TYPE_WATER_1, 1291.56f, 790.837f, 7.1f, 3.14238f, 0, 0, 0.694215f, -0.719768f, GO_STATE_READY))
_water1GUID = go->GetGUID();
if (GameObject const* go = CreateObject(BG_DS_OBJECT_TYPE_WATER_2, 1291.56f, 790.837f, 7.1f, 3.14238f, 0, 0, 0.694215f, -0.719768f, GO_STATE_READY))
_water2GUID = go->GetGUID();
}
void OnStart() override
{
for (ObjectGuid const& guid : _doorGUIDs)
{
if (GameObject* door = battlegroundMap->GetGameObject(guid))
{
door->UseDoorOrButton();
door->DespawnOrUnsummon(5s);
}
}
_scheduler.Schedule(1min, [&](TaskContext)
{
CreateObject(BG_DS_OBJECT_TYPE_BUFF_1, 1291.7f, 813.424f, 7.11472f, 4.64562f, 0, 0, 0.730314f, -0.683111f);
CreateObject(BG_DS_OBJECT_TYPE_BUFF_2, 1291.7f, 768.911f, 7.11472f, 1.55194f, 0, 0, 0.700409f, 0.713742f);
});
_events.ScheduleEvent(BG_DS_EVENT_WATERFALL_WARNING, BG_DS_WATERFALL_TIMER_MIN, BG_DS_WATERFALL_TIMER_MAX);
_pipeKnockBackTimer = BG_DS_PIPE_KNOCKBACK_FIRST_DELAY;
// Remove collision and water
if (GameObject* go = battlegroundMap->GetGameObject(_water1GUID))
go->UseDoorOrButton();
if (GameObject* go = battlegroundMap->GetGameObject(_water2GUID))
go->UseDoorOrButton();
for (const auto& [playerGuid, _] : battleground->GetPlayers())
if (Player* player = ObjectAccessor::FindPlayer(playerGuid))
player->RemoveAurasDueToSpell(SPELL_WARL_DEMONIC_CIRCLE);
}
void AddObject(uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, GOState goState, GuidVector guidVector) const
{
if (GameObject const* go = CreateObject(entry, x, y, z, o, rotation0, rotation1, rotation2, rotation3, goState))
guidVector.emplace_back(go->GetGUID());
}
void SetData(uint32 dataId, uint32 value) override
{
ArenaScript::SetData(dataId, value);
if (dataId == BG_DS_DATA_PIPE_KNOCKBACK_COUNT)
_pipeKnockBackCount = value;
}
uint32 GetData(uint32 dataId) const override
{
if (dataId == BG_DS_DATA_PIPE_KNOCKBACK_COUNT)
return _pipeKnockBackCount;
return ArenaScript::GetData(dataId);
}
private:
GuidVector _doorGUIDs;
ObjectGuid _water1GUID;
ObjectGuid _water2GUID;
ObjectGuid _waterfallCreatureGUID;
GuidVector _pipeCreatureGUIDs;
TaskScheduler _scheduler;
EventMap _events;
uint32 _pipeKnockBackTimer;
uint8 _pipeKnockBackCount;
};
class at_ds_pipe_knockback : public AreaTriggerScript
{
public:
at_ds_pipe_knockback() : AreaTriggerScript("at_ds_pipe_knockback") { }
void Trigger(Player* player) const
{
if (Battleground const* battleground = player->GetBattleground())
{
if (battleground->GetStatus() != STATUS_IN_PROGRESS)
return;
// Remove effects of Demonic Circle Summon
player->RemoveAurasDueToSpell(arena_dalaran_sewers::SPELL_WARL_DEMONIC_CIRCLE);
// Someone has get back into the pipes and the knockback has already been performed,
// so we reset the knockback count for kicking the player again into the arena.
if (battleground->GetBgMap()->GetBattlegroundScript()->GetData(arena_dalaran_sewers::BG_DS_DATA_PIPE_KNOCKBACK_COUNT) >= arena_dalaran_sewers::BG_DS_PIPE_KNOCKBACK_TOTAL_COUNT)
battleground->GetBgMap()->GetBattlegroundScript()->SetData(arena_dalaran_sewers::BG_DS_DATA_PIPE_KNOCKBACK_COUNT, 0);
}
}
bool OnTrigger(Player* player, AreaTriggerEntry const* /*trigger*/) override
{
Trigger(player);
return true;
}
bool OnExit(Player* player, AreaTriggerEntry const* /*trigger*/) override
{
Trigger(player);
return true;
}
};
void AddSC_arena_dalaran_sewers()
{
RegisterBattlegroundMapScript(arena_dalaran_sewers, 617);
new at_ds_pipe_knockback();
}

View File

@@ -0,0 +1,677 @@
/*
* 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 "AreaTrigger.h"
#include "BattlegroundScript.h"
#include "Battleground.h"
#include "BattlegroundMgr.h"
#include "GameObject.h"
#include "GameTime.h"
#include "Map.h"
#include "ObjectAccessor.h"
#include "Player.h"
#include "ScriptMgr.h"
#include "SpellAuras.h"
#include "Timer.h"
enum EyeOfTheStormWorldStates
{
EY_ALLIANCE_RESOURCES = 1776,
EY_HORDE_RESOURCES = 1777,
EY_MAX_RESOURCES = 1780,
EY_ALLIANCE_BASE = 2752,
EY_HORDE_BASE = 2753,
DRAENEI_RUINS_HORDE_CONTROL = 2733,
DRAENEI_RUINS_ALLIANCE_CONTROL = 2732,
DRAENEI_RUINS_UNCONTROL = 2731,
MAGE_TOWER_ALLIANCE_CONTROL = 2730,
MAGE_TOWER_HORDE_CONTROL = 2729,
MAGE_TOWER_UNCONTROL = 2728,
FEL_REAVER_HORDE_CONTROL = 2727,
FEL_REAVER_ALLIANCE_CONTROL = 2726,
FEL_REAVER_UNCONTROL = 2725,
BLOOD_ELF_HORDE_CONTROL = 2724,
BLOOD_ELF_ALLIANCE_CONTROL = 2723,
BLOOD_ELF_UNCONTROL = 2722,
PROGRESS_BAR_PERCENT_GREY = 2720, //100 = empty (only grey), 0 = blue|red (no grey)
PROGRESS_BAR_STATUS = 2719, //50 init!, 48 ... hordak bere .. 33 .. 0 = full 100% hordacky, 100 = full alliance
PROGRESS_BAR_SHOW = 2718, //1 init, 0 druhy send - bez messagu, 1 = controlled aliance
NETHERSTORM_FLAG = 8863,
//set to 2 when flag is picked up, and to 1 if it is dropped
NETHERSTORM_FLAG_STATE_ALLIANCE = 9808,
NETHERSTORM_FLAG_STATE_HORDE = 9809,
DRAENEI_RUINS_HORDE_CONTROL_STATE = 17362,
DRAENEI_RUINS_ALLIANCE_CONTROL_STATE = 17366,
MAGE_TOWER_HORDE_CONTROL_STATE = 17361,
MAGE_TOWER_ALLIANCE_CONTROL_STATE = 17368,
FEL_REAVER_HORDE_CONTROL_STATE = 17364,
FEL_REAVER_ALLIANCE_CONTROL_STATE = 17367,
BLOOD_ELF_HORDE_CONTROL_STATE = 17363,
BLOOD_ELF_ALLIANCE_CONTROL_STATE = 17365,
};
enum EyeOfTheStormSounds
{
//strange ids, but sure about them
BG_EY_SOUND_FLAG_PICKED_UP_ALLIANCE = 8212,
BG_EY_SOUND_FLAG_CAPTURED_HORDE = 8213,
BG_EY_SOUND_FLAG_PICKED_UP_HORDE = 8174,
BG_EY_SOUND_FLAG_CAPTURED_ALLIANCE = 8173,
BG_EY_SOUND_FLAG_RESET = 8192
};
enum EyeOfTheStormSpells
{
BG_EY_NETHERSTORM_FLAG_SPELL = 34976,
BG_EY_PLAYER_DROPPED_FLAG_SPELL = 34991,
// Focused/Brutal Assault
BG_EY_FOCUSED_ASSAULT_SPELL = 46392,
BG_EY_BRUTAL_ASSAULT_SPELL = 46393
};
enum EyeOfTheStormObjectEntry
{
BG_OBJECT_A_DOOR_EY_ENTRY = 184719, //Alliance door
BG_OBJECT_H_DOOR_EY_ENTRY = 184720, //Horde door
BG_OBJECT_FLAG2_EY_ENTRY = 208977, //Netherstorm flag (flagstand)
BG_OBJECT_BE_TOWER_CAP_EY_ENTRY = 184080, //BE Tower Cap Pt
BG_OBJECT_FR_TOWER_CAP_EY_ENTRY = 184081, //Fel Reaver Cap Pt
BG_OBJECT_HU_TOWER_CAP_EY_ENTRY = 184082, //Human Tower Cap Pt
BG_OBJECT_DR_TOWER_CAP_EY_ENTRY = 184083, //Draenei Tower Cap Pt
};
enum EyeOfTheStormPointsTrigger
{
AREATRIGGER_CAPTURE_FLAG = 33
};
enum EyeOfTheStormPoints
{
FEL_REAVER = 0,
BLOOD_ELF = 1,
DRAENEI_RUINS = 2,
MAGE_TOWER = 3,
EY_PLAYERS_OUT_OF_POINTS = 4,
EY_POINTS_MAX = 4
};
constexpr uint32 BG_EY_NotEYWeekendHonorTicks = 260;
constexpr uint32 BG_EY_EYWeekendHonorTicks = 160;
enum BG_EY_Score
{
BG_EY_WARNING_NEAR_VICTORY_SCORE = 1200,
BG_EY_MAX_TEAM_SCORE = 1500
};
enum BG_EY_FlagState
{
BG_EY_FLAG_STATE_ON_BASE = 0,
BG_EY_FLAG_STATE_WAIT_RESPAWN = 1,
BG_EY_FLAG_STATE_ON_PLAYER = 2,
BG_EY_FLAG_STATE_ON_GROUND = 3
};
enum EYBattlegroundPointState
{
EY_POINT_NO_OWNER = 0,
EY_POINT_STATE_UNCONTROLLED = 0,
EY_POINT_UNDER_CONTROL = 3
};
enum BG_EY_ExploitTeleportLocations
{
EY_EXPLOIT_TELEPORT_LOCATION_ALLIANCE = 3773,
EY_EXPLOIT_TELEPORT_LOCATION_HORDE = 3772
};
enum EyeOFtheStormBroadcastTexts
{
BG_EY_TEXT_ALLIANCE_TAKEN_FEL_REAVER_RUINS = 17828,
BG_EY_TEXT_HORDE_TAKEN_FEL_REAVER_RUINS = 17829,
BG_EY_TEXT_ALLIANCE_LOST_FEL_REAVER_RUINS = 91961,
BG_EY_TEXT_HORDE_LOST_FEL_REAVER_RUINS = 91962,
BG_EY_TEXT_ALLIANCE_TAKEN_BLOOD_ELF_TOWER = 17819,
BG_EY_TEXT_HORDE_TAKEN_BLOOD_ELF_TOWER = 17823,
BG_EY_TEXT_ALLIANCE_LOST_BLOOD_ELF_TOWER = 91957,
BG_EY_TEXT_HORDE_LOST_BLOOD_ELF_TOWER = 91958,
BG_EY_TEXT_ALLIANCE_TAKEN_DRAENEI_RUINS = 17827,
BG_EY_TEXT_HORDE_TAKEN_DRAENEI_RUINS = 91917,
BG_EY_TEXT_ALLIANCE_LOST_DRAENEI_RUINS = 91959,
BG_EY_TEXT_HORDE_LOST_DRAENEI_RUINS = 91960,
BG_EY_TEXT_ALLIANCE_TAKEN_MAGE_TOWER = 17824,
BG_EY_TEXT_HORDE_TAKEN_MAGE_TOWER = 17825,
BG_EY_TEXT_ALLIANCE_LOST_MAGE_TOWER = 91963,
BG_EY_TEXT_HORDE_LOST_MAGE_TOWER = 91964,
BG_EY_TEXT_TAKEN_FLAG = 18359,
BG_EY_TEXT_FLAG_DROPPED = 18361,
BG_EY_TEXT_FLAG_RESET = 18364,
BG_EY_TEXT_ALLIANCE_CAPTURED_FLAG = 18375,
BG_EY_TEXT_HORDE_CAPTURED_FLAG = 18384,
};
struct BattlegroundEYPointIconsStruct
{
BattlegroundEYPointIconsStruct(uint32 _WorldStateControlIndex, uint32 _WorldStateAllianceControlledIndex, uint32 _WorldStateHordeControlledIndex,
uint32 worldStateAllianceStatusBarIcon, uint32 worldStateHordeStatusBarIcon)
: WorldStateControlIndex(_WorldStateControlIndex), WorldStateAllianceControlledIndex(_WorldStateAllianceControlledIndex), WorldStateHordeControlledIndex(_WorldStateHordeControlledIndex),
WorldStateAllianceStatusBarIcon(worldStateAllianceStatusBarIcon), WorldStateHordeStatusBarIcon(worldStateHordeStatusBarIcon) { }
uint32 WorldStateControlIndex;
uint32 WorldStateAllianceControlledIndex;
uint32 WorldStateHordeControlledIndex;
uint32 WorldStateAllianceStatusBarIcon;
uint32 WorldStateHordeStatusBarIcon;
};
struct BattlegroundEYLosingPointStruct
{
BattlegroundEYLosingPointStruct(uint32 _MessageIdAlliance, uint32 _MessageIdHorde)
: MessageIdAlliance(_MessageIdAlliance), MessageIdHorde(_MessageIdHorde)
{ }
uint32 MessageIdAlliance;
uint32 MessageIdHorde;
};
struct BattlegroundEYCapturingPointStruct
{
BattlegroundEYCapturingPointStruct(uint32 _MessageIdAlliance, uint32 _MessageIdHorde)
: MessageIdAlliance(_MessageIdAlliance), MessageIdHorde(_MessageIdHorde)
{ }
uint32 MessageIdAlliance;
uint32 MessageIdHorde;
};
class BattlegroundEYControlZoneHandler : public ControlZoneHandler
{
public:
explicit BattlegroundEYControlZoneHandler(uint32 point) : _point(point) { }
uint32 GetPoint() const { return _point; }
private:
uint32 _point;
};
const std::array<BattlegroundEYPointIconsStruct, EY_POINTS_MAX> m_PointsIconStruct =
{
BattlegroundEYPointIconsStruct(FEL_REAVER_UNCONTROL, FEL_REAVER_ALLIANCE_CONTROL, FEL_REAVER_HORDE_CONTROL, FEL_REAVER_ALLIANCE_CONTROL_STATE, FEL_REAVER_HORDE_CONTROL_STATE),
BattlegroundEYPointIconsStruct(BLOOD_ELF_UNCONTROL, BLOOD_ELF_ALLIANCE_CONTROL, BLOOD_ELF_HORDE_CONTROL, BLOOD_ELF_ALLIANCE_CONTROL_STATE, BLOOD_ELF_HORDE_CONTROL_STATE),
BattlegroundEYPointIconsStruct(DRAENEI_RUINS_UNCONTROL, DRAENEI_RUINS_ALLIANCE_CONTROL, DRAENEI_RUINS_HORDE_CONTROL, DRAENEI_RUINS_ALLIANCE_CONTROL_STATE, DRAENEI_RUINS_HORDE_CONTROL_STATE),
BattlegroundEYPointIconsStruct(MAGE_TOWER_UNCONTROL, MAGE_TOWER_ALLIANCE_CONTROL, MAGE_TOWER_HORDE_CONTROL, MAGE_TOWER_ALLIANCE_CONTROL_STATE, MAGE_TOWER_HORDE_CONTROL_STATE)
};
const std::array<BattlegroundEYLosingPointStruct, EY_POINTS_MAX> m_LosingPointTypes =
{
BattlegroundEYLosingPointStruct(BG_EY_TEXT_ALLIANCE_LOST_FEL_REAVER_RUINS, BG_EY_TEXT_HORDE_LOST_FEL_REAVER_RUINS),
BattlegroundEYLosingPointStruct(BG_EY_TEXT_ALLIANCE_LOST_BLOOD_ELF_TOWER, BG_EY_TEXT_HORDE_LOST_BLOOD_ELF_TOWER),
BattlegroundEYLosingPointStruct(BG_EY_TEXT_ALLIANCE_LOST_DRAENEI_RUINS, BG_EY_TEXT_HORDE_LOST_DRAENEI_RUINS),
BattlegroundEYLosingPointStruct(BG_EY_TEXT_ALLIANCE_LOST_MAGE_TOWER, BG_EY_TEXT_HORDE_LOST_MAGE_TOWER)
};
const std::array<BattlegroundEYCapturingPointStruct, EY_POINTS_MAX> m_CapturingPointTypes =
{
BattlegroundEYCapturingPointStruct(BG_EY_TEXT_ALLIANCE_TAKEN_FEL_REAVER_RUINS, BG_EY_TEXT_HORDE_TAKEN_FEL_REAVER_RUINS),
BattlegroundEYCapturingPointStruct(BG_EY_TEXT_ALLIANCE_TAKEN_BLOOD_ELF_TOWER, BG_EY_TEXT_HORDE_TAKEN_BLOOD_ELF_TOWER),
BattlegroundEYCapturingPointStruct(BG_EY_TEXT_ALLIANCE_TAKEN_DRAENEI_RUINS, BG_EY_TEXT_HORDE_TAKEN_DRAENEI_RUINS),
BattlegroundEYCapturingPointStruct(BG_EY_TEXT_ALLIANCE_TAKEN_MAGE_TOWER, BG_EY_TEXT_HORDE_TAKEN_MAGE_TOWER)
};
struct battleground_eye_of_the_storm : BattlegroundScript
{
enum PvpStats
{
PVP_STAT_FLAG_CAPTURES = 183
};
static constexpr Seconds POINTS_TICK_TIME = 2s;
static constexpr Seconds BG_EY_FLAG_ASSAULT_TIMER = 30s;
static constexpr uint16 BG_EY_FLAG_BRUTAL_ASSAULT_STACK_COUNT = 5;
static constexpr uint32 BG_EY_EVENT_START_BATTLE = 13180;
static constexpr std::array<uint8, EY_POINTS_MAX> BG_EY_TickPoints = { 1, 2, 5, 10 };
static constexpr std::array<uint32, EY_POINTS_MAX> BG_EY_FlagPoints = { 75, 85, 100, 500 };
explicit battleground_eye_of_the_storm(BattlegroundMap* map) : BattlegroundScript(map)
{
_honorScoreTics = { 0, 0 };
_honorTics = 0;
_pointsTimer.Reset(POINTS_TICK_TIME);
_assaultEnabled = false;
_assaultStackCount = 0;
_flagAssaultTimer.Reset(BG_EY_FLAG_ASSAULT_TIMER);
_controlZoneHandlers[BG_OBJECT_FR_TOWER_CAP_EY_ENTRY] = std::make_unique<BattlegroundEYControlZoneHandler>(FEL_REAVER);
_controlZoneHandlers[BG_OBJECT_BE_TOWER_CAP_EY_ENTRY] = std::make_unique<BattlegroundEYControlZoneHandler>(BLOOD_ELF);
_controlZoneHandlers[BG_OBJECT_DR_TOWER_CAP_EY_ENTRY] = std::make_unique<BattlegroundEYControlZoneHandler>(DRAENEI_RUINS);
_controlZoneHandlers[BG_OBJECT_HU_TOWER_CAP_EY_ENTRY] = std::make_unique<BattlegroundEYControlZoneHandler>(MAGE_TOWER);
bool isBGWeekend = sBattlegroundMgr->IsBGWeekend(battleground->GetTypeID());
_honorTics = (isBGWeekend) ? BG_EY_EYWeekendHonorTicks : BG_EY_NotEYWeekendHonorTicks;
}
void OnInit() override
{
UpdateWorldState(EY_MAX_RESOURCES, BG_EY_MAX_TEAM_SCORE);
}
void OnUpdate(uint32 diff) override
{
if (battleground->GetStatus() != STATUS_IN_PROGRESS)
return;
_pointsTimer.Update(diff);
if (_pointsTimer.Passed())
{
_pointsTimer.Reset(POINTS_TICK_TIME);
uint8 baseCountAlliance = GetControlledBaseCount(TEAM_ALLIANCE);
uint8 baseCountHorde = GetControlledBaseCount(TEAM_HORDE);
if (baseCountAlliance > 0)
AddPoint(ALLIANCE, BG_EY_TickPoints[baseCountAlliance - 1]);
if (baseCountHorde > 0)
AddPoint(HORDE, BG_EY_TickPoints[baseCountHorde - 1]);
}
if (_assaultEnabled)
{
_flagAssaultTimer.Update(diff);
if (_flagAssaultTimer.Passed())
{
_flagAssaultTimer.Reset(BG_EY_FLAG_ASSAULT_TIMER);
if (_assaultStackCount < std::numeric_limits<uint8>::max())
{
_assaultStackCount++;
// update assault debuff stacks
DoForFlagKeepers([&](Player* player) -> void
{
ApplyAssaultDebuffToPlayer(player);
});
}
}
}
}
void OnStart() override
{
for (ObjectGuid const& door : _doorGUIDs)
{
if (GameObject* gameObject = battlegroundMap->GetGameObject(door))
{
gameObject->UseDoorOrButton();
gameObject->DespawnOrUnsummon(3s);
}
}
// Achievement: Flurry
TriggerGameEvent(BG_EY_EVENT_START_BATTLE);
}
void AddPoint(Team team, uint32 points)
{
battleground->AddPoint(team, points);
TeamId const team_index = Battleground::GetTeamIndexByTeamId(team);
_honorScoreTics[team_index] += points;
if (_honorScoreTics[team_index] >= _honorTics)
{
battleground->RewardHonorToTeam(battleground->GetBonusHonorFromKill(1), team);
_honorScoreTics[team_index] -= _honorTics;
}
UpdateTeamScore(team_index);
}
uint8 GetControlledBaseCount(TeamId teamId) const
{
uint8 baseCount = 0;
for (auto const& controlZoneHandler : _controlZoneHandlers)
{
uint32 point = controlZoneHandler.second->GetPoint();
switch (teamId)
{
case TEAM_ALLIANCE:
if (battlegroundMap->GetWorldStateValue(m_PointsIconStruct[point].WorldStateAllianceControlledIndex) == 1)
baseCount++;
break;
case TEAM_HORDE:
if (battlegroundMap->GetWorldStateValue(m_PointsIconStruct[point].WorldStateHordeControlledIndex) == 1)
baseCount++;
break;
default:
break;
}
}
return baseCount;
}
void DoForFlagKeepers(std::function<void(Player*)> const& action) const
{
if (GameObject const* flag = battlegroundMap->GetGameObject(_flagGUID))
if (Player* carrier = ObjectAccessor::FindPlayer(flag->GetFlagCarrierGUID()))
action(carrier);
}
void ResetAssaultDebuff()
{
_assaultEnabled = false;
_assaultStackCount = 0;
_flagAssaultTimer.Reset(BG_EY_FLAG_ASSAULT_TIMER);
DoForFlagKeepers([&](Player* player) -> void
{
RemoveAssaultDebuffFromPlayer(player);
});
}
void ApplyAssaultDebuffToPlayer(Player* player)
{
if (_assaultStackCount == 0)
return;
uint32 spellId = BG_EY_FOCUSED_ASSAULT_SPELL;
if (_assaultStackCount >= BG_EY_FLAG_BRUTAL_ASSAULT_STACK_COUNT)
{
player->RemoveAurasDueToSpell(BG_EY_FOCUSED_ASSAULT_SPELL);
spellId = BG_EY_BRUTAL_ASSAULT_SPELL;
}
Aura* aura = player->GetAura(spellId);
if (!aura)
{
player->CastSpell(player, spellId, true);
aura = player->GetAura(spellId);
}
if (aura)
aura->SetStackAmount(_assaultStackCount);
}
void RemoveAssaultDebuffFromPlayer(Player* player)
{
player->RemoveAurasDueToSpell(BG_EY_FOCUSED_ASSAULT_SPELL);
player->RemoveAurasDueToSpell(BG_EY_BRUTAL_ASSAULT_SPELL);
}
void UpdateTeamScore(TeamId Team) const
{
uint32 score = battleground->GetTeamScore(Team);
if (score >= BG_EY_MAX_TEAM_SCORE)
{
score = BG_EY_MAX_TEAM_SCORE;
if (Team == TEAM_ALLIANCE)
battleground->EndBattleground(ALLIANCE);
else
battleground->EndBattleground(HORDE);
}
if (Team == TEAM_ALLIANCE)
UpdateWorldState(EY_ALLIANCE_RESOURCES, score);
else
UpdateWorldState(EY_HORDE_RESOURCES, score);
}
void OnEnd(Team winner) override
{
BattlegroundScript::OnEnd(winner);
// Win reward
if (winner == ALLIANCE)
battleground->RewardHonorToTeam(battleground->GetBonusHonorFromKill(1), ALLIANCE);
if (winner == HORDE)
battleground->RewardHonorToTeam(battleground->GetBonusHonorFromKill(1), HORDE);
// Complete map reward
battleground->RewardHonorToTeam(battleground->GetBonusHonorFromKill(1), ALLIANCE);
battleground->RewardHonorToTeam(battleground->GetBonusHonorFromKill(1), HORDE);
}
void UpdatePointsCount(TeamId teamId) const
{
if (teamId == TEAM_ALLIANCE)
UpdateWorldState(EY_ALLIANCE_BASE, GetControlledBaseCount(TEAM_ALLIANCE));
else
UpdateWorldState(EY_HORDE_BASE, GetControlledBaseCount(TEAM_HORDE));
}
void OnGameObjectCreate(GameObject* gameObject) override
{
switch (gameObject->GetEntry())
{
case BG_OBJECT_A_DOOR_EY_ENTRY:
case BG_OBJECT_H_DOOR_EY_ENTRY:
_doorGUIDs.insert(gameObject->GetGUID());
break;
case BG_OBJECT_FLAG2_EY_ENTRY:
_flagGUID = gameObject->GetGUID();
break;
default:
break;
}
}
bool CanCaptureFlag(AreaTrigger* areaTrigger, Player* player) override
{
if (areaTrigger->GetEntry() != AREATRIGGER_CAPTURE_FLAG)
return false;
if (GameObject const* flag = battlegroundMap->GetGameObject(_flagGUID))
{
if (flag->GetFlagCarrierGUID() != player->GetGUID())
return false;
}
if (GameObject const* controlzone = player->FindNearestGameObjectWithOptions(40.0f, { .StringId = "bg_eye_of_the_storm_control_zone" }))
{
uint32 const point = _controlZoneHandlers[controlzone->GetEntry()]->GetPoint();
switch (battleground->GetPlayerTeam(player->GetGUID()))
{
case ALLIANCE:
return battlegroundMap->GetWorldStateValue(m_PointsIconStruct[point].WorldStateAllianceControlledIndex) == 1;
case HORDE:
return battlegroundMap->GetWorldStateValue(m_PointsIconStruct[point].WorldStateHordeControlledIndex) == 1;
default:
return false;
}
}
return false;
}
void OnCaptureFlag(AreaTrigger* areaTrigger, Player* player) override
{
if (areaTrigger->GetEntry() != AREATRIGGER_CAPTURE_FLAG)
return;
uint32 const baseCount = GetControlledBaseCount(Battleground::GetTeamIndexByTeamId(battleground->GetPlayerTeam(player->GetGUID())));
if (GameObject const* gameObject = battlegroundMap->GetGameObject(_flagGUID))
gameObject->HandleCustomTypeCommand(GameObjectType::SetNewFlagState(FlagState::Respawning, player));
Team const team = Team(battleground->GetPlayerTeam(player->GetGUID()));
if (team == ALLIANCE)
{
battleground->SendBroadcastText(BG_EY_TEXT_ALLIANCE_CAPTURED_FLAG, CHAT_MSG_BG_SYSTEM_ALLIANCE, player);
battleground->PlaySoundToAll(BG_EY_SOUND_FLAG_CAPTURED_ALLIANCE);
}
else
{
battleground->SendBroadcastText(BG_EY_TEXT_HORDE_CAPTURED_FLAG, CHAT_MSG_BG_SYSTEM_HORDE, player);
battleground->PlaySoundToAll(BG_EY_SOUND_FLAG_CAPTURED_HORDE);
}
if (baseCount > 0)
AddPoint(team, BG_EY_FlagPoints[baseCount - 1]);
UpdateWorldState(NETHERSTORM_FLAG_STATE_HORDE, BG_EY_FLAG_STATE_ON_BASE);
UpdateWorldState(NETHERSTORM_FLAG_STATE_ALLIANCE, BG_EY_FLAG_STATE_ON_BASE);
battleground->UpdatePvpStat(player, PVP_STAT_FLAG_CAPTURES, 1);
ResetAssaultDebuff();
player->RemoveAurasDueToSpell(BG_EY_NETHERSTORM_FLAG_SPELL);
player->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::PvPActive);
}
void OnFlagStateChange(GameObject* /*flagInBase*/, FlagState /*oldValue*/, FlagState newValue, Player* player) override
{
switch (newValue)
{
case FlagState::InBase:
ResetAssaultDebuff();
break;
case FlagState::Dropped:
player->CastSpell(player, SPELL_RECENTLY_DROPPED_NEUTRAL_FLAG, true);
RemoveAssaultDebuffFromPlayer(player);
UpdateWorldState(NETHERSTORM_FLAG_STATE_HORDE, BG_EY_FLAG_STATE_WAIT_RESPAWN);
UpdateWorldState(NETHERSTORM_FLAG_STATE_ALLIANCE, BG_EY_FLAG_STATE_WAIT_RESPAWN);
if (battleground->GetPlayerTeam(player->GetGUID()) == ALLIANCE)
battleground->SendBroadcastText(BG_EY_TEXT_FLAG_DROPPED, CHAT_MSG_BG_SYSTEM_ALLIANCE);
else
battleground->SendBroadcastText(BG_EY_TEXT_FLAG_DROPPED, CHAT_MSG_BG_SYSTEM_HORDE);
break;
case FlagState::Taken:
if (battleground->GetPlayerTeam(player->GetGUID()) == ALLIANCE)
{
UpdateWorldState(NETHERSTORM_FLAG_STATE_ALLIANCE, BG_EY_FLAG_STATE_ON_PLAYER);
battleground->PlaySoundToAll(BG_EY_SOUND_FLAG_PICKED_UP_ALLIANCE);
battleground->SendBroadcastText(BG_EY_TEXT_TAKEN_FLAG, CHAT_MSG_BG_SYSTEM_ALLIANCE, player);
}
else
{
UpdateWorldState(NETHERSTORM_FLAG_STATE_HORDE, BG_EY_FLAG_STATE_ON_PLAYER);
battleground->PlaySoundToAll(BG_EY_SOUND_FLAG_PICKED_UP_HORDE);
battleground->SendBroadcastText(BG_EY_TEXT_TAKEN_FLAG, CHAT_MSG_BG_SYSTEM_HORDE, player);
}
ApplyAssaultDebuffToPlayer(player);
_assaultEnabled = true;
player->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::PvPActive);
break;
case FlagState::Respawning:
ResetAssaultDebuff();
break;
default:
break;
}
UpdateWorldState(NETHERSTORM_FLAG, AsUnderlyingType(newValue));
}
void EventTeamLostPoint(TeamId teamId, uint32 point, GameObject* controlZone) const
{
if (teamId == TEAM_ALLIANCE)
{
battleground->SendBroadcastText(m_LosingPointTypes[point].MessageIdAlliance, CHAT_MSG_BG_SYSTEM_ALLIANCE, controlZone);
UpdateWorldState(m_PointsIconStruct[point].WorldStateAllianceControlledIndex, 0);
}
else if (teamId == TEAM_HORDE)
{
battleground->SendBroadcastText(m_LosingPointTypes[point].MessageIdHorde, CHAT_MSG_BG_SYSTEM_HORDE, controlZone);
UpdateWorldState(m_PointsIconStruct[point].WorldStateHordeControlledIndex, 0);
}
UpdateWorldState(m_PointsIconStruct[point].WorldStateControlIndex, 1);
UpdatePointsCount(teamId);
}
void EventTeamCapturedPoint(TeamId teamId, uint32 point, GameObject* controlZone) const
{
if (teamId == TEAM_ALLIANCE)
{
battleground->SendBroadcastText(m_CapturingPointTypes[point].MessageIdAlliance, CHAT_MSG_BG_SYSTEM_ALLIANCE, controlZone);
UpdateWorldState(m_PointsIconStruct[point].WorldStateAllianceControlledIndex, 1);
}
else if (teamId == TEAM_HORDE)
{
battleground->SendBroadcastText(m_CapturingPointTypes[point].MessageIdHorde, CHAT_MSG_BG_SYSTEM_HORDE, controlZone);
UpdateWorldState(m_PointsIconStruct[point].WorldStateHordeControlledIndex, 1);
}
UpdateWorldState(m_PointsIconStruct[point].WorldStateControlIndex, 0);
UpdatePointsCount(teamId);
}
Team GetPrematureWinner() override
{
if (battleground->GetTeamScore(TEAM_ALLIANCE) > battleground->GetTeamScore(TEAM_HORDE))
return ALLIANCE;
if (battleground->GetTeamScore(TEAM_HORDE) > battleground->GetTeamScore(TEAM_ALLIANCE))
return HORDE;
return BattlegroundScript::GetPrematureWinner();
}
void ProcessEvent(WorldObject* obj, uint32 eventId, WorldObject* invoker) override
{
BattlegroundScript::ProcessEvent(obj, eventId, invoker);
if (invoker)
{
if (GameObject* gameobject = invoker->ToGameObject())
{
if (gameobject->GetGoType() == GAMEOBJECT_TYPE_CONTROL_ZONE)
{
if (!_controlZoneHandlers.contains(gameobject->GetEntry()))
return;
auto controlzone = gameobject->GetGOInfo()->controlZone;
BattlegroundEYControlZoneHandler& handler = *_controlZoneHandlers[invoker->GetEntry()];
if (eventId == controlzone.NeutralEventAlliance)
EventTeamLostPoint(TEAM_ALLIANCE, handler.GetPoint(), gameobject);
else if (eventId == controlzone.NeutralEventHorde)
EventTeamLostPoint(TEAM_HORDE, handler.GetPoint(), gameobject);
else if (eventId == controlzone.ProgressEventAlliance)
EventTeamCapturedPoint(TEAM_ALLIANCE, handler.GetPoint(), gameobject);
else if (eventId == controlzone.ProgressEventHorde)
EventTeamCapturedPoint(TEAM_HORDE, handler.GetPoint(), gameobject);
}
}
}
}
private:
std::array<uint32, PVP_TEAMS_COUNT> _honorScoreTics;
TimeTracker _pointsTimer;
uint32 _honorTics;
std::unordered_map<uint32, std::unique_ptr<BattlegroundEYControlZoneHandler>> _controlZoneHandlers;
GuidUnorderedSet _doorGUIDs;
ObjectGuid _flagGUID;
// Focused/Brutal Assault
bool _assaultEnabled;
TimeTracker _flagAssaultTimer;
uint8 _assaultStackCount;
};
void AddSC_battleground_eye_of_the_storm()
{
RegisterBattlegroundMapScript(battleground_eye_of_the_storm, 566);
}

View File

@@ -0,0 +1,902 @@
/*
* 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 "BattlegroundScript.h"
#include "Battleground.h"
#include "BattlegroundMgr.h"
#include "GameTime.h"
#include "isle_of_conquest.h"
#include "Map.h"
#include "Player.h"
#include "ScriptMgr.h"
#include "TaskScheduler.h"
#include "TemporarySummon.h"
#include "Timer.h"
#include "Transport.h"
#include "TransportMgr.h"
#include "Vehicle.h"
inline constexpr uint16 MAX_REINFORCEMENTS = 400;
enum BannersTypes
{
BANNER_A_CONTROLLED,
BANNER_A_CONTESTED,
BANNER_H_CONTROLLED,
BANNER_H_CONTESTED
};
enum BG_IC_ExploitTeleportLocations
{
IC_EXPLOIT_TELEPORT_LOCATION_ALLIANCE = 3986,
IC_EXPLOIT_TELEPORT_LOCATION_HORDE = 3983
};
enum BG_IC_GateState
{
BG_IC_GATE_OK = 1,
BG_IC_GATE_DAMAGED = 2,
BG_IC_GATE_DESTROYED = 3
};
enum ICDoorList
{
BG_IC_H_FRONT,
BG_IC_H_WEST,
BG_IC_H_EAST,
BG_IC_A_FRONT,
BG_IC_A_WEST,
BG_IC_A_EAST,
BG_IC_MAXDOOR
};
enum ICNodePointType
{
NODE_TYPE_REFINERY,
NODE_TYPE_QUARRY,
NODE_TYPE_DOCKS,
NODE_TYPE_HANGAR,
NODE_TYPE_WORKSHOP,
// Graveyards
NODE_TYPE_GRAVEYARD_A,
NODE_TYPE_GRAVEYARD_H,
MAX_NODE_TYPES
};
enum class IsleOfConquestNodeState
{
Neutral,
ConflictA,
ConflictH,
ControlledA,
ControlledH
};
enum ICBroadcastTexts
{
BG_IC_TEXT_FRONT_GATE_HORDE_DESTROYED = 35409,
BG_IC_TEXT_FRONT_GATE_ALLIANCE_DESTROYED = 35410,
BG_IC_TEXT_WEST_GATE_HORDE_DESTROYED = 35411,
BG_IC_TEXT_WEST_GATE_ALLIANCE_DESTROYED = 35412,
BG_IC_TEXT_EAST_GATE_HORDE_DESTROYED = 35413,
BG_IC_TEXT_EAST_GATE_ALLIANCE_DESTROYED = 35414
};
// I.E: Hangar, Quarry, Graveyards .. etc
struct IoCStaticNodeInfo
{
ICNodePointType NodeType;
struct
{
uint32 Assaulted;
uint32 Defended;
uint32 AllianceTaken;
uint32 HordeTaken;
} TextIds;
struct
{
int32 Uncontrolled;
int32 ConflictA;
int32 ConflictH;
int32 ControlledA;
int32 ControlledH;
} WorldStateIds;
};
class ICNodePoint
{
public:
explicit ICNodePoint(IsleOfConquestNodeState state, IoCStaticNodeInfo const& nodeInfo) : _state(state), _nodeInfo(nodeInfo)
{
switch (state)
{
case IsleOfConquestNodeState::ControlledH:
_lastControlled = TEAM_HORDE;
break;
case IsleOfConquestNodeState::ControlledA:
_lastControlled = TEAM_ALLIANCE;
break;
case IsleOfConquestNodeState::ConflictA:
case IsleOfConquestNodeState::ConflictH:
case IsleOfConquestNodeState::Neutral:
_lastControlled = TEAM_NEUTRAL;
break;
}
}
IsleOfConquestNodeState GetState() const { return _state; }
bool IsContested() const
{
return _state == IsleOfConquestNodeState::ConflictA || _state == IsleOfConquestNodeState::ConflictH;
}
TeamId GetLastControlledTeam() const { return _lastControlled; }
IoCStaticNodeInfo const& GetNodeInfo() const { return _nodeInfo; }
void UpdateState(IsleOfConquestNodeState state)
{
switch (state)
{
case IsleOfConquestNodeState::ControlledA:
_lastControlled = TEAM_ALLIANCE;
break;
case IsleOfConquestNodeState::ControlledH:
_lastControlled = TEAM_HORDE;
break;
case IsleOfConquestNodeState::Neutral:
_lastControlled = TEAM_NEUTRAL;
break;
case IsleOfConquestNodeState::ConflictA:
case IsleOfConquestNodeState::ConflictH:
break;
}
_state = state;
}
private:
IsleOfConquestNodeState _state;
TeamId _lastControlled;
IoCStaticNodeInfo _nodeInfo;
};
const IoCStaticNodeInfo nodePointInitial[MAX_NODE_TYPES] =
{
{ NODE_TYPE_REFINERY, { 35377, 35378, 35379, 35380 }, { BG_IC_REFINERY_UNCONTROLLED, BG_IC_REFINERY_CONFLICT_A, BG_IC_REFINERY_CONFLICT_H, BG_IC_REFINERY_CONTROLLED_A, BG_IC_REFINERY_CONTROLLED_H } },
{ NODE_TYPE_QUARRY, { 35373, 35374, 35375, 35376 }, { BG_IC_QUARRY_UNCONTROLLED, BG_IC_QUARRY_CONFLICT_A, BG_IC_QUARRY_CONFLICT_H, BG_IC_QUARRY_CONTROLLED_A, BG_IC_QUARRY_CONTROLLED_H } },
{ NODE_TYPE_DOCKS, { 35365, 35366, 35367, 35368 }, { BG_IC_DOCKS_UNCONTROLLED, BG_IC_DOCKS_CONFLICT_A, BG_IC_DOCKS_CONFLICT_H, BG_IC_DOCKS_CONTROLLED_A, BG_IC_DOCKS_CONTROLLED_H } },
{ NODE_TYPE_HANGAR, { 35369, 35370, 35371, 35372 }, { BG_IC_HANGAR_UNCONTROLLED, BG_IC_HANGAR_CONFLICT_A, BG_IC_HANGAR_CONFLICT_H, BG_IC_HANGAR_CONTROLLED_A, BG_IC_HANGAR_CONTROLLED_H } },
{ NODE_TYPE_WORKSHOP, { 35278, 35286, 35279, 35280 }, { BG_IC_WORKSHOP_UNCONTROLLED, BG_IC_WORKSHOP_CONFLICT_A, BG_IC_WORKSHOP_CONFLICT_H, BG_IC_WORKSHOP_CONTROLLED_A, BG_IC_WORKSHOP_CONTROLLED_H } },
{ NODE_TYPE_GRAVEYARD_A, { 35461, 35459, 35463, 35466 }, { BG_IC_ALLIANCE_KEEP_UNCONTROLLED, BG_IC_ALLIANCE_KEEP_CONFLICT_A, BG_IC_ALLIANCE_KEEP_CONFLICT_H, BG_IC_ALLIANCE_KEEP_CONTROLLED_A, BG_IC_ALLIANCE_KEEP_CONTROLLED_H } },
{ NODE_TYPE_GRAVEYARD_H, { 35462, 35460, 35464, 35465 }, { BG_IC_HORDE_KEEP_UNCONTROLLED, BG_IC_HORDE_KEEP_CONFLICT_A, BG_IC_HORDE_KEEP_CONFLICT_H, BG_IC_HORDE_KEEP_CONTROLLED_A, BG_IC_HORDE_KEEP_CONTROLLED_H } }
};
enum HonorRewards
{
RESOURCE_HONOR_AMOUNT = 12,
WINNER_HONOR_AMOUNT = 500
};
enum IsleOfConquestPvpStats
{
PVP_STAT_BASES_ASSAULTED = 245,
PVP_STAT_BASES_DEFENDED = 246
};
enum IsleOfConquestGameObjects
{
GO_TELEPORTER_1 = 195314, // 195314 H-OUT 66549
GO_TELEPORTER_2 = 195313, // 195313 H-IN 66548
GO_TELEPORTER_3 = 195315, // 195315 A-OUT 66549
GO_TELEPORTER_4 = 195316, // 195316 A-IN 66548
GO_TELEPORTER_EFFECTS_A = 195701,
GO_TELEPORTER_EFFECTS_H = 195702,
GO_DOODAD_HU_PORTCULLIS01 = 195436,
GO_DOODAD_ND_HUMAN_GATE_CLOSEDFX_DOOR01 = 195703,
GO_DOODAD_PORTCULLISACTIVE02 = 195452,
GO_DOODAD_VR_PORTCULLIS01 = 195437,
GO_HORDE_GATE_1 = 195494,
GO_HORDE_GATE_2 = 195495,
GO_HORDE_GATE_3 = 195496,
GO_ALLIANCE_GATE_1 = 195699,
GO_ALLIANCE_GATE_2 = 195700,
GO_ALLIANCE_GATE_3 = 195698,
GO_DOODAD_ND_WINTERORC_WALL_GATEFX_DOOR01 = 195491,
// banners
GO_BANNER_WORKSHOP_CONTROLLED_H = 195130,
GO_BANNER_WORKSHOP_CONTROLLED_A = 195132,
GO_BANNER_WORKSHOP_CONTROLLED_N = 195133,
GO_BANNER_WORKSHOP_CONTESTED_A = 195144,
GO_BANNER_WORKSHOP_CONTESTED_H = 195145,
GO_BANNER_DOCKS_CONTROLLED_A = 195149,
GO_BANNER_DOCKS_CONTESTED_A = 195150,
GO_BANNER_DOCKS_CONTROLLED_H = 195151,
GO_BANNER_DOCKS_CONTESTED_H = 195152,
GO_BANNER_DOCKS_CONTROLLED_N = 195157,
GO_BANNER_HANGAR_CONTROLLED_A = 195153,
GO_BANNER_HANGAR_CONTESTED_A = 195154,
GO_BANNER_HANGAR_CONTROLLED_H = 195155,
GO_BANNER_HANGAR_CONTESTED_H = 195156,
GO_BANNER_HANGAR_CONTROLLED_N = 195158,
GO_BANNER_QUARRY_CONTROLLED_A = 195334,
GO_BANNER_QUARRY_CONTROLLED_H = 195336,
GO_BANNER_QUARRY_CONTESTED_A = 195335,
GO_BANNER_QUARRY_CONTESTED_H = 195337,
GO_BANNER_QUARRY_CONTROLLED_N = 195338,
GO_BANNER_REFINERY_CONTROLLED_A = 195339,
GO_BANNER_REFINERY_CONTROLLED_H = 195341,
GO_BANNER_REFINERY_CONTESTED_A = 195340,
GO_BANNER_REFINERY_CONTESTED_H = 195342,
GO_BANNER_REFINERY_CONTROLLED_N = 195343,
GO_BANNER_HORDE_KEEP_CONTROLLED_A = 195391,
GO_BANNER_HORDE_KEEP_CONTROLLED_H = 195393,
GO_BANNER_HORDE_KEEP_CONTESTED_A = 195392,
GO_BANNER_HORDE_KEEP_CONTESTED_H = 195394,
GO_BANNER_ALLIANCE_KEEP_CONTROLLED_A = 195396,
GO_BANNER_ALLIANCE_KEEP_CONTROLLED_H = 195398,
GO_BANNER_ALLIANCE_KEEP_CONTESTED_A = 195397,
GO_BANNER_ALLIANCE_KEEP_CONTESTED_H = 195399,
GO_KEEP_GATE_H = 195223,
GO_KEEP_GATE_A = 195451,
GO_KEEP_GATE_2_A = 195452,
GO_HORDE_GUNSHIP = 195276,
GO_ALLIANCE_GUNSHIP = 195121
};
static constexpr Seconds IOC_RESOURCE_TIMER = 45s;
static constexpr Position GunshipTeleportTriggerPosition[2] =
{
{ 11.69964981079101562f, 0.034145999699831008f, 20.62075996398925781f, 3.211405754089355468f },
{ 7.30560922622680664f, -0.09524600207805633f, 34.51021575927734375f, 3.159045934677124023f }
};
struct battleground_isle_of_conquest : BattlegroundScript
{
explicit battleground_isle_of_conquest(BattlegroundMap* map) : BattlegroundScript(map)
{
_factionReinforcements = { MAX_REINFORCEMENTS, MAX_REINFORCEMENTS };
_gateStatus = { BG_IC_GATE_OK, BG_IC_GATE_OK, BG_IC_GATE_OK, BG_IC_GATE_OK, BG_IC_GATE_OK, BG_IC_GATE_OK };
_gunshipGUIDs = { };
_cannonGUIDs = { };
_nodePoints = { };
_keepGateGUIDs = { };
_keepBannerGUIDs = { };
_nodePoints[NODE_TYPE_REFINERY] = std::make_unique<ICNodePoint>(IsleOfConquestNodeState::Neutral, nodePointInitial[NODE_TYPE_REFINERY]);
_nodePoints[NODE_TYPE_QUARRY] = std::make_unique<ICNodePoint>(IsleOfConquestNodeState::Neutral, nodePointInitial[NODE_TYPE_QUARRY]);
_nodePoints[NODE_TYPE_DOCKS] = std::make_unique<ICNodePoint>(IsleOfConquestNodeState::Neutral, nodePointInitial[NODE_TYPE_DOCKS]);
_nodePoints[NODE_TYPE_HANGAR] = std::make_unique<ICNodePoint>(IsleOfConquestNodeState::Neutral, nodePointInitial[NODE_TYPE_HANGAR]);
_nodePoints[NODE_TYPE_WORKSHOP] = std::make_unique<ICNodePoint>(IsleOfConquestNodeState::Neutral, nodePointInitial[NODE_TYPE_WORKSHOP]);
_nodePoints[NODE_TYPE_GRAVEYARD_A] = std::make_unique<ICNodePoint>(IsleOfConquestNodeState::ControlledA, nodePointInitial[NODE_TYPE_GRAVEYARD_A]);
_nodePoints[NODE_TYPE_GRAVEYARD_H] = std::make_unique<ICNodePoint>(IsleOfConquestNodeState::ControlledH, nodePointInitial[NODE_TYPE_GRAVEYARD_H]);
_resourceTimer.Reset(IOC_RESOURCE_TIMER);
}
void OnUpdate(uint32 diff) override
{
BattlegroundScript::OnUpdate(diff);
if (battleground->GetStatus() != STATUS_IN_PROGRESS)
return;
_scheduler.Update(diff);
_resourceTimer.Update(diff);
if (_resourceTimer.Passed())
{
for (uint8 i = 0; i < NODE_TYPE_DOCKS; ++i)
{
if (_nodePoints[i]->GetLastControlledTeam() != TEAM_NEUTRAL && !_nodePoints[i]->IsContested())
{
_factionReinforcements[_nodePoints[i]->GetLastControlledTeam()] += 1;
battleground->RewardHonorToTeam(RESOURCE_HONOR_AMOUNT, _nodePoints[i]->GetLastControlledTeam() == TEAM_ALLIANCE ? ALLIANCE : HORDE);
UpdateWorldState((_nodePoints[i]->GetLastControlledTeam() == TEAM_ALLIANCE ? BG_IC_ALLIANCE_REINFORCEMENTS : BG_IC_HORDE_REINFORCEMENTS), _factionReinforcements[_nodePoints[i]->GetLastControlledTeam()]);
}
}
_resourceTimer.Reset(IOC_RESOURCE_TIMER);
}
}
void OnStart() override
{
BattlegroundScript::OnStart();
auto gameobjectAction = [&](GuidVector const& guids, std::function<void(GameObject*)> const& action) -> void
{
for (ObjectGuid const& guid : guids)
if (GameObject* gameObject = battlegroundMap->GetGameObject(guid))
action(gameObject);
};
gameobjectAction(_mainGateDoorGUIDs, [&](GameObject* gameobject) -> void
{
gameobject->UseDoorOrButton();
gameobject->DespawnOrUnsummon(20s);
});
gameobjectAction(_portcullisGUIDs, [&](GameObject* gameobject) -> void
{
gameobject->UseDoorOrButton();
});
gameobjectAction(_teleporterGUIDs, [&](GameObject* gameobject) -> void
{
gameobject->RemoveFlag(GO_FLAG_NOT_SELECTABLE);
});
gameobjectAction(_teleporterEffectGUIDs, [&](GameObject* gameobject) -> void
{
gameobject->SetGoState(GO_STATE_ACTIVE);
});
_scheduler.Schedule(20s, [&](TaskContext)
{
for (ObjectGuid const& guid : _wallGUIDs)
if (GameObject* gameobject = battlegroundMap->GetGameObject(guid))
gameobject->SetDestructibleState(GO_DESTRUCTIBLE_DAMAGED);
});
}
void OnUnitKilled(Creature* unit, Unit* killer) override
{
BattlegroundScript::OnUnitKilled(unit, killer);
if (battleground->GetStatus() != STATUS_IN_PROGRESS)
return;
uint32 entry = unit->GetEntry();
if (entry == NPC_HIGH_COMMANDER_HALFORD_WYRMBANE)
{
battleground->RewardHonorToTeam(WINNER_HONOR_AMOUNT, HORDE);
battleground->EndBattleground(HORDE);
}
else if (entry == NPC_OVERLORD_AGMAR)
{
battleground->RewardHonorToTeam(WINNER_HONOR_AMOUNT, ALLIANCE);
battleground->EndBattleground(ALLIANCE);
}
//Achievement Mowed Down
// TO-DO: This should be done on the script of each vehicle of the BG.
if (unit->IsVehicle())
{
if (Player* killerPlayer = killer->GetCharmerOrOwnerPlayerOrPlayerItself())
killerPlayer->CastSpell(killerPlayer, SPELL_DESTROYED_VEHICLE_ACHIEVEMENT, true);
}
}
void OnPlayerKilled(Player* player, Player* killer) override
{
BattlegroundScript::OnPlayerKilled(player, killer);
if (battleground->GetStatus() != STATUS_IN_PROGRESS)
return;
TeamId const victimTeamId = Battleground::GetTeamIndexByTeamId(battleground->GetPlayerTeam(player->GetGUID()));
_factionReinforcements[victimTeamId] -= 1;
UpdateWorldState((battleground->GetPlayerTeam(player->GetGUID()) == ALLIANCE ? BG_IC_ALLIANCE_REINFORCEMENTS : BG_IC_HORDE_REINFORCEMENTS), _factionReinforcements[victimTeamId]);
// we must end the battleground
if (_factionReinforcements[victimTeamId] < 1)
battleground->EndBattleground(battleground->GetPlayerTeam(killer->GetGUID()));
}
static uint32 GetGateIDFromEntry(uint32 id)
{
switch (id)
{
case GO_HORDE_GATE_1:
return BG_IC_H_FRONT;
case GO_HORDE_GATE_2:
return BG_IC_H_WEST;
case GO_HORDE_GATE_3:
return BG_IC_H_EAST;
case GO_ALLIANCE_GATE_3:
return BG_IC_A_FRONT;
case GO_ALLIANCE_GATE_1:
return BG_IC_A_WEST;
case GO_ALLIANCE_GATE_2:
return BG_IC_A_EAST;
default:
return 0;
}
}
static int32 GetWorldStateFromGateEntry(uint32 id, bool open)
{
int32 uws = 0;
switch (id)
{
case GO_HORDE_GATE_1:
uws = (open ? BG_IC_GATE_FRONT_H_WS_OPEN : BG_IC_GATE_FRONT_H_WS_CLOSED);
break;
case GO_HORDE_GATE_2:
uws = (open ? BG_IC_GATE_WEST_H_WS_OPEN : BG_IC_GATE_WEST_H_WS_CLOSED);
break;
case GO_HORDE_GATE_3:
uws = (open ? BG_IC_GATE_EAST_H_WS_OPEN : BG_IC_GATE_EAST_H_WS_CLOSED);
break;
case GO_ALLIANCE_GATE_3:
uws = (open ? BG_IC_GATE_FRONT_A_WS_OPEN : BG_IC_GATE_FRONT_A_WS_CLOSED);
break;
case GO_ALLIANCE_GATE_1:
uws = (open ? BG_IC_GATE_WEST_A_WS_OPEN : BG_IC_GATE_WEST_A_WS_CLOSED);
break;
case GO_ALLIANCE_GATE_2:
uws = (open ? BG_IC_GATE_EAST_A_WS_OPEN : BG_IC_GATE_EAST_A_WS_CLOSED);
break;
default:
break;
}
return uws;
}
void UpdateNodeWorldState(ICNodePoint const& node) const
{
UpdateWorldState(node.GetNodeInfo().WorldStateIds.ConflictA, node.GetState() == IsleOfConquestNodeState::ConflictA);
UpdateWorldState(node.GetNodeInfo().WorldStateIds.ConflictH, node.GetState() == IsleOfConquestNodeState::ConflictH);
UpdateWorldState(node.GetNodeInfo().WorldStateIds.ControlledA, node.GetState() == IsleOfConquestNodeState::ControlledA);
UpdateWorldState(node.GetNodeInfo().WorldStateIds.ControlledH, node.GetState() == IsleOfConquestNodeState::ControlledH);
UpdateWorldState(node.GetNodeInfo().WorldStateIds.Uncontrolled, node.GetState() == IsleOfConquestNodeState::Neutral);
}
static ICNodePointType BannerToNodeType(uint32 bannerId)
{
switch (bannerId)
{
case GO_BANNER_ALLIANCE_KEEP_CONTESTED_A:
case GO_BANNER_ALLIANCE_KEEP_CONTESTED_H:
case GO_BANNER_ALLIANCE_KEEP_CONTROLLED_A:
case GO_BANNER_ALLIANCE_KEEP_CONTROLLED_H:
return NODE_TYPE_GRAVEYARD_A;
case GO_BANNER_HORDE_KEEP_CONTESTED_A:
case GO_BANNER_HORDE_KEEP_CONTESTED_H:
case GO_BANNER_HORDE_KEEP_CONTROLLED_A:
case GO_BANNER_HORDE_KEEP_CONTROLLED_H:
return NODE_TYPE_GRAVEYARD_H;
case GO_BANNER_DOCKS_CONTESTED_A:
case GO_BANNER_DOCKS_CONTESTED_H:
case GO_BANNER_DOCKS_CONTROLLED_A:
case GO_BANNER_DOCKS_CONTROLLED_H:
case GO_BANNER_DOCKS_CONTROLLED_N:
return NODE_TYPE_DOCKS;
case GO_BANNER_HANGAR_CONTESTED_A:
case GO_BANNER_HANGAR_CONTESTED_H:
case GO_BANNER_HANGAR_CONTROLLED_A:
case GO_BANNER_HANGAR_CONTROLLED_H:
case GO_BANNER_HANGAR_CONTROLLED_N:
return NODE_TYPE_HANGAR;
case GO_BANNER_WORKSHOP_CONTESTED_A:
case GO_BANNER_WORKSHOP_CONTESTED_H:
case GO_BANNER_WORKSHOP_CONTROLLED_A:
case GO_BANNER_WORKSHOP_CONTROLLED_H:
case GO_BANNER_WORKSHOP_CONTROLLED_N:
return NODE_TYPE_WORKSHOP;
case GO_BANNER_QUARRY_CONTESTED_A:
case GO_BANNER_QUARRY_CONTESTED_H:
case GO_BANNER_QUARRY_CONTROLLED_A:
case GO_BANNER_QUARRY_CONTROLLED_H:
case GO_BANNER_QUARRY_CONTROLLED_N:
return NODE_TYPE_QUARRY;
case GO_BANNER_REFINERY_CONTESTED_A:
case GO_BANNER_REFINERY_CONTESTED_H:
case GO_BANNER_REFINERY_CONTROLLED_A:
case GO_BANNER_REFINERY_CONTROLLED_H:
case GO_BANNER_REFINERY_CONTROLLED_N:
return NODE_TYPE_REFINERY;
default:
break;
}
return MAX_NODE_TYPES;
}
void HandleCapturedNodes(ICNodePoint& node)
{
if (node.GetLastControlledTeam() == TEAM_NEUTRAL)
return;
switch (node.GetNodeInfo().NodeType)
{
case NODE_TYPE_QUARRY:
case NODE_TYPE_REFINERY:
battlegroundMap->UpdateAreaDependentAuras();
break;
case NODE_TYPE_HANGAR:
if (Transport* transport = battlegroundMap->GetTransport(_gunshipGUIDs[node.GetLastControlledTeam()]))
{
// Can't have this in spawngroup, creature is on a transport
if (TempSummon* trigger = transport->SummonPassenger(NPC_WORLD_TRIGGER_NOT_FLOATING, GunshipTeleportTriggerPosition[node.GetLastControlledTeam()], TEMPSUMMON_MANUAL_DESPAWN))
_gunshipTeleportTarget = trigger->GetGUID();
transport->EnableMovement(true);
}
for (ObjectGuid const& guid : _cannonGUIDs[node.GetLastControlledTeam()])
if (Creature* cannon = battlegroundMap->GetCreature(guid))
cannon->SetUninteractible(false);
break;
default:
break;
}
}
void OnCreatureCreate(Creature* creature) override
{
BattlegroundScript::OnCreatureCreate(creature);
if (creature->HasStringId("bg_ioc_faction_1735"))
creature->SetFaction(FACTION_HORDE_GENERIC_WG);
else if (creature->HasStringId("bg_ioc_faction_1732"))
creature->SetFaction(FACTION_ALLIANCE_GENERIC_WG);
switch (creature->GetEntry())
{
case NPC_ALLIANCE_GUNSHIP_CANNON:
_cannonGUIDs[TEAM_ALLIANCE].emplace_back(creature->GetGUID());
creature->SetUninteractible(true);
creature->SetControlled(true, UNIT_STATE_ROOT);
break;
case NPC_HORDE_GUNSHIP_CANNON:
_cannonGUIDs[TEAM_HORDE].emplace_back(creature->GetGUID());
creature->SetUninteractible(true);
creature->SetControlled(true, UNIT_STATE_ROOT);
break;
default:
break;
}
}
void OnGameObjectCreate(GameObject* gameobject) override
{
BattlegroundScript::OnGameObjectCreate(gameobject);
if (gameobject->IsDestructibleBuilding())
_wallGUIDs.emplace_back(gameobject->GetGUID());
if (gameobject->HasStringId("bg_ioc_faction_1735"))
gameobject->SetFaction(FACTION_HORDE_GENERIC_WG);
else if (gameobject->HasStringId("bg_ioc_faction_1732"))
gameobject->SetFaction(FACTION_ALLIANCE_GENERIC_WG);
switch (gameobject->GetEntry())
{
case GO_TELEPORTER_1:
case GO_TELEPORTER_2:
case GO_TELEPORTER_3:
case GO_TELEPORTER_4:
_teleporterGUIDs.emplace_back(gameobject->GetGUID());
break;
case GO_TELEPORTER_EFFECTS_A:
case GO_TELEPORTER_EFFECTS_H:
_teleporterEffectGUIDs.emplace_back(gameobject->GetGUID());
break;
case GO_DOODAD_ND_HUMAN_GATE_CLOSEDFX_DOOR01:
case GO_DOODAD_ND_WINTERORC_WALL_GATEFX_DOOR01:
_mainGateDoorGUIDs.emplace_back(gameobject->GetGUID());
break;
case GO_DOODAD_HU_PORTCULLIS01:
case GO_DOODAD_VR_PORTCULLIS01:
_portcullisGUIDs.emplace_back(gameobject->GetGUID());
break;
case GO_KEEP_GATE_H:
_keepGateGUIDs[TEAM_HORDE].emplace_back(gameobject->GetGUID());
break;
case GO_KEEP_GATE_A:
case GO_KEEP_GATE_2_A:
_keepGateGUIDs[TEAM_ALLIANCE].emplace_back(gameobject->GetGUID());
break;
case GO_BANNER_ALLIANCE_KEEP_CONTROLLED_A:
_keepBannerGUIDs[TEAM_ALLIANCE] = gameobject->GetGUID();
break;
case GO_BANNER_HORDE_KEEP_CONTROLLED_H:
_keepBannerGUIDs[TEAM_HORDE] = gameobject->GetGUID();
break;
default:
break;
}
}
void OnInit() override
{
BattlegroundScript::OnInit();
if (Transport* transport = sTransportMgr->CreateTransport(GO_HORDE_GUNSHIP, battlegroundMap))
{
_gunshipGUIDs[TEAM_HORDE] = transport->GetGUID();
transport->EnableMovement(false);
}
if (Transport* transport = sTransportMgr->CreateTransport(GO_ALLIANCE_GUNSHIP, battlegroundMap))
{
_gunshipGUIDs[TEAM_ALLIANCE] = transport->GetGUID();
transport->EnableMovement(false);
}
}
void DoAction(uint32 actionId, WorldObject* source, WorldObject* target) override
{
BattlegroundScript::DoAction(actionId, source, target);
switch (actionId)
{
case ACTION_IOC_INTERACT_CAPTURABLE_OBJECT:
OnPlayerInteractWithBanner(WorldObject::ToPlayer(source), WorldObject::ToGameObject(target));
break;
case ACTION_IOC_CAPTURE_CAPTURABLE_OBJECT:
HandleCaptureNodeAction(WorldObject::ToGameObject(target));
break;
default:
break;
}
}
void OnPlayerInteractWithBanner(Player* player, GameObject* banner)
{
if (!player || !banner)
return;
Team const playerTeam = battleground->GetPlayerTeam(player->GetGUID());
TeamId const playerTeamId = Battleground::GetTeamIndexByTeamId(playerTeam);
ICNodePointType const nodeType = BannerToNodeType(banner->GetEntry());
if (nodeType == MAX_NODE_TYPES)
return;
ICNodePoint& node = *_nodePoints[nodeType];
bool assault = false;
bool defend = false;
switch (node.GetState())
{
case IsleOfConquestNodeState::Neutral:
assault = true;
break;
case IsleOfConquestNodeState::ControlledH:
assault = playerTeamId != TEAM_HORDE;
break;
case IsleOfConquestNodeState::ControlledA:
assault = playerTeamId != TEAM_ALLIANCE;
break;
case IsleOfConquestNodeState::ConflictA:
defend = playerTeamId == node.GetLastControlledTeam();
assault = !defend && playerTeamId == TEAM_HORDE;
break;
case IsleOfConquestNodeState::ConflictH:
defend = playerTeamId == node.GetLastControlledTeam();
assault = !defend && playerTeamId == TEAM_ALLIANCE;
break;
}
if (assault)
OnPlayerAssaultNode(player, node);
else if (defend)
OnPlayerDefendNode(player, node);
battlegroundMap->UpdateSpawnGroupConditions();
}
void OnPlayerAssaultNode(Player* player, ICNodePoint& node)
{
if (!player)
return;
Team const playerTeam = battleground->GetPlayerTeam(player->GetGUID());
TeamId const playerTeamId = Battleground::GetTeamIndexByTeamId(playerTeam);
IsleOfConquestNodeState const newState = playerTeamId == TEAM_HORDE ? IsleOfConquestNodeState::ConflictH : IsleOfConquestNodeState::ConflictA;
node.UpdateState(newState);
battleground->UpdatePvpStat(player, PVP_STAT_BASES_ASSAULTED, 1);
ChatMsg const messageType = playerTeamId == TEAM_ALLIANCE ? CHAT_MSG_BG_SYSTEM_ALLIANCE : CHAT_MSG_BG_SYSTEM_HORDE;
battleground->SendBroadcastText(node.GetNodeInfo().TextIds.Assaulted, messageType, player);
UpdateNodeWorldState(node);
// apply side effects of each node, only if it wasn't neutral before
if (node.GetLastControlledTeam() == TEAM_NEUTRAL)
return;
switch (node.GetNodeInfo().NodeType)
{
case NODE_TYPE_HANGAR:
if (Transport* transport = battlegroundMap->GetTransport(_gunshipGUIDs[node.GetLastControlledTeam()]))
transport->EnableMovement(false);
for (ObjectGuid const& guid : _cannonGUIDs[node.GetLastControlledTeam()])
{
if (Creature* cannon = battlegroundMap->GetCreature(guid))
{
cannon->GetVehicleKit()->RemoveAllPassengers();
cannon->SetUninteractible(true);
}
}
// Despawn teleport trigger target
if (Creature* creature = battlegroundMap->GetCreature(_gunshipTeleportTarget))
creature->DespawnOrUnsummon();
break;
default:
break;
}
}
void OnPlayerDefendNode(Player* player, ICNodePoint& node)
{
if (!player)
return;
Team const playerTeam = battleground->GetPlayerTeam(player->GetGUID());
TeamId const playerTeamId = Battleground::GetTeamIndexByTeamId(playerTeam);
node.UpdateState(playerTeamId == TEAM_HORDE ? IsleOfConquestNodeState::ControlledH : IsleOfConquestNodeState::ControlledA);
HandleCapturedNodes(node);
battleground->UpdatePvpStat(player, PVP_STAT_BASES_DEFENDED, 1);
ChatMsg const messageType = playerTeamId == TEAM_ALLIANCE ? CHAT_MSG_BG_SYSTEM_ALLIANCE : CHAT_MSG_BG_SYSTEM_HORDE;
battleground->SendBroadcastText(node.GetNodeInfo().TextIds.Defended, messageType, player);
UpdateNodeWorldState(node);
}
void ProcessEvent(WorldObject* target, uint32 eventId, WorldObject* invoker) override
{
BattlegroundScript::ProcessEvent(target, eventId, invoker);
if (GameObject* obj = Object::ToGameObject(target))
if (obj->GetGoType() == GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING)
if (obj->GetGOInfo()->destructibleBuilding.DestroyedEvent == eventId)
OnGateDestroyed(obj, invoker);
}
void HandleCaptureNodeAction(GameObject* banner)
{
if (!banner)
return;
ICNodePointType const nodeType = BannerToNodeType(banner->GetEntry());
if (nodeType == MAX_NODE_TYPES)
return;
ICNodePoint& node = *_nodePoints[nodeType];
if (node.GetState() == IsleOfConquestNodeState::ConflictH)
node.UpdateState(IsleOfConquestNodeState::ControlledH);
else if (node.GetState() == IsleOfConquestNodeState::ConflictA)
node.UpdateState(IsleOfConquestNodeState::ControlledA);
HandleCapturedNodes(node);
ChatMsg const messageType = node.GetLastControlledTeam() == TEAM_ALLIANCE ? CHAT_MSG_BG_SYSTEM_ALLIANCE : CHAT_MSG_BG_SYSTEM_HORDE;
uint32 const textId = node.GetLastControlledTeam() == TEAM_ALLIANCE ? node.GetNodeInfo().TextIds.AllianceTaken : node.GetNodeInfo().TextIds.HordeTaken;
battleground->SendBroadcastText(textId, messageType);
UpdateNodeWorldState(node);
}
void OnGateDestroyed(GameObject* gate, WorldObject* destroyer)
{
_gateStatus[GetGateIDFromEntry(gate->GetEntry())] = BG_IC_GATE_DESTROYED;
int32 const wsGateOpen = GetWorldStateFromGateEntry(gate->GetEntry(), true);
int32 const wsGateClosed = GetWorldStateFromGateEntry(gate->GetEntry(), false);
if (wsGateOpen)
{
UpdateWorldState(wsGateClosed, 0);
UpdateWorldState(wsGateOpen, 1);
}
TeamId teamId = TEAM_NEUTRAL;
uint32 textId;
ChatMsg msgType;
switch (gate->GetEntry())
{
case GO_HORDE_GATE_1:
textId = BG_IC_TEXT_FRONT_GATE_HORDE_DESTROYED;
msgType = CHAT_MSG_BG_SYSTEM_ALLIANCE;
teamId = TEAM_HORDE;
break;
case GO_HORDE_GATE_2:
textId = BG_IC_TEXT_WEST_GATE_HORDE_DESTROYED;
msgType = CHAT_MSG_BG_SYSTEM_ALLIANCE;
teamId = TEAM_HORDE;
break;
case GO_HORDE_GATE_3:
textId = BG_IC_TEXT_EAST_GATE_HORDE_DESTROYED;
msgType = CHAT_MSG_BG_SYSTEM_ALLIANCE;
teamId = TEAM_HORDE;
break;
case GO_ALLIANCE_GATE_1:
textId = BG_IC_TEXT_WEST_GATE_ALLIANCE_DESTROYED;
msgType = CHAT_MSG_BG_SYSTEM_HORDE;
teamId = TEAM_ALLIANCE;
break;
case GO_ALLIANCE_GATE_2:
textId = BG_IC_TEXT_EAST_GATE_ALLIANCE_DESTROYED;
msgType = CHAT_MSG_BG_SYSTEM_HORDE;
teamId = TEAM_ALLIANCE;
break;
case GO_ALLIANCE_GATE_3:
textId = BG_IC_TEXT_FRONT_GATE_ALLIANCE_DESTROYED;
msgType = CHAT_MSG_BG_SYSTEM_HORDE;
teamId = TEAM_ALLIANCE;
break;
default:
return;
}
if (teamId != TEAM_NEUTRAL)
{
GuidVector const keepGates = _keepGateGUIDs[teamId];
ObjectGuid const bannerGuid = _keepBannerGUIDs[teamId];
for (ObjectGuid const& guid : keepGates)
if (GameObject* keepGate = battlegroundMap->GetGameObject(guid))
keepGate->UseDoorOrButton();
if (GameObject* banner = battlegroundMap->GetGameObject(bannerGuid))
banner->RemoveFlag(GO_FLAG_NOT_SELECTABLE);
}
battleground->SendBroadcastText(textId, msgType, destroyer);
}
private:
std::array<uint16, PVP_TEAMS_COUNT> _factionReinforcements;
std::array<BG_IC_GateState, 6> _gateStatus;
std::array<std::unique_ptr<ICNodePoint>, 7> _nodePoints;
std::array<ObjectGuid, PVP_TEAMS_COUNT> _gunshipGUIDs;
GuidVector _teleporterGUIDs;
GuidVector _teleporterEffectGUIDs;
GuidVector _mainGateDoorGUIDs;
GuidVector _portcullisGUIDs;
GuidVector _wallGUIDs;
std::array<GuidVector, PVP_TEAMS_COUNT> _cannonGUIDs;
std::array<GuidVector, PVP_TEAMS_COUNT> _keepGateGUIDs;
std::array<ObjectGuid, PVP_TEAMS_COUNT> _keepBannerGUIDs;
ObjectGuid _gunshipTeleportTarget;
TaskScheduler _scheduler;
TimeTracker _resourceTimer;
};
void AddSC_battleground_isle_of_conquest()
{
RegisterBattlegroundMapScript(battleground_isle_of_conquest, 628);
}

View File

@@ -16,7 +16,7 @@
*/
#include "ScriptMgr.h"
#include "BattlegroundIC.h"
#include "isle_of_conquest.h"
#include "ScriptedCreature.h"
enum BossSpells

View File

@@ -15,8 +15,9 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "isle_of_conquest.h"
#include "ScriptMgr.h"
#include "BattlegroundIC.h"
#include "Battleground.h"
#include "GameObject.h"
#include "GameObjectAI.h"
#include "Map.h"

View File

@@ -0,0 +1,132 @@
/*
* 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/>.
*/
#ifndef TRINITYCORE_ISLE_OF_CONQUEST_H
#define TRINITYCORE_ISLE_OF_CONQUEST_H
enum CreaturesIC
{
NPC_HIGH_COMMANDER_HALFORD_WYRMBANE = 34924, // Alliance Boss
NPC_OVERLORD_AGMAR = 34922, // Horde Boss
NPC_KOR_KRON_GUARD = 34918, // horde guard
NPC_SEVEN_TH_LEGION_INFANTRY = 34919, // alliance guard
NPC_KEEP_CANNON = 34944,
NPC_DEMOLISHER = 34775,
NPC_SIEGE_ENGINE_H = 35069,
NPC_SIEGE_ENGINE_A = 34776,
NPC_GLAIVE_THROWER_A = 34802,
NPC_GLAIVE_THROWER_H = 35273,
NPC_CATAPULT = 34793,
NPC_HORDE_GUNSHIP_CANNON = 34935,
NPC_ALLIANCE_GUNSHIP_CANNON = 34929,
NPC_HORDE_GUNSHIP_CAPTAIN = 35003,
NPC_ALLIANCE_GUNSHIP_CAPTAIN = 34960,
NPC_WORLD_TRIGGER_NOT_FLOATING = 34984,
NPC_WORLD_TRIGGER_ALLIANCE_FRIENDLY = 20213,
NPC_WORLD_TRIGGER_HORDE_FRIENDLY = 20212
};
enum Actions
{
ACTION_GUNSHIP_READY = 1,
ACTION_IOC_INTERACT_CAPTURABLE_OBJECT = 2,
ACTION_IOC_CAPTURE_CAPTURABLE_OBJECT = 3
};
enum Spells
{
SPELL_OIL_REFINERY = 68719,
SPELL_QUARRY = 68720,
SPELL_PARACHUTE = 66656,
SPELL_SLOW_FALL = 12438,
SPELL_DESTROYED_VEHICLE_ACHIEVEMENT = 68357,
SPELL_BACK_DOOR_JOB_ACHIEVEMENT = 68502,
SPELL_DRIVING_CREDIT_DEMOLISHER = 68365,
SPELL_DRIVING_CREDIT_GLAIVE = 68363,
SPELL_DRIVING_CREDIT_SIEGE = 68364,
SPELL_DRIVING_CREDIT_CATAPULT = 68362,
SPELL_SIMPLE_TELEPORT = 12980,
SPELL_TELEPORT_VISUAL_ONLY = 51347,
SPELL_PARACHUTE_IC = 66657,
SPELL_LAUNCH_NO_FALLING_DAMAGE = 66251
};
enum ICWorldStates
{
BG_IC_ALLIANCE_REINFORCEMENTS_SET = 4221,
BG_IC_HORDE_REINFORCEMENTS_SET = 4222,
BG_IC_ALLIANCE_REINFORCEMENTS = 4226,
BG_IC_HORDE_REINFORCEMENTS = 4227,
BG_IC_MAX_REINFORCEMENTS = 17377,
BG_IC_GATE_FRONT_H_WS_CLOSED = 4317,
BG_IC_GATE_WEST_H_WS_CLOSED = 4318,
BG_IC_GATE_EAST_H_WS_CLOSED = 4319,
BG_IC_GATE_FRONT_A_WS_CLOSED = 4328,
BG_IC_GATE_WEST_A_WS_CLOSED = 4327,
BG_IC_GATE_EAST_A_WS_CLOSED = 4326,
BG_IC_GATE_FRONT_H_WS_OPEN = 4322,
BG_IC_GATE_WEST_H_WS_OPEN = 4321,
BG_IC_GATE_EAST_H_WS_OPEN = 4320,
BG_IC_GATE_FRONT_A_WS_OPEN = 4323,
BG_IC_GATE_WEST_A_WS_OPEN = 4324,
BG_IC_GATE_EAST_A_WS_OPEN = 4325,
BG_IC_DOCKS_UNCONTROLLED = 4301,
BG_IC_DOCKS_CONFLICT_A = 4305,
BG_IC_DOCKS_CONFLICT_H = 4302,
BG_IC_DOCKS_CONTROLLED_A = 4304,
BG_IC_DOCKS_CONTROLLED_H = 4303,
BG_IC_HANGAR_UNCONTROLLED = 4296,
BG_IC_HANGAR_CONFLICT_A = 4300,
BG_IC_HANGAR_CONFLICT_H = 4297,
BG_IC_HANGAR_CONTROLLED_A = 4299,
BG_IC_HANGAR_CONTROLLED_H = 4298,
BG_IC_QUARRY_UNCONTROLLED = 4306,
BG_IC_QUARRY_CONFLICT_A = 4310,
BG_IC_QUARRY_CONFLICT_H = 4307,
BG_IC_QUARRY_CONTROLLED_A = 4309,
BG_IC_QUARRY_CONTROLLED_H = 4308,
BG_IC_REFINERY_UNCONTROLLED = 4311,
BG_IC_REFINERY_CONFLICT_A = 4315,
BG_IC_REFINERY_CONFLICT_H = 4312,
BG_IC_REFINERY_CONTROLLED_A = 4314,
BG_IC_REFINERY_CONTROLLED_H = 4313,
BG_IC_WORKSHOP_UNCONTROLLED = 4294,
BG_IC_WORKSHOP_CONFLICT_A = 4228,
BG_IC_WORKSHOP_CONFLICT_H = 4293,
BG_IC_WORKSHOP_CONTROLLED_A = 4229,
BG_IC_WORKSHOP_CONTROLLED_H = 4230,
BG_IC_ALLIANCE_KEEP_UNCONTROLLED = 4341,
BG_IC_ALLIANCE_KEEP_CONFLICT_A = 4342,
BG_IC_ALLIANCE_KEEP_CONFLICT_H = 4343,
BG_IC_ALLIANCE_KEEP_CONTROLLED_A = 4339,
BG_IC_ALLIANCE_KEEP_CONTROLLED_H = 4340,
BG_IC_HORDE_KEEP_UNCONTROLLED = 4346,
BG_IC_HORDE_KEEP_CONFLICT_A = 4347,
BG_IC_HORDE_KEEP_CONFLICT_H = 4348,
BG_IC_HORDE_KEEP_CONTROLLED_A = 4344,
BG_IC_HORDE_KEEP_CONTROLLED_H = 4345
};
#endif

View File

@@ -0,0 +1,84 @@
/*
* 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 "Battleground.h"
#include "BattlegroundScript.h"
#include "GameObject.h"
#include "Map.h"
#include "ScriptMgr.h"
#include "TaskScheduler.h"
struct arena_nagrand : ArenaScript
{
enum GameObjects
{
BG_NA_OBJECT_TYPE_DOOR_1 = 183978,
BG_NA_OBJECT_TYPE_DOOR_2 = 183980,
BG_NA_OBJECT_TYPE_DOOR_3 = 183977,
BG_NA_OBJECT_TYPE_DOOR_4 = 183979,
BG_NA_OBJECT_TYPE_BUFF_1 = 184663,
BG_NA_OBJECT_TYPE_BUFF_2 = 184664
};
explicit arena_nagrand(BattlegroundMap* map) : ArenaScript(map) { }
void OnUpdate(uint32 diff) override
{
_scheduler.Update(diff);
}
void OnInit() override
{
AddDoor(BG_NA_OBJECT_TYPE_DOOR_1, 4031.854f, 2966.833f, 12.6462f, -2.648788f, 0, 0, 0.9697962f, -0.2439165f);
AddDoor(BG_NA_OBJECT_TYPE_DOOR_2, 4081.179f, 2874.97f, 12.39171f, 0.4928045f, 0, 0, 0.2439165f, 0.9697962f);
AddDoor(BG_NA_OBJECT_TYPE_DOOR_3, 4023.709f, 2981.777f, 10.70117f, -2.648788f, 0, 0, 0.9697962f, -0.2439165f);
AddDoor(BG_NA_OBJECT_TYPE_DOOR_4, 4090.064f, 2858.438f, 10.23631f, 0.4928045f, 0, 0, 0.2439165f, 0.9697962f);
}
void OnStart() override
{
for (ObjectGuid const& guid : _doorGUIDs)
{
if (GameObject* door = battlegroundMap->GetGameObject(guid))
{
door->UseDoorOrButton();
door->DespawnOrUnsummon(5s);
}
}
_scheduler.Schedule(1min, [&](TaskContext)
{
CreateObject(BG_NA_OBJECT_TYPE_BUFF_1, 4009.189941f, 2895.250000f, 13.052700f, -1.448624f, 0, 0, 0.6626201f, -0.7489557f);
CreateObject(BG_NA_OBJECT_TYPE_BUFF_2, 4103.330078f, 2946.350098f, 13.051300f, -0.06981307f, 0, 0, 0.03489945f, -0.9993908f);
});
}
void AddDoor(uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, GOState goState = GO_STATE_READY)
{
if (GameObject const* go = CreateObject(entry, x, y, z, o, rotation0, rotation1, rotation2, rotation3, goState))
_doorGUIDs.emplace_back(go->GetGUID());
}
private:
GuidVector _doorGUIDs;
TaskScheduler _scheduler;
};
void AddSC_arena_nagrand()
{
RegisterBattlegroundMapScript(arena_nagrand, 1505);
}

View File

@@ -0,0 +1,302 @@
/*
* 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 "Battleground.h"
#include "BattlegroundScript.h"
#include "GameObject.h"
#include "Map.h"
#include "ObjectAccessor.h"
#include "ScriptMgr.h"
#include "TaskScheduler.h"
struct arena_ring_of_valor : ArenaScript
{
enum BattlegroundRVGameObjects
{
BG_RV_OBJECT_TYPE_BUFF_1 = 184663,
BG_RV_OBJECT_TYPE_BUFF_2 = 184664,
BG_RV_OBJECT_TYPE_FIRE_1 = 192704,
BG_RV_OBJECT_TYPE_FIRE_2 = 192705,
BG_RV_OBJECT_TYPE_FIREDOOR_2 = 192387,
BG_RV_OBJECT_TYPE_FIREDOOR_1 = 192388,
BG_RV_OBJECT_TYPE_PULLEY_1 = 192389,
BG_RV_OBJECT_TYPE_PULLEY_2 = 192390,
BG_RV_OBJECT_TYPE_GEAR_1 = 192393,
BG_RV_OBJECT_TYPE_GEAR_2 = 192394,
BG_RV_OBJECT_TYPE_ELEVATOR_1 = 194582,
BG_RV_OBJECT_TYPE_ELEVATOR_2 = 194586,
BG_RV_OBJECT_TYPE_PILAR_COLLISION_1 = 194580, // axe
BG_RV_OBJECT_TYPE_PILAR_COLLISION_2 = 194579, // arena // big
BG_RV_OBJECT_TYPE_PILAR_COLLISION_3 = 194581, // lightning
BG_RV_OBJECT_TYPE_PILAR_COLLISION_4 = 194578, // ivory // big
BG_RV_OBJECT_TYPE_PILAR_1 = 194583, // axe
BG_RV_OBJECT_TYPE_PILAR_2 = 194584, // arena
BG_RV_OBJECT_TYPE_PILAR_3 = 194585, // lightning
BG_RV_OBJECT_TYPE_PILAR_4 = 194587 // ivory
};
enum BattlegroundRVData
{
BG_RV_STATE_OPEN_FENCES,
BG_RV_STATE_SWITCH_PILLARS,
BG_RV_STATE_CLOSE_FIRE,
BG_RV_PILLAR_SWITCH_TIMER = 25000,
BG_RV_FIRE_TO_PILLAR_TIMER = 20000,
BG_RV_CLOSE_FIRE_TIMER = 5000,
BG_RV_FIRST_TIMER = 20133,
};
explicit arena_ring_of_valor(BattlegroundMap* map) : ArenaScript(map), _timer(0), _state(0), _pillarCollision(false) { }
void OnUpdate(uint32 diff) override
{
if (battleground->GetStatus() != STATUS_IN_PROGRESS)
return;
_scheduler.Update(diff);
if (_timer < diff)
{
switch (_state)
{
case BG_RV_STATE_OPEN_FENCES:
// Open fire (only at game start)
for (ObjectGuid const& guid : _fireGUIDs)
if (GameObject* go = battlegroundMap->GetGameObject(guid))
go->UseDoorOrButton();
for (ObjectGuid const& guid : _firedoorGUIDs)
if (GameObject* go = battlegroundMap->GetGameObject(guid))
go->UseDoorOrButton();
_timer = BG_RV_CLOSE_FIRE_TIMER;
_state = BG_RV_STATE_CLOSE_FIRE;
break;
case BG_RV_STATE_CLOSE_FIRE:
for (ObjectGuid const& guid : _fireGUIDs)
if (GameObject* go = battlegroundMap->GetGameObject(guid))
go->ResetDoorOrButton();
for (ObjectGuid const& guid : _firedoorGUIDs)
if (GameObject* go = battlegroundMap->GetGameObject(guid))
go->ResetDoorOrButton();
// Fire got closed after five seconds, leaves twenty seconds before toggling pillars
_timer = BG_RV_FIRE_TO_PILLAR_TIMER;
_state = BG_RV_STATE_SWITCH_PILLARS;
break;
case BG_RV_STATE_SWITCH_PILLARS:
TogglePillarCollision();
_timer = BG_RV_PILLAR_SWITCH_TIMER;
break;
default:
break;
}
}
else
_timer -= diff;
}
void OnInit() override
{
CreateObject(BG_RV_OBJECT_TYPE_ELEVATOR_1, 763.536377f, -294.535767f, 0.505383f, 3.141593f, 0.0f, 0.0f, 0.0f, 0.0f);
CreateObject(BG_RV_OBJECT_TYPE_ELEVATOR_2, 763.506348f, -273.873352f, 0.505383f, 0.000000f, 0.0f, 0.0f, 0.0f, 0.0f);
CreateObject(BG_RV_OBJECT_TYPE_FIRE_1, 743.543457f, -283.799469f, 28.286655f, 3.141593f, 0.0f, 0.0f, 0.0f, 0.0f);
CreateObject(BG_RV_OBJECT_TYPE_FIRE_2, 782.971802f, -283.799469f, 28.286655f, 3.141593f, 0.0f, 0.0f, 0.0f, 0.0f);
CreateObject(BG_RV_OBJECT_TYPE_FIREDOOR_1, 743.711060f, -284.099609f, 27.542587f, 3.141593f, 0.0f, 0.0f, 0.0f, 0.0f);
CreateObject(BG_RV_OBJECT_TYPE_FIREDOOR_2, 783.221252f, -284.133362f, 27.535686f, 0.000000f, 0.0f, 0.0f, 0.0f, 0.0f);
CreateObject(BG_RV_OBJECT_TYPE_GEAR_1, 763.664551f, -261.872986f, 26.686588f, 0.000000f, 0.0f, 0.0f, 0.0f, 0.0f);
CreateObject(BG_RV_OBJECT_TYPE_GEAR_2, 763.578979f, -306.146149f, 26.665222f, 3.141593f, 0.0f, 0.0f, 0.0f, 0.0f);
CreateObject(BG_RV_OBJECT_TYPE_PULLEY_1, 700.722290f, -283.990662f, 39.517582f, 3.141593f, 0.0f, 0.0f, 0.0f, 0.0f);
CreateObject(BG_RV_OBJECT_TYPE_PULLEY_2, 826.303833f, -283.996429f, 39.517582f, 0.000000f, 0.0f, 0.0f, 0.0f, 0.0f);
CreateObject(BG_RV_OBJECT_TYPE_PILAR_1, 763.632385f, -306.162384f, 25.909504f, 3.141593f, 0.0f, 0.0f, 0.0f, 0.0f);
CreateObject(BG_RV_OBJECT_TYPE_PILAR_2, 723.644287f, -284.493256f, 24.648525f, 3.141593f, 0.0f, 0.0f, 0.0f, 0.0f);
CreateObject(BG_RV_OBJECT_TYPE_PILAR_3, 763.611145f, -261.856750f, 25.909504f, 0.000000f, 0.0f, 0.0f, 0.0f, 0.0f);
CreateObject(BG_RV_OBJECT_TYPE_PILAR_4, 802.211609f, -284.493256f, 24.648525f, 0.000000f, 0.0f, 0.0f, 0.0f, 0.0f);
CreateObject(BG_RV_OBJECT_TYPE_PILAR_COLLISION_1, 763.632385f, -306.162384f, 30.639660f, 3.141593f, 0.0f, 0.0f, 0.0f, 0.0f);
CreateObject(BG_RV_OBJECT_TYPE_PILAR_COLLISION_2, 723.644287f, -284.493256f, 32.382710f, 0.000000f, 0.0f, 0.0f, 0.0f, 0.0f);
CreateObject(BG_RV_OBJECT_TYPE_PILAR_COLLISION_3, 763.611145f, -261.856750f, 30.639660f, 0.000000f, 0.0f, 0.0f, 0.0f, 0.0f);
CreateObject(BG_RV_OBJECT_TYPE_PILAR_COLLISION_4, 802.211609f, -284.493256f, 32.382710f, 3.141593f, 0.0f, 0.0f, 0.0f, 0.0f);
}
void OnStart() override
{
for (ObjectGuid const& guid : _elevatorGUIDs)
{
if (GameObject* door = battlegroundMap->GetGameObject(guid))
{
door->UseDoorOrButton();
door->DespawnOrUnsummon(5s);
}
}
_state = BG_RV_STATE_OPEN_FENCES;
_timer = BG_RV_FIRST_TIMER;
// Should be false at first, TogglePillarCollision will do it.
_pillarCollision = true;
TogglePillarCollision();
_scheduler.Schedule(1min, [&](TaskContext)
{
CreateObject(BG_RV_OBJECT_TYPE_BUFF_1, 735.551819f, -284.794678f, 28.276682f, 0.034906f, 0.0f, 0.0f, 0.0f, 0.0f);
CreateObject(BG_RV_OBJECT_TYPE_BUFF_2, 791.224487f, -284.794464f, 28.276682f, 2.600535f, 0.0f, 0.0f, 0.0f, 0.0f);
});
}
void TogglePillarCollision()
{
// Toggle visual pillars, pulley, gear, and collision based on previous state
GuidVector smallPillarGuids;
smallPillarGuids.insert(std::end(smallPillarGuids), std::begin(_pillarSmallGUIDs), std::end(_pillarSmallGUIDs));
smallPillarGuids.insert(std::end(smallPillarGuids), std::begin(_gearGUIDs), std::end(_gearGUIDs));
for (ObjectGuid const& guid : smallPillarGuids)
{
if (GameObject* go = battlegroundMap->GetGameObject(guid))
{
if (_pillarCollision)
go->UseDoorOrButton();
else
go->ResetDoorOrButton();
}
}
GuidVector bigPillarGuids;
bigPillarGuids.insert(std::end(bigPillarGuids), std::begin(_pillarBigGUIDs), std::end(_pillarBigGUIDs));
bigPillarGuids.insert(std::end(bigPillarGuids), std::begin(_pulleyGUIDs), std::end(_pulleyGUIDs));
for (ObjectGuid const& guid : bigPillarGuids)
{
if (GameObject* go = battlegroundMap->GetGameObject(guid))
{
if (_pillarCollision)
go->ResetDoorOrButton();
else
go->UseDoorOrButton();
}
}
GuidVector allObjects;
allObjects.insert(std::end(allObjects), std::begin(smallPillarGuids), std::end(smallPillarGuids));
allObjects.insert(std::end(allObjects), std::begin(bigPillarGuids), std::end(bigPillarGuids));
allObjects.insert(std::end(allObjects), std::begin(_pillarSmallCollisionGUIDs), std::end(_pillarSmallCollisionGUIDs));
allObjects.insert(std::end(allObjects), std::begin(_pillarBigCollisionGUIDs), std::end(_pillarBigCollisionGUIDs));
for (ObjectGuid const& guid : allObjects)
{
if (GameObject* go = battlegroundMap->GetGameObject(guid))
{
bool isCollision = false;
switch (go->GetEntry())
{
case BG_RV_OBJECT_TYPE_PILAR_COLLISION_1:
case BG_RV_OBJECT_TYPE_PILAR_COLLISION_2:
case BG_RV_OBJECT_TYPE_PILAR_COLLISION_3:
case BG_RV_OBJECT_TYPE_PILAR_COLLISION_4:
isCollision = true;
break;
default:
break;
}
if (isCollision)
{
GOState state = ((go->GetGOInfo()->door.startOpen != 0) == _pillarCollision) ? GO_STATE_ACTIVE : GO_STATE_READY;
go->SetGoState(state);
}
for (auto const& [playerGuid, _]: battleground->GetPlayers())
if (Player* player = ObjectAccessor::FindPlayer(playerGuid))
go->SendUpdateToPlayer(player);
}
}
_pillarCollision = !_pillarCollision;
}
void OnGameObjectCreate(GameObject* gameobject) override
{
ArenaScript::OnGameObjectCreate(gameobject);
switch (gameobject->GetEntry())
{
case BG_RV_OBJECT_TYPE_ELEVATOR_1:
case BG_RV_OBJECT_TYPE_ELEVATOR_2:
_elevatorGUIDs.emplace_back(gameobject->GetGUID());
break;
case BG_RV_OBJECT_TYPE_FIRE_1:
case BG_RV_OBJECT_TYPE_FIRE_2:
_fireGUIDs.emplace_back(gameobject->GetGUID());
break;
case BG_RV_OBJECT_TYPE_FIREDOOR_1:
case BG_RV_OBJECT_TYPE_FIREDOOR_2:
_firedoorGUIDs.emplace_back(gameobject->GetGUID());
break;
case BG_RV_OBJECT_TYPE_GEAR_1:
case BG_RV_OBJECT_TYPE_GEAR_2:
_gearGUIDs.emplace_back(gameobject->GetGUID());
break;
case BG_RV_OBJECT_TYPE_PILAR_1:
case BG_RV_OBJECT_TYPE_PILAR_3:
_pillarSmallGUIDs.emplace_back(gameobject->GetGUID());
break;
case BG_RV_OBJECT_TYPE_PILAR_2:
case BG_RV_OBJECT_TYPE_PILAR_4:
_pillarBigGUIDs.emplace_back(gameobject->GetGUID());
break;
case BG_RV_OBJECT_TYPE_PILAR_COLLISION_1:
case BG_RV_OBJECT_TYPE_PILAR_COLLISION_3:
_pillarSmallCollisionGUIDs.emplace_back(gameobject->GetGUID());
break;
case BG_RV_OBJECT_TYPE_PILAR_COLLISION_2:
case BG_RV_OBJECT_TYPE_PILAR_COLLISION_4:
_pillarBigCollisionGUIDs.emplace_back(gameobject->GetGUID());
break;
case BG_RV_OBJECT_TYPE_PULLEY_1:
case BG_RV_OBJECT_TYPE_PULLEY_2:
_pulleyGUIDs.emplace_back(gameobject->GetGUID());
break;
default:
break;
}
}
private:
GuidVector _elevatorGUIDs;
GuidVector _gearGUIDs;
GuidVector _fireGUIDs;
GuidVector _firedoorGUIDs;
GuidVector _pillarSmallCollisionGUIDs;
GuidVector _pillarBigCollisionGUIDs;
GuidVector _pillarSmallGUIDs;
GuidVector _pillarBigGUIDs;
GuidVector _pulleyGUIDs;
TaskScheduler _scheduler;
uint32 _timer;
uint32 _state;
bool _pillarCollision;
};
void AddSC_arena_ring_of_valor()
{
RegisterBattlegroundMapScript(arena_ring_of_valor, 618);
}

View File

@@ -0,0 +1,80 @@
/*
* 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 "Battleground.h"
#include "BattlegroundScript.h"
#include "GameObject.h"
#include "Map.h"
#include "ScriptMgr.h"
#include "TaskScheduler.h"
struct arena_ruins_of_lordaeron : ArenaScript
{
enum BattlegroundRLGameObjects
{
BG_RL_OBJECT_TYPE_DOOR_1 = 185918,
BG_RL_OBJECT_TYPE_DOOR_2 = 185917,
BG_RL_OBJECT_TYPE_BUFF_1 = 184663,
BG_RL_OBJECT_TYPE_BUFF_2 = 184664
};
explicit arena_ruins_of_lordaeron(BattlegroundMap* map) : ArenaScript(map) { }
void OnUpdate(uint32 diff) override
{
_scheduler.Update(diff);
}
void OnInit() override
{
AddDoor(BG_RL_OBJECT_TYPE_DOOR_1, 1293.561f, 1601.938f, 31.60557f, -1.457349f, 0, 0, -0.6658813f, 0.7460576f);
AddDoor(BG_RL_OBJECT_TYPE_DOOR_2, 1278.648f, 1730.557f, 31.60557f, 1.684245f, 0, 0, 0.7460582f, 0.6658807f);
}
void OnStart() override
{
for (ObjectGuid const& guid : _doorGUIDs)
{
if (GameObject* door = battlegroundMap->GetGameObject(guid))
{
door->UseDoorOrButton();
door->DespawnOrUnsummon(5s);
}
}
_scheduler.Schedule(1min, [&](TaskContext)
{
CreateObject(BG_RL_OBJECT_TYPE_BUFF_1, 1328.719971f, 1632.719971f, 36.730400f, -1.448624f, 0, 0, 0.6626201f, -0.7489557f);
CreateObject(BG_RL_OBJECT_TYPE_BUFF_2, 1243.300049f, 1699.170044f, 34.872601f, -0.06981307f, 0, 0, 0.03489945f, -0.9993908f);
});
}
void AddDoor(uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, GOState goState = GO_STATE_READY)
{
if (GameObject const* go = CreateObject(entry, x, y, z, o, rotation0, rotation1, rotation2, rotation3, goState))
_doorGUIDs.emplace_back(go->GetGUID());
}
private:
GuidVector _doorGUIDs;
TaskScheduler _scheduler;
};
void AddSC_arena_ruins_of_lordaeron()
{
RegisterBattlegroundMapScript(arena_ruins_of_lordaeron, 572);
}

View File

@@ -15,8 +15,8 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "strand_of_the_ancients.h"
#include "ScriptMgr.h"
#include "BattlegroundSA.h"
#include "GameObject.h"
#include "GameObjectAI.h"
#include "Player.h"

View File

@@ -0,0 +1,26 @@
/*
* 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/>.
*/
#ifndef TRINITYCORE_STRAND_OF_THE_ANCIENTS_H
#define TRINITYCORE_STRAND_OF_THE_ANCIENTS_H
enum StrandOfTheAncientSharedActions
{
ACTION_SOTA_CAPTURE_GRAVEYARD
};
#endif

View File

@@ -0,0 +1,35 @@
/*
* 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 "BattlegroundScript.h"
#include "ScriptMgr.h"
struct battleground_twin_peaks : BattlegroundScript
{
enum PvpStats : uint32
{
BG_TP_FLAG_CAPTURES = 290,
BG_TP_FLAG_RETURNS = 291
};
explicit battleground_twin_peaks(BattlegroundMap* map) : BattlegroundScript(map) { }
};
void AddSC_battleground_twin_peaks()
{
RegisterBattlegroundMapScript(battleground_twin_peaks, 726);
}

View File

@@ -0,0 +1,608 @@
/*
* 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 "AreaTrigger.h"
#include "BattlegroundScript.h"
#include "Battleground.h"
#include "BattlegroundMgr.h"
#include "GameObject.h"
#include "GameTime.h"
#include "Map.h"
#include "ObjectAccessor.h"
#include "Player.h"
#include "ScriptMgr.h"
#include "SpellAuras.h"
#include "Timer.h"
struct battleground_warsong_gulch : BattlegroundScript
{
static constexpr Seconds FLAG_ASSAULT_TIMER = 30s;
enum Misc
{
MAX_TEAM_SCORE = 3,
FLAG_BRUTAL_ASSAULT_STACK_COUNT = 5
};
enum Spells : uint32
{
SPELL_FOCUSED_ASSAULT = 46392,
SPELL_BRUTAL_ASSAULT = 46393,
SPELL_CAPTURED_ALLIANCE_COSMETIC_FX = 262508,
SPELL_CAPTURED_HORDE_COSMETIC_FX = 262512,
SPELL_WARSONG_FLAG = 23333,
SPELL_WARSONG_FLAG_DROPPED = 23334,
SPELL_SILVERWING_FLAG = 23335,
SPELL_SILVERWING_FLAG_DROPPED = 23336,
SPELL_QUICK_CAP_TIMER = 183317,
};
enum AreaTriggers : uint32
{
AT_CAPTURE_POINT_ALLIANCE = 30,
AT_CAPTURE_POINT_HORDE = 31
};
enum Events : uint32
{
EVENT_START_BATTLE = 35912
};
enum PvpStats : uint32
{
PVP_STAT_FLAG_CAPTURES = 928,
PVP_STAT_FLAG_RETURNS = 929
};
enum WorldStates : int32
{
WORLD_STATE_FLAG_STATE_ALLIANCE = 1545,
WORLD_STATE_FLAG_STATE_HORDE = 1546,
WORLD_STATE_FLAG_STATE_NEUTRAL = 1547,
WORLD_STATE_HORDE_FLAG_COUNT_PICKED_UP = 17712,
WORLD_STATE_ALLIANCE_FLAG_COUNT_PICKED_UP = 17713,
WORLD_STATE_FLAG_CAPTURES_ALLIANCE = 1581,
WORLD_STATE_FLAG_CAPTURES_HORDE = 1582,
WORLD_STATE_FLAG_CAPTURES_MAX = 1601,
WORLD_STATE_FLAG_CAPTURES_MAX_NEW = 17303,
WORLD_STATE_FLAG_CONTROL_HORDE = 2338,
WORLD_STATE_FLAG_CONTROL_ALLIANCE = 2339,
WORLD_STATE_STATE_TIMER = 4248,
WORLD_STATE_STATE_TIMER_ACTIVE = 4247
};
enum Texts
{
TEXT_START_ONE_MINUTE = 10015,
TEXT_START_HALF_MINUTE = 10016,
TEXT_BATTLE_HAS_BEGUN = 10014,
TEXT_CAPTURED_HORDE_FLAG = 9801,
TEXT_CAPTURED_ALLIANCE_FLAG = 9802,
TEXT_FLAGS_PLACED = 9803,
TEXT_ALLIANCE_FLAG_PICKED_UP = 9804,
TEXT_ALLIANCE_FLAG_DROPPED = 9805,
TEXT_HORDE_FLAG_PICKED_UP = 9807,
TEXT_HORDE_FLAG_DROPPED = 9806,
TEXT_ALLIANCE_FLAG_RETURNED = 9808,
TEXT_HORDE_FLAG_RETURNED = 9809
};
enum Sounds
{
SOUND_FLAG_CAPTURED_ALLIANCE = 8173,
SOUND_FLAG_CAPTURED_HORDE = 8213,
SOUND_FLAG_PLACED = 8232,
SOUND_FLAG_RETURNED = 8192,
SOUND_HORDE_FLAG_PICKED_UP = 8212,
SOUND_ALLIANCE_FLAG_PICKED_UP = 8174,
SOUND_FLAGS_RESPAWNED = 8232
};
enum GameObjects
{
OBJECT_ALLIANCE_DOOR = 309704,
OBJECT_PORTCULLIS_009 = 309705,
OBJECT_PORTCULLIS_002 = 309883,
OBJECT_COLLISION_PC_SIZE = 242273,
OBJECT_HORDE_GATE_1 = 352709,
OBJECT_HORDE_GATE_2 = 352710,
OBJECT_ALLIANCE_FLAG_IN_BASE = 227741,
OBJECT_HORDE_FLAG_IN_BASE = 227740
};
static constexpr std::array<std::array<uint32, 3>, 2> HONOR_REWARDS =
{{
{ 20, 40, 40 },
{ 60, 40, 80 }
}};
explicit battleground_warsong_gulch(BattlegroundMap* map) : BattlegroundScript(map), _lastFlagCaptureTeam(TEAM_OTHER), _bothFlagsKept(false), _flags({ }), _assaultStackCount(0), _capturePointAreaTriggers({ })
{
_flagAssaultTimer.Reset(FLAG_ASSAULT_TIMER);
if (sBattlegroundMgr->IsBGWeekend(battleground->GetTypeID()))
{
_reputationCapture = 45;
_honorWinKills = 3;
_honorEndKills = 4;
}
else
{
_reputationCapture = 35;
_honorWinKills = 1;
_honorEndKills = 2;
}
}
void OnUpdate(uint32 diff) override
{
BattlegroundScript::OnUpdate(diff);
if (battleground->GetStatus() == STATUS_IN_PROGRESS)
{
if (battleground->GetElapsedTime() >= 17 * MINUTE * IN_MILLISECONDS)
{
if (battleground->GetTeamScore(TEAM_ALLIANCE) == 0)
{
if (battleground->GetTeamScore(TEAM_HORDE) == 0) // No one scored - result is tie
battleground->EndBattleground(TEAM_OTHER);
else // Horde has more points and thus wins
battleground->EndBattleground(HORDE);
}
else if (battleground->GetTeamScore(TEAM_HORDE) == 0) // Alliance has > 0, Horde has 0, alliance wins
battleground->EndBattleground(ALLIANCE);
else if (battleground->GetTeamScore(TEAM_HORDE) == battleground->GetTeamScore(TEAM_ALLIANCE)) // Team score equal, winner is team that scored the last flag
battleground->EndBattleground(_lastFlagCaptureTeam);
else if (battleground->GetTeamScore(TEAM_HORDE) > battleground->GetTeamScore(TEAM_ALLIANCE)) // Last but not least, check who has the higher score
battleground->EndBattleground(HORDE);
else
battleground->EndBattleground(ALLIANCE);
}
}
if (_bothFlagsKept)
{
_flagAssaultTimer.Update(diff);
if (_flagAssaultTimer.Passed())
{
_flagAssaultTimer.Reset(FLAG_ASSAULT_TIMER);
if (_assaultStackCount < std::numeric_limits<uint8>::max())
{
_assaultStackCount++;
// update assault debuff stacks
DoForFlagKeepers([&](Player* player) -> void
{
ApplyAssaultDebuffToPlayer(player);
});
}
}
}
}
void OnStart() override
{
BattlegroundScript::OnStart();
for (ObjectGuid door : _doors)
{
if (GameObject* gameObject = battlegroundMap->GetGameObject(door))
{
gameObject->UseDoorOrButton();
gameObject->DespawnOrUnsummon(3s);
}
}
UpdateWorldState(WORLD_STATE_STATE_TIMER_ACTIVE, 1);
UpdateWorldState(WORLD_STATE_STATE_TIMER, std::chrono::system_clock::to_time_t(GameTime::GetSystemTime() + 15min));
// players joining later are not eligibles
TriggerGameEvent(EVENT_START_BATTLE);
}
void OnEnd(Team winner) override
{
BattlegroundScript::OnEnd(winner);
// Win reward
if (winner == ALLIANCE)
battleground->RewardHonorToTeam(battleground->GetBonusHonorFromKill(_honorWinKills), ALLIANCE);
if (winner == HORDE)
battleground->RewardHonorToTeam(battleground->GetBonusHonorFromKill(_honorWinKills), HORDE);
// Complete map_end rewards (even if no team wins)
battleground->RewardHonorToTeam(battleground->GetBonusHonorFromKill(_honorEndKills), ALLIANCE);
battleground->RewardHonorToTeam(battleground->GetBonusHonorFromKill(_honorEndKills), HORDE);
}
void DoForFlagKeepers(std::function<void(Player*)> const& action) const
{
for (ObjectGuid flagGUID : _flags)
if (GameObject const* flag = battlegroundMap->GetGameObject(flagGUID))
if (Player* carrier = ObjectAccessor::FindPlayer(flag->GetFlagCarrierGUID()))
action(carrier);
}
void ResetAssaultDebuff()
{
_bothFlagsKept = false;
_assaultStackCount = 0;
_flagAssaultTimer.Reset(FLAG_ASSAULT_TIMER);
DoForFlagKeepers([&](Player* player) -> void
{
RemoveAssaultDebuffFromPlayer(player);
});
}
void ApplyAssaultDebuffToPlayer(Player* player) const
{
if (_assaultStackCount == 0)
return;
uint32 spellId = SPELL_FOCUSED_ASSAULT;
if (_assaultStackCount >= FLAG_BRUTAL_ASSAULT_STACK_COUNT)
{
player->RemoveAurasDueToSpell(SPELL_FOCUSED_ASSAULT);
spellId = SPELL_BRUTAL_ASSAULT;
}
Aura* aura = player->GetAura(spellId);
if (!aura)
{
player->CastSpell(player, spellId, true);
aura = player->GetAura(spellId);
}
if (aura)
aura->SetStackAmount(_assaultStackCount);
}
void RemoveAssaultDebuffFromPlayer(Player* player) const
{
player->RemoveAurasDueToSpell(SPELL_FOCUSED_ASSAULT);
player->RemoveAurasDueToSpell(SPELL_BRUTAL_ASSAULT);
}
FlagState GetFlagState(TeamId team) const
{
if (GameObject const* flag = battlegroundMap->GetGameObject(_flags[team]))
return flag->GetFlagState();
return FlagState(0);
}
ObjectGuid const& GetFlagCarrierGUID(TeamId team) const
{
if (GameObject const* flag = battlegroundMap->GetGameObject(_flags[team]))
return flag->GetFlagCarrierGUID();
return ObjectGuid::Empty;
}
void HandleFlagRoomCapturePoint()
{
DoForFlagKeepers([&](Player* player) -> void
{
TeamId const team = Battleground::GetTeamIndexByTeamId(battleground->GetPlayerTeam(player->GetGUID()));
if (AreaTrigger* trigger = battlegroundMap->GetAreaTrigger(_capturePointAreaTriggers[team]))
if (trigger->GetInsideUnits().contains(player->GetGUID()))
if (CanCaptureFlag(trigger, player))
OnCaptureFlag(trigger, player);
});
}
void UpdateFlagState(uint32 team, FlagState value) const
{
auto transformValueToOtherTeamControlWorldState = [](FlagState state)
{
switch (state)
{
case FlagState::InBase:
case FlagState::Dropped:
case FlagState::Respawning:
return 1;
case FlagState::Taken:
return 2;
default:
return 0;
}
};
if (team == ALLIANCE)
{
UpdateWorldState(WORLD_STATE_FLAG_STATE_ALLIANCE, AsUnderlyingType(value));
UpdateWorldState(WORLD_STATE_FLAG_CONTROL_HORDE, transformValueToOtherTeamControlWorldState(value));
}
else
{
UpdateWorldState(WORLD_STATE_FLAG_STATE_HORDE, AsUnderlyingType(value));
UpdateWorldState(WORLD_STATE_FLAG_CONTROL_ALLIANCE, transformValueToOtherTeamControlWorldState(value));
}
}
void UpdateTeamScore(TeamId team) const
{
if (team == TEAM_ALLIANCE)
UpdateWorldState(WORLD_STATE_FLAG_CAPTURES_ALLIANCE, battleground->GetTeamScore(team));
else
UpdateWorldState(WORLD_STATE_FLAG_CAPTURES_HORDE, battleground->GetTeamScore(team));
}
void OnGameObjectCreate(GameObject* gameObject) override
{
BattlegroundScript::OnGameObjectCreate(gameObject);
switch (gameObject->GetEntry())
{
case OBJECT_ALLIANCE_DOOR:
case OBJECT_PORTCULLIS_009:
case OBJECT_PORTCULLIS_002:
case OBJECT_COLLISION_PC_SIZE:
case OBJECT_HORDE_GATE_1:
case OBJECT_HORDE_GATE_2:
_doors.insert(gameObject->GetGUID());
break;
case OBJECT_ALLIANCE_FLAG_IN_BASE:
_flags[TEAM_ALLIANCE] = gameObject->GetGUID();
break;
case OBJECT_HORDE_FLAG_IN_BASE:
_flags[TEAM_HORDE] = gameObject->GetGUID();
break;
default:
break;
}
}
void OnAreaTriggerCreate(AreaTrigger* areaTrigger) override
{
BattlegroundScript::OnAreaTriggerCreate(areaTrigger);
if (!areaTrigger->IsStaticSpawn())
return;
switch (areaTrigger->GetEntry())
{
case AT_CAPTURE_POINT_ALLIANCE:
_capturePointAreaTriggers[TEAM_ALLIANCE] = areaTrigger->GetGUID();
break;
case AT_CAPTURE_POINT_HORDE:
_capturePointAreaTriggers[TEAM_HORDE] = areaTrigger->GetGUID();
break;
default:
break;
}
}
void OnFlagStateChange(GameObject* flagInBase, FlagState oldValue, FlagState newValue, Player* player) override
{
BattlegroundScript::OnFlagStateChange(flagInBase, oldValue, newValue, player);
Team const team = flagInBase->GetEntry() == OBJECT_HORDE_FLAG_IN_BASE ? HORDE : ALLIANCE;
TeamId const otherTeamId = Battleground::GetTeamIndexByTeamId(GetOtherTeam(team));
UpdateFlagState(team, newValue);
switch (newValue)
{
case FlagState::InBase:
{
if (battleground->GetStatus() == STATUS_IN_PROGRESS)
{
ResetAssaultDebuff();
if (player)
{
// flag got returned to base by player interaction
battleground->UpdatePvpStat(player, PVP_STAT_FLAG_RETURNS, 1); // +1 flag returns
if (team == ALLIANCE)
{
battleground->SendBroadcastText(TEXT_ALLIANCE_FLAG_RETURNED, CHAT_MSG_BG_SYSTEM_ALLIANCE, player);
battleground->PlaySoundToAll(SOUND_FLAG_RETURNED);
}
else
{
battleground->SendBroadcastText(TEXT_HORDE_FLAG_RETURNED, CHAT_MSG_BG_SYSTEM_HORDE, player);
battleground->PlaySoundToAll(SOUND_FLAG_RETURNED);
}
}
// Flag respawned due to timeout/capture
else if (GetFlagState(otherTeamId) != FlagState::Respawning)
{
// if other flag is respawning, we will let that one handle the message and sound to prevent double message/sound.
battleground->SendBroadcastText(TEXT_FLAGS_PLACED, CHAT_MSG_BG_SYSTEM_NEUTRAL);
battleground->PlaySoundToAll(SOUND_FLAGS_RESPAWNED);
}
HandleFlagRoomCapturePoint();
}
break;
}
case FlagState::Dropped:
{
player->RemoveAurasDueToSpell(SPELL_QUICK_CAP_TIMER);
RemoveAssaultDebuffFromPlayer(player);
uint32 recentlyDroppedSpellId = SPELL_RECENTLY_DROPPED_HORDE_FLAG;
if (team == ALLIANCE)
{
recentlyDroppedSpellId = SPELL_RECENTLY_DROPPED_ALLIANCE_FLAG;
battleground->SendBroadcastText(TEXT_ALLIANCE_FLAG_DROPPED, CHAT_MSG_BG_SYSTEM_ALLIANCE, player);
}
else
battleground->SendBroadcastText(TEXT_HORDE_FLAG_DROPPED, CHAT_MSG_BG_SYSTEM_HORDE, player);
player->CastSpell(player, recentlyDroppedSpellId, true);
break;
}
case FlagState::Taken:
{
if (team == HORDE)
{
battleground->SendBroadcastText(TEXT_HORDE_FLAG_PICKED_UP, CHAT_MSG_BG_SYSTEM_HORDE, player);
battleground->PlaySoundToAll(SOUND_HORDE_FLAG_PICKED_UP);
}
else
{
battleground->SendBroadcastText(TEXT_ALLIANCE_FLAG_PICKED_UP, CHAT_MSG_BG_SYSTEM_ALLIANCE, player);
battleground->PlaySoundToAll(SOUND_ALLIANCE_FLAG_PICKED_UP);
}
if (GetFlagState(otherTeamId) == FlagState::Taken)
_bothFlagsKept = true;
ApplyAssaultDebuffToPlayer(player);
flagInBase->CastSpell(player, SPELL_QUICK_CAP_TIMER, true);
player->StartCriteria(CriteriaStartEvent::BeSpellTarget, SPELL_QUICK_CAP_TIMER, Seconds(GameTime::GetGameTime() - flagInBase->GetFlagTakenFromBaseTime()));
break;
}
case FlagState::Respawning:
ResetAssaultDebuff();
break;
default:
break;
}
}
bool CanCaptureFlag(AreaTrigger* areaTrigger, Player* player) override
{
if (battleground->GetStatus() != STATUS_IN_PROGRESS)
return false;
Team const team = battleground->GetPlayerTeam(player->GetGUID());
TeamId const teamId = Battleground::GetTeamIndexByTeamId(team);
TeamId const otherTeamId = Battleground::GetTeamIndexByTeamId(GetOtherTeam(team));
if (areaTrigger->GetGUID() != _capturePointAreaTriggers[teamId])
return false;
// check if enemy flag's carrier is this player
if (GetFlagCarrierGUID(otherTeamId) != player->GetGUID())
return false;
// check that team's flag is in base
return GetFlagState(teamId) == FlagState::InBase;
}
void OnCaptureFlag(AreaTrigger* areaTrigger, Player* player) override
{
BattlegroundScript::OnCaptureFlag(areaTrigger, player);
Team winner = TEAM_OTHER;
Team const team = battleground->GetPlayerTeam(player->GetGUID());
TeamId const teamId = Battleground::GetTeamIndexByTeamId(team);
TeamId const otherTeamId = Battleground::GetTeamIndexByTeamId(GetOtherTeam(team));
/*
1. Update flag states & score world states
2. update points
3. chat message & sound
4. update criterias & achievements
5. remove all related auras
?. Reward honor & reputation
*/
// 1. update the flag states
for (ObjectGuid const& flagGuid: _flags)
if (GameObject const* flag = battlegroundMap->GetGameObject(flagGuid))
flag->HandleCustomTypeCommand(GameObjectType::SetNewFlagState(FlagState::Respawning, player));
// 2. update points
if (battleground->GetTeamScore(teamId) < MAX_TEAM_SCORE)
battleground->AddPoint(team, 1);
UpdateTeamScore(teamId);
// 3. chat message & sound
if (team == ALLIANCE)
{
battleground->SendBroadcastText(TEXT_CAPTURED_HORDE_FLAG, CHAT_MSG_BG_SYSTEM_HORDE, player);
battleground->PlaySoundToAll(SOUND_FLAG_CAPTURED_ALLIANCE);
battleground->RewardReputationToTeam(890, _reputationCapture, ALLIANCE);
player->CastSpell(player, SPELL_CAPTURED_ALLIANCE_COSMETIC_FX);
}
else
{
battleground->SendBroadcastText(TEXT_CAPTURED_ALLIANCE_FLAG, CHAT_MSG_BG_SYSTEM_ALLIANCE, player);
battleground->PlaySoundToAll(SOUND_FLAG_CAPTURED_HORDE);
battleground->RewardReputationToTeam(889, _reputationCapture, HORDE);
player->CastSpell(player, SPELL_CAPTURED_HORDE_COSMETIC_FX);
}
// 4. update criteria's for achievement, player score etc.
battleground->UpdatePvpStat(player, PVP_STAT_FLAG_CAPTURES, 1); // +1 flag captures
// 5. Remove all related auras
RemoveAssaultDebuffFromPlayer(player);
if (GameObject const* flag = battlegroundMap->GetGameObject(_flags[otherTeamId]))
player->RemoveAurasDueToSpell(flag->GetGOInfo()->newflag.pickupSpell, flag->GetGUID());
player->RemoveAurasDueToSpell(SPELL_QUICK_CAP_TIMER);
player->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::PvPActive);
battleground->RewardHonorToTeam(battleground->GetBonusHonorFromKill(2), team);
// update last flag capture to be used if teamscore is equal
SetLastFlagCapture(team);
if (battleground->GetTeamScore(teamId) == MAX_TEAM_SCORE)
winner = team;
if (winner)
{
UpdateWorldState(WORLD_STATE_FLAG_STATE_ALLIANCE, 1);
UpdateWorldState(WORLD_STATE_FLAG_STATE_HORDE, 1);
UpdateWorldState(WORLD_STATE_STATE_TIMER_ACTIVE, 0);
battleground->RewardHonorToTeam(HONOR_REWARDS[BattlegroundMgr::IsBGWeekend(battleground->GetTypeID()) ? 1 : 0][0], winner);
battleground->EndBattleground(winner);
}
}
Team GetPrematureWinner() override
{
if (battleground->GetTeamScore(TEAM_ALLIANCE) > battleground->GetTeamScore(TEAM_HORDE))
return ALLIANCE;
if (battleground->GetTeamScore(TEAM_HORDE) > battleground->GetTeamScore(TEAM_ALLIANCE))
return HORDE;
return BattlegroundScript::GetPrematureWinner();
}
void SetLastFlagCapture(Team team)
{
_lastFlagCaptureTeam = team;
}
private:
Team _lastFlagCaptureTeam;
bool _bothFlagsKept;
GuidSet _doors;
std::array<ObjectGuid, PVP_TEAMS_COUNT> _flags;
TimeTracker _flagAssaultTimer;
uint8 _assaultStackCount;
std::array<ObjectGuid, PVP_TEAMS_COUNT> _capturePointAreaTriggers;
uint32 _honorWinKills;
uint32 _honorEndKills;
uint32 _reputationCapture;
};
void AddSC_battleground_warsong_gulch()
{
RegisterBattlegroundMapScript(battleground_warsong_gulch, 2106);
}

View File

@@ -0,0 +1,95 @@
/*
* 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/>.
*/
// This is where scripts' loading functions should be declared:
// Alterac Valley
void AddSC_alterac_valley();
void AddSC_boss_balinda();
void AddSC_boss_drekthar();
void AddSC_boss_galvangar();
void AddSC_boss_vanndar();
void AddSC_battleground_alterac_valley();
// Arathi Basin
void AddSC_arathi_basin();
void AddSC_battleground_arathi_basin();
// Eye of the storm
void AddSC_battleground_eye_of_the_storm();
// Warsong Gulch
void AddSC_battleground_warsong_gulch();
// Isle of Conquest
void AddSC_battleground_isle_of_conquest();
void AddSC_isle_of_conquest();
void AddSC_boss_ioc_horde_alliance();
// Strand of the Ancients
void AddSC_battleground_strand_of_the_ancients();
void AddSC_strand_of_the_ancients();
// Blade's Edge Arena
void AddSC_arena_blades_edge();
void AddSC_arena_dalaran_sewers();
void AddSC_arena_nagrand();
void AddSC_arena_ruins_of_lordaeron();
void AddSC_arena_ring_of_valor();
void AddSC_battleground_twin_peaks();
void AddSC_battleground_battle_for_gilneas();
// The name of this function should match:
// void Add${NameOfDirectory}Scripts()
void AddBattlegroundsScripts()
{
// Alterac Valley
AddSC_alterac_valley();
AddSC_boss_balinda();
AddSC_boss_drekthar();
AddSC_boss_galvangar();
AddSC_boss_vanndar();
AddSC_battleground_alterac_valley();
// Arathi Basin
AddSC_arathi_basin();
AddSC_battleground_arathi_basin();
// Eye of the Storm
AddSC_battleground_eye_of_the_storm();
// Warsong Gulch
AddSC_battleground_warsong_gulch();
// Isle of Conquest
AddSC_battleground_isle_of_conquest();
AddSC_isle_of_conquest();
AddSC_boss_ioc_horde_alliance();
// Strand of the Ancients
AddSC_battleground_strand_of_the_ancients();
AddSC_strand_of_the_ancients();
AddSC_arena_blades_edge();
AddSC_arena_dalaran_sewers();
AddSC_arena_nagrand();
AddSC_arena_ruins_of_lordaeron();
AddSC_arena_ring_of_valor();
AddSC_battleground_twin_peaks();
AddSC_battleground_battle_for_gilneas();
}

View File

@@ -1418,15 +1418,11 @@ public:
if (linked)
{
if (Battleground* bg = player->GetBattleground())
nearestLoc = bg->GetClosestGraveyard(player);
if (Battlefield* bf = sBattlefieldMgr->GetBattlefieldToZoneId(player->GetMap(), player->GetZoneId()))
nearestLoc = bf->GetClosestGraveyard(player);
else
{
if (Battlefield* bf = sBattlefieldMgr->GetBattlefieldToZoneId(player->GetMap(), player->GetZoneId()))
nearestLoc = bf->GetClosestGraveyard(player);
else
nearestLoc = sObjectMgr->GetClosestGraveyard(*player, player->GetTeam(), player);
}
nearestLoc = sObjectMgr->GetClosestGraveyard(*player, player->GetTeam(), player);
}
else
{

View File

@@ -16,12 +16,6 @@
*/
// This is where scripts' loading functions should be declared:
void AddSC_alterac_valley(); //Alterac Valley
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_argaloth();
@@ -211,12 +205,6 @@ void AddSC_undercity();
// void Add${NameOfDirectory}Scripts()
void AddEasternKingdomsScripts()
{
AddSC_alterac_valley(); //Alterac Valley
AddSC_boss_balinda();
AddSC_boss_drekthar();
AddSC_boss_galvangar();
AddSC_boss_vanndar();
AddSC_arathi_basin(); //Arathi Basin
AddSC_boss_alizabal(); //Baradin Hold
AddSC_boss_occuthar();
AddSC_boss_argaloth();

View File

@@ -194,9 +194,6 @@ void AddSC_boss_baltharus_the_warborn();
void AddSC_boss_saviana_ragefire();
void AddSC_boss_general_zarithrian();
void AddSC_boss_halion();
// Isle of Conquest
void AddSC_isle_of_conquest();
void AddSC_boss_ioc_horde_alliance();
void AddSC_dalaran();
void AddSC_borean_tundra();
@@ -210,8 +207,6 @@ void AddSC_wintergrasp();
void AddSC_zuldrak();
void AddSC_crystalsong_forest();
void AddSC_strand_of_the_ancients();
// The name of this function should match:
// void Add${NameOfDirectory}Scripts()
void AddNorthrendScripts()
@@ -394,9 +389,6 @@ void AddNorthrendScripts()
AddSC_boss_saviana_ragefire();
AddSC_boss_general_zarithrian();
AddSC_boss_halion();
// Isle of Conquest
AddSC_isle_of_conquest();
AddSC_boss_ioc_horde_alliance();
AddSC_dalaran();
AddSC_borean_tundra();
@@ -408,6 +400,4 @@ void AddNorthrendScripts()
AddSC_storm_peaks();
AddSC_wintergrasp();
AddSC_zuldrak();
AddSC_strand_of_the_ancients();
}

View File

@@ -24,7 +24,6 @@ SDCategory: Dalaran
Script Data End */
#include "ScriptMgr.h"
#include "BattlegroundDS.h"
#include "Containers.h"
#include "DatabaseEnv.h"
#include "Mail.h"
@@ -254,44 +253,8 @@ private:
EventMap events;
};
class at_ds_pipe_knockback : public AreaTriggerScript
{
public:
at_ds_pipe_knockback() : AreaTriggerScript("at_ds_pipe_knockback") { }
void Trigger(Player* player) const
{
if (Battleground* battleground = player->GetBattleground())
{
if (battleground->GetStatus() != STATUS_IN_PROGRESS)
return;
// Remove effects of Demonic Circle Summon
player->RemoveAurasDueToSpell(SPELL_WARL_DEMONIC_CIRCLE);
// Someone has get back into the pipes and the knockback has already been performed,
// so we reset the knockback count for kicking the player again into the arena.
if (battleground->GetData(BG_DS_DATA_PIPE_KNOCKBACK_COUNT) >= BG_DS_PIPE_KNOCKBACK_TOTAL_COUNT)
battleground->SetData(BG_DS_DATA_PIPE_KNOCKBACK_COUNT, 0);
}
}
bool OnTrigger(Player* player, AreaTriggerEntry const* /*trigger*/) override
{
Trigger(player);
return true;
}
bool OnExit(Player* player, AreaTriggerEntry const* /*trigger*/) override
{
Trigger(player);
return true;
}
};
void AddSC_dalaran()
{
RegisterCreatureAI(npc_mageguard_dalaran);
RegisterCreatureAI(npc_minigob_manabonk);
new at_ds_pipe_knockback();
}

View File

@@ -3081,9 +3081,6 @@ class spell_item_rocket_boots : public SpellScript
void HandleDummy(SpellEffIndex /* effIndex */)
{
Player* caster = GetCaster()->ToPlayer();
if (Battleground* bg = caster->GetBattleground())
bg->EventPlayerDroppedFlag(caster);
caster->GetSpellHistory()->ResetCooldown(SPELL_ROCKET_BOOTS_PROC);
caster->CastSpell(caster, SPELL_ROCKET_BOOTS_PROC, true);
}