aboutsummaryrefslogtreecommitdiff
path: root/src/server/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/scripts')
-rw-r--r--src/server/scripts/Battlegrounds/AlteracValley/alterac_valley.cpp (renamed from src/server/scripts/EasternKingdoms/AlteracValley/alterac_valley.cpp)29
-rw-r--r--src/server/scripts/Battlegrounds/AlteracValley/alterac_valley.h39
-rw-r--r--src/server/scripts/Battlegrounds/AlteracValley/battleground_alterac_valley.cpp1369
-rw-r--r--src/server/scripts/Battlegrounds/AlteracValley/boss_balinda.cpp (renamed from src/server/scripts/EasternKingdoms/AlteracValley/boss_balinda.cpp)0
-rw-r--r--src/server/scripts/Battlegrounds/AlteracValley/boss_drekthar.cpp (renamed from src/server/scripts/EasternKingdoms/AlteracValley/boss_drekthar.cpp)0
-rw-r--r--src/server/scripts/Battlegrounds/AlteracValley/boss_galvangar.cpp (renamed from src/server/scripts/EasternKingdoms/AlteracValley/boss_galvangar.cpp)0
-rw-r--r--src/server/scripts/Battlegrounds/AlteracValley/boss_vanndar.cpp (renamed from src/server/scripts/EasternKingdoms/AlteracValley/boss_vanndar.cpp)0
-rw-r--r--src/server/scripts/Battlegrounds/ArathiBasin/arathi_basin.cpp (renamed from src/server/scripts/EasternKingdoms/ArathiBasin/arathi_basin.cpp)0
-rw-r--r--src/server/scripts/Battlegrounds/ArathiBasin/battleground_arathi_basin.cpp605
-rw-r--r--src/server/scripts/Battlegrounds/BattleForGilneas/battleground_battle_for_gilneas.cpp35
-rw-r--r--src/server/scripts/Battlegrounds/BladesEdge/arena_blades_edge.cpp84
-rw-r--r--src/server/scripts/Battlegrounds/DalaranSewers/arena_dalaran_sewers.cpp266
-rw-r--r--src/server/scripts/Battlegrounds/EyeOfTheStorm/battleground_eye_of_the_storm.cpp677
-rw-r--r--src/server/scripts/Battlegrounds/IsleOfConquest/battleground_isle_of_conquest.cpp902
-rw-r--r--src/server/scripts/Battlegrounds/IsleOfConquest/boss_ioc_horde_alliance.cpp (renamed from src/server/scripts/Northrend/IsleOfConquest/boss_ioc_horde_alliance.cpp)2
-rw-r--r--src/server/scripts/Battlegrounds/IsleOfConquest/isle_of_conquest.cpp (renamed from src/server/scripts/Northrend/IsleOfConquest/isle_of_conquest.cpp)3
-rw-r--r--src/server/scripts/Battlegrounds/IsleOfConquest/isle_of_conquest.h132
-rw-r--r--src/server/scripts/Battlegrounds/NagrandArena/arena_nagrand_arena.cpp84
-rw-r--r--src/server/scripts/Battlegrounds/RingOfValor/arena_ring_of_valor.cpp302
-rw-r--r--src/server/scripts/Battlegrounds/RuinsOfLordaeron/arena_ruins_of_lordaeron.cpp80
-rw-r--r--src/server/scripts/Battlegrounds/StrandOfTheAncients/battleground_strand_of_the_ancients.cpp1059
-rw-r--r--src/server/scripts/Battlegrounds/StrandOfTheAncients/strand_of_the_ancients.cpp (renamed from src/server/scripts/Northrend/StrandOfTheAncients/strand_of_the_ancients.cpp)2
-rw-r--r--src/server/scripts/Battlegrounds/StrandOfTheAncients/strand_of_the_ancients.h26
-rw-r--r--src/server/scripts/Battlegrounds/TwinPeaks/battleground_twin_peaks.cpp35
-rw-r--r--src/server/scripts/Battlegrounds/WarsongGulch/battleground_warsong_gulch.cpp608
-rw-r--r--src/server/scripts/Battlegrounds/battlegrounds_script_loader.cpp95
-rw-r--r--src/server/scripts/Commands/cs_debug.cpp12
-rw-r--r--src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp12
-rw-r--r--src/server/scripts/Northrend/northrend_script_loader.cpp10
-rw-r--r--src/server/scripts/Northrend/zone_dalaran.cpp37
-rw-r--r--src/server/scripts/Spells/spell_item.cpp3
31 files changed, 6434 insertions, 74 deletions
diff --git a/src/server/scripts/EasternKingdoms/AlteracValley/alterac_valley.cpp b/src/server/scripts/Battlegrounds/AlteracValley/alterac_valley.cpp
index 629be86a525..94af6a25a53 100644
--- a/src/server/scripts/EasternKingdoms/AlteracValley/alterac_valley.cpp
+++ b/src/server/scripts/Battlegrounds/AlteracValley/alterac_valley.cpp
@@ -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");
}
diff --git a/src/server/scripts/Battlegrounds/AlteracValley/alterac_valley.h b/src/server/scripts/Battlegrounds/AlteracValley/alterac_valley.h
new file mode 100644
index 00000000000..4bd5dea255a
--- /dev/null
+++ b/src/server/scripts/Battlegrounds/AlteracValley/alterac_valley.h
@@ -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
diff --git a/src/server/scripts/Battlegrounds/AlteracValley/battleground_alterac_valley.cpp b/src/server/scripts/Battlegrounds/AlteracValley/battleground_alterac_valley.cpp
new file mode 100644
index 00000000000..1616b77ec1e
--- /dev/null
+++ b/src/server/scripts/Battlegrounds/AlteracValley/battleground_alterac_valley.cpp
@@ -0,0 +1,1369 @@
+/*
+ * 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 "alterac_valley.h"
+#include "Battleground.h"
+#include "BattlegroundMgr.h"
+#include "BattlegroundPackets.h"
+#include "Creature.h"
+#include "CreatureAI.h"
+#include "GameObject.h"
+#include "GameTime.h"
+#include "Log.h"
+#include "Map.h"
+#include "Player.h"
+#include "ScriptMgr.h"
+
+constexpr uint32 BG_AV_SCORE_INITIAL_POINTS = 700;
+constexpr uint32 BG_AV_EVENT_START_BATTLE = 9166; // Achievement: The Alterac Blitz
+
+enum BG_AV_BroadcastTexts
+{
+ BG_AV_TEXT_START_ONE_MINUTE = 10638,
+ BG_AV_TEXT_START_HALF_MINUTE = 10639,
+ BG_AV_TEXT_BATTLE_HAS_BEGUN = 10640,
+
+ BG_AV_TEXT_ALLIANCE_NEAR_LOSE = 23210,
+ BG_AV_TEXT_HORDE_NEAR_LOSE = 23211
+};
+
+enum BG_AV_Sounds
+{
+ AV_SOUND_NEAR_VICTORY = 8456, /// @todo: Not confirmed yet
+
+ AV_SOUND_ALLIANCE_ASSAULTS = 8212, //tower, grave + enemy boss if someone tries to attack him
+ AV_SOUND_HORDE_ASSAULTS = 8174,
+ AV_SOUND_ALLIANCE_GOOD = 8173, //if something good happens for the team: wins(maybe only through killing the boss), captures mine or grave, destroys tower and defends grave
+ AV_SOUND_HORDE_GOOD = 8213,
+ AV_SOUND_BOTH_TOWER_DEFEND = 8192,
+
+ AV_SOUND_ALLIANCE_CAPTAIN = 8232, //gets called when someone attacks them and at the beginning after 5min+rand(x)*10sec (maybe buff)
+ AV_SOUND_HORDE_CAPTAIN = 8333
+};
+
+constexpr Seconds BG_AV_MINE_RESOURCE_TIMER = 45s;
+
+enum class AlteracValleyMine : uint8
+{
+ North = 0,
+ South
+};
+
+enum BG_AV_CreatureIds
+{
+ BG_AV_CREATURE_VANNDAR = 11948,
+ BG_AV_CREATURE_DREKTHAR = 11946,
+ BG_AV_CREATURE_BALINDA = 11949,
+ BG_AV_CREATURE_GALVANGAR = 11947,
+ BG_AV_CREATURE_MORLOCH = 11657,
+ BG_AV_CREATURE_UMI_THORSON = 13078,
+ BG_AV_CREATURE_KEETAR = 13079,
+ BG_AV_CREATURE_TASKMASTER_SNIVVLE = 11677,
+ BG_AV_CREATURE_AGI_RUMBLESTOMP = 13086,
+ BG_AV_CREATURE_MASHA_SWIFTCUT = 13088,
+ BG_AV_CREATURE_HERALD = 14848,
+
+ BG_AV_CREATURE_STORMPIKE_DEFENDER = 12050,
+ BG_AV_CREATURE_FROSTWOLF_GUARDIAN = 12053,
+ BG_AV_CREATURE_SEASONED_DEFENDER = 13326,
+ BG_AV_CREATURE_SEASONED_GUARDIAN = 13328,
+ BG_AV_CREATURE_VETERAN_DEFENDER = 13331,
+ BG_AV_CREATURE_VETERAN_GUARDIAN = 13332,
+ BG_AV_CREATURE_CHAMPION_DEFENDER = 13422,
+ BG_AV_CREATURE_CHAMPION_GUARDIAN = 13421
+};
+
+enum BG_AV_ObjectIds
+{
+ //cause the mangos-system is a bit different, we don't use the right go-ids for every node.. if we want to be 100% like another big server, we must take one object for every node
+ //snowfall 4flags as eyecandy 179424 (alliance neutral)
+ //Banners - stolen from battleground_AB.h ;-)
+ BG_AV_OBJECTID_BANNER_A = 178925, // can only be used by horde
+ BG_AV_OBJECTID_BANNER_H = 178943, // can only be used by alliance
+ BG_AV_OBJECTID_BANNER_CONT_A = 178940, // can only be used by horde
+ BG_AV_OBJECTID_BANNER_CONT_H = 179435, // can only be used by alliance
+
+ BG_AV_OBJECTID_BANNER_A_B = 178365,
+ BG_AV_OBJECTID_BANNER_H_B = 178364,
+ BG_AV_OBJECTID_BANNER_CONT_A_B = 179286,
+ BG_AV_OBJECTID_BANNER_CONT_H_B = 179287,
+ BG_AV_OBJECTID_BANNER_SNOWFALL_N = 180418,
+
+ //snowfall eyecandy banner:
+ BG_AV_OBJECTID_SNOWFALL_CANDY_A = 179044,
+ BG_AV_OBJECTID_SNOWFALL_CANDY_PA = 179424,
+ BG_AV_OBJECTID_SNOWFALL_CANDY_H = 179064,
+ BG_AV_OBJECTID_SNOWFALL_CANDY_PH = 179425,
+
+ //banners on top of towers:
+ BG_AV_OBJECTID_TOWER_BANNER_A = 178927, //[PH] Alliance A1 Tower Banner BIG
+ BG_AV_OBJECTID_TOWER_BANNER_H = 178955, //[PH] Horde H1 Tower Banner BIG
+ BG_AV_OBJECTID_TOWER_BANNER_PA = 179446, //[PH] Alliance H1 Tower Pre-Banner BIG
+ BG_AV_OBJECTID_TOWER_BANNER_PH = 179436, //[PH] Horde A1 Tower Pre-Banner BIG
+
+ //Auras
+ BG_AV_OBJECTID_AURA_A = 180421,
+ BG_AV_OBJECTID_AURA_H = 180422,
+ BG_AV_OBJECTID_AURA_N = 180423,
+ BG_AV_OBJECTID_AURA_A_S = 180100,
+ BG_AV_OBJECTID_AURA_H_S = 180101,
+ BG_AV_OBJECTID_AURA_N_S = 180102,
+
+ BG_AV_OBJECTID_GATE = 180424,
+ BG_AV_GHOST_GATE = 180322,
+
+ //mine supplies
+ BG_AV_OBJECTID_MINE_N = 178785,
+ BG_AV_OBJECTID_MINE_S = 178784,
+
+ BG_AV_OBJECTID_FIRE = 179065,
+ BG_AV_OBJECTID_SMOKE = 179066,
+
+ // Towers
+ BG_AV_OBJECTID_SOUTH_BUNKER_CONTROLLED_TOWER_BANNER = 178927,
+ BG_AV_OBJECTID_SOUTH_BUNKER_CONTROLLED_BANNER = 178925,
+ BG_AV_OBJECTID_SOUTH_BUNKER_CONTESTED_BANNER = 179435,
+ BG_AV_OBJECTID_SOUTH_BUNKER_CONTESTED_TOWER_BANNER = 179436,
+
+ BG_AV_OBJECTID_NORTH_BUNKER_CONTROLLED_TOWER_BANNER = 178932,
+ BG_AV_OBJECTID_NORTH_BUNKER_CONTROLLED_BANNER = 178929,
+ BG_AV_OBJECTID_NORTH_BUNKER_CONTESTED_BANNER = 179439,
+ BG_AV_OBJECTID_NORTH_BUNKER_CONTESTED_TOWER_BANNER = 179440,
+
+ BG_AV_OBJECTID_EAST_TOWER_CONTROLLED_TOWER_BANNER = 178956,
+ BG_AV_OBJECTID_EAST_TOWER_CONTROLLED_BANNER = 178944,
+ BG_AV_OBJECTID_EAST_TOWER_CONTESTED_BANNER = 179449,
+ BG_AV_OBJECTID_EAST_TOWER_CONTESTED_TOWER_BANNER = 179450,
+
+ BG_AV_OBJECTID_WEST_TOWER_CONTROLLED_TOWER_BANNER = 178955,
+ BG_AV_OBJECTID_WEST_TOWER_CONTROLLED_BANNER = 178943,
+ BG_AV_OBJECTID_WEST_TOWER_CONTESTED_BANNER = 179445,
+ BG_AV_OBJECTID_WEST_TOWER_CONTESTED_TOWER_BANNER = 179446,
+
+ BG_AV_OBJECTID_TOWER_POINT_CONTROLLED_TOWER_BANNER = 178957,
+ BG_AV_OBJECTID_TOWER_POINT_CONTROLLED_BANNER = 178945,
+ BG_AV_OBJECTID_TOWER_POINT_CONTESTED_BANNER = 179453,
+ BG_AV_OBJECTID_TOWER_POINT_CONTESTED_TOWER_BANNER = 179454,
+
+ BG_AV_OBJECTID_ICEBLOOD_TOWER_CONTROLLED_TOWER_BANNER = 178958,
+ BG_AV_OBJECTID_ICEBLOOD_TOWER_CONTROLLED_BANNER = 178946,
+ BG_AV_OBJECTID_ICEBLOOD_TOWER_CONTESTED_BANNER = 178940,
+ BG_AV_OBJECTID_ICEBLOOD_TOWER_CONTESTED_TOWER_BANNER = 179458,
+
+ BG_AV_OBJECTID_STONEHEARTH_BUNKER_CONTROLLED_TOWER_BANNER = 178948,
+ BG_AV_OBJECTID_STONEHEARTH_BUNKER_CONTROLLED_BANNER = 178936,
+ BG_AV_OBJECTID_STONEHEARTH_BUNKER_CONTESTED_BANNER = 179443,
+ BG_AV_OBJECTID_STONEHEARTH_BUNKER_CONTESTED_TOWER_BANNER = 179444,
+
+ BG_AV_OBJECTID_ICEWING_BUNKER_CONTROLLED_TOWER_BANNER = 178947,
+ BG_AV_OBJECTID_ICEWING_BUNKER_CONTROLLED_BANNER = 178935,
+ BG_AV_OBJECTID_ICEWING_BUNKER_CONTESTED_BANNER = 179441,
+ BG_AV_OBJECTID_ICEWING_BUNKER_CONTESTED_TOWER_BANNER = 179442,
+
+ // Graveyards
+ BG_AV_OBJECTID_AID_STATION_ALLIANCE_CONTROLLED = 179465,
+ BG_AV_OBJECTID_AID_STATION_HORDE_CONTESTED = 179468,
+ BG_AV_OBJECTID_AID_STATION_HORDE_CONTROLLED = 179467,
+ BG_AV_OBJECTID_AID_STATION_ALLIANCE_CONTESTED = 179466,
+
+ BG_AV_OBJECTID_STORMPIKE_ALLIANCE_CONTROLLED = 178389,
+ BG_AV_OBJECTID_STORMPIKE_HORDE_CONTESTED = 179287,
+ BG_AV_OBJECTID_STORMPIKE_HORDE_CONTROLLED = 178388,
+ BG_AV_OBJECTID_STORMPIKE_ALLIANCE_CONTESTED = 179286,
+
+ BG_AV_OBJECTID_STONEHEARTH_HORDE_CONTESTED = 179310,
+ BG_AV_OBJECTID_STONEHEARTH_HORDE_CONTROLLED = 179285,
+ BG_AV_OBJECTID_STONEHEARTH_ALLIANCE_CONTESTED = 179308,
+ BG_AV_OBJECTID_STONEHEARTH_ALLIANCE_CONTROLLED = 179284,
+
+ BG_AV_OBJECTID_SNOWFALL_NEUTRAL = 180418,
+ BG_AV_OBJECTID_SNOWFALL_HORDE_CONTESTED = 180420,
+ BG_AV_OBJECTID_SNOWFALL_ALLIANCE_CONTESTED = 180419,
+ BG_AV_OBJECTID_SNOWFALL_HORDE_CONTROLLED = 178364,
+ BG_AV_OBJECTID_SNOWFALL_ALLIANCE_CONTROLLED = 178365,
+
+ BG_AV_OBJECTID_ICEBLOOD_HORDE_CONTROLLED = 179483,
+ BG_AV_OBJECTID_ICEBLOOD_ALLIANCE_CONTESTED = 179482,
+ BG_AV_OBJECTID_ICEBLOOD_ALLIANCE_CONTROLLED = 179481,
+ BG_AV_OBJECTID_ICEBLOOD_HORDE_CONTESTED = 179484,
+
+ BG_AV_OBJECTID_FROSTWOLF_HORDE_CONTROLLED = 178393,
+ BG_AV_OBJECTID_FROSTWOLF_ALLIANCE_CONTESTED = 179304,
+ BG_AV_OBJECTID_FROSTWOLF_ALLIANCE_CONTROLLED = 178394,
+ BG_AV_OBJECTID_FROSTWOLF_HORDE_CONTESTED = 179305,
+
+ BG_AV_OBJECTID_FROSTWOLF_HUT_HORDE_CONTROLLED = 179472,
+ BG_AV_OBJECTID_FROSTWOLF_HUT_ALLIANCE_CONTESTED = 179471,
+ BG_AV_OBJECTID_FROSTWOLF_HUT_ALLIANCE_CONTROLLED = 179470,
+ BG_AV_OBJECTID_FROSTWOLF_HUT_HORDE_CONTESTED = 179473
+};
+
+enum BG_AV_Nodes
+{
+ BG_AV_NODES_FIRSTAID_STATION = 0,
+ BG_AV_NODES_STORMPIKE_GRAVE = 1,
+ BG_AV_NODES_STONEHEART_GRAVE = 2,
+ BG_AV_NODES_SNOWFALL_GRAVE = 3,
+ BG_AV_NODES_ICEBLOOD_GRAVE = 4,
+ BG_AV_NODES_FROSTWOLF_GRAVE = 5,
+ BG_AV_NODES_FROSTWOLF_HUT = 6,
+ BG_AV_NODES_DUNBALDAR_SOUTH = 7,
+ BG_AV_NODES_DUNBALDAR_NORTH = 8,
+ BG_AV_NODES_ICEWING_BUNKER = 9,
+ BG_AV_NODES_STONEHEART_BUNKER = 10,
+ BG_AV_NODES_ICEBLOOD_TOWER = 11,
+ BG_AV_NODES_TOWER_POINT = 12,
+ BG_AV_NODES_FROSTWOLF_ETOWER = 13,
+ BG_AV_NODES_FROSTWOLF_WTOWER = 14,
+
+ BG_AV_NODES_MAX = 15
+};
+
+enum BG_AV_BUFF
+{ /// @todo: Add all other buffs here
+ AV_BUFF_ARMOR = 21163,
+ AV_BUFF_A_CAPTAIN = 23693, //the buff which the alliance captain does
+ AV_BUFF_H_CAPTAIN = 22751 //the buff which the horde captain does
+};
+enum BG_AV_States
+{
+ POINT_NEUTRAL = 0,
+ POINT_ASSAULTED = 1,
+ POINT_DESTROYED = 2,
+ POINT_CONTROLED = 3
+};
+
+enum BG_AV_WorldStates
+{
+ AV_WS_ALLIANCE_REINFORCEMENTS = 3127,
+ AV_WS_HORDE_REINFORCEMENTS = 3128,
+ AV_WS_SHOW_HORDE_REINFORCEMENTS = 3133,
+ AV_WS_SHOW_ALLIANCE_REINFORCEMENTS = 3134,
+ AV_WS_MAX_REINFORCEMENTS = 3136,
+
+// Graves
+ // Alliance
+ //Stormpike first aid station
+ AV_WS_STORMPIKE_AID_STATION_ALLIANCE_CONTROLLED = 1325,
+ AV_WS_STORMPIKE_AID_STATION_IN_CONFLICT_ALLIANCE_ATTACKING = 1326,
+ AV_WS_STORMPIKE_AID_STATION_HORDE_CONTROLLED = 1327,
+ AV_WS_STORMPIKE_AID_STATION_IN_CONFLICT_HORDE_ATTACKING = 1328,
+ //Stormpike Graveyard
+ AV_WS_STORMPIKE_GRAVEYARD_ALLIANCE_CONTROLLED = 1333,
+ AV_WS_STORMPIKE_GRAVEYARD_IN_CONFLICT_ALLIANCE_ATTACKING = 1335,
+ AV_WS_STORMPIKE_GRAVEYARD_HORDE_CONTROLLED = 1334,
+ AV_WS_STORMPIKE_GRAVEYARD_IN_CONFLICT_HORDE_ATTACKING = 1336,
+ //Stoneheart Grave
+ AV_WS_STONEHEARTH_GRAVEYARD_ALLIANCE_CONTROLLED = 1302,
+ AV_WS_STONEHEARTH_GRAVEYARD_IN_CONFLICT_ALLIANCE_ATTACKING = 1304,
+ AV_WS_STONEHEARTH_GRAVEYARD_HORDE_CONTROLLED = 1301,
+ AV_WS_STONEHEARTH_GRAVEYARD_IN_CONFLICT_HORDE_ATTACKING = 1303,
+ //Neutral
+ //Snowfall Grave
+ AV_WS_SNOWFALL_GRAVEYARD_UNCONTROLLED = 1966,
+ AV_WS_SNOWFALL_GRAVEYARD_ALLIANCE_CONTROLLED = 1341,
+ AV_WS_SNOWFALL_GRAVEYARD_IN_CONFLICT_ALLIANCE_ATTACKING = 1343,
+ AV_WS_SNOWFALL_GRAVEYARD_HORDE_CONTROLLED = 1342,
+ AV_WS_SNOWFALL_GRAVEYARD_IN_CONFLICT_HORDE_ATTACKING = 1344,
+ //Horde
+ //Iceblood grave
+ AV_WS_ICEBLOOD_GRAVEYARD_ALLIANCE_CONTROLLED = 1346,
+ AV_WS_ICEBLOOD_GRAVEYARD_IN_CONFLICT_ALLIANCE_ATTACKING = 1348,
+ AV_WS_ICEBLOOD_GRAVEYARD_HORDE_CONTROLLED = 1347,
+ AV_WS_ICEBLOOD_GRAVEYARD_IN_CONFLICT_HORDE_ATTACKING = 1349,
+ //Frostwolf Grave
+ AV_WS_FROSTWOLF_GRAVEYARD_ALLIANCE_CONTROLLED = 1337,
+ AV_WS_FROSTWOLF_GRAVEYARD_IN_CONFLICT_ALLIANCE_ATTACKING = 1339,
+ AV_WS_FROSTWOLF_GRAVEYARD_HORDE_CONTROLLED = 1338,
+ AV_WS_FROSTWOLF_GRAVEYARD_IN_CONFLICT_HORDE_ATTACKING = 1340,
+ //Frostwolf Hut
+ AV_WS_FROSTWOLF_RELIEF_HUT_ALLIANCE_CONTROLLED = 1329,
+ AV_WS_FROSTWOLF_RELIEF_HUT_IN_CONFLICT_ALLIANCE_ATTACKING = 1331,
+ AV_WS_FROSTWOLF_RELIEF_HUT_HORDE_CONTROLLED = 1330,
+ AV_WS_FROSTWOLF_RELIEF_HUT_IN_CONFLICT_HORDE_ATTACKING = 1332,
+
+//Towers
+ //Alliance
+ //Dunbaldar South Bunker
+ AV_WS_DUN_BALDAR_SOUTH_BUNKER_OWNER = 1181,
+ AV_WS_DUN_BALDAR_SOUTH_BUNKER_ALLIANCE_CONTROLLED = 1361,
+ AV_WS_DUN_BALDAR_SOUTH_BUNKER_DESTROYED = 1370,
+ AV_WS_DUN_BALDAR_SOUTH_BUNKER_IN_CONFLICT_HORDE_ATTACKING = 1378,
+ AV_WS_DUN_BALDAR_SOUTH_BUNKER_IN_CONFLICT_ALLIANCE_ATTACKING = 1374, // unused
+ //Dunbaldar North Bunker
+ AV_WS_DUN_BALDAR_NORTH_BUNKER_OWNER = 1182,
+ AV_WS_DUN_BALDAR_NORTH_BUNKER_ALLIANCE_CONTROLLED = 1362,
+ AV_WS_DUN_BALDAR_NORTH_BUNKER_DESTROYED = 1371,
+ AV_WS_DUN_BALDAR_NORTH_BUNKER_IN_CONFLICT_HORDE_ATTACKING = 1379,
+ AV_WS_DUN_BALDAR_NORTH_BUNKER_IN_CONFLICT_ALLIANCE_ATTACKING = 1375, // unused
+ //Icewing Bunker
+ AV_WS_ICEWING_BUNKER_OWNER = 1183,
+ AV_WS_ICEWING_BUNKER_ALLIANCE_CONTROLLED = 1363,
+ AV_WS_ICEWING_BUNKER_DESTROYED = 1372,
+ AV_WS_ICEWING_BUNKER_IN_CONFLICT_HORDE_ATTACKING = 1380,
+ AV_WS_ICEWING_BUNKER_IN_CONFLICT_ALLIANCE_ATTACKING = 1376, // unused
+ //Stoneheart Bunker
+ AV_WS_STONEHEARTH_BUNKER_OWNER = 1184,
+ AV_WS_STONEHEARTH_BUNKER_ALLIANCE_CONTROLLED = 1364,
+ AV_WS_STONEHEARTH_BUNKER_DESTROYED = 1373,
+ AV_WS_STONEHEARTH_BUNKER_IN_CONFLICT_HORDE_ATTACKING = 1381,
+ AV_WS_STONEHEARTH_BUNKER_IN_CONFLICT_ALLIANCE_ATTACKING = 1377, // unused
+ //Horde
+ //Iceblood Tower
+ AV_WS_ICEBLOOD_TOWER_OWNER = 1187,
+ AV_WS_ICEBLOOD_TOWER_DESTROYED = 1368,
+ AV_WS_ICEBLOOD_TOWER_HORDE_CONTROLLED = 1385,
+ AV_WS_ICEBLOOD_TOWER_IN_CONFLICT_ALLIANCE_ATTACKING = 1390,
+ AV_WS_ICEBLOOD_TOWER_IN_CONFLICT_HORDE_ATTACKING = 1395, // unused
+ //Tower Point
+ AV_WS_TOWER_POINT_OWNER = 1188,
+ AV_WS_TOWER_POINT_DESTROYED = 1367,
+ AV_WS_TOWER_POINT_HORDE_CONTROLLED = 1384,
+ AV_WS_TOWER_POINT_IN_CONFLICT_ALLIANCE_ATTACKING = 1389,
+ AV_WS_TOWER_POINT_IN_CONFLICT_HORDE_ATTACKING = 1394, // unused
+ //Frostwolf West
+ AV_WS_WEST_FROSTWOLF_TOWER_OWNER = 1185,
+ AV_WS_WEST_FROSTWOLF_TOWER_DESTROYED = 1365,
+ AV_WS_WEST_FROSTWOLF_TOWER_HORDE_CONTROLLED = 1382,
+ AV_WS_WEST_FROSTWOLF_TOWER_IN_CONFLICT_ALLIANCE_ATTACKING = 1387,
+ AV_WS_WEST_FROSTWOLF_TOWER_IN_CONFLICT_HORDE_ATTACKING = 1392, // unused
+ //Frostwolf East
+ AV_WS_EAST_FROSTWOLF_TOWER_OWNER = 1186,
+ AV_WS_EAST_FROSTWOLF_TOWER_DESTROYED = 1366,
+ AV_WS_EAST_FROSTWOLF_TOWER_HORDE_CONTROLLED = 1383,
+ AV_WS_EAST_FROSTWOLF_TOWER_IN_CONFLICT_ALLIANCE_ATTACKING = 1388,
+ AV_WS_EAST_FROSTWOLF_TOWER_IN_CONFLICT_HORDE_ATTACKING = 1393, // unused
+
+//Mines
+ AV_WS_IRONDEEP_MINE_OWNER = 801,
+ AV_WS_IRONDEEP_MINE_TROGG_CONTROLLED = 1360,
+ AV_WS_IRONDEEP_MINE_ALLIANCE_CONTROLLED = 1358,
+ AV_WS_IRONDEEP_MINE_HORDE_CONTROLLED = 1359,
+
+ AV_WS_COLDTOOTH_MINE_OWNER = 804,
+ AV_WS_COLDTOOTH_MINE_KOBOLD_CONTROLLED = 1357,
+ AV_WS_COLDTOOTH_MINE_ALLIANCE_CONTROLLED = 1355,
+ AV_WS_COLDTOOTH_MINE_HORDE_CONTROLLED = 1356,
+
+//Turnins
+ AV_WS_IVUS_STORM_CRYSTAL_COUNT = 1043,
+ AV_WS_IVUS_STORM_CRYSTAL_MAX = 1044,
+ AV_WS_LOKHOLAR_STORMPIKE_SOLDIERS_BLOOD_COUNT = 923,
+ AV_WS_LOKHOLAR_STORMPIKE_SOLDIERS_BLOOD_MAX = 922,
+
+//Bosses
+ AV_WS_DREKTHAR_ALIVE = 601,
+ AV_WS_VANDAAR_ALIVE = 602,
+
+//Captains
+ AV_WS_GALVAGAR_ALIVE = 1352,
+ AV_WS_BALINDA_ALIVE = 1351,
+};
+
+struct StaticMineInfo
+{
+ int32 WorldStateOwner;
+ int32 WorldStateAllianceControlled;
+ int32 WorldStateHordeControlled;
+ int32 WorldStateNeutralControlled;
+ uint8 TextIdAlliance;
+ uint8 TextIdHorde;
+};
+
+struct AlteracValleyMineInfo
+{
+ Team Owner;
+
+ StaticMineInfo StaticInfo;
+};
+
+struct StaticNodeInfo
+{
+ BG_AV_Nodes NodeId;
+
+ struct
+ {
+ uint8 AllianceCapture;
+ uint8 AllianceAttack;
+ uint8 HordeCapture;
+ uint8 HordeAttack;
+ } TextIds;
+
+ struct
+ {
+ int32 AllianceControl;
+ int32 AllianceAssault;
+ int32 HordeControl;
+ int32 HordeAssault;
+ int32 Owner;
+ } WorldStateIds;
+
+ struct
+ {
+ std::string AllianceOrDefend;
+ std::string HordeOrDestroy;
+ } StringIds;
+};
+
+static StaticNodeInfo const BGAVNodeInfo[] =
+{
+ { BG_AV_NODES_FIRSTAID_STATION, { 47, 48, 45, 46 }, { 1325, 1326, 1327, 1328, 0 }, { "bg_av_herald_stormpike_aid_station_alliance", "bg_av_herald_stormpike_aid_station_horde" } }, // Stormpike First Aid Station
+ { BG_AV_NODES_STORMPIKE_GRAVE, { 1, 2, 3, 4 }, { 1333, 1335, 1334, 1336, 0 }, { "bg_av_herald_stormpike_alliance", "bg_av_herald_stormpike_horde" } }, // Stormpike Graveyard
+ { BG_AV_NODES_STONEHEART_GRAVE, { 55, 56, 53, 54 }, { 1302, 1304, 1301, 1303, 0 }, { "bg_av_herald_stonehearth_alliance", "bg_av_herald_stonehearth_horde" } }, // Stoneheart Graveyard
+ { BG_AV_NODES_SNOWFALL_GRAVE, { 5, 6, 7, 8 }, { 1341, 1343, 1342, 1344, 0 }, { "bg_av_herald_snowfall_alliance", "bg_av_herald_snowfall_horde" } }, // Snowfall Graveyard
+ { BG_AV_NODES_ICEBLOOD_GRAVE, { 59, 60, 57, 58 }, { 1346, 1348, 1347, 1349, 0 }, { "bg_av_herald_iceblood_alliance", "bg_av_herald_iceblood_horde" } }, // Iceblood Graveyard
+ { BG_AV_NODES_FROSTWOLF_GRAVE, { 9, 10, 11, 12 }, { 1337, 1339, 1338, 1340, 0 }, { "bg_av_herald_frostwolf_alliance", "bg_av_herald_frostwolf_horde" } }, // Frostwolf Graveyard
+ { BG_AV_NODES_FROSTWOLF_HUT, { 51, 52, 49, 50 }, { 1329, 1331, 1330, 1332, 0 }, { "bg_av_herald_frostwolf_hut_alliance", "bg_av_herald_frostwolf_hut_horde" } }, // Frostwolf Hut
+ { BG_AV_NODES_DUNBALDAR_SOUTH, { 16, 15, 14, 13 }, { 1361, 1375, 1370, 1378, 1181 }, { "bg_av_herald_south_bunker_defend", "bg_av_herald_south_bunker_attack" } }, // Dunbaldar South Bunker
+ { BG_AV_NODES_DUNBALDAR_NORTH, { 20, 19, 18, 17 }, { 1362, 1374, 1371, 1379, 1182 }, { "bg_av_herald_north_bunker_defend", "bg_av_herald_south_bunker_attack" } }, // Dunbaldar North Bunker
+ { BG_AV_NODES_ICEWING_BUNKER, { 24, 23, 22, 21 }, { 1363, 1376, 1372, 1380, 1183 }, { "bg_av_herald_icewing_bunker_defend", "bg_av_herald_icewing_bunker_attack" } }, // Icewing Bunker
+ { BG_AV_NODES_STONEHEART_BUNKER, { 28, 27, 26, 25 }, { 1364, 1377, 1373, 1381, 1184 }, { "bg_av_herald_stonehearth_bunker_defend", "bg_av_herald_stonehearth_bunker_attack" } }, // Stoneheart Bunker
+ { BG_AV_NODES_ICEBLOOD_TOWER, { 44, 43, 42, 41 }, { 1368, 1390, 1385, 1395, 1188 }, { "bg_av_herald_iceblood_tower_defend", "bg_av_herald_iceblood_tower_attack" } }, // Iceblood Tower
+ { BG_AV_NODES_TOWER_POINT, { 40, 39, 38, 37 }, { 1367, 1389, 1384, 1394, 1187 }, { "bg_av_herald_tower_point_defend", "bg_av_herald_tower_point_attack" } }, // Tower Point
+ { BG_AV_NODES_FROSTWOLF_ETOWER, { 36, 35, 34, 33 }, { 1366, 1388, 1383, 1393, 1186 }, { "bg_av_herald_east_tower_defend", "bg_av_herald_east_tower_attack" } }, // Frostwolf East Tower
+ { BG_AV_NODES_FROSTWOLF_WTOWER, { 32, 31, 30, 29 }, { 1365, 1387, 1382, 1392, 1185 }, { "bg_av_herald_west_tower_defend", "bg_av_herald_west_tower_attack" } }, // Frostwolf West Tower
+};
+
+enum Texts
+{
+ // Herold
+ // Towers/Graveyards = 1 - 60
+ TEXT_COLDTOOTH_MINE_ALLIANCE_TAKEN = 61,
+ TEXT_IRONDEEP_MINE_ALLIANCE_TAKEN = 62,
+ TEXT_COLDTOOTH_MINE_HORDE_TAKEN = 63,
+ TEXT_IRONDEEP_MINE_HORDE_TAKEN = 64,
+ TEXT_FROSTWOLF_GENERAL_DEAD = 65, /// @todo: sound is missing
+ TEXT_STORMPIKE_GENERAL_DEAD = 66, /// @todo: sound is missing
+ TEXT_ALLIANCE_WINS = 67, // NYI /// @todo: sound is missing
+ TEXT_HORDE_WINS = 68, // NYI /// @todo: sound is missing
+
+ // Taskmaster Snivvle
+ TEXT_SNIVVLE_RANDOM = 0
+};
+
+enum BG_AV_ExploitTeleportLocations
+{
+ AV_EXPLOIT_TELEPORT_LOCATION_ALLIANCE = 3664,
+ AV_EXPLOIT_TELEPORT_LOCATION_HORDE = 3665
+};
+
+struct BG_AV_NodeInfo
+{
+ BG_AV_States State;
+ BG_AV_States PrevState;
+ uint16 TotalOwner;
+ Team Owner;
+ uint16 PrevOwner;
+ bool Tower;
+};
+
+inline BG_AV_Nodes& operator++(BG_AV_Nodes& i) { return i = BG_AV_Nodes(i + 1); }
+
+struct battleground_alterac_valley : BattlegroundScript
+{
+ enum QuestIds
+ {
+ AV_QUEST_A_SCRAPS1 = 7223,
+ AV_QUEST_A_SCRAPS2 = 6781,
+ AV_QUEST_H_SCRAPS1 = 7224,
+ AV_QUEST_H_SCRAPS2 = 6741,
+ AV_QUEST_A_COMMANDER1 = 6942, //soldier
+ AV_QUEST_H_COMMANDER1 = 6825,
+ AV_QUEST_A_COMMANDER2 = 6941, //leutnant
+ AV_QUEST_H_COMMANDER2 = 6826,
+ AV_QUEST_A_COMMANDER3 = 6943, //commander
+ AV_QUEST_H_COMMANDER3 = 6827,
+ AV_QUEST_A_BOSS1 = 7386, // 5 cristal/blood
+ AV_QUEST_H_BOSS1 = 7385,
+ AV_QUEST_A_BOSS2 = 6881, // 1
+ AV_QUEST_H_BOSS2 = 6801,
+ AV_QUEST_A_NEAR_MINE = 5892, //the mine near start location of team
+ AV_QUEST_H_NEAR_MINE = 5893,
+ AV_QUEST_A_OTHER_MINE = 6982, //the other mine ;)
+ AV_QUEST_H_OTHER_MINE = 6985,
+ AV_QUEST_A_RIDER_HIDE = 7026,
+ AV_QUEST_H_RIDER_HIDE = 7002,
+ AV_QUEST_A_RIDER_TAME = 7027,
+ AV_QUEST_H_RIDER_TAME = 7001
+ };
+
+ enum Data : uint32
+ {
+ DATA_DEFENDER_TIER_HORDE = 1,
+ DATA_DEFENDER_TIER_ALLIANCE = 2,
+ };
+
+ enum DefenderTier : uint32
+ {
+ BG_AV_DEFENDER_TIER_DEFENDER,
+ BG_AV_DEFENDER_TIER_SEASONED,
+ BG_AV_DEFENDER_TIER_VETERAN,
+ BG_AV_DEFENDER_TIER_CHAMPION
+ };
+
+ enum PvpStats
+ {
+ PVP_STAT_TOWERS_ASSAULTED = 61,
+ PVP_STAT_GRAVEYARDS_ASSAULTED = 63,
+ PVP_STAT_TOWERS_DEFENDED = 64,
+ PVP_STAT_GRAVEYARDS_DEFENDED = 65,
+ PVP_STAT_SECONDARY_OBJECTIVES = 82
+ };
+
+ enum Misc
+ {
+ NEAR_LOSE_POINTS = 140
+ };
+
+ enum HonorKillBonus
+ {
+ HONOR_KILL_BONUS_BOSS = 4,
+ HONOR_KILL_BONUS_CAPTAIN = 3,
+ HONOR_KILL_BONUS_SURVIVING_TOWER = 2,
+ HONOR_KILL_BONUS_SURVIVING_CAPTAIN = 2,
+ HONOR_KILL_BONUS_DESTROY_TOWER = 3
+ };
+
+ enum ReputationGains
+ {
+ REP_GAIN_BOSS = 350,
+ REP_GAIN_CAPTAIN = 125,
+ REP_GAIN_DESTROY_TOWER = 12,
+ REP_GAIN_SURVIVING_TOWER = 12,
+ REP_GAIN_SURVIVING_CAPTAIN = 125
+ };
+
+ enum ResourceLoss
+ {
+ RESOURCE_LOSS_TOWER = -75,
+ RESOURCE_LOSS_CAPTAIN = -100
+ };
+
+ enum Spells
+ {
+ SPELL_COMPLETE_ALTERAC_VALLEY_QUEST = 23658,
+ };
+
+ enum Factions
+ {
+ FACTION_FROSTWOLF_CLAN = 729,
+ FACTION_STORMPIKE_GUARD = 730,
+ };
+
+ explicit battleground_alterac_valley(BattlegroundMap* map) : BattlegroundScript(map)
+ {
+ _teamResources = { BG_AV_SCORE_INITIAL_POINTS, BG_AV_SCORE_INITIAL_POINTS };
+ _isInformedNearVictory = { false, false };
+
+ for (uint8 i = 0; i < 2; i++) //forloop for both teams (it just make 0 == alliance and 1 == horde also for both mines 0=north 1=south
+ {
+ for (uint8 j = 0; j < 9; j++)
+ _teamQuestStatus[i][j] = 0;
+
+ _captainBuffTimer[i].Reset(120000 + urand(0, 4) * 60); //as far as i could see, the buff is randomly so i make 2minutes (thats the duration of the buff itself) + 0-4minutes @todo get the right times
+ }
+
+ _mineInfo[uint8(AlteracValleyMine::North)] = { TEAM_OTHER, { AV_WS_IRONDEEP_MINE_OWNER, AV_WS_IRONDEEP_MINE_ALLIANCE_CONTROLLED, AV_WS_IRONDEEP_MINE_HORDE_CONTROLLED, AV_WS_IRONDEEP_MINE_TROGG_CONTROLLED, TEXT_IRONDEEP_MINE_ALLIANCE_TAKEN, TEXT_IRONDEEP_MINE_HORDE_TAKEN } };
+ _mineInfo[uint8(AlteracValleyMine::South)] = { TEAM_OTHER, { AV_WS_COLDTOOTH_MINE_OWNER, AV_WS_COLDTOOTH_MINE_ALLIANCE_CONTROLLED, AV_WS_COLDTOOTH_MINE_HORDE_CONTROLLED, AV_WS_COLDTOOTH_MINE_KOBOLD_CONTROLLED, TEXT_COLDTOOTH_MINE_ALLIANCE_TAKEN, TEXT_COLDTOOTH_MINE_HORDE_TAKEN } };
+
+ for (BG_AV_Nodes i = BG_AV_NODES_FIRSTAID_STATION; i <= BG_AV_NODES_STONEHEART_GRAVE; ++i) //alliance graves
+ InitNode(i, ALLIANCE, false);
+ for (BG_AV_Nodes i = BG_AV_NODES_DUNBALDAR_SOUTH; i <= BG_AV_NODES_STONEHEART_BUNKER; ++i) //alliance towers
+ InitNode(i, ALLIANCE, true);
+ for (BG_AV_Nodes i = BG_AV_NODES_ICEBLOOD_GRAVE; i <= BG_AV_NODES_FROSTWOLF_HUT; ++i) //horde graves
+ InitNode(i, HORDE, false);
+ for (BG_AV_Nodes i = BG_AV_NODES_ICEBLOOD_TOWER; i <= BG_AV_NODES_FROSTWOLF_WTOWER; ++i) //horde towers
+ InitNode(i, HORDE, true);
+ InitNode(BG_AV_NODES_SNOWFALL_GRAVE, TEAM_OTHER, false); //give snowfall neutral owner
+
+ _mineResourceTimer.Reset(BG_AV_MINE_RESOURCE_TIMER);
+ }
+
+ void OnUpdate(uint32 diff) override
+ {
+ if (battleground->GetStatus() != STATUS_IN_PROGRESS)
+ return;
+
+ _mineResourceTimer.Update(diff);
+ if (_mineResourceTimer.Passed())
+ {
+ for (AlteracValleyMineInfo const& info : _mineInfo)
+ {
+ if (info.Owner == TEAM_OTHER)
+ continue;
+
+ UpdateScore(info.Owner, 1);
+ }
+
+ _mineResourceTimer.Reset(BG_AV_MINE_RESOURCE_TIMER);
+ }
+
+ for (uint8 i = TEAM_ALLIANCE; i <= TEAM_HORDE; i++)
+ {
+ if (!IsCaptainAlive(TeamId(i)))
+ continue;
+
+ _captainBuffTimer[i].Update(diff);
+ if (_captainBuffTimer[i].Passed())
+ {
+ if (i == 0)
+ {
+ battleground->CastSpellOnTeam(AV_BUFF_A_CAPTAIN, ALLIANCE);
+ if (Creature const* creature = battlegroundMap->GetCreature(_balindaGUID))
+ creature->AI()->DoAction(ACTION_BUFF_YELL);
+ }
+ else
+ {
+ battleground->CastSpellOnTeam(AV_BUFF_H_CAPTAIN, HORDE);
+ if (Creature const* creature = battlegroundMap->GetCreature(_galvangarGUID))
+ creature->AI()->DoAction(ACTION_BUFF_YELL);
+ }
+
+ _captainBuffTimer[i].Reset(120000 + urand(0, 4) * 60000); //as far as i could see, the buff is randomly so i make 2minutes (thats the duration of the buff itself) + 0-4minutes @todo get the right times
+ }
+ }
+ }
+
+ void OnPlayerKilled(Player* victim, Player* /*killer*/) override
+ {
+ UpdateScore(battleground->GetPlayerTeam(victim->GetGUID()), -1);
+ }
+
+ void OnUnitKilled(Creature* victim, Unit* killer) override
+ {
+ switch (victim->GetEntry())
+ {
+ case BG_AV_CREATURE_VANNDAR:
+ {
+ UpdateWorldState(AV_WS_VANDAAR_ALIVE, 0);
+ battleground->CastSpellOnTeam(SPELL_COMPLETE_ALTERAC_VALLEY_QUEST, HORDE); //this is a spell which finishes a quest where a player has to kill the boss
+ battleground->RewardReputationToTeam(FACTION_FROSTWOLF_CLAN, REP_GAIN_BOSS, HORDE);
+ battleground->RewardHonorToTeam(battleground->GetBonusHonorFromKill(HONOR_KILL_BONUS_BOSS), HORDE);
+ battleground->EndBattleground(HORDE);
+ break;
+ }
+ case BG_AV_CREATURE_DREKTHAR:
+ {
+ UpdateWorldState(AV_WS_DREKTHAR_ALIVE, 0);
+ battleground->CastSpellOnTeam(SPELL_COMPLETE_ALTERAC_VALLEY_QUEST, ALLIANCE); //this is a spell which finishes a quest where a player has to kill the boss
+ battleground->RewardReputationToTeam(FACTION_STORMPIKE_GUARD, REP_GAIN_BOSS, ALLIANCE);
+ battleground->RewardHonorToTeam(battleground->GetBonusHonorFromKill(HONOR_KILL_BONUS_BOSS), ALLIANCE);
+ battleground->EndBattleground(ALLIANCE);
+ break;
+ }
+ case BG_AV_CREATURE_BALINDA:
+ {
+ UpdateWorldState(AV_WS_BALINDA_ALIVE, 0);
+ battleground->RewardReputationToTeam(FACTION_FROSTWOLF_CLAN, REP_GAIN_CAPTAIN, HORDE);
+ battleground->RewardHonorToTeam(battleground->GetBonusHonorFromKill(HONOR_KILL_BONUS_CAPTAIN), HORDE);
+ UpdateScore(ALLIANCE, RESOURCE_LOSS_CAPTAIN);
+ if (Creature const* herald = FindHerald("bg_av_herald_horde_win"))
+ herald->AI()->Talk(TEXT_STORMPIKE_GENERAL_DEAD);
+ break;
+ }
+ case BG_AV_CREATURE_GALVANGAR:
+ {
+ UpdateWorldState(AV_WS_GALVAGAR_ALIVE, 0);
+ battleground->RewardReputationToTeam(FACTION_STORMPIKE_GUARD, REP_GAIN_CAPTAIN, ALLIANCE);
+ battleground->RewardHonorToTeam(battleground->GetBonusHonorFromKill(HONOR_KILL_BONUS_CAPTAIN), ALLIANCE);
+ UpdateScore(HORDE, RESOURCE_LOSS_CAPTAIN);
+ if (Creature const* herald = FindHerald("bg_av_herald_alliance_win"))
+ herald->AI()->Talk(TEXT_FROSTWOLF_GENERAL_DEAD);
+ break;
+ }
+ case BG_AV_CREATURE_MORLOCH:
+ {
+ // if mine is not owned by morloch, then nothing happens
+ if (_mineInfo[uint8(AlteracValleyMine::North)].Owner != TEAM_OTHER)
+ break;
+
+ Team const killerTeam = battleground->GetPlayerTeam(Coalesce<Unit>(killer->GetCharmerOrOwnerPlayerOrPlayerItself(), killer)->GetGUID());
+ ChangeMineOwner(AlteracValleyMine::North, killerTeam);
+ break;
+ }
+ case BG_AV_CREATURE_TASKMASTER_SNIVVLE:
+ {
+ if (_mineInfo[uint8(AlteracValleyMine::South)].Owner != TEAM_OTHER)
+ break;
+
+ Team const killerTeam = battleground->GetPlayerTeam(Coalesce<Unit>(killer->GetCharmerOrOwnerPlayerOrPlayerItself(), killer)->GetGUID());
+ ChangeMineOwner(AlteracValleyMine::South, killerTeam);
+ break;
+ }
+ case BG_AV_CREATURE_UMI_THORSON:
+ case BG_AV_CREATURE_KEETAR:
+ {
+ Team const killerTeam = battleground->GetPlayerTeam(Coalesce<Unit>(killer->GetCharmerOrOwnerPlayerOrPlayerItself(), killer)->GetGUID());
+ ChangeMineOwner(AlteracValleyMine::North, killerTeam);
+ break;
+ }
+ case BG_AV_CREATURE_AGI_RUMBLESTOMP:
+ case BG_AV_CREATURE_MASHA_SWIFTCUT:
+ {
+ Team const killerTeam = battleground->GetPlayerTeam(Coalesce<Unit>(killer->GetCharmerOrOwnerPlayerOrPlayerItself(), killer)->GetGUID());
+ ChangeMineOwner(AlteracValleyMine::South, killerTeam);
+ break;
+ }
+ }
+ }
+
+ bool IsCaptainAlive(TeamId teamId) const
+ {
+ if (teamId == TEAM_HORDE)
+ return battlegroundMap->GetWorldStateValue(AV_WS_GALVAGAR_ALIVE) == 1;
+
+ if (teamId == TEAM_ALLIANCE)
+ return battlegroundMap->GetWorldStateValue(AV_WS_BALINDA_ALIVE) == 1;
+
+ return false;
+ }
+
+ void OnStart() override
+ {
+ UpdateWorldState(AV_WS_SHOW_HORDE_REINFORCEMENTS, 1);
+ UpdateWorldState(AV_WS_SHOW_ALLIANCE_REINFORCEMENTS, 1);
+
+ // Achievement: The Alterac Blitz
+ TriggerGameEvent(BG_AV_EVENT_START_BATTLE);
+
+ for (ObjectGuid const& guid : _doorGUIDs)
+ {
+ if (GameObject* gameObject = battlegroundMap->GetGameObject(guid))
+ {
+ gameObject->UseDoorOrButton();
+ Seconds delay = gameObject->GetEntry() == BG_AV_GHOST_GATE ? 0s : 3s;
+ gameObject->DespawnOrUnsummon(delay);
+ }
+ }
+ }
+
+ void OnEnd(Team winner) override
+ {
+ BattlegroundScript::OnEnd(winner);
+ //calculate bonuskills for both teams:
+ //first towers:
+ std::array<uint8, PVP_TEAMS_COUNT> kills = { 0, 0 };
+ std::array<uint8, PVP_TEAMS_COUNT> rep = { 0, 0 };
+
+ for (BG_AV_Nodes i = BG_AV_NODES_DUNBALDAR_SOUTH; i <= BG_AV_NODES_FROSTWOLF_WTOWER; ++i)
+ {
+ if (_nodes[i].State == POINT_CONTROLED)
+ {
+ if (_nodes[i].Owner == ALLIANCE)
+ {
+ rep[TEAM_ALLIANCE] += REP_GAIN_SURVIVING_TOWER;
+ kills[TEAM_ALLIANCE] += HONOR_KILL_BONUS_SURVIVING_TOWER;
+ }
+ else
+ {
+ rep[TEAM_HORDE] += REP_GAIN_SURVIVING_TOWER;
+ kills[TEAM_HORDE] += HONOR_KILL_BONUS_SURVIVING_TOWER;
+ }
+ }
+ }
+
+ for (uint8 i = TEAM_ALLIANCE; i <= TEAM_HORDE; ++i)
+ {
+ if (IsCaptainAlive(TeamId(i)))
+ {
+ kills[i] += HONOR_KILL_BONUS_SURVIVING_CAPTAIN;
+ rep[i] += REP_GAIN_SURVIVING_CAPTAIN;
+ }
+ if (rep[i] != 0)
+ battleground->RewardReputationToTeam(i == 0 ? FACTION_STORMPIKE_GUARD : FACTION_FROSTWOLF_CLAN, rep[i], i == 0 ? ALLIANCE : HORDE);
+ if (kills[i] != 0)
+ battleground->RewardHonorToTeam(battleground->GetBonusHonorFromKill(kills[i]), i == 0 ? ALLIANCE : HORDE);
+ }
+ }
+
+ void OnPlayerLeft(Player* player) override
+ {
+ BattlegroundScript::OnPlayerLeft(player);
+ if (!player)
+ return;
+
+ player->RemoveAurasDueToSpell(AV_BUFF_ARMOR);
+ }
+
+ void EventPlayerDestroyedPoint(GameObject* gameobject)
+ {
+ if (!gameobject)
+ return;
+
+ BG_AV_Nodes const node = GetNodeThroughObject(gameobject->GetEntry());
+ DestroyNode(node);
+ UpdateNodeWorldState(node);
+
+ Team const owner = _nodes[node].Owner;
+ if (IsTower(node))
+ {
+ UpdateScore((owner == ALLIANCE) ? HORDE : ALLIANCE, RESOURCE_LOSS_TOWER);
+ battleground->RewardReputationToTeam(owner == ALLIANCE ? FACTION_STORMPIKE_GUARD : FACTION_FROSTWOLF_CLAN, REP_GAIN_DESTROY_TOWER, owner);
+ battleground->RewardHonorToTeam(battleground->GetBonusHonorFromKill(HONOR_KILL_BONUS_DESTROY_TOWER), owner);
+ }
+
+ if (StaticNodeInfo const* nodeInfo = GetStaticNodeInfo(node))
+ if (Creature const* herald = FindHerald(nodeInfo->StringIds.HordeOrDestroy))
+ herald->AI()->Talk(owner == ALLIANCE ? nodeInfo->TextIds.AllianceCapture : nodeInfo->TextIds.HordeCapture);
+
+ battlegroundMap->UpdateSpawnGroupConditions();
+ }
+
+ void DoAction(uint32 actionId, WorldObject* source, WorldObject* target) override
+ {
+ Team const team = battleground->GetPlayerTeam(source->GetGUID());
+ TeamId const teamIndex = Battleground::GetTeamIndexByTeamId(team);
+
+ switch (actionId)
+ {
+ case ACTION_AV_CAPTURE_CAPTURABLE_OBJECT:
+ EventPlayerDestroyedPoint(source->ToGameObject());
+ break;
+ case ACTION_AV_INTERACT_CAPTURABLE_OBJECT:
+ if (target && source && source->IsPlayer())
+ HandleInteractCapturableObject(source->ToPlayer(), target->ToGameObject());
+ break;
+ case ACTION_TURN_IN_SCRAPS:
+ _teamQuestStatus[teamIndex][0] += 20;
+ break;
+ case ACTION_TURN_IN_COMMANDER_1:
+ _teamQuestStatus[teamIndex][1]++;
+ battleground->RewardReputationToTeam(teamIndex, 1, team);
+ if (_teamQuestStatus[teamIndex][1] == 30)
+ TC_LOG_DEBUG("bg.battleground", "BG_AV action {} completed (need to implement some events here", actionId);
+ break;
+ case ACTION_TURN_IN_COMMANDER_2:
+ _teamQuestStatus[teamIndex][2]++;
+ battleground->RewardReputationToTeam(teamIndex, 1, team);
+ if (_teamQuestStatus[teamIndex][2] == 60)
+ TC_LOG_DEBUG("bg.battleground", "BG_AV action {} completed (need to implement some events here", actionId);
+ break;
+ case ACTION_TURN_IN_COMMANDER_3:
+ _teamQuestStatus[teamIndex][3]++;
+ battleground->RewardReputationToTeam(teamIndex, 1, team);
+ if (_teamQuestStatus[teamIndex][3] == 120)
+ TC_LOG_DEBUG("bg.battleground", "BG_AV action {} completed (need to implement some events here", actionId);
+ break;
+ case ACTION_TURN_IN_BOSS_1:
+ _teamQuestStatus[teamIndex][4] += 4; //you can turn in 5 or 1 item..
+ [[fallthrough]];
+ case ACTION_TURN_IN_BOSS_2:
+ _teamQuestStatus[teamIndex][4]++;
+ if (_teamQuestStatus[teamIndex][4] >= 200)
+ TC_LOG_DEBUG("bg.battleground", "BG_AV action {} completed (need to implement some events here", actionId);
+ UpdateWorldState(teamIndex == TEAM_ALLIANCE ? AV_WS_IVUS_STORM_CRYSTAL_COUNT : AV_WS_LOKHOLAR_STORMPIKE_SOLDIERS_BLOOD_COUNT, _teamQuestStatus[teamIndex][4]);
+ break;
+ case ACTION_TURN_IN_NEAR_MINE:
+ _teamQuestStatus[teamIndex][5]++;
+ if (_teamQuestStatus[teamIndex][5] == 28)
+ {
+ TC_LOG_DEBUG("bg.battleground", "BG_AV action {} completed (need to implement some events here", actionId);
+ if (_teamQuestStatus[teamIndex][6] == 7)
+ TC_LOG_DEBUG("bg.battleground", "BG_AV action {} completed (need to implement some events here - ground assault ready", actionId);
+ }
+ break;
+ case ACTION_TURN_IN_OTHER_MINE:
+ _teamQuestStatus[teamIndex][6]++;
+ if (_teamQuestStatus[teamIndex][6] == 7)
+ {
+ TC_LOG_DEBUG("bg.battleground", "BG_AV action {} completed (need to implement some events here", actionId);
+ if (_teamQuestStatus[teamIndex][5] == 20)
+ TC_LOG_DEBUG("bg.battleground", "BG_AV action {} completed (need to implement some events here - ground assault ready", actionId);
+ }
+ break;
+ case ACTION_TURN_IN_RIDER_HIDE:
+ _teamQuestStatus[teamIndex][7]++;
+ if (_teamQuestStatus[teamIndex][7] == 25)
+ {
+ TC_LOG_DEBUG("bg.battleground", "BG_AV action {} completed (need to implement some events here", actionId);
+ if (_teamQuestStatus[teamIndex][8] == 25)
+ TC_LOG_DEBUG("bg.battleground", "BG_AV action {} completed (need to implement some events here - rider assault ready", actionId);
+ }
+ break;
+ case ACTION_TURN_IN_RIDER_TAME:
+ _teamQuestStatus[teamIndex][8]++;
+ if (_teamQuestStatus[teamIndex][8] == 25)
+ {
+ TC_LOG_DEBUG("bg.battleground", "BG_AV action {} completed (need to implement some events here", actionId);
+ if (_teamQuestStatus[teamIndex][7] == 25)
+ TC_LOG_DEBUG("bg.battleground", "BG_AV action {} completed (need to implement some events here - rider assault ready", actionId);
+ }
+ break;
+ default:
+ TC_LOG_ERROR("bg.battleground", "BattlegroundAV::DoAction: {}. Unhandled action.", actionId);
+ break;
+ }
+ }
+
+ void ChangeMineOwner(AlteracValleyMine mine, Team team, bool initial = false)
+ {
+ if (team != ALLIANCE && team != HORDE)
+ team = TEAM_OTHER;
+
+ AlteracValleyMineInfo& mineInfo = _mineInfo[uint8(mine)];
+
+ if (mineInfo.Owner == team && !initial)
+ return;
+
+ mineInfo.Owner = team;
+
+ SendMineWorldStates(mine);
+
+ uint8 const textId = team == ALLIANCE ? mineInfo.StaticInfo.TextIdAlliance : mineInfo.StaticInfo.TextIdHorde;
+
+ std::string const stringId = team == ALLIANCE ? "bg_av_herald_mine_alliance" : "bg_av_herald_mine_horde";
+
+ if (Creature const* herald = FindHerald(stringId))
+ herald->AI()->Talk(textId);
+ }
+
+ static BG_AV_Nodes GetNodeThroughObject(uint32 object)
+ {
+ switch (object)
+ {
+ case BG_AV_OBJECTID_AID_STATION_ALLIANCE_CONTROLLED:
+ case BG_AV_OBJECTID_AID_STATION_HORDE_CONTESTED:
+ case BG_AV_OBJECTID_AID_STATION_HORDE_CONTROLLED:
+ case BG_AV_OBJECTID_AID_STATION_ALLIANCE_CONTESTED:
+ return BG_AV_NODES_FIRSTAID_STATION;
+ case BG_AV_OBJECTID_STORMPIKE_ALLIANCE_CONTROLLED:
+ case BG_AV_OBJECTID_STORMPIKE_HORDE_CONTESTED:
+ case BG_AV_OBJECTID_STORMPIKE_HORDE_CONTROLLED:
+ case BG_AV_OBJECTID_STORMPIKE_ALLIANCE_CONTESTED:
+ return BG_AV_NODES_STORMPIKE_GRAVE;
+ case BG_AV_OBJECTID_STONEHEARTH_HORDE_CONTESTED:
+ case BG_AV_OBJECTID_STONEHEARTH_HORDE_CONTROLLED:
+ case BG_AV_OBJECTID_STONEHEARTH_ALLIANCE_CONTESTED:
+ case BG_AV_OBJECTID_STONEHEARTH_ALLIANCE_CONTROLLED:
+ return BG_AV_NODES_STONEHEART_GRAVE;
+ case BG_AV_OBJECTID_SNOWFALL_NEUTRAL:
+ case BG_AV_OBJECTID_SNOWFALL_HORDE_CONTESTED:
+ case BG_AV_OBJECTID_SNOWFALL_ALLIANCE_CONTESTED:
+ case BG_AV_OBJECTID_SNOWFALL_HORDE_CONTROLLED:
+ case BG_AV_OBJECTID_SNOWFALL_ALLIANCE_CONTROLLED:
+ return BG_AV_NODES_SNOWFALL_GRAVE;
+ case BG_AV_OBJECTID_ICEBLOOD_HORDE_CONTROLLED:
+ case BG_AV_OBJECTID_ICEBLOOD_ALLIANCE_CONTESTED:
+ case BG_AV_OBJECTID_ICEBLOOD_ALLIANCE_CONTROLLED:
+ case BG_AV_OBJECTID_ICEBLOOD_HORDE_CONTESTED:
+ return BG_AV_NODES_ICEBLOOD_GRAVE;
+ case BG_AV_OBJECTID_FROSTWOLF_HORDE_CONTROLLED:
+ case BG_AV_OBJECTID_FROSTWOLF_ALLIANCE_CONTESTED:
+ case BG_AV_OBJECTID_FROSTWOLF_ALLIANCE_CONTROLLED:
+ case BG_AV_OBJECTID_FROSTWOLF_HORDE_CONTESTED:
+ return BG_AV_NODES_FROSTWOLF_GRAVE;
+ case BG_AV_OBJECTID_FROSTWOLF_HUT_HORDE_CONTROLLED:
+ case BG_AV_OBJECTID_FROSTWOLF_HUT_ALLIANCE_CONTESTED:
+ case BG_AV_OBJECTID_FROSTWOLF_HUT_ALLIANCE_CONTROLLED:
+ case BG_AV_OBJECTID_FROSTWOLF_HUT_HORDE_CONTESTED:
+ return BG_AV_NODES_FROSTWOLF_HUT;
+ case BG_AV_OBJECTID_SOUTH_BUNKER_CONTROLLED_TOWER_BANNER:
+ case BG_AV_OBJECTID_SOUTH_BUNKER_CONTROLLED_BANNER:
+ case BG_AV_OBJECTID_SOUTH_BUNKER_CONTESTED_BANNER:
+ case BG_AV_OBJECTID_SOUTH_BUNKER_CONTESTED_TOWER_BANNER:
+ return BG_AV_NODES_DUNBALDAR_SOUTH;
+ case BG_AV_OBJECTID_NORTH_BUNKER_CONTROLLED_TOWER_BANNER:
+ case BG_AV_OBJECTID_NORTH_BUNKER_CONTROLLED_BANNER:
+ case BG_AV_OBJECTID_NORTH_BUNKER_CONTESTED_BANNER:
+ case BG_AV_OBJECTID_NORTH_BUNKER_CONTESTED_TOWER_BANNER:
+ return BG_AV_NODES_DUNBALDAR_NORTH;
+ case BG_AV_OBJECTID_EAST_TOWER_CONTROLLED_TOWER_BANNER:
+ case BG_AV_OBJECTID_EAST_TOWER_CONTROLLED_BANNER:
+ case BG_AV_OBJECTID_EAST_TOWER_CONTESTED_BANNER:
+ case BG_AV_OBJECTID_EAST_TOWER_CONTESTED_TOWER_BANNER:
+ return BG_AV_NODES_FROSTWOLF_ETOWER;
+ case BG_AV_OBJECTID_WEST_TOWER_CONTROLLED_TOWER_BANNER:
+ case BG_AV_OBJECTID_WEST_TOWER_CONTROLLED_BANNER:
+ case BG_AV_OBJECTID_WEST_TOWER_CONTESTED_BANNER:
+ case BG_AV_OBJECTID_WEST_TOWER_CONTESTED_TOWER_BANNER:
+ return BG_AV_NODES_FROSTWOLF_WTOWER;
+ case BG_AV_OBJECTID_TOWER_POINT_CONTROLLED_TOWER_BANNER:
+ case BG_AV_OBJECTID_TOWER_POINT_CONTROLLED_BANNER:
+ case BG_AV_OBJECTID_TOWER_POINT_CONTESTED_BANNER:
+ case BG_AV_OBJECTID_TOWER_POINT_CONTESTED_TOWER_BANNER:
+ return BG_AV_NODES_TOWER_POINT;
+ case BG_AV_OBJECTID_ICEBLOOD_TOWER_CONTROLLED_TOWER_BANNER:
+ case BG_AV_OBJECTID_ICEBLOOD_TOWER_CONTROLLED_BANNER:
+ case BG_AV_OBJECTID_ICEBLOOD_TOWER_CONTESTED_BANNER:
+ case BG_AV_OBJECTID_ICEBLOOD_TOWER_CONTESTED_TOWER_BANNER:
+ return BG_AV_NODES_ICEBLOOD_TOWER;
+ case BG_AV_OBJECTID_STONEHEARTH_BUNKER_CONTROLLED_TOWER_BANNER:
+ case BG_AV_OBJECTID_STONEHEARTH_BUNKER_CONTROLLED_BANNER:
+ case BG_AV_OBJECTID_STONEHEARTH_BUNKER_CONTESTED_BANNER:
+ case BG_AV_OBJECTID_STONEHEARTH_BUNKER_CONTESTED_TOWER_BANNER:
+ return BG_AV_NODES_STONEHEART_BUNKER;
+ case BG_AV_OBJECTID_ICEWING_BUNKER_CONTROLLED_TOWER_BANNER:
+ case BG_AV_OBJECTID_ICEWING_BUNKER_CONTROLLED_BANNER:
+ case BG_AV_OBJECTID_ICEWING_BUNKER_CONTESTED_BANNER:
+ case BG_AV_OBJECTID_ICEWING_BUNKER_CONTESTED_TOWER_BANNER:
+ return BG_AV_NODES_ICEWING_BUNKER;
+ default:
+ TC_LOG_ERROR("bg.battleground", "BattlegroundAV: ERROR! GetPlace got a wrong object :(");
+ ABORT();
+ return BG_AV_Nodes(0);
+ }
+ }
+
+ void HandleInteractCapturableObject(Player* player, GameObject* target)
+ {
+ if (!player || !target)
+ return;
+
+ switch (target->GetEntry())
+ {
+ // graveyards
+ case BG_AV_OBJECTID_AID_STATION_ALLIANCE_CONTROLLED:
+ case BG_AV_OBJECTID_AID_STATION_HORDE_CONTROLLED:
+ case BG_AV_OBJECTID_FROSTWOLF_ALLIANCE_CONTROLLED:
+ case BG_AV_OBJECTID_FROSTWOLF_HORDE_CONTROLLED:
+ case BG_AV_OBJECTID_FROSTWOLF_HUT_ALLIANCE_CONTROLLED:
+ case BG_AV_OBJECTID_FROSTWOLF_HUT_HORDE_CONTROLLED:
+ case BG_AV_OBJECTID_ICEBLOOD_ALLIANCE_CONTROLLED:
+ case BG_AV_OBJECTID_ICEBLOOD_HORDE_CONTROLLED:
+ case BG_AV_OBJECTID_STONEHEARTH_ALLIANCE_CONTROLLED:
+ case BG_AV_OBJECTID_STONEHEARTH_HORDE_CONTROLLED:
+ case BG_AV_OBJECTID_STORMPIKE_ALLIANCE_CONTROLLED:
+ case BG_AV_OBJECTID_STORMPIKE_HORDE_CONTROLLED:
+ // Snowfall
+ case BG_AV_OBJECTID_SNOWFALL_NEUTRAL:
+ case BG_AV_OBJECTID_SNOWFALL_ALLIANCE_CONTROLLED:
+ case BG_AV_OBJECTID_SNOWFALL_HORDE_CONTROLLED:
+ // towers
+ case BG_AV_OBJECTID_EAST_TOWER_CONTROLLED_BANNER:
+ case BG_AV_OBJECTID_WEST_TOWER_CONTROLLED_BANNER:
+ case BG_AV_OBJECTID_TOWER_POINT_CONTROLLED_BANNER:
+ case BG_AV_OBJECTID_ICEBLOOD_TOWER_CONTROLLED_BANNER:
+ case BG_AV_OBJECTID_STONEHEARTH_BUNKER_CONTROLLED_BANNER:
+ case BG_AV_OBJECTID_ICEWING_BUNKER_CONTROLLED_BANNER:
+ case BG_AV_OBJECTID_SOUTH_BUNKER_CONTROLLED_BANNER:
+ case BG_AV_OBJECTID_NORTH_BUNKER_CONTROLLED_BANNER:
+ EventPlayerAssaultsPoint(player, target->GetEntry());
+ break;
+ // graveyards
+ case BG_AV_OBJECTID_AID_STATION_ALLIANCE_CONTESTED:
+ case BG_AV_OBJECTID_AID_STATION_HORDE_CONTESTED:
+ case BG_AV_OBJECTID_FROSTWOLF_ALLIANCE_CONTESTED:
+ case BG_AV_OBJECTID_FROSTWOLF_HORDE_CONTESTED:
+ case BG_AV_OBJECTID_FROSTWOLF_HUT_ALLIANCE_CONTESTED:
+ case BG_AV_OBJECTID_FROSTWOLF_HUT_HORDE_CONTESTED:
+ case BG_AV_OBJECTID_ICEBLOOD_ALLIANCE_CONTESTED:
+ case BG_AV_OBJECTID_ICEBLOOD_HORDE_CONTESTED:
+ case BG_AV_OBJECTID_STONEHEARTH_ALLIANCE_CONTESTED:
+ case BG_AV_OBJECTID_STONEHEARTH_HORDE_CONTESTED:
+ case BG_AV_OBJECTID_STORMPIKE_ALLIANCE_CONTESTED:
+ case BG_AV_OBJECTID_STORMPIKE_HORDE_CONTESTED:
+ // towers
+ case BG_AV_OBJECTID_EAST_TOWER_CONTESTED_BANNER:
+ case BG_AV_OBJECTID_WEST_TOWER_CONTESTED_BANNER:
+ case BG_AV_OBJECTID_TOWER_POINT_CONTESTED_BANNER:
+ case BG_AV_OBJECTID_ICEBLOOD_TOWER_CONTESTED_BANNER:
+ case BG_AV_OBJECTID_STONEHEARTH_BUNKER_CONTESTED_BANNER:
+ case BG_AV_OBJECTID_ICEWING_BUNKER_CONTESTED_BANNER:
+ case BG_AV_OBJECTID_SOUTH_BUNKER_CONTESTED_BANNER:
+ case BG_AV_OBJECTID_NORTH_BUNKER_CONTESTED_BANNER:
+ EventPlayerDefendsPoint(player, target->GetEntry());
+ break;
+ // Snowfall special cases (either defend/assault)
+ case BG_AV_OBJECTID_SNOWFALL_ALLIANCE_CONTESTED:
+ case BG_AV_OBJECTID_SNOWFALL_HORDE_CONTESTED:
+ {
+ BG_AV_Nodes const node = GetNodeThroughObject(target->GetEntry());
+ if (_nodes[node].TotalOwner == TEAM_OTHER)
+ EventPlayerAssaultsPoint(player, target->GetEntry());
+ else
+ EventPlayerDefendsPoint(player, target->GetEntry());
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ void EventPlayerDefendsPoint(Player* player, uint32 object)
+ {
+ BG_AV_Nodes node = GetNodeThroughObject(object);
+
+ Team const owner = _nodes[node].Owner;
+ Team const team = battleground->GetPlayerTeam(player->GetGUID());
+
+ if (owner == team || _nodes[node].State != POINT_ASSAULTED)
+ return;
+
+ TC_LOG_DEBUG("bg.battleground", "player defends point object: {} node: {}", object, node);
+ if (_nodes[node].PrevOwner != team)
+ {
+ TC_LOG_ERROR("bg.battleground", "BG_AV: player defends point which doesn't belong to his team {}", node);
+ return;
+ }
+
+ DefendNode(node, team);
+ UpdateNodeWorldState(node);
+
+ if (StaticNodeInfo const* nodeInfo = GetStaticNodeInfo(node))
+ {
+ std::string stringId;
+
+ if (IsTower(node))
+ stringId = nodeInfo->StringIds.AllianceOrDefend;
+ else
+ stringId = team == ALLIANCE ? nodeInfo->StringIds.AllianceOrDefend : nodeInfo->StringIds.HordeOrDestroy;
+
+ if (Creature const* herald = FindHerald(stringId))
+ herald->AI()->Talk(team == ALLIANCE ? nodeInfo->TextIds.AllianceCapture : nodeInfo->TextIds.HordeCapture);
+ }
+
+ // update the statistic for the defending player
+ battleground->UpdatePvpStat(player, IsTower(node) ? PVP_STAT_TOWERS_DEFENDED : PVP_STAT_GRAVEYARDS_DEFENDED, 1);
+ battlegroundMap->UpdateSpawnGroupConditions();
+ }
+
+ void EventPlayerAssaultsPoint(Player* player, uint32 object)
+ {
+ BG_AV_Nodes node = GetNodeThroughObject(object);
+ Team const owner = _nodes[node].Owner; //maybe name it prevowner
+ Team const team = battleground->GetPlayerTeam(player->GetGUID());
+
+ TC_LOG_DEBUG("bg.battleground", "bg_av: player assaults point object {} node {}", object, node);
+ if (owner == team || team == _nodes[node].TotalOwner)
+ return; //surely a gm used this object
+
+ AssaultNode(node, team);
+ UpdateNodeWorldState(node);
+
+ if (StaticNodeInfo const* nodeInfo = GetStaticNodeInfo(node))
+ {
+ std::string stringId;
+ if (IsTower(node))
+ stringId = nodeInfo->StringIds.HordeOrDestroy;
+ else
+ stringId = team == ALLIANCE ? nodeInfo->StringIds.AllianceOrDefend : nodeInfo->StringIds.HordeOrDestroy;
+
+ if (Creature const* herald = FindHerald(stringId))
+ herald->AI()->Talk(team == ALLIANCE ? nodeInfo->TextIds.AllianceAttack : nodeInfo->TextIds.HordeAttack);
+ }
+
+ // update the statistic for the assaulting player
+ battleground->UpdatePvpStat(player, (IsTower(node)) ? PVP_STAT_TOWERS_ASSAULTED : PVP_STAT_GRAVEYARDS_ASSAULTED, 1);
+ battlegroundMap->UpdateSpawnGroupConditions();
+ }
+
+ void UpdateNodeWorldState(BG_AV_Nodes node) const
+ {
+ if (StaticNodeInfo const* nodeInfo = GetStaticNodeInfo(node))
+ {
+ uint16 const owner = _nodes[node].Owner;
+ BG_AV_States const state = _nodes[node].State;
+
+ UpdateWorldState(nodeInfo->WorldStateIds.AllianceAssault, owner == ALLIANCE && state == POINT_ASSAULTED);
+ UpdateWorldState(nodeInfo->WorldStateIds.AllianceControl, owner == ALLIANCE && state >= POINT_DESTROYED);
+ UpdateWorldState(nodeInfo->WorldStateIds.HordeAssault, owner == HORDE && state == POINT_ASSAULTED);
+ UpdateWorldState(nodeInfo->WorldStateIds.HordeControl, owner == HORDE && state >= POINT_DESTROYED);
+ if (nodeInfo->WorldStateIds.Owner)
+ UpdateWorldState(nodeInfo->WorldStateIds.Owner, owner == HORDE ? 2 : owner == ALLIANCE ? 1 : 0);
+ }
+
+ if (node == BG_AV_NODES_SNOWFALL_GRAVE)
+ UpdateWorldState(AV_WS_SNOWFALL_GRAVEYARD_UNCONTROLLED, _nodes[node].Owner == TEAM_OTHER);
+ }
+
+ void SendMineWorldStates(AlteracValleyMine mine) const
+ {
+ AlteracValleyMineInfo const& mineInfo = _mineInfo[uint8(mine)];
+ UpdateWorldState(mineInfo.StaticInfo.WorldStateHordeControlled, mineInfo.Owner == HORDE);
+ UpdateWorldState(mineInfo.StaticInfo.WorldStateAllianceControlled, mineInfo.Owner == ALLIANCE);
+ UpdateWorldState(mineInfo.StaticInfo.WorldStateNeutralControlled, mineInfo.Owner == TEAM_OTHER);
+ UpdateWorldState(mineInfo.StaticInfo.WorldStateOwner, mineInfo.Owner == HORDE ? 2 : mineInfo.Owner == ALLIANCE ? 1 : 0);
+ }
+
+ void AssaultNode(BG_AV_Nodes node, Team team)
+ {
+ _nodes[node].PrevOwner = _nodes[node].Owner;
+ _nodes[node].Owner = team;
+ _nodes[node].PrevState = _nodes[node].State;
+ _nodes[node].State = POINT_ASSAULTED;
+ }
+
+ void DestroyNode(BG_AV_Nodes node)
+ {
+ _nodes[node].TotalOwner = _nodes[node].Owner;
+ _nodes[node].PrevOwner = _nodes[node].Owner;
+ _nodes[node].PrevState = _nodes[node].State;
+ _nodes[node].State = (_nodes[node].Tower) ? POINT_DESTROYED : POINT_CONTROLED;
+ }
+
+ void InitNode(BG_AV_Nodes node, Team team, bool tower)
+ {
+ _nodes[node].TotalOwner = team;
+ _nodes[node].Owner = team;
+ _nodes[node].PrevOwner = 0;
+ _nodes[node].State = POINT_CONTROLED;
+ _nodes[node].PrevState = _nodes[node].State;
+ _nodes[node].State = POINT_CONTROLED;
+ _nodes[node].Tower = tower;
+ }
+
+ void DefendNode(BG_AV_Nodes node, Team team)
+ {
+ _nodes[node].PrevOwner = _nodes[node].Owner;
+ _nodes[node].Owner = team;
+ _nodes[node].PrevState = _nodes[node].State;
+ _nodes[node].State = POINT_CONTROLED;
+ }
+
+ Team GetPrematureWinner() override
+ {
+ uint32 const allianceScore = _teamResources[Battleground::GetTeamIndexByTeamId(ALLIANCE)];
+ uint32 const hordeScore = _teamResources[Battleground::GetTeamIndexByTeamId(HORDE)];
+
+ if (allianceScore > hordeScore)
+ return ALLIANCE;
+ if (hordeScore > allianceScore)
+ return HORDE;
+
+ return BattlegroundScript::GetPrematureWinner();
+ }
+
+ void OnGameObjectCreate(GameObject* gameObject) override
+ {
+ switch (gameObject->GetEntry())
+ {
+ case BG_AV_GHOST_GATE:
+ case BG_AV_OBJECTID_GATE:
+ _doorGUIDs.insert(gameObject->GetGUID());
+ break;
+ default:
+ break;
+ }
+ }
+
+ void OnCreatureCreate(Creature* creature) override
+ {
+ switch (creature->GetEntry())
+ {
+ case BG_AV_CREATURE_GALVANGAR:
+ _galvangarGUID = creature->GetGUID();
+ break;
+ case BG_AV_CREATURE_BALINDA:
+ _balindaGUID = creature->GetGUID();
+ break;
+ case BG_AV_CREATURE_HERALD:
+ _heraldGUIDs.insert(creature->GetGUID());
+ break;
+ default:
+ break;
+ }
+ }
+
+ uint32 GetData(uint32 dataId) const override
+ {
+ auto getDefenderTierForTeam = [&](TeamId teamId) -> DefenderTier
+ {
+ if (_teamQuestStatus[teamId][0] < 500)
+ return BG_AV_DEFENDER_TIER_DEFENDER;
+
+ if (_teamQuestStatus[teamId][0] < 1000)
+ return BG_AV_DEFENDER_TIER_SEASONED;
+
+ if (_teamQuestStatus[teamId][0] < 1500)
+ return BG_AV_DEFENDER_TIER_VETERAN;
+
+ return BG_AV_DEFENDER_TIER_CHAMPION;
+ };
+
+ switch (dataId)
+ {
+ case DATA_DEFENDER_TIER_ALLIANCE:
+ return getDefenderTierForTeam(TEAM_ALLIANCE);
+ case DATA_DEFENDER_TIER_HORDE:
+ return getDefenderTierForTeam(TEAM_HORDE);
+ default:
+ return BattlegroundScript::GetData(dataId);
+ }
+ }
+
+ Creature* FindHerald(std::string_view stringId) const
+ {
+ for (ObjectGuid const& guid : _heraldGUIDs)
+ if (Creature* creature = battlegroundMap->GetCreature(guid))
+ if (creature->HasStringId(stringId))
+ return creature;
+
+ return nullptr;
+ }
+
+ static StaticNodeInfo const* GetStaticNodeInfo(BG_AV_Nodes node)
+ {
+ for (const auto& nodeInfo : BGAVNodeInfo)
+ if (nodeInfo.NodeId == node)
+ return &nodeInfo;
+
+ return nullptr;
+ }
+
+ bool IsTower(BG_AV_Nodes node) const { return _nodes[node].Tower; }
+
+ void UpdateScore(Team team, int16 points)
+ {
+ ASSERT(team == ALLIANCE || team == HORDE);
+ TeamId const teamindex = Battleground::GetTeamIndexByTeamId(team);
+ _teamResources[teamindex] += points;
+
+ UpdateWorldState(teamindex == TEAM_HORDE ? AV_WS_HORDE_REINFORCEMENTS : AV_WS_ALLIANCE_REINFORCEMENTS, _teamResources[teamindex]);
+ if (points < 0)
+ {
+ if (_teamResources[teamindex] < 1)
+ {
+ _teamResources[teamindex] = 0;
+ battleground->EndBattleground(teamindex == TEAM_HORDE ? ALLIANCE : HORDE);
+ }
+ else if (!_isInformedNearVictory[teamindex] && _teamResources[teamindex] < NEAR_LOSE_POINTS)
+ {
+ if (teamindex == TEAM_ALLIANCE)
+ battleground->SendBroadcastText(BG_AV_TEXT_ALLIANCE_NEAR_LOSE, CHAT_MSG_BG_SYSTEM_ALLIANCE);
+ else
+ battleground->SendBroadcastText(BG_AV_TEXT_HORDE_NEAR_LOSE, CHAT_MSG_BG_SYSTEM_HORDE);
+ battleground->PlaySoundToAll(AV_SOUND_NEAR_VICTORY);
+ _isInformedNearVictory[teamindex] = true;
+ }
+ }
+ }
+
+private:
+ /*variables */
+ std::array<int32, PVP_TEAMS_COUNT> _teamResources;
+ uint32 _teamQuestStatus[PVP_TEAMS_COUNT][9]; //[x][y] x=team y=questcounter
+
+ std::array<BG_AV_NodeInfo, BG_AV_NODES_MAX> _nodes;
+
+ TimeTracker _mineResourceTimer; //ticks for both teams
+
+ std::array<AlteracValleyMineInfo, 2> _mineInfo;
+
+ std::array<TimeTracker, PVP_TEAMS_COUNT> _captainBuffTimer;
+
+ std::array<bool, PVP_TEAMS_COUNT> _isInformedNearVictory;
+ GuidUnorderedSet _doorGUIDs;
+ ObjectGuid _balindaGUID;
+ ObjectGuid _galvangarGUID;
+ GuidUnorderedSet _heraldGUIDs;
+};
+
+void AddSC_battleground_alterac_valley()
+{
+ RegisterBattlegroundMapScript(battleground_alterac_valley, 30);
+}
diff --git a/src/server/scripts/EasternKingdoms/AlteracValley/boss_balinda.cpp b/src/server/scripts/Battlegrounds/AlteracValley/boss_balinda.cpp
index 38987c82428..38987c82428 100644
--- a/src/server/scripts/EasternKingdoms/AlteracValley/boss_balinda.cpp
+++ b/src/server/scripts/Battlegrounds/AlteracValley/boss_balinda.cpp
diff --git a/src/server/scripts/EasternKingdoms/AlteracValley/boss_drekthar.cpp b/src/server/scripts/Battlegrounds/AlteracValley/boss_drekthar.cpp
index f7ec0bb3da9..f7ec0bb3da9 100644
--- a/src/server/scripts/EasternKingdoms/AlteracValley/boss_drekthar.cpp
+++ b/src/server/scripts/Battlegrounds/AlteracValley/boss_drekthar.cpp
diff --git a/src/server/scripts/EasternKingdoms/AlteracValley/boss_galvangar.cpp b/src/server/scripts/Battlegrounds/AlteracValley/boss_galvangar.cpp
index 741387ec033..741387ec033 100644
--- a/src/server/scripts/EasternKingdoms/AlteracValley/boss_galvangar.cpp
+++ b/src/server/scripts/Battlegrounds/AlteracValley/boss_galvangar.cpp
diff --git a/src/server/scripts/EasternKingdoms/AlteracValley/boss_vanndar.cpp b/src/server/scripts/Battlegrounds/AlteracValley/boss_vanndar.cpp
index 83c1fcc813e..83c1fcc813e 100644
--- a/src/server/scripts/EasternKingdoms/AlteracValley/boss_vanndar.cpp
+++ b/src/server/scripts/Battlegrounds/AlteracValley/boss_vanndar.cpp
diff --git a/src/server/scripts/EasternKingdoms/ArathiBasin/arathi_basin.cpp b/src/server/scripts/Battlegrounds/ArathiBasin/arathi_basin.cpp
index 4a30195833f..4a30195833f 100644
--- a/src/server/scripts/EasternKingdoms/ArathiBasin/arathi_basin.cpp
+++ b/src/server/scripts/Battlegrounds/ArathiBasin/arathi_basin.cpp
diff --git a/src/server/scripts/Battlegrounds/ArathiBasin/battleground_arathi_basin.cpp b/src/server/scripts/Battlegrounds/ArathiBasin/battleground_arathi_basin.cpp
new file mode 100644
index 00000000000..f30216bf067
--- /dev/null
+++ b/src/server/scripts/Battlegrounds/ArathiBasin/battleground_arathi_basin.cpp
@@ -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);
+}
diff --git a/src/server/scripts/Battlegrounds/BattleForGilneas/battleground_battle_for_gilneas.cpp b/src/server/scripts/Battlegrounds/BattleForGilneas/battleground_battle_for_gilneas.cpp
new file mode 100644
index 00000000000..ff049d2dd11
--- /dev/null
+++ b/src/server/scripts/Battlegrounds/BattleForGilneas/battleground_battle_for_gilneas.cpp
@@ -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);
+}
diff --git a/src/server/scripts/Battlegrounds/BladesEdge/arena_blades_edge.cpp b/src/server/scripts/Battlegrounds/BladesEdge/arena_blades_edge.cpp
new file mode 100644
index 00000000000..f0ac3bfc212
--- /dev/null
+++ b/src/server/scripts/Battlegrounds/BladesEdge/arena_blades_edge.cpp
@@ -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);
+}
diff --git a/src/server/scripts/Battlegrounds/DalaranSewers/arena_dalaran_sewers.cpp b/src/server/scripts/Battlegrounds/DalaranSewers/arena_dalaran_sewers.cpp
new file mode 100644
index 00000000000..bbdf5d4ab3b
--- /dev/null
+++ b/src/server/scripts/Battlegrounds/DalaranSewers/arena_dalaran_sewers.cpp
@@ -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();
+}
diff --git a/src/server/scripts/Battlegrounds/EyeOfTheStorm/battleground_eye_of_the_storm.cpp b/src/server/scripts/Battlegrounds/EyeOfTheStorm/battleground_eye_of_the_storm.cpp
new file mode 100644
index 00000000000..3c8ef48438e
--- /dev/null
+++ b/src/server/scripts/Battlegrounds/EyeOfTheStorm/battleground_eye_of_the_storm.cpp
@@ -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);
+}
diff --git a/src/server/scripts/Battlegrounds/IsleOfConquest/battleground_isle_of_conquest.cpp b/src/server/scripts/Battlegrounds/IsleOfConquest/battleground_isle_of_conquest.cpp
new file mode 100644
index 00000000000..5d55df8d6b7
--- /dev/null
+++ b/src/server/scripts/Battlegrounds/IsleOfConquest/battleground_isle_of_conquest.cpp
@@ -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);
+}
diff --git a/src/server/scripts/Northrend/IsleOfConquest/boss_ioc_horde_alliance.cpp b/src/server/scripts/Battlegrounds/IsleOfConquest/boss_ioc_horde_alliance.cpp
index 77f5e53207e..05a13de842b 100644
--- a/src/server/scripts/Northrend/IsleOfConquest/boss_ioc_horde_alliance.cpp
+++ b/src/server/scripts/Battlegrounds/IsleOfConquest/boss_ioc_horde_alliance.cpp
@@ -16,7 +16,7 @@
*/
#include "ScriptMgr.h"
-#include "BattlegroundIC.h"
+#include "isle_of_conquest.h"
#include "ScriptedCreature.h"
enum BossSpells
diff --git a/src/server/scripts/Northrend/IsleOfConquest/isle_of_conquest.cpp b/src/server/scripts/Battlegrounds/IsleOfConquest/isle_of_conquest.cpp
index 1492335ce15..2c9fdce6596 100644
--- a/src/server/scripts/Northrend/IsleOfConquest/isle_of_conquest.cpp
+++ b/src/server/scripts/Battlegrounds/IsleOfConquest/isle_of_conquest.cpp
@@ -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"
diff --git a/src/server/scripts/Battlegrounds/IsleOfConquest/isle_of_conquest.h b/src/server/scripts/Battlegrounds/IsleOfConquest/isle_of_conquest.h
new file mode 100644
index 00000000000..ab4c92abae6
--- /dev/null
+++ b/src/server/scripts/Battlegrounds/IsleOfConquest/isle_of_conquest.h
@@ -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
diff --git a/src/server/scripts/Battlegrounds/NagrandArena/arena_nagrand_arena.cpp b/src/server/scripts/Battlegrounds/NagrandArena/arena_nagrand_arena.cpp
new file mode 100644
index 00000000000..e3f83c6acb2
--- /dev/null
+++ b/src/server/scripts/Battlegrounds/NagrandArena/arena_nagrand_arena.cpp
@@ -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);
+}
diff --git a/src/server/scripts/Battlegrounds/RingOfValor/arena_ring_of_valor.cpp b/src/server/scripts/Battlegrounds/RingOfValor/arena_ring_of_valor.cpp
new file mode 100644
index 00000000000..3c2dbdc473a
--- /dev/null
+++ b/src/server/scripts/Battlegrounds/RingOfValor/arena_ring_of_valor.cpp
@@ -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);
+}
diff --git a/src/server/scripts/Battlegrounds/RuinsOfLordaeron/arena_ruins_of_lordaeron.cpp b/src/server/scripts/Battlegrounds/RuinsOfLordaeron/arena_ruins_of_lordaeron.cpp
new file mode 100644
index 00000000000..75f9c6caef1
--- /dev/null
+++ b/src/server/scripts/Battlegrounds/RuinsOfLordaeron/arena_ruins_of_lordaeron.cpp
@@ -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);
+}
diff --git a/src/server/scripts/Battlegrounds/StrandOfTheAncients/battleground_strand_of_the_ancients.cpp b/src/server/scripts/Battlegrounds/StrandOfTheAncients/battleground_strand_of_the_ancients.cpp
new file mode 100644
index 00000000000..dba78903864
--- /dev/null
+++ b/src/server/scripts/Battlegrounds/StrandOfTheAncients/battleground_strand_of_the_ancients.cpp
@@ -0,0 +1,1059 @@
+/*
+ * 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 "BattlegroundScore.h"
+#include "Creature.h"
+#include "CreatureAI.h"
+#include "GameObject.h"
+#include "GameTime.h"
+#include "Map.h"
+#include "ObjectAccessor.h"
+#include "ObjectMgr.h"
+#include "Player.h"
+#include "ScriptMgr.h"
+#include "strand_of_the_ancients.h"
+#include "VehicleDefines.h"
+#include "WorldStateMgr.h"
+
+enum BG_SA_Status
+{
+ BG_SA_NOT_STARTED = 0,
+ BG_SA_WARMUP,
+ BG_SA_ROUND_ONE,
+ BG_SA_SECOND_WARMUP,
+ BG_SA_ROUND_TWO,
+ BG_SA_BONUS_ROUND
+};
+
+enum BG_SA_GateState
+{
+ // alliance is defender
+ BG_SA_ALLIANCE_GATE_OK = 1,
+ BG_SA_ALLIANCE_GATE_DAMAGED = 2,
+ BG_SA_ALLIANCE_GATE_DESTROYED = 3,
+ // horde is defender
+ BG_SA_HORDE_GATE_OK = 4,
+ BG_SA_HORDE_GATE_DAMAGED = 5,
+ BG_SA_HORDE_GATE_DESTROYED = 6,
+};
+
+enum StrandOfTheAncientsGameObjects
+{
+ GO_SEAFORIUM_BOMB_H = 194086, // Used by horde players
+ GO_SEAFORIUM_BOMB_A = 190753, // Used by alliance players
+ GO_SEAFORIUM_CHARGE_H = 257572,
+ GO_SEAFORIUM_CHARGE_A = 257565,
+
+ GO_GRAVEYARD_WEST_H = 191307,
+ GO_GRAVEYARD_WEST_A = 191308,
+
+ GO_GRAVEYARD_EAST_H = 191305,
+ GO_GRAVEYARD_EAST_A = 191306,
+
+ GO_GRAVEYARD_CENTRAL_H = 191309,
+ GO_GRAVEYARD_CENTRAL_A = 191310,
+
+ GO_COLLISION_DOOR = 194162,
+ GO_TITAN_RELIC_A = 194083,
+ GO_TITAN_RELIC_H = 194082,
+
+ GO_GATE_OF_THE_GREEN_EMERALD = 190722,
+ GO_GATE_OF_THE_PURPLE_AMETHYST = 190723,
+ GO_GATE_OF_THE_BLUE_SAPPHIRE = 190724,
+ GO_GATE_OF_THE_RED_SUN = 190726,
+ GO_GATE_OF_THE_YELLOW_MOON = 190727,
+ GO_CHAMBER_OF_ANCIENT_RELICS = 192549
+};
+
+enum BG_SA_Timers
+{
+ BG_SA_BOAT_START = 60 * IN_MILLISECONDS,
+ BG_SA_WARMUPLENGTH = 120 * IN_MILLISECONDS,
+ BG_SA_ROUNDLENGTH = 600 * IN_MILLISECONDS
+};
+
+enum SASounds
+{
+ SOUND_GRAVEYARD_TAKEN_HORDE = 8174,
+ SOUND_GRAVEYARD_TAKEN_ALLIANCE = 8212,
+ SOUND_DEFEAT_HORDE = 15905,
+ SOUND_VICTORY_HORDE = 15906,
+ SOUND_VICTORY_ALLIANCE = 15907,
+ SOUND_DEFEAT_ALLIANCE = 15908,
+ SOUND_WALL_DESTROYED_ALLIANCE = 15909,
+ SOUND_WALL_DESTROYED_HORDE = 15910,
+ SOUND_WALL_ATTACKED_HORDE = 15911,
+ SOUND_WALL_ATTACKED_ALLIANCE = 15912
+};
+
+enum SATexts
+{
+ // Kanrethad
+ TEXT_ROUND_STARTED = 1,
+ TEXT_ROUND_1_FINISHED = 2,
+
+ // Rigger Sparklight / Gorgril Rigspark
+ TEXT_SPARKLIGHT_RIGSPARK_SPAWN = 1,
+
+ // World Trigger
+ TEXT_BLUE_GATE_UNDER_ATTACK = 1,
+ TEXT_GREEN_GATE_UNDER_ATTACK = 2,
+ TEXT_RED_GATE_UNDER_ATTACK = 3,
+ TEXT_PURPLE_GATE_UNDER_ATTACK = 4,
+ TEXT_YELLOW_GATE_UNDER_ATTACK = 5,
+ TEXT_YELLOW_GATE_DESTROYED = 6,
+ TEXT_PURPLE_GATE_DESTROYED = 7,
+ TEXT_RED_GATE_DESTROYED = 8,
+ TEXT_GREEN_GATE_DESTROYED = 9,
+ TEXT_BLUE_GATE_DESTROYED = 10,
+ TEXT_EAST_GRAVEYARD_CAPTURED_A = 11,
+ TEXT_WEST_GRAVEYARD_CAPTURED_A = 12,
+ TEXT_SOUTH_GRAVEYARD_CAPTURED_A = 13,
+ TEXT_EAST_GRAVEYARD_CAPTURED_H = 14,
+ TEXT_WEST_GRAVEYARD_CAPTURED_H = 15,
+ TEXT_SOUTH_GRAVEYARD_CAPTURED_H = 16,
+ TEXT_ANCIENT_GATE_UNDER_ATTACK = 17,
+ TEXT_ANCIENT_GATE_DESTROYED = 18
+};
+
+enum SAWorldStates
+{
+ BG_SA_TIMER = 3557,
+ BG_SA_ALLY_ATTACKS = 4352,
+ BG_SA_HORDE_ATTACKS = 4353,
+ BG_SA_PURPLE_GATEWS = 3614,
+ BG_SA_RED_GATEWS = 3617,
+ BG_SA_BLUE_GATEWS = 3620,
+ BG_SA_GREEN_GATEWS = 3623,
+ BG_SA_YELLOW_GATEWS = 3638,
+ BG_SA_ANCIENT_GATEWS = 3849,
+
+ BG_SA_LEFT_GY_ALLIANCE = 3635,
+ BG_SA_RIGHT_GY_ALLIANCE = 3636,
+ BG_SA_CENTER_GY_ALLIANCE = 3637,
+
+ BG_SA_RIGHT_ATT_TOKEN_ALL = 3627,
+ BG_SA_LEFT_ATT_TOKEN_ALL = 3626,
+ BG_SA_LEFT_ATT_TOKEN_HRD = 3629,
+ BG_SA_RIGHT_ATT_TOKEN_HRD = 3628,
+ BG_SA_HORDE_DEFENCE_TOKEN = 3631,
+ BG_SA_ALLIANCE_DEFENCE_TOKEN = 3630,
+
+ BG_SA_RIGHT_GY_HORDE = 3632,
+ BG_SA_LEFT_GY_HORDE = 3633,
+ BG_SA_CENTER_GY_HORDE = 3634,
+
+ BG_SA_BONUS_TIMER = 3571,
+
+ BG_SA_ENABLE_TIMER = 3564,
+ BG_SA_ATTACKER_TEAM = 3690,
+ BG_SA_DESTROYED_ALLIANCE_VEHICLES = 3955,
+ BG_SA_DESTROYED_HORDE_VEHICLES = 3956,
+};
+
+enum BG_SA_Boat
+{
+ BG_SA_BOAT_ONE_A = 208000,
+ BG_SA_BOAT_TWO_H = 208001,
+ BG_SA_BOAT_ONE_H = 193184,
+ BG_SA_BOAT_TWO_A = 193185
+};
+
+static constexpr uint32 BG_SA_Factions[2] =
+{
+ 1732,
+ 1735,
+};
+
+enum class StrandOfTheAncientsGraveyard
+{
+ West,
+ East,
+ Central
+};
+
+enum BG_SA_BroadcastTexts
+{
+ BG_SA_TEXT_ALLIANCE_CAPTURED_TITAN_PORTAL = 28944,
+ BG_SA_TEXT_HORDE_CAPTURED_TITAN_PORTAL = 28945,
+
+ BG_SA_TEXT_ROUND_TWO_START_ONE_MINUTE = 29448,
+ BG_SA_TEXT_ROUND_TWO_START_HALF_MINUTE = 29449
+};
+
+enum class DefenseLine
+{
+ First,
+ Second,
+ Third,
+ Last
+};
+
+struct GateInfo
+{
+ uint32 GameObjectId;
+ uint32 WorldState;
+ uint8 DamagedText;
+ uint8 DestroyedText;
+ DefenseLine LineOfDefense;
+};
+
+GateInfo const Gates[] =
+{
+ { GO_GATE_OF_THE_GREEN_EMERALD, BG_SA_GREEN_GATEWS, TEXT_GREEN_GATE_UNDER_ATTACK, TEXT_GREEN_GATE_DESTROYED, DefenseLine::First },
+ { GO_GATE_OF_THE_YELLOW_MOON, BG_SA_YELLOW_GATEWS, TEXT_YELLOW_GATE_UNDER_ATTACK, TEXT_YELLOW_GATE_DESTROYED, DefenseLine::Third },
+ { GO_GATE_OF_THE_BLUE_SAPPHIRE, BG_SA_BLUE_GATEWS, TEXT_BLUE_GATE_UNDER_ATTACK, TEXT_BLUE_GATE_DESTROYED, DefenseLine::First },
+ { GO_GATE_OF_THE_RED_SUN, BG_SA_RED_GATEWS, TEXT_RED_GATE_UNDER_ATTACK, TEXT_RED_GATE_DESTROYED, DefenseLine::Second },
+ { GO_GATE_OF_THE_PURPLE_AMETHYST, BG_SA_PURPLE_GATEWS, TEXT_PURPLE_GATE_UNDER_ATTACK, TEXT_PURPLE_GATE_DESTROYED, DefenseLine::Second },
+ { GO_CHAMBER_OF_ANCIENT_RELICS, BG_SA_ANCIENT_GATEWS, TEXT_ANCIENT_GATE_UNDER_ATTACK, TEXT_ANCIENT_GATE_DESTROYED, DefenseLine::Last }
+};
+
+struct BG_SA_RoundScore
+{
+ TeamId winner;
+ uint32 time;
+};
+
+enum StrandOfTheAncientsPvpStats
+{
+ PVP_STAT_GATES_DESTROYED = 231,
+ PVP_STAT_DEMOLISHERS_DESTROYED = 232
+};
+
+enum StrandOfTheAncientsEvents
+{
+ EVENT_HORDE_ASSAULT_STARTED = 21702,
+ EVENT_ALLIANCE_ASSAULT_STARTED = 23748,
+ EVENT_TITAN_RELIC_ACTIVATED = 20572
+};
+
+enum StrandOfTheAncientsCreatures
+{
+ NPC_KANRETHAD = 29,
+ NPC_DEMOLISHER = 28781,
+ NPC_ANTIPERSONNEL_CANNON = 27894,
+ NPC_RIGGER_SPARKLIGHT = 29260,
+ NPC_GORGRIL_RIGSPARK = 29262,
+ NPC_WORLD_TRIGGER = 22515,
+ NPC_DEMOLISHER_SA = 28781
+};
+
+enum StrandOfTheAncientsSpawnPositions
+{
+ SPAWN_DEFENDERS = 1399
+};
+
+enum StrandOfTheAncientsData
+{
+ DATA_ATTACKERS = 1,
+ DATA_STATUS = 2
+};
+
+enum StrandOfTheAncientSpells
+{
+ SPELL_TELEPORT_DEFENDER = 52364,
+ SPELL_TELEPORT_ATTACKERS = 60178,
+ SPELL_END_OF_ROUND = 52459,
+ SPELL_REMOVE_SEAFORIUM = 59077,
+ SPELL_ALLIANCE_CONTROL_PHASE_SHIFT = 60027,
+ SPELL_HORDE_CONTROL_PHASE_SHIFT = 60028,
+ SPELL_CARRYING_SEAFORIUM_CHARGE = 52415
+};
+
+static constexpr Position spawnPositionOnTransport[] =
+{
+ { 0.0f, 5.0f, 9.6f, 3.14f },
+ { -6.0f, -3.0f, 8.6f, 0.0f }
+};
+
+struct battleground_strand_of_the_ancients : BattlegroundScript
+{
+ explicit battleground_strand_of_the_ancients(BattlegroundMap* map) : BattlegroundScript(map)
+ {
+ _timerEnabled = false;
+ _updateWaitTimer = 0;
+ _signaledRoundTwo = false;
+ _signaledRoundTwoHalfMin = false;
+ _initSecondRound = false;
+ _attackers = static_cast<TeamId>(urand(TEAM_ALLIANCE, TEAM_HORDE));
+ _totalTime = 0;
+ _endRoundTimer = 0;
+ _shipsStarted = false;
+ _status = BG_SA_NOT_STARTED;
+
+ _roundScores = { };
+
+ for (BG_SA_RoundScore& roundScore : _roundScores)
+ {
+ roundScore.winner = TEAM_ALLIANCE;
+ roundScore.time = 0;
+ }
+
+ _boatGUIDs = { };
+ _staticBombGUIDs = { };
+ }
+
+ void OnInit() override
+ {
+ BattlegroundScript::OnInit();
+ _status = BG_SA_WARMUP;
+ ResetObjs();
+ }
+
+ void OnUpdate(uint32 diff) override
+ {
+ BattlegroundScript::OnUpdate(diff);
+ if (_initSecondRound)
+ {
+ if (_updateWaitTimer < diff)
+ {
+ if (!_signaledRoundTwo)
+ {
+ _signaledRoundTwo = true;
+ _initSecondRound = false;
+ battleground->SendBroadcastText(BG_SA_TEXT_ROUND_TWO_START_ONE_MINUTE, CHAT_MSG_BG_SYSTEM_NEUTRAL);
+ }
+ }
+ else
+ {
+ _updateWaitTimer -= diff;
+ return;
+ }
+ }
+ _totalTime += diff;
+
+ if (_status == BG_SA_WARMUP)
+ {
+ _endRoundTimer = BG_SA_ROUNDLENGTH;
+ UpdateWorldState(BG_SA_TIMER, GameTime::GetGameTime() + (_endRoundTimer / 1000));
+ if (_totalTime >= BG_SA_WARMUPLENGTH)
+ {
+ if (Creature* c = FindKanrethad())
+ battleground->SendChatMessage(c, TEXT_ROUND_STARTED);
+
+ _totalTime = 0;
+ ToggleTimer();
+ _status = BG_SA_ROUND_ONE;
+ TriggerGameEvent((_attackers == TEAM_ALLIANCE) ? EVENT_ALLIANCE_ASSAULT_STARTED : EVENT_HORDE_ASSAULT_STARTED);
+ }
+ if (_totalTime >= BG_SA_BOAT_START)
+ StartShips();
+ return;
+ }
+ else if (_status == BG_SA_SECOND_WARMUP)
+ {
+ if (_roundScores[0].time < BG_SA_ROUNDLENGTH)
+ _endRoundTimer = _roundScores[0].time;
+ else
+ _endRoundTimer = BG_SA_ROUNDLENGTH;
+
+ UpdateWorldState(BG_SA_TIMER, GameTime::GetGameTime() + (_endRoundTimer / 1000));
+ if (_totalTime >= 60000)
+ {
+ if (Creature* c = FindKanrethad())
+ battleground->SendChatMessage(c, TEXT_ROUND_STARTED);
+
+ _totalTime = 0;
+ ToggleTimer();
+ _status = BG_SA_ROUND_TWO;
+ TriggerGameEvent((_attackers == TEAM_ALLIANCE) ? EVENT_ALLIANCE_ASSAULT_STARTED : EVENT_HORDE_ASSAULT_STARTED);
+ // status was set to STATUS_WAIT_JOIN manually for Preparation, set it back now
+ battleground->SetStatus(STATUS_IN_PROGRESS);
+ for (const auto& [playerGuid, bp] : battleground->GetPlayers())
+ if (Player* p = ObjectAccessor::FindPlayer(playerGuid))
+ p->RemoveAurasDueToSpell(SPELL_PREPARATION);
+ }
+ if (_totalTime >= 30000)
+ {
+ if (!_signaledRoundTwoHalfMin)
+ {
+ _signaledRoundTwoHalfMin = true;
+ battleground->SendBroadcastText(BG_SA_TEXT_ROUND_TWO_START_HALF_MINUTE, CHAT_MSG_BG_SYSTEM_NEUTRAL);
+ }
+ }
+ StartShips();
+ return;
+ }
+ else if (battleground->GetStatus() == STATUS_IN_PROGRESS)
+ {
+ if (_status == BG_SA_ROUND_ONE)
+ {
+ if (_totalTime >= BG_SA_ROUNDLENGTH)
+ {
+ EndRound();
+ return;
+ }
+ }
+ else if (_status == BG_SA_ROUND_TWO)
+ {
+ if (_totalTime >= _endRoundTimer)
+ {
+ battleground->CastSpellOnTeam(SPELL_END_OF_ROUND, ALLIANCE);
+ battleground->CastSpellOnTeam(SPELL_END_OF_ROUND, HORDE);
+ _roundScores[1].time = BG_SA_ROUNDLENGTH;
+ _roundScores[1].winner = (_attackers == TEAM_ALLIANCE) ? TEAM_HORDE : TEAM_ALLIANCE;
+ if (_roundScores[0].time == _roundScores[1].time)
+ battleground->EndBattleground(TEAM_OTHER);
+ else if (_roundScores[0].time < _roundScores[1].time)
+ battleground->EndBattleground(_roundScores[0].winner == TEAM_ALLIANCE ? ALLIANCE : HORDE);
+ else
+ battleground->EndBattleground(_roundScores[1].winner == TEAM_ALLIANCE ? ALLIANCE : HORDE);
+ return;
+ }
+ }
+ }
+ }
+
+ void Reset()
+ {
+ _totalTime = 0;
+ _shipsStarted = false;
+ _status = BG_SA_WARMUP;
+ }
+
+ void ResetObjs()
+ {
+ for (ObjectGuid const& bombGuid : _dynamicBombGUIDs)
+ if (GameObject* bomb = battlegroundMap->GetGameObject(bombGuid))
+ bomb->Delete();
+
+ _dynamicBombGUIDs.clear();
+
+ TeamId const defenders = _attackers == TEAM_ALLIANCE ? TEAM_HORDE : TEAM_ALLIANCE;
+
+ _totalTime = 0;
+ _shipsStarted = false;
+
+ UpdateWorldState(BG_SA_ALLY_ATTACKS, _attackers == TEAM_ALLIANCE);
+ UpdateWorldState(BG_SA_HORDE_ATTACKS, _attackers == TEAM_HORDE);
+
+ UpdateWorldState(BG_SA_RIGHT_ATT_TOKEN_ALL, _attackers == TEAM_ALLIANCE);
+ UpdateWorldState(BG_SA_LEFT_ATT_TOKEN_ALL, _attackers == TEAM_ALLIANCE);
+
+ UpdateWorldState(BG_SA_RIGHT_ATT_TOKEN_HRD, _attackers == TEAM_HORDE);
+ UpdateWorldState(BG_SA_LEFT_ATT_TOKEN_HRD, _attackers == TEAM_HORDE);
+
+ UpdateWorldState(BG_SA_HORDE_DEFENCE_TOKEN, defenders == TEAM_HORDE);
+ UpdateWorldState(BG_SA_ALLIANCE_DEFENCE_TOKEN, defenders == TEAM_ALLIANCE);
+
+ CaptureGraveyard(StrandOfTheAncientsGraveyard::Central, defenders);
+ CaptureGraveyard(StrandOfTheAncientsGraveyard::West, defenders);
+ CaptureGraveyard(StrandOfTheAncientsGraveyard::East, defenders);
+
+ UpdateWorldState(BG_SA_ATTACKER_TEAM, _attackers);
+
+ for (ObjectGuid const& guid : _gateGUIDs)
+ if (GameObject* gate = battlegroundMap->GetGameObject(guid))
+ gate->SetDestructibleState(GO_DESTRUCTIBLE_INTACT, nullptr, true);
+
+ BG_SA_GateState const state = _attackers == TEAM_ALLIANCE ? BG_SA_HORDE_GATE_OK : BG_SA_ALLIANCE_GATE_OK;
+ UpdateWorldState(BG_SA_PURPLE_GATEWS, state);
+ UpdateWorldState(BG_SA_RED_GATEWS, state);
+ UpdateWorldState(BG_SA_BLUE_GATEWS, state);
+ UpdateWorldState(BG_SA_GREEN_GATEWS, state);
+ UpdateWorldState(BG_SA_YELLOW_GATEWS, state);
+ UpdateWorldState(BG_SA_ANCIENT_GATEWS, state);
+
+ battlegroundMap->UpdateSpawnGroupConditions();
+
+ if (GameObject* door = battlegroundMap->GetGameObject(_collisionDoorGUID))
+ door->ResetDoorOrButton();
+
+ battleground->SetStatus(STATUS_WAIT_JOIN);
+ battlegroundMap->DoOnPlayers([&](Player* player)
+ {
+ SendTransportInit(player);
+ });
+
+ TeleportPlayers();
+ }
+
+ void StartShips()
+ {
+ if (_shipsStarted)
+ return;
+
+ for (ObjectGuid const& guid : _boatGUIDs[_attackers])
+ {
+ if (GameObject* boat = battlegroundMap->GetGameObject(guid))
+ {
+ boat->SetGoState(GO_STATE_TRANSPORT_STOPPED);
+
+ // make sure every player knows the transport exists & is moving
+ for (auto const& [playerGuid, _] : battleground->GetPlayers())
+ if (Player* player = ObjectAccessor::FindPlayer(playerGuid))
+ boat->SendUpdateToPlayer(player);
+ }
+ }
+
+ _shipsStarted = true;
+ }
+
+ void OnPlayerJoined(Player* player, bool inBattleground) override
+ {
+ BattlegroundScript::OnPlayerJoined(player, inBattleground);
+ SendTransportInit(player);
+ if (!inBattleground)
+ TeleportToEntrancePosition(player);
+ }
+
+ void TeleportPlayers() const
+ {
+ for (auto const& [playerGuid, bp] : battleground->GetPlayers())
+ {
+ if (Player* player = ObjectAccessor::FindPlayer(playerGuid))
+ {
+ // should remove spirit of redemption
+ if (player->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION))
+ player->RemoveAurasByType(SPELL_AURA_MOD_SHAPESHIFT);
+
+ if (!player->IsAlive())
+ {
+ player->ResurrectPlayer(1.0f);
+ player->SpawnCorpseBones();
+ }
+
+ player->ResetAllPowers();
+ player->CombatStopWithPets(true);
+
+ player->CastSpell(player, SPELL_PREPARATION, true);
+
+ TeleportToEntrancePosition(player);
+ }
+ }
+ }
+
+ // This function teleports player to entrance position, but it's not implemented correctly
+ // It is also used on round swap; which should be handled by the following spells: 52365, 52528, 53464, 53465 (Split Teleport (FACTION) (Boat X))
+ // This spell however cannot work with current system because of grid limitations.
+ // On battleground start, this function should work fine, except that it is called to late and we need a NearTeleport to solve this.
+ void TeleportToEntrancePosition(Player* player) const
+ {
+ if (Battleground::GetTeamIndexByTeamId(battleground->GetPlayerTeam(player->GetGUID())) == _attackers)
+ {
+ ObjectGuid const boatGUID = _boatGUIDs[_attackers][urand(0, 1)];
+
+ if (GameObject* boat = battlegroundMap->GetGameObject(boatGUID))
+ {
+ if (TransportBase* transport = boat->ToTransportBase())
+ {
+ player->Relocate(spawnPositionOnTransport[_attackers]);
+ transport->AddPassenger(player);
+ player->m_movementInfo.transport.pos.Relocate(spawnPositionOnTransport[_attackers]);
+ float x, y, z, o;
+ spawnPositionOnTransport[_attackers].GetPosition(x, y, z, o);
+ transport->CalculatePassengerPosition(x, y, z, &o);
+ player->Relocate(x, y, z, o);
+
+ if (player->IsInWorld())
+ player->NearTeleportTo({ x, y, z, o });
+ }
+ }
+ }
+ else if (WorldSafeLocsEntry const* defenderSpawn = sObjectMgr->GetWorldSafeLoc(SPAWN_DEFENDERS))
+ {
+ if (player->IsInWorld())
+ player->TeleportTo(defenderSpawn->Loc);
+ else
+ player->WorldRelocate(defenderSpawn->Loc);
+ }
+ }
+
+ void ProcessEvent(WorldObject* obj, uint32 eventId, WorldObject* invoker) override
+ {
+ BattlegroundScript::ProcessEvent(obj, eventId, invoker);
+
+ switch (eventId)
+ {
+ case EVENT_ALLIANCE_ASSAULT_STARTED:
+ for (ObjectGuid const& bombGuid : _staticBombGUIDs[TEAM_ALLIANCE])
+ if (GameObject* bomb = battlegroundMap->GetGameObject(bombGuid))
+ bomb->RemoveFlag(GO_FLAG_NOT_SELECTABLE);
+ break;
+ case EVENT_HORDE_ASSAULT_STARTED:
+ for (ObjectGuid const& bombGuid : _staticBombGUIDs[TEAM_HORDE])
+ if (GameObject* bomb = battlegroundMap->GetGameObject(bombGuid))
+ bomb->RemoveFlag(GO_FLAG_NOT_SELECTABLE);
+ break;
+ default:
+ break;
+ }
+
+ if (GameObject* go = Object::ToGameObject(obj))
+ {
+ switch (go->GetGoType())
+ {
+ case GAMEOBJECT_TYPE_GOOBER:
+ if (invoker)
+ if (eventId == EVENT_TITAN_RELIC_ACTIVATED)
+ TitanRelicActivated(invoker->ToPlayer());
+ break;
+ case GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING:
+ {
+ if (GateInfo const* gate = GetGate(obj->GetEntry()))
+ {
+ uint32 gateId = gate->GameObjectId;
+
+ // damaged
+ if (eventId == go->GetGOInfo()->destructibleBuilding.DamagedEvent)
+ {
+ BG_SA_GateState gateState = _attackers == TEAM_HORDE ? BG_SA_ALLIANCE_GATE_DAMAGED : BG_SA_HORDE_GATE_DAMAGED;
+
+ if (Creature* c = obj->FindNearestCreature(NPC_WORLD_TRIGGER, 500.0f))
+ battleground->SendChatMessage(c, gate->DamagedText, invoker);
+
+ battleground->PlaySoundToAll(_attackers == TEAM_ALLIANCE ? SOUND_WALL_ATTACKED_ALLIANCE : SOUND_WALL_ATTACKED_HORDE);
+
+ UpdateWorldState(gate->WorldState, gateState);
+ }
+ // destroyed
+ else if (eventId == go->GetGOInfo()->destructibleBuilding.DestroyedEvent)
+ {
+ BG_SA_GateState gateState = _attackers == TEAM_HORDE ? BG_SA_ALLIANCE_GATE_DESTROYED : BG_SA_HORDE_GATE_DESTROYED;
+ if (Creature* c = obj->FindNearestCreature(NPC_WORLD_TRIGGER, 500.0f))
+ battleground->SendChatMessage(c, gate->DestroyedText, invoker);
+
+ battleground->PlaySoundToAll(_attackers == TEAM_ALLIANCE ? SOUND_WALL_DESTROYED_ALLIANCE : SOUND_WALL_DESTROYED_HORDE);
+
+ // check if other gate from same line of defense is already destroyed for honor reward
+ bool rewardHonor = true;
+ switch (gateId)
+ {
+ case GO_GATE_OF_THE_GREEN_EMERALD:
+ if (IsGateDestroyed(GetGate(GO_GATE_OF_THE_BLUE_SAPPHIRE)))
+ rewardHonor = false;
+ break;
+ case GO_GATE_OF_THE_BLUE_SAPPHIRE:
+ if (IsGateDestroyed(GetGate(GO_GATE_OF_THE_GREEN_EMERALD)))
+ rewardHonor = false;
+ break;
+ case GO_GATE_OF_THE_RED_SUN:
+ if (IsGateDestroyed(GetGate(GO_GATE_OF_THE_PURPLE_AMETHYST)))
+ rewardHonor = false;
+ break;
+ case GO_GATE_OF_THE_PURPLE_AMETHYST:
+ if (IsGateDestroyed(GetGate(GO_GATE_OF_THE_RED_SUN)))
+ rewardHonor = false;
+ break;
+ default:
+ break;
+ }
+
+ if (invoker)
+ {
+ if (Unit* unit = invoker->ToUnit())
+ {
+ if (Player* player = unit->GetCharmerOrOwnerPlayerOrPlayerItself())
+ {
+ battleground->UpdatePvpStat(player, PVP_STAT_GATES_DESTROYED, 1);
+ if (rewardHonor)
+ battleground->UpdatePlayerScore(player, SCORE_BONUS_HONOR, battleground->GetBonusHonorFromKill(1));
+ }
+ }
+ }
+
+ if (rewardHonor)
+ MakeObjectsInteractable(gate->LineOfDefense);
+
+ UpdateWorldState(gate->WorldState, gateState);
+ battlegroundMap->UpdateSpawnGroupConditions();
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ }
+
+ void OnUnitKilled(Creature* victim, Unit* killer) override
+ {
+ if (victim->GetEntry() == NPC_DEMOLISHER_SA)
+ {
+ if (Player* killerPlayer = killer->GetCharmerOrOwnerPlayerOrPlayerItself())
+ battleground->UpdatePvpStat(killerPlayer, PVP_STAT_DEMOLISHERS_DESTROYED, 1);
+ int32 worldStateId = _attackers == TEAM_HORDE ? BG_SA_DESTROYED_HORDE_VEHICLES : BG_SA_DESTROYED_ALLIANCE_VEHICLES;
+ int32 currentDestroyedVehicles = sWorldStateMgr->GetValue(worldStateId, battlegroundMap);
+ UpdateWorldState(worldStateId, currentDestroyedVehicles + 1);
+ }
+ }
+
+ void CaptureGraveyard(StrandOfTheAncientsGraveyard graveyard, TeamId teamId)
+ {
+ switch (graveyard)
+ {
+ case StrandOfTheAncientsGraveyard::West:
+ UpdateWorldState(BG_SA_LEFT_GY_ALLIANCE, teamId == TEAM_ALLIANCE);
+ UpdateWorldState(BG_SA_LEFT_GY_HORDE, teamId == TEAM_HORDE);
+ break;
+ case StrandOfTheAncientsGraveyard::East:
+ UpdateWorldState(BG_SA_RIGHT_GY_ALLIANCE, teamId == TEAM_ALLIANCE);
+ UpdateWorldState(BG_SA_RIGHT_GY_HORDE, teamId == TEAM_HORDE);
+ break;
+ case StrandOfTheAncientsGraveyard::Central:
+ UpdateWorldState(BG_SA_CENTER_GY_ALLIANCE, teamId == TEAM_ALLIANCE);
+ UpdateWorldState(BG_SA_CENTER_GY_HORDE, teamId == TEAM_HORDE);
+
+ CaptureGraveyard(StrandOfTheAncientsGraveyard::East, teamId);
+ CaptureGraveyard(StrandOfTheAncientsGraveyard::West, teamId);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void TitanRelicActivated(Player const* clicker)
+ {
+ if (!clicker)
+ return;
+
+ TeamId const clickerTeamId = Battleground::GetTeamIndexByTeamId(battleground->GetPlayerTeam(clicker->GetGUID()));
+ if (clickerTeamId == _attackers)
+ {
+ if (clickerTeamId == TEAM_ALLIANCE)
+ battleground->SendBroadcastText(BG_SA_TEXT_ALLIANCE_CAPTURED_TITAN_PORTAL, CHAT_MSG_BG_SYSTEM_ALLIANCE);
+ else
+ battleground->SendBroadcastText(BG_SA_TEXT_HORDE_CAPTURED_TITAN_PORTAL, CHAT_MSG_BG_SYSTEM_HORDE);
+
+ if (_status == BG_SA_ROUND_ONE)
+ {
+ EndRound();
+ // Achievement Storm the Beach (1310)
+ for (auto itr = battleground->GetPlayers().begin(); itr != battleground->GetPlayers().end(); ++itr)
+ {
+ if (Player* player = ObjectAccessor::FindPlayer(itr->first))
+ if (Battleground::GetTeamIndexByTeamId(battleground->GetPlayerTeam(player->GetGUID())) == _attackers)
+ player->UpdateCriteria(CriteriaType::BeSpellTarget, 65246);
+ }
+
+ if (Creature* c = FindKanrethad())
+ battleground->SendChatMessage(c, TEXT_ROUND_1_FINISHED);
+ }
+ else if (_status == BG_SA_ROUND_TWO)
+ {
+ _roundScores[1].winner = _attackers;
+ _roundScores[1].time = _totalTime;
+ ToggleTimer();
+ // Achievement Storm the Beach (1310)
+ for (auto itr = battleground->GetPlayers().begin(); itr != battleground->GetPlayers().end(); ++itr)
+ {
+ if (Player* player = ObjectAccessor::FindPlayer(itr->first))
+ if (Battleground::GetTeamIndexByTeamId(battleground->GetPlayerTeam(player->GetGUID())) == _attackers && _roundScores[1].winner == _attackers)
+ player->UpdateCriteria(CriteriaType::BeSpellTarget, 65246);
+ }
+
+ if (_roundScores[0].time == _roundScores[1].time)
+ battleground->EndBattleground(TEAM_OTHER);
+ else if (_roundScores[0].time < _roundScores[1].time)
+ battleground->EndBattleground(_roundScores[0].winner == TEAM_ALLIANCE ? ALLIANCE : HORDE);
+ else
+ battleground->EndBattleground(_roundScores[1].winner == TEAM_ALLIANCE ? ALLIANCE : HORDE);
+ }
+ }
+ }
+
+ void ToggleTimer()
+ {
+ _timerEnabled = !_timerEnabled;
+ UpdateWorldState(BG_SA_ENABLE_TIMER, _timerEnabled);
+ }
+
+ void OnEnd(Team winner) override
+ {
+ BattlegroundScript::OnEnd(winner);
+
+ // honor reward for winning
+ if (winner == ALLIANCE)
+ battleground->RewardHonorToTeam(battleground->GetBonusHonorFromKill(1), ALLIANCE);
+ else if (winner == HORDE)
+ battleground->RewardHonorToTeam(battleground->GetBonusHonorFromKill(1), HORDE);
+
+ // complete map_end rewards (even if no team wins)
+ battleground->RewardHonorToTeam(battleground->GetBonusHonorFromKill(2), ALLIANCE);
+ battleground->RewardHonorToTeam(battleground->GetBonusHonorFromKill(2), HORDE);
+ }
+
+ void SendTransportInit(Player* player) const
+ {
+ for (ObjectGuid const& boatGuid : _boatGUIDs[_attackers])
+ if (GameObject* boat = battlegroundMap->GetGameObject(boatGuid))
+ boat->SendUpdateToPlayer(player);
+ }
+
+ bool IsGateDestroyed(GateInfo const* gateInfo) const
+ {
+ if (!gateInfo)
+ return false;
+
+ int32 value = battlegroundMap->GetWorldStateValue(gateInfo->WorldState);
+ return value == BG_SA_ALLIANCE_GATE_DESTROYED || value == BG_SA_HORDE_GATE_DESTROYED;
+ }
+
+ void HandleCaptureGraveyardAction(GameObject const* graveyardBanner, Player const* player)
+ {
+ if (!graveyardBanner || !player)
+ return;
+
+ TeamId const teamId = Battleground::GetTeamIndexByTeamId(battleground->GetPlayerTeam(player->GetGUID()));
+ // Only attackers can capture graveyard by gameobject action
+ if (teamId != _attackers)
+ return;
+
+ switch (graveyardBanner->GetEntry())
+ {
+ case GO_GRAVEYARD_WEST_A:
+ case GO_GRAVEYARD_WEST_H:
+ CaptureGraveyard(StrandOfTheAncientsGraveyard::West, teamId);
+ break;
+ case GO_GRAVEYARD_EAST_A:
+ case GO_GRAVEYARD_EAST_H:
+ CaptureGraveyard(StrandOfTheAncientsGraveyard::East, teamId);
+ break;
+ case GO_GRAVEYARD_CENTRAL_A:
+ case GO_GRAVEYARD_CENTRAL_H:
+ CaptureGraveyard(StrandOfTheAncientsGraveyard::Central, teamId);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void MakeObjectsInteractable(DefenseLine defenseLine) const
+ {
+ auto makeInteractable = [&](ObjectGuid const& guid) -> void
+ {
+ if (GameObject* gameObject = battlegroundMap->GetGameObject(guid))
+ gameObject->RemoveFlag(GO_FLAG_NOT_SELECTABLE);
+ };
+
+ switch (defenseLine)
+ {
+ case DefenseLine::First:
+ makeInteractable(_graveyardWest);
+ makeInteractable(_graveyardEast);
+ break;
+ case DefenseLine::Second:
+ makeInteractable(_graveyardCentral);
+ break;
+ case DefenseLine::Third:
+ break;
+ case DefenseLine::Last:
+ // make titan orb interactable
+ if (GameObject* door = battlegroundMap->GetGameObject(_collisionDoorGUID))
+ door->UseDoorOrButton();
+
+ makeInteractable(_titanRelicGUID);
+ break;
+ default:
+ break;
+ }
+ }
+
+ Creature* FindKanrethad() const
+ {
+ return battlegroundMap->GetCreature(_kanrethadGUID);
+ }
+
+ void EndRound()
+ {
+ _roundScores[0].winner = _attackers;
+ _roundScores[0].time = std::min<uint32>(_totalTime, BG_SA_ROUNDLENGTH);
+
+ _attackers = (_attackers == TEAM_ALLIANCE) ? TEAM_HORDE : TEAM_ALLIANCE;
+ _status = BG_SA_SECOND_WARMUP;
+ _totalTime = 0;
+ ToggleTimer();
+
+ _updateWaitTimer = 5000;
+ _signaledRoundTwo = false;
+ _signaledRoundTwoHalfMin = false;
+ _initSecondRound = true;
+ ResetObjs();
+ battlegroundMap->UpdateAreaDependentAuras();
+
+ battleground->CastSpellOnTeam(SPELL_END_OF_ROUND, ALLIANCE);
+ battleground->CastSpellOnTeam(SPELL_END_OF_ROUND, HORDE);
+
+ battleground->RemoveAuraOnTeam(SPELL_CARRYING_SEAFORIUM_CHARGE, HORDE);
+ battleground->RemoveAuraOnTeam(SPELL_CARRYING_SEAFORIUM_CHARGE, ALLIANCE);
+ }
+
+ void OnGameObjectCreate(GameObject* gameobject) override
+ {
+ BattlegroundScript::OnGameObjectCreate(gameobject);
+
+ if (gameobject->GetGoType() == GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING)
+ _gateGUIDs.insert(gameobject->GetGUID());
+
+ switch (gameobject->GetEntry())
+ {
+ case BG_SA_BOAT_ONE_A:
+ _boatGUIDs[TEAM_ALLIANCE][0] = gameobject->GetGUID();
+ break;
+ case BG_SA_BOAT_TWO_A:
+ _boatGUIDs[TEAM_ALLIANCE][1] = gameobject->GetGUID();
+ break;
+ case BG_SA_BOAT_ONE_H:
+ _boatGUIDs[TEAM_HORDE][0] = gameobject->GetGUID();
+ break;
+ case BG_SA_BOAT_TWO_H:
+ _boatGUIDs[TEAM_HORDE][1] = gameobject->GetGUID();
+ break;
+ case GO_SEAFORIUM_BOMB_A:
+ _staticBombGUIDs[TEAM_ALLIANCE].insert(gameobject->GetGUID());
+ if (_status != BG_SA_SECOND_WARMUP && _status != BG_SA_WARMUP)
+ gameobject->RemoveFlag(GO_FLAG_NOT_SELECTABLE);
+ break;
+ case GO_SEAFORIUM_BOMB_H:
+ _staticBombGUIDs[TEAM_HORDE].insert(gameobject->GetGUID());
+ if (_status != BG_SA_SECOND_WARMUP && _status != BG_SA_WARMUP)
+ gameobject->RemoveFlag(GO_FLAG_NOT_SELECTABLE);
+ break;
+ case GO_SEAFORIUM_CHARGE_A:
+ case GO_SEAFORIUM_CHARGE_H:
+ _dynamicBombGUIDs.insert(gameobject->GetGUID());
+ break;
+ case GO_GRAVEYARD_EAST_A:
+ case GO_GRAVEYARD_EAST_H:
+ _graveyardEast = gameobject->GetGUID();
+ break;
+ case GO_GRAVEYARD_WEST_A:
+ case GO_GRAVEYARD_WEST_H:
+ _graveyardWest = gameobject->GetGUID();
+ break;
+ case GO_GRAVEYARD_CENTRAL_A:
+ case GO_GRAVEYARD_CENTRAL_H:
+ _graveyardCentral = gameobject->GetGUID();
+ break;
+ case GO_COLLISION_DOOR:
+ _collisionDoorGUID = gameobject->GetGUID();
+ break;
+ case GO_TITAN_RELIC_A:
+ case GO_TITAN_RELIC_H:
+ _titanRelicGUID = gameobject->GetGUID();
+ break;
+ default:
+ break;
+ }
+ }
+
+ void DoAction(uint32 actionId, WorldObject* source, WorldObject* target) override
+ {
+ BattlegroundScript::DoAction(actionId, source, target);
+
+ switch (actionId)
+ {
+ case ACTION_SOTA_CAPTURE_GRAVEYARD:
+ HandleCaptureGraveyardAction(Object::ToGameObject(target), Object::ToPlayer(source));
+ break;
+ default:
+ break;
+ }
+ }
+
+ void OnCreatureCreate(Creature* creature) override
+ {
+ BattlegroundScript::OnCreatureCreate(creature);
+ switch (creature->GetEntry())
+ {
+ case NPC_DEMOLISHER:
+ creature->SetFaction(BG_SA_Factions[_attackers]);
+ break;
+ case NPC_ANTIPERSONNEL_CANNON:
+ creature->SetFaction(BG_SA_Factions[_attackers == TEAM_HORDE ? TEAM_ALLIANCE : TEAM_HORDE]);
+ break;
+ case NPC_KANRETHAD:
+ _kanrethadGUID = creature->GetGUID();
+ break;
+ case NPC_RIGGER_SPARKLIGHT:
+ case NPC_GORGRIL_RIGSPARK:
+ creature->AI()->Talk(TEXT_SPARKLIGHT_RIGSPARK_SPAWN);
+ break;
+ default:
+ break;
+ }
+ }
+
+ uint32 GetData(uint32 dataId) const override
+ {
+ switch (dataId)
+ {
+ case DATA_ATTACKERS:
+ return _attackers;
+ case DATA_STATUS:
+ return _status;
+ default:
+ return BattlegroundScript::GetData(dataId);
+ }
+ }
+
+ static GateInfo const* GetGate(uint32 entry)
+ {
+ for (GateInfo const& gate : Gates)
+ if (gate.GameObjectId == entry)
+ return &gate;
+
+ return nullptr;
+ }
+
+private:
+ /// Id of attacker team
+ TeamId _attackers;
+
+ /// Totale elapsed time of current round
+ uint32 _totalTime;
+ /// Max time of round
+ uint32 _endRoundTimer;
+ /// For know if boats has start moving or not yet
+ bool _shipsStarted;
+ /// Statu of battle (Start or not, and what round)
+ BG_SA_Status _status;
+ /// Score of each round
+ std::array<BG_SA_RoundScore, 2> _roundScores;
+ /// used for know we are in timer phase or not (used for worldstate update)
+ bool _timerEnabled;
+ /// 5secs before starting the 1min countdown for second round
+ uint32 _updateWaitTimer;
+ /// for know if warning about second round start has been sent
+ bool _signaledRoundTwo;
+ /// for know if warning about second round start has been sent
+ bool _signaledRoundTwoHalfMin;
+ /// for know if second round has been init
+ bool _initSecondRound;
+
+ // [team][boat_idx]
+ std::array<std::array<ObjectGuid, 2 /*BOAT_COUNT*/>, PVP_TEAMS_COUNT> _boatGUIDs;
+ std::array<GuidUnorderedSet, PVP_TEAMS_COUNT> _staticBombGUIDs; // bombs ready to be picked up
+ GuidUnorderedSet _dynamicBombGUIDs; // bombs thrown by players, ready to explode/disarm
+
+ ObjectGuid _graveyardWest;
+ ObjectGuid _graveyardEast;
+ ObjectGuid _graveyardCentral;
+ GuidUnorderedSet _gateGUIDs;
+ ObjectGuid _collisionDoorGUID;
+ ObjectGuid _kanrethadGUID;
+ ObjectGuid _titanRelicGUID;
+};
+
+void AddSC_battleground_strand_of_the_ancients()
+{
+ RegisterBattlegroundMapScript(battleground_strand_of_the_ancients, 607);
+}
diff --git a/src/server/scripts/Northrend/StrandOfTheAncients/strand_of_the_ancients.cpp b/src/server/scripts/Battlegrounds/StrandOfTheAncients/strand_of_the_ancients.cpp
index ed268327760..0ad0c7381e2 100644
--- a/src/server/scripts/Northrend/StrandOfTheAncients/strand_of_the_ancients.cpp
+++ b/src/server/scripts/Battlegrounds/StrandOfTheAncients/strand_of_the_ancients.cpp
@@ -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"
diff --git a/src/server/scripts/Battlegrounds/StrandOfTheAncients/strand_of_the_ancients.h b/src/server/scripts/Battlegrounds/StrandOfTheAncients/strand_of_the_ancients.h
new file mode 100644
index 00000000000..4d86099136d
--- /dev/null
+++ b/src/server/scripts/Battlegrounds/StrandOfTheAncients/strand_of_the_ancients.h
@@ -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
diff --git a/src/server/scripts/Battlegrounds/TwinPeaks/battleground_twin_peaks.cpp b/src/server/scripts/Battlegrounds/TwinPeaks/battleground_twin_peaks.cpp
new file mode 100644
index 00000000000..73f8db98aab
--- /dev/null
+++ b/src/server/scripts/Battlegrounds/TwinPeaks/battleground_twin_peaks.cpp
@@ -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);
+}
diff --git a/src/server/scripts/Battlegrounds/WarsongGulch/battleground_warsong_gulch.cpp b/src/server/scripts/Battlegrounds/WarsongGulch/battleground_warsong_gulch.cpp
new file mode 100644
index 00000000000..be76b69abf1
--- /dev/null
+++ b/src/server/scripts/Battlegrounds/WarsongGulch/battleground_warsong_gulch.cpp
@@ -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);
+}
diff --git a/src/server/scripts/Battlegrounds/battlegrounds_script_loader.cpp b/src/server/scripts/Battlegrounds/battlegrounds_script_loader.cpp
new file mode 100644
index 00000000000..da8062fee38
--- /dev/null
+++ b/src/server/scripts/Battlegrounds/battlegrounds_script_loader.cpp
@@ -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();
+}
diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp
index d03dd7b96cb..7f4468dbdb9 100644
--- a/src/server/scripts/Commands/cs_debug.cpp
+++ b/src/server/scripts/Commands/cs_debug.cpp
@@ -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
{
diff --git a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp
index 673f1e9bfad..b818c1e6f10 100644
--- a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp
+++ b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp
@@ -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();
diff --git a/src/server/scripts/Northrend/northrend_script_loader.cpp b/src/server/scripts/Northrend/northrend_script_loader.cpp
index fe2514d804e..639aa223fa8 100644
--- a/src/server/scripts/Northrend/northrend_script_loader.cpp
+++ b/src/server/scripts/Northrend/northrend_script_loader.cpp
@@ -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();
}
diff --git a/src/server/scripts/Northrend/zone_dalaran.cpp b/src/server/scripts/Northrend/zone_dalaran.cpp
index 46460521b6b..92fc14b2c64 100644
--- a/src/server/scripts/Northrend/zone_dalaran.cpp
+++ b/src/server/scripts/Northrend/zone_dalaran.cpp
@@ -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();
}
diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp
index 828523e0bf3..f0c1e460815 100644
--- a/src/server/scripts/Spells/spell_item.cpp
+++ b/src/server/scripts/Spells/spell_item.cpp
@@ -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);
}