aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMihapro <Mihapro@users.noreply.github.com>2016-07-15 14:39:41 +0200
committerAokromes <Aokromes@users.noreply.github.com>2016-07-15 14:39:41 +0200
commitb7c2d309e666a21877977597e17ab9b4728fff0b (patch)
tree7cb6f1033ce0d451d8e275d59c11cdfc7b23744c /src
parenta5b6d1992a50d4eaf4a7e13dc27e4c876467341a (diff)
[6.x] Core/Battlefield: Tol Barad (#17124)
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Battlefield/Battlefield.h4
-rw-r--r--src/server/game/Battlefield/BattlefieldMgr.cpp4
-rw-r--r--src/server/game/Battlefield/Zones/BattlefieldTB.cpp869
-rw-r--r--src/server/game/Battlefield/Zones/BattlefieldTB.h728
-rw-r--r--src/server/game/Entities/Player/Player.cpp28
-rw-r--r--src/server/game/Spells/SpellMgr.cpp4
-rw-r--r--src/server/game/World/World.cpp10
-rw-r--r--src/server/game/World/World.h8
-rw-r--r--src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/zone_tol_barad.cpp131
-rw-r--r--src/server/worldserver/worldserver.conf.dist58
11 files changed, 1841 insertions, 5 deletions
diff --git a/src/server/game/Battlefield/Battlefield.h b/src/server/game/Battlefield/Battlefield.h
index 172e1f9246c..eb0c3895c8c 100644
--- a/src/server/game/Battlefield/Battlefield.h
+++ b/src/server/game/Battlefield/Battlefield.h
@@ -107,14 +107,14 @@ class TC_GAME_API BfCapturePoint
virtual void SendChangePhase();
bool SetCapturePointData(GameObject* capturePoint);
+ bool DelCapturePoint();
GameObject* GetCapturePointGo();
uint32 GetCapturePointEntry() const { return m_capturePointEntry; }
TeamId GetTeamId() const { return m_team; }
+ BattlefieldObjectiveStates GetObjectiveState() const { return m_State; }
protected:
- bool DelCapturePoint();
-
// active Players in the area of the objective, 0 - alliance, 1 - horde
GuidSet m_activePlayers[BG_TEAMS_COUNT];
diff --git a/src/server/game/Battlefield/BattlefieldMgr.cpp b/src/server/game/Battlefield/BattlefieldMgr.cpp
index b92b2e64318..b4b4e269b28 100644
--- a/src/server/game/Battlefield/BattlefieldMgr.cpp
+++ b/src/server/game/Battlefield/BattlefieldMgr.cpp
@@ -17,6 +17,7 @@
#include "BattlefieldMgr.h"
#include "BattlefieldWG.h"
+#include "BattlefieldTB.h"
#include "Player.h"
BattlefieldMgr::BattlefieldMgr()
@@ -53,8 +54,6 @@ void BattlefieldMgr::InitBattlefield()
TC_LOG_INFO("bg.battlefield", "Battlefield: Wintergrasp successfully initiated.");
}
- /*
- For Cataclysm: Tol Barad
Battlefield* tb = new BattlefieldTB;
// respawn, init variables
if (!tb->SetupBattlefield())
@@ -67,7 +66,6 @@ void BattlefieldMgr::InitBattlefield()
_battlefieldSet.push_back(tb);
TC_LOG_DEBUG("bg.battlefield", "Battlefield: Tol Barad successfully initiated.");
}
- */
}
void BattlefieldMgr::AddZone(uint32 zoneId, Battlefield* bf)
diff --git a/src/server/game/Battlefield/Zones/BattlefieldTB.cpp b/src/server/game/Battlefield/Zones/BattlefieldTB.cpp
new file mode 100644
index 00000000000..affc1e0db47
--- /dev/null
+++ b/src/server/game/Battlefield/Zones/BattlefieldTB.cpp
@@ -0,0 +1,869 @@
+/*
+* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
+*
+* 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/>.
+*/
+
+// TO-DO:
+// - Implement proper support for vehicles (Player::VehicleSpellInitialize())
+// - Siege Engine Turret (45564) crashing server (Auras: Unknown Shapeshift Type: 24)
+// - Graveyard spirit phasing, ressurection, Spiritual Immunity aura for players nearby
+// - Warn and teleport players out of the Baradin Hold instance (need sniffs; spell 94964?)
+// - Not sure, but players should probably be able to ressurect from guide spirits when there's no battle
+// - Check and script achievements
+
+#include "BattlefieldTB.h"
+#include "AchievementMgr.h"
+#include "CreatureTextMgr.h"
+#include "Battleground.h"
+#include "MapManager.h"
+#include "ObjectMgr.h"
+#include "Opcodes.h"
+#include "Player.h"
+#include "SpellAuras.h"
+#include "TemporarySummon.h"
+#include "WorldSession.h"
+
+BattlefieldTB::~BattlefieldTB() { }
+
+bool BattlefieldTB::SetupBattlefield()
+{
+ m_TypeId = BATTLEFIELD_TB; // See enum BattlefieldTypes
+ m_BattleId = BATTLEFIELD_BATTLEID_TB;
+ m_ZoneId = BATTLEFIELD_TB_ZONEID;
+ m_MapId = BATTLEFIELD_TB_MAPID;
+ m_Map = sMapMgr->CreateBaseMap(m_MapId);
+
+ InitStalker(NPC_DEBUG_ANNOUNCER, TolBaradDebugAnnouncerPos);
+
+ m_MaxPlayer = sWorld->getIntConfig(CONFIG_TOLBARAD_PLR_MAX);
+ m_IsEnabled = sWorld->getBoolConfig(CONFIG_TOLBARAD_ENABLE);
+ m_MinPlayer = sWorld->getIntConfig(CONFIG_TOLBARAD_PLR_MIN);
+ m_MinLevel = sWorld->getIntConfig(CONFIG_TOLBARAD_PLR_MIN_LVL);
+ m_BattleTime = sWorld->getIntConfig(CONFIG_TOLBARAD_BATTLETIME) * MINUTE * IN_MILLISECONDS;
+ m_BonusTime = sWorld->getIntConfig(CONFIG_TOLBARAD_BONUSTIME) * MINUTE * IN_MILLISECONDS;
+ m_NoWarBattleTime = sWorld->getIntConfig(CONFIG_TOLBARAD_NOBATTLETIME) * MINUTE * IN_MILLISECONDS;
+ m_RestartAfterCrash = sWorld->getIntConfig(CONFIG_TOLBARAD_RESTART_AFTER_CRASH) * MINUTE * IN_MILLISECONDS;
+
+ m_TimeForAcceptInvite = 20;
+ m_StartGroupingTimer = 15 * MINUTE * IN_MILLISECONDS;
+ m_StartGrouping = false;
+ m_isActive = false;
+
+ KickPosition.Relocate(-605.5f, 1181.31f, 95.96f, 6.177155f);
+ KickPosition.m_mapId = m_MapId;
+
+ RegisterZone(m_ZoneId);
+
+ m_Data32.resize(BATTLEFIELD_TB_DATA_MAX);
+
+ m_saveTimer = 5 * MINUTE * IN_MILLISECONDS;
+
+ updatedNPCAndObjects = true;
+ m_updateObjectsTimer = 0;
+
+ // Was there a battle going on or time isn't set yet? Then use m_RestartAfterCrash
+ if (sWorld->getWorldState(TB_WS_STATE_BATTLE) == 1 || sWorld->getWorldState(TB_WS_TIME_NEXT_BATTLE) == 0)
+ sWorld->setWorldState(TB_WS_TIME_NEXT_BATTLE, m_RestartAfterCrash);
+
+ // Set timer
+ m_Timer = sWorld->getWorldState(TB_WS_TIME_NEXT_BATTLE);
+
+ // Defending team isn't set yet? Choose randomly.
+ if (sWorld->getWorldState(TB_WS_FACTION_CONTROLLING) == 0)
+ sWorld->setWorldState(TB_WS_FACTION_CONTROLLING, uint64(urand(1, 2)));
+
+ // Set defender team
+ SetDefenderTeam(TeamId(sWorld->getWorldState(TB_WS_FACTION_CONTROLLING) - 1));
+
+ // Just to save world states
+ SendInitWorldStatesToAll();
+
+ // Create capture points
+ for (uint8 i = 0; i < TB_BASE_COUNT; i++)
+ {
+ TolBaradCapturePoint* capturePoint = new TolBaradCapturePoint(this, GetDefenderTeam());
+
+ //Spawn flag pole
+ if (GameObject* go = SpawnGameObject(TBCapturePoints[i].entryFlagPole[GetDefenderTeam()], TBCapturePoints[i].x, TBCapturePoints[i].y, TBCapturePoints[i].z, TBCapturePoints[i].o))
+ {
+ go->SetGoArtKit(GetDefenderTeam() == TEAM_ALLIANCE ? TB_GO_ARTKIT_FLAG_ALLIANCE : TB_GO_ARTKIT_FLAG_HORDE);
+ capturePoint->SetCapturePointData(go);
+ }
+ AddCapturePoint(capturePoint);
+ }
+
+ // Spawn towers
+ for (uint8 i = 0; i < TB_TOWERS_COUNT; i++)
+ if (GameObject* go = SpawnGameObject(TBTowers[i].entry, TBTowers[i].x, TBTowers[i].y, TBTowers[i].z, TBTowers[i].o))
+ Towers.insert(go->GetGUID());
+
+ // Init Graveyards
+ SetGraveyardNumber(BATTLEFIELD_TB_GRAVEYARD_MAX);
+
+ // Graveyards
+ for (uint8 i = 0; i < BATTLEFIELD_TB_GRAVEYARD_MAX; i++)
+ {
+ BfGraveyard* graveyard = new BfGraveyard(this);
+
+ // When between games, the graveyard is controlled by the defending team
+ graveyard->Initialize(GetDefenderTeam(), TBGraveyards[i].gyid);
+
+ // Spawn spirits
+ for (uint8 team = 0; team < 2; team++)
+ if (Creature* creature = SpawnCreature(TBGraveyards[i].spiritEntry[team], TBGraveyards[i].x, TBGraveyards[i].y, TBGraveyards[i].z, TBGraveyards[i].o, TeamId(team)))
+ graveyard->SetSpirit(creature, TeamId(team));
+
+ m_GraveyardList[i] = graveyard;
+ }
+
+ // Time warning vars
+ warnedFiveMinutes = false;
+ warnedTwoMinutes = false;
+ warnedOneMinute = false;
+
+ UpdateNPCsAndGameObjects();
+
+ return true;
+}
+
+bool BattlefieldTB::Update(uint32 diff)
+{
+ bool m_return = Battlefield::Update(diff);
+
+ // Minutes till battle preparation warnings
+ if (GetState() == BATTLEFIELD_INACTIVE)
+ {
+ if (m_Timer <= 5 * MINUTE * IN_MILLISECONDS + m_StartGroupingTimer && !warnedFiveMinutes)
+ {
+ warnedFiveMinutes = true;
+ SendWarning(TB_TEXT_PREPARATIONS_IN_5_MIN);
+ }
+
+ if (m_Timer <= 2 * MINUTE * IN_MILLISECONDS + m_StartGroupingTimer && !warnedTwoMinutes)
+ {
+ warnedTwoMinutes = true;
+ SendWarning(TB_TEXT_PREPARATIONS_IN_2_MIN);
+ }
+
+ if (m_Timer <= 1 * MINUTE * IN_MILLISECONDS + m_StartGroupingTimer && !warnedOneMinute)
+ {
+ warnedOneMinute = true;
+ SendWarning(TB_TEXT_PREPARATIONS_IN_1_MIN);
+ }
+ }
+
+ if (!updatedNPCAndObjects)
+ {
+ if (m_updateObjectsTimer <= diff)
+ {
+ UpdateNPCsAndGameObjects();
+ updatedNPCAndObjects = true;
+ }
+ else
+ m_updateObjectsTimer -= diff;
+ }
+
+ if (m_saveTimer <= diff)
+ {
+ if (!IsWarTime())
+ sWorld->setWorldState(TB_WS_TIME_NEXT_BATTLE, m_Timer);
+ m_saveTimer = 60 * IN_MILLISECONDS;
+ }
+ else
+ m_saveTimer -= diff;
+
+ return m_return;
+}
+
+void BattlefieldTB::OnPlayerEnterZone(Player* player)
+{
+ if (!m_isActive)
+ RemoveAurasFromPlayer(player);
+
+ SendInitWorldStatesTo(player);
+}
+
+void BattlefieldTB::OnPlayerLeaveZone(Player* player)
+{
+ if (!m_isActive)
+ RemoveAurasFromPlayer(player);
+}
+
+void BattlefieldTB::OnPlayerJoinWar(Player* player)
+{
+ RemoveAurasFromPlayer(player);
+
+ player->SetPvP(true);
+
+ // Bonus damage buff for attackers
+ if (player->GetTeam() == GetAttackerTeam() && GetData(BATTLEFIELD_TB_DATA_TOWERS_DESTROYED) > 0)
+ player->CastCustomSpell(SPELL_TOWER_ATTACK_BONUS, SPELLVALUE_AURA_STACK, GetData(BATTLEFIELD_TB_DATA_TOWERS_DESTROYED), player, TRIGGERED_FULL_MASK);
+}
+
+
+void BattlefieldTB::OnPlayerLeaveWar(Player* player)
+{
+ RemoveAurasFromPlayer(player);
+}
+
+void BattlefieldTB::RemoveAurasFromPlayer(Player* player)
+{
+ player->RemoveAurasDueToSpell(SPELL_TB_SLOW_FALL);
+ player->RemoveAurasDueToSpell(SPELL_TB_VETERAN);
+ player->RemoveAurasDueToSpell(SPELL_TOWER_ATTACK_BONUS);
+ player->RemoveAurasDueToSpell(SPELL_TB_SPIRITUAL_IMMUNITY);
+}
+
+// 62 fields, [7]-[68]
+void BattlefieldTB::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet)
+{
+ packet.Worldstates.emplace_back(uint32(TB_WS_ALLIANCE_ATTACKING_SHOW), int32(IsWarTime() && GetAttackerTeam() == TEAM_ALLIANCE ? 1 : 0));
+ packet.Worldstates.emplace_back(uint32(TB_WS_HORDE_ATTACKING_SHOW), int32(IsWarTime() && GetAttackerTeam() == TEAM_HORDE ? 1 : 0));
+
+ // Not sure if TB
+ //packet.Worldstates.emplace_back(uint32(TB_WS_9_UNKNOWN), int32(1));
+
+ packet.Worldstates.emplace_back(uint32(TB_WS_SOUTH_DAMAGED_NEUTRAL), int32(0));
+ packet.Worldstates.emplace_back(uint32(TB_WS_SOUTH_INTACT_NEUTRAL), int32(0));
+
+ packet.Worldstates.emplace_back(uint32(TB_WS_PROGRESS_SHOW), int32(0));
+
+ // Buildings/bases
+ for (BfCapturePointMap::iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr)
+ {
+ uint8 i = TB_BASE_COUNT;
+ switch (itr->second->GetCapturePointEntry())
+ {
+ case GO_CAPTURE_POINT_NORTH_A_DEFENDING:
+ case GO_CAPTURE_POINT_NORTH_H_DEFENDING:
+ i = TB_BASE_IRONCLAD_GARRISON;
+ break;
+ case GO_CAPTURE_POINT_EAST_A_DEFENDING:
+ case GO_CAPTURE_POINT_EAST_H_DEFENDING:
+ i = TB_BASE_SLAGWORKS;
+ break;
+ case GO_CAPTURE_POINT_WEST_A_DEFENDING:
+ case GO_CAPTURE_POINT_WEST_H_DEFENDING:
+ i = TB_BASE_WARDENS_VIGIL;
+ break;
+ default:
+ continue;
+ }
+
+ TeamId team = TEAM_NEUTRAL;
+ bool controlled = false;
+ bool capturing = false;
+
+ switch (itr->second->GetObjectiveState())
+ {
+ case BF_CAPTUREPOINT_OBJECTIVESTATE_ALLIANCE:
+ case BF_CAPTUREPOINT_OBJECTIVESTATE_HORDE:
+ controlled = true;
+ team = itr->second->GetTeamId();
+ break;
+ case BF_CAPTUREPOINT_OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE:
+ case BF_CAPTUREPOINT_OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE:
+ team = TEAM_ALLIANCE;
+ capturing = true;
+ break;
+ case BF_CAPTUREPOINT_OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE:
+ case BF_CAPTUREPOINT_OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE:
+ team = TEAM_HORDE;
+ capturing = true;
+ break;
+ default:
+ team = TEAM_NEUTRAL;
+ break;
+ }
+
+ packet.Worldstates.emplace_back(uint32(TBCapturePoints[i].wsControlled[TEAM_ALLIANCE]), int32(team == TEAM_ALLIANCE && controlled ? 1 : 0));
+ packet.Worldstates.emplace_back(uint32(TBCapturePoints[i].wsCapturing[TEAM_ALLIANCE]), int32(team == TEAM_ALLIANCE && capturing ? 1 : 0));
+ packet.Worldstates.emplace_back(uint32(TBCapturePoints[i].wsNeutral), int32(team == TEAM_NEUTRAL ? 1 : 0));
+ packet.Worldstates.emplace_back(uint32(TBCapturePoints[i].wsCapturing[TEAM_HORDE]), int32(team == TEAM_HORDE && capturing ? 1 : 0));
+ packet.Worldstates.emplace_back(uint32(TBCapturePoints[i].wsControlled[TEAM_HORDE]), int32(team == TEAM_HORDE && controlled ? 1 : 0));
+ }
+
+ packet.Worldstates.emplace_back(uint32(TB_WS_TOWERS_DESTROYED_SHOW), int32(GetData(BATTLEFIELD_TB_DATA_TOWERS_DESTROYED)));
+ packet.Worldstates.emplace_back(uint32(TB_WS_BUILDINGS_CAPTURED_SHOW), int32(IsWarTime() ? 1 : 0));
+ packet.Worldstates.emplace_back(uint32(TB_WS_BUILDINGS_CAPTURED), int32(GetData(BATTLEFIELD_TB_DATA_BUILDINGS_CAPTURED)));
+ packet.Worldstates.emplace_back(uint32(TB_WS_TOWERS_DESTROYED), int32(0));
+
+ packet.Worldstates.emplace_back(uint32(TB_WS_TIME_BATTLE_END_SHOW), int32(IsWarTime() ? 1 : 0));
+
+ packet.Worldstates.emplace_back(uint32(TB_WS_STATE_BATTLE), int32(IsWarTime() ? 1 : 0));
+ packet.Worldstates.emplace_back(uint32(TB_WS_STATE_PREPARATIONS), int32(GetState() == BATTLEFIELD_WARMUP ? 1 : 0));
+
+ // Not sure if TB
+ //packet.Worldstates.emplace_back(uint32(TB_WS_35_UNKNOWN), int32(0));
+ //packet.Worldstates.emplace_back(uint32(TB_WS_36_UNKNOWN), int32(0));
+ //packet.Worldstates.emplace_back(uint32(TB_WS_37_UNKNOWN), int32(0));
+
+ // Unused tower icons
+ packet.Worldstates.emplace_back(uint32(TB_WS_WEST_DAMAGED_NEUTRAL), int32(0));
+ packet.Worldstates.emplace_back(uint32(TB_WS_WEST_INTACT_NEUTRAL), int32(0));
+ packet.Worldstates.emplace_back(uint32(TB_WS_EAST_DAMAGED_NEUTRAL), int32(0));
+ packet.Worldstates.emplace_back(uint32(TB_WS_EAST_INTACT_NEUTRAL), int32(0));
+
+ // Towers/spires
+ for (uint8 i = 0; i < TB_TOWERS_COUNT; i++)
+ {
+ // Find gameobject
+ for (ObjectGuid guid : Towers)
+ {
+ GameObject* tower = GetGameObject(guid);
+ if (!tower || tower->GetEntry() != TBTowers[i].entry)
+ continue;
+
+ TeamId team = GetDefenderTeam(); // 0-false -> alliance; 1-true -> horde
+ bool intact = tower->GetDestructibleState() == GO_DESTRUCTIBLE_INTACT;
+ bool damaged = tower->GetDestructibleState() == GO_DESTRUCTIBLE_DAMAGED;
+ bool destroyed = tower->GetDestructibleState() == GO_DESTRUCTIBLE_DESTROYED;
+
+ packet.Worldstates.emplace_back(uint32(TBTowers[i].wsIntact[TEAM_ALLIANCE]), int32(!team && intact ? 1 : 0));
+ packet.Worldstates.emplace_back(uint32(TBTowers[i].wsDamaged[TEAM_ALLIANCE]), int32(!team && damaged ? 1 : 0));
+ packet.Worldstates.emplace_back(uint32(TBTowers[i].wsDestroyed), int32(destroyed ? 1 : 0));
+ packet.Worldstates.emplace_back(uint32(TBTowers[i].wsDamaged[TEAM_HORDE]), int32(team && damaged ? 1 : 0));
+ packet.Worldstates.emplace_back(uint32(TBTowers[i].wsIntact[TEAM_HORDE]), int32(team && intact ? 1 : 0));
+ }
+ }
+
+ packet.Worldstates.emplace_back(uint32(TB_WS_TIME_NEXT_BATTLE_SHOW), int32(!IsWarTime() ? 1 : 0));
+
+ packet.Worldstates.emplace_back(uint32(TB_WS_ALLIANCE_CONTROLS_SHOW), int32(!IsWarTime() && GetDefenderTeam() == TEAM_ALLIANCE ? 1 : 0));
+ packet.Worldstates.emplace_back(uint32(TB_WS_HORDE_CONTROLS_SHOW), int32(!IsWarTime() && GetDefenderTeam() == TEAM_HORDE ? 1 : 0));
+
+ packet.Worldstates.emplace_back(uint32(TB_WS_TIME_BATTLE_END), int32(IsWarTime() ? time(NULL) + (m_Timer / 1000) : 0));
+ packet.Worldstates.emplace_back(uint32(TB_WS_TIME_NEXT_BATTLE), int32(!IsWarTime() ? time(NULL) + (m_Timer / 1000) : 0));
+
+ // Not sure if TB
+ //packet.Worldstates.emplace_back(uint32(TB_WS_65_UNKNOWN), int32(0));
+ //packet.Worldstates.emplace_back(uint32(TB_WS_66_UNKNOWN), int32(0));
+
+ packet.Worldstates.emplace_back(uint32(TB_WS_KEEP_ALLIANCE), int32(GetDefenderTeam() == TEAM_ALLIANCE ? 1 : 0));
+ packet.Worldstates.emplace_back(uint32(TB_WS_KEEP_HORDE), int32(GetDefenderTeam() == TEAM_HORDE ? 1 : 0));
+}
+
+void BattlefieldTB::SendInitWorldStatesTo(Player* player)
+{
+ WorldPackets::WorldState::InitWorldStates packet;
+ packet.AreaID = m_ZoneId;
+ packet.MapID = m_MapId;
+ packet.SubareaID = 0;
+
+ FillInitialWorldStates(packet);
+
+ player->SendDirectMessage(packet.Write());
+}
+
+void BattlefieldTB::SendInitWorldStatesToAll()
+{
+ // Save
+ sWorld->setWorldState(TB_WS_STATE_BATTLE, uint64(IsWarTime() ? 1 : 0));
+ sWorld->setWorldState(TB_WS_ALLIANCE_CONTROLS_SHOW, uint64(!IsWarTime() && GetDefenderTeam() == TEAM_ALLIANCE ? 1 : 0));
+ sWorld->setWorldState(TB_WS_HORDE_CONTROLS_SHOW, uint64(!IsWarTime() && GetDefenderTeam() == TEAM_HORDE ? 1 : 0));
+ sWorld->setWorldState(TB_WS_ALLIANCE_ATTACKING_SHOW, uint64(IsWarTime() && GetAttackerTeam() == TEAM_ALLIANCE ? 1 : 0));
+ sWorld->setWorldState(TB_WS_HORDE_ATTACKING_SHOW, uint64(IsWarTime() && GetAttackerTeam() == TEAM_HORDE ? 1 : 0));
+ sWorld->setWorldState(TB_WS_TIME_NEXT_BATTLE, uint64(!IsWarTime() ? m_Timer : 0));
+ sWorld->setWorldState(TB_WS_TIME_NEXT_BATTLE_SHOW, uint64(!IsWarTime() ? 1 : 0));
+
+ // Tol Barad
+ for (uint8 team = 0; team < 2; team++)
+ for (GuidSet::iterator itr = m_players[team].begin(); itr != m_players[team].end(); ++itr)
+ if (Player* player = ObjectAccessor::FindPlayer(*itr))
+ SendInitWorldStatesTo(player);
+
+ // Tol Barad Peninsula
+ Map::PlayerList const& players = m_Map->GetPlayers();
+ for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
+ if (Player* player = itr->GetSource()->ToPlayer())
+ if (player->GetZoneId() == 5389) // ZONE_TOL_BARAD_PENINSULA
+ player->SendInitWorldStates(5389, player->GetAreaId());
+}
+
+void BattlefieldTB::OnStartGrouping()
+{
+ UpdateNPCsAndGameObjects();
+
+ SendUpdateWorldState(TB_WS_STATE_PREPARATIONS, uint32(1));
+
+ // Teleport players out of questing area
+ for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team)
+ for (GuidSet::const_iterator itr = m_players[team].begin(); itr != m_players[team].end(); ++itr)
+ if (Player* player = ObjectAccessor::FindPlayer(*itr))
+ if (player->GetAreaId() == TBQuestAreas[m_iCellblockRandom].entry)
+ player->CastSpell(player, TBQuestAreas[m_iCellblockRandom].teleportSpell, true);
+
+ // Should we also teleport players out of Baradin Hold underground area?
+};
+
+void BattlefieldTB::OnBattleStart()
+{
+ SetData(BATTLEFIELD_TB_DATA_BUILDINGS_CAPTURED, uint32(0));
+ SetData(BATTLEFIELD_TB_DATA_TOWERS_INTACT, uint32(3));
+ SetData(BATTLEFIELD_TB_DATA_TOWERS_DESTROYED, uint32(0));
+
+ UpdateNPCsAndGameObjects();
+
+ SendInitWorldStatesToAll();
+};
+
+void BattlefieldTB::OnBattleEnd(bool endByTimer)
+{
+ if (!endByTimer) // Attackers win (but now they are defenders already)
+ SendWarning(GetDefenderTeam() == TEAM_ALLIANCE ? TB_TEXT_FORTRESS_CAPTURE_ALLIANCE : TB_TEXT_FORTRESS_CAPTURE_HORDE);
+ else // Defenders win
+ SendWarning(GetDefenderTeam() == TEAM_ALLIANCE ? TB_TEXT_FORTRESS_DEFEND_ALLIANCE : TB_TEXT_FORTRESS_DEFEND_HORDE);
+
+ // UpdateNPCsAndGameObjects() must be called 1 minute after battle ends
+ m_updateObjectsTimer = 1 * MINUTE * IN_MILLISECONDS;
+ updatedNPCAndObjects = false;
+
+ // Complete quest
+ TeamCastSpell(GetDefenderTeam(), GetDefenderTeam() == TEAM_ALLIANCE ? SPELL_VICTORY_ALLIANCE : SPELL_VICTORY_HORDE);
+
+ // Rewards
+ TeamCastSpell(GetDefenderTeam(), GetDefenderTeam() == TEAM_ALLIANCE ? SPELL_REWARD_VICTORY_ALLIANCE : SPELL_REWARD_VICTORY_HORDE);
+ for (uint32 i = 0; i < GetData(BATTLEFIELD_TB_DATA_TOWERS_INTACT); i++) // Unsure, for each intact tower or only once for having any tower intact?
+ TeamCastSpell(GetDefenderTeam(), SPELL_REWARD_TOWER_INTACT);
+ TeamCastSpell(GetAttackerTeam(), SPELL_REWARD_DEFEAT);
+
+ for (uint8 team = 0; team < 2; ++team)
+ {
+ for (GuidSet::const_iterator itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr)
+ if (Player* player = ObjectAccessor::FindPlayer(*itr))
+ RemoveAurasFromPlayer(player);
+
+ m_PlayersInWar[team].clear();
+ }
+
+ // Reset time warning vars
+ warnedFiveMinutes = false;
+ warnedTwoMinutes = false;
+ warnedOneMinute = false;
+};
+
+void BattlefieldTB::UpdateNPCsAndGameObjects()
+{
+ for (ObjectGuid guid : BattleInactiveNPCs)
+ if (Creature* creature = GetCreature(guid))
+ HideNpc(creature);
+
+ for (ObjectGuid guid : BattleInactiveGOs)
+ if (GameObject* gameobject = GetGameObject(guid))
+ gameobject->SetRespawnTime(RESPAWN_ONE_DAY);
+
+ for (ObjectGuid guid : TemporaryNPCs)
+ if (Creature* creature = GetCreature(guid))
+ creature->RemoveFromWorld();
+ TemporaryNPCs.clear();
+
+ for (ObjectGuid guid : TemporaryGOs)
+ if (GameObject* gameobject = GetGameObject(guid))
+ gameobject->Delete();
+ TemporaryGOs.clear();
+
+ // Tol Barad gates - closed during warmup
+ if (GameObject* gates = GetGameObject(TBGatesGUID))
+ gates->SetGoState(GetState() == BATTLEFIELD_WARMUP ? GO_STATE_READY : GO_STATE_ACTIVE);
+
+ // Baradin Hold door - open when inactive
+ if (GameObject* door = GetGameObject(TBDoorGUID))
+ door->SetGoState(GetState() == BATTLEFIELD_INACTIVE ? GO_STATE_ACTIVE : GO_STATE_READY);
+
+ // Decide which cellblock and questgiver will be active.
+ m_iCellblockRandom = GetState() == BATTLEFIELD_INACTIVE ? urand(0, CELLBLOCK_MAX - 1) : CELLBLOCK_NONE;
+
+ // To The Hole gate
+ if (GameObject* door = GetGameObject(m_gateToTheHoleGUID))
+ door->SetGoState(m_iCellblockRandom == CELLBLOCK_THE_HOLE ? GO_STATE_ACTIVE : GO_STATE_READY);
+
+ // D-Block gate
+ if (GameObject* door = GetGameObject(m_gateDBlockGUID))
+ door->SetGoState(m_iCellblockRandom == CELLBLOCK_D_BLOCK ? GO_STATE_ACTIVE : GO_STATE_READY);
+
+ // Cursed Depths gate
+ if (GameObject* door = GetGameObject(m_gateCursedDepthsGUID))
+ door->SetGoState(m_iCellblockRandom == CELLBLOCK_CURSED_DEPTHS ? GO_STATE_ACTIVE : GO_STATE_READY);
+
+ if (GetState() == BATTLEFIELD_INACTIVE)
+ {
+ // Delete capture points
+ for (BfCapturePointMap::iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr)
+ itr->second->DelCapturePoint();
+ m_capturePoints.clear();
+
+ // Create capture points
+ for (uint8 i = 0; i < TB_BASE_COUNT; i++)
+ {
+ TolBaradCapturePoint* capturePoint = new TolBaradCapturePoint(this, GetDefenderTeam());
+
+ //Spawn flag pole
+ if (GameObject* go = SpawnGameObject(TBCapturePoints[i].entryFlagPole[GetDefenderTeam()], TBCapturePoints[i].x, TBCapturePoints[i].y, TBCapturePoints[i].z, TBCapturePoints[i].o))
+ {
+ go->SetGoArtKit(GetDefenderTeam() == TEAM_ALLIANCE ? TB_GO_ARTKIT_FLAG_ALLIANCE : TB_GO_ARTKIT_FLAG_HORDE);
+ capturePoint->SetCapturePointData(go);
+ }
+
+ AddCapturePoint(capturePoint);
+ }
+
+ for (ObjectGuid guid : BattleInactiveNPCs)
+ if (Creature* creature = GetCreature(guid))
+ ShowNpc(creature, true);
+
+ for (ObjectGuid guid : BattleInactiveGOs)
+ if (GameObject* gameobject = GetGameObject(guid))
+ gameobject->SetRespawnTime(RESPAWN_IMMEDIATELY);
+
+ for (uint8 i = 0; i < TB_QUEST_INFANTRY_MAX; i++)
+ {
+ uint32 entry = TB_QUEST_INFANTRY[GetDefenderTeam()][urand(0,3)];
+ if (Creature* creature = SpawnCreature(entry, TBQuestInfantrySpawnData[i], GetDefenderTeam()))
+ TemporaryNPCs.insert(creature->GetGUID());
+ }
+
+ for (uint8 i = 0; i < TB_GUARDS_MAX; i++)
+ if (Creature* creature = SpawnCreature(GetDefenderTeam() == TEAM_ALLIANCE ? NPC_BARADIN_GUARD : NPC_HELLSCREAMS_SENTRY, GuardNPCSpawns[i], GetDefenderTeam()))
+ TemporaryNPCs.insert(creature->GetGUID());
+
+ for (uint8 i = 0; i < TB_FACTION_NPC_MAX; i++)
+ if (Creature* creature = SpawnCreature(GetDefenderTeam() == TEAM_ALLIANCE ? FactionNPCSpawns[i].entryAlliance : FactionNPCSpawns[i].entryHorde, FactionNPCSpawns[i].x, FactionNPCSpawns[i].y, FactionNPCSpawns[i].z, FactionNPCSpawns[i].o, GetDefenderTeam()))
+ TemporaryNPCs.insert(creature->GetGUID());
+
+ if (Creature* creature = SpawnCreature(RandomQuestgivers[GetDefenderTeam()][m_iCellblockRandom], RandomQuestgiverPos, GetDefenderTeam()))
+ TemporaryNPCs.insert(creature->GetGUID());
+
+ // Spawn portals
+ for (uint8 i = 0; i < TB_PORTAL_MAX; i++)
+ if (GameObject* go = SpawnGameObject(TBPortalEntry[GetDefenderTeam()], TBPortals[i].GetPositionX(), TBPortals[i].GetPositionY(), TBPortals[i].GetPositionZ(), TBPortals[i].GetOrientation()))
+ TemporaryGOs.insert(go->GetGUID());
+
+ // Update towers
+ for (ObjectGuid guid : Towers)
+ if (GameObject* go = GetGameObject(guid))
+ go->SetDestructibleState(GO_DESTRUCTIBLE_REBUILDING);
+ }
+ else if (GetState() == BATTLEFIELD_IN_PROGRESS)
+ {
+ for (uint8 i = 0; i < TB_ABANDONED_SIEGE_ENGINE_COUNT; i++)
+ if (Creature* creature = SpawnCreature(NPC_ABANDONED_SIEGE_ENGINE, TBAbandonedSiegeEngineSpawnData[i], GetDefenderTeam()))
+ TemporaryNPCs.insert(creature->GetGUID());
+
+ for (ObjectGuid guid : Towers)
+ {
+ if (GameObject* go = GetGameObject(guid))
+ {
+ go->SetDestructibleState(GO_DESTRUCTIBLE_INTACT);
+ go->ModifyHealth(go->GetGOValue()->Building.MaxHealth);
+ }
+ }
+ }
+
+ // Spawn banners
+ for (uint8 i = 0; i < TB_BANNER_MAX; i++)
+ if (GameObject* go = SpawnGameObject(TBBannerEntry[GetDefenderTeam()], TBBanners[i].GetPositionX(), TBBanners[i].GetPositionY(), TBBanners[i].GetPositionZ(), TBBanners[i].GetOrientation()))
+ TemporaryGOs.insert(go->GetGUID());
+
+ // Set graveyard controls
+ for (uint8 i = 0; i < BATTLEFIELD_TB_GRAVEYARD_MAX; i++)
+ if (BfGraveyard* graveyard = GetGraveyardById(i))
+ graveyard->GiveControlTo(!IsWarTime() || TBGraveyards[i].defenderControls ? GetDefenderTeam() : GetAttackerTeam());
+};
+
+void BattlefieldTB::OnCreatureCreate(Creature* creature)
+{
+ switch (creature->GetEntry())
+ {
+ // Store NPCs that need visibility toggling
+ case NPC_TOLBARAD_CAPTIVE_SPIRIT:
+ case NPC_TOLBARAD_CELLBLOCK_OOZE:
+ case NPC_TOLBARAD_ARCHMAGE_GALUS:
+ case NPC_TOLBARAD_GHASTLY_CONVICT:
+ case NPC_TOLBARAD_SHIVARRA_DESTROYER:
+ case NPC_TOLBARAD_CELL_WATCHER:
+ case NPC_TOLBARAD_SVARNOS:
+ case NPC_TOLBARAD_JAILED_WRATHGUARD:
+ case NPC_TOLBARAD_IMPRISONED_IMP:
+ case NPC_TOLBARAD_WARDEN_SILVA:
+ case NPC_TOLBARAD_WARDEN_GUARD:
+ case NPC_TOLBARAD_IMPRISONED_WORKER:
+ case NPC_TOLBARAD_EXILED_MAGE:
+ case NPC_CROCOLISK:
+ case NPC_PROBLIM:
+ BattleInactiveNPCs.insert(creature->GetGUID());
+ if (GetState() == BATTLEFIELD_WARMUP) // If battle is about to start, we must hide these.
+ HideNpc(creature);
+ break;
+ case NPC_ABANDONED_SIEGE_ENGINE:
+ creature->setFaction(TBFactions[GetDefenderTeam()]);
+ creature->CastSpell(creature, SPELL_THICK_LAYER_OF_RUST, true);
+ break;
+ case NPC_SIEGE_ENGINE_TURRET:
+ if (Unit* vehiclebase = creature->GetCharmerOrOwner()->GetVehicleBase())
+ creature->EnterVehicle(vehiclebase);
+ break;
+ case NPC_TOWER_RANGE_FINDER:
+ creature->CastSpell(creature, SPELL_TOWER_RANGE_FINDER_PERIODIC, true);
+ break;
+ case NPC_TB_GY_SPIRIT_BARADIN_HOLD_A:
+ case NPC_TB_GY_SPIRIT_BARADIN_HOLD_H:
+ case NPC_TB_GY_SPIRIT_IRONCLAD_GARRISON_A:
+ case NPC_TB_GY_SPIRIT_WARDENS_VIGIL_A:
+ case NPC_TB_GY_SPIRIT_EAST_SPIRE_A:
+ case NPC_TB_GY_SPIRIT_SOUTH_SPIRE_A:
+ case NPC_TB_GY_SPIRIT_WEST_SPIRE_A:
+ case NPC_TB_GY_SPIRIT_SLAGWORKS_A:
+ case NPC_TB_GY_SPIRIT_IRONCLAD_GARRISON_H:
+ case NPC_TB_GY_SPIRIT_WARDENS_VIGIL_H:
+ case NPC_TB_GY_SPIRIT_SLAGWORKS_H:
+ case NPC_TB_GY_SPIRIT_WEST_SPIRE_H:
+ case NPC_TB_GY_SPIRIT_EAST_SPIRE_H:
+ case NPC_TB_GY_SPIRIT_SOUTH_SPIRE_H:
+ creature->CastSpell(creature, SPELL_TB_SPIRITUAL_IMMUNITY, true);
+ creature->CastSpell(creature, SPELL_TB_SPIRIT_HEAL_CHANNEL, true);
+ break;
+ default:
+ break;
+ }
+};
+
+void BattlefieldTB::OnGameObjectCreate(GameObject* go)
+{
+ switch (go->GetEntry())
+ {
+ case GO_TOLBARAD_GATES:
+ TBGatesGUID = go->GetGUID();
+ go->SetGoState(GetState() == BATTLEFIELD_WARMUP ? GO_STATE_READY : GO_STATE_ACTIVE);
+ break;
+ case GO_TOLBARAD_DOOR:
+ TBDoorGUID = go->GetGUID();
+ go->SetGoState(GetState() == BATTLEFIELD_INACTIVE ? GO_STATE_ACTIVE : GO_STATE_READY);
+ break;
+ case GO_GATE_TO_THE_HOLE:
+ m_gateToTheHoleGUID = go->GetGUID();
+ go->SetGoState(m_iCellblockRandom == CELLBLOCK_THE_HOLE ? GO_STATE_ACTIVE : GO_STATE_READY);
+ break;
+ case GO_GATE_D_BLOCK:
+ m_gateDBlockGUID = go->GetGUID();
+ go->SetGoState(m_iCellblockRandom == CELLBLOCK_D_BLOCK ? GO_STATE_ACTIVE : GO_STATE_READY);
+ break;
+ case GO_CURSED_DEPTHS_GATE:
+ m_gateCursedDepthsGUID = go->GetGUID();
+ go->SetGoState(m_iCellblockRandom == CELLBLOCK_CURSED_DEPTHS ? GO_STATE_ACTIVE : GO_STATE_READY);
+ break;
+ case GO_CRATE_OF_CELLBLOCK_RATIONS:
+ case GO_CURSED_SHACKLES:
+ case GO_DUSTY_PRISON_JOURNAL:
+ case GO_TB_MEETING_STONE:
+ case GO_TB_INSTANCE_VISUAL_1:
+ case GO_TB_INSTANCE_VISUAL_2:
+ case GO_TB_INSTANCE_VISUAL_3:
+ case GO_TB_INSTANCE_VISUAL_4:
+ BattleInactiveGOs.insert(go->GetGUID());
+ if (GetState() == BATTLEFIELD_WARMUP) // If battle is about to start, we must hide these.
+ go->SetRespawnTime(RESPAWN_ONE_DAY);
+ break;
+ default:
+ break;
+ }
+};
+
+void BattlefieldTB::ProcessEvent(WorldObject* obj, uint32 eventId)
+{
+ if (!IsWarTime())
+ return;
+
+ if (eventId == EVENT_COUNT_CAPTURED_BASE)
+ {
+ UpdateCapturedBaseCount();
+ return;
+ }
+
+ if (!obj)
+ return;
+
+ GameObject* go = obj->ToGameObject();
+ if (!go)
+ return;
+
+ TBTowerId towerId;
+ switch (go->GetEntry())
+ {
+ case GO_WEST_SPIRE:
+ towerId = TB_TOWER_WEST_SPIRE;
+ break;
+ case GO_EAST_SPIRE:
+ towerId = TB_TOWER_EAST_SPIRE;
+ break;
+ case GO_SOUTH_SPIRE:
+ towerId = TB_TOWER_SOUTH_SPIRE;
+ break;
+ default:
+ return;
+ }
+
+ if (go->GetDestructibleState() == GO_DESTRUCTIBLE_DAMAGED)
+ TowerDamaged(towerId);
+ else if (go->GetDestructibleState() == GO_DESTRUCTIBLE_DESTROYED)
+ TowerDestroyed(towerId);
+}
+
+void BattlefieldTB::TowerDamaged(TBTowerId tbTowerId)
+{
+ if (!IsWarTime())
+ return;
+
+ SendWarning(TBTowers[tbTowerId].textDamaged);
+
+ SetData(BATTLEFIELD_TB_DATA_TOWERS_INTACT, GetData(BATTLEFIELD_TB_DATA_TOWERS_INTACT) - 1);
+
+ SendUpdateWorldState(uint32(TBTowers[tbTowerId].wsIntact[GetDefenderTeam()]), int32(0));
+ SendUpdateWorldState(uint32(TBTowers[tbTowerId].wsDamaged[GetDefenderTeam()]), int32(1));
+
+ TeamCastSpell(GetAttackerTeam(), SPELL_REWARD_TOWER_DAMAGED);
+}
+
+void BattlefieldTB::TowerDestroyed(TBTowerId tbTowerId)
+{
+ if (!IsWarTime())
+ return;
+
+ // Add 5 minute bonus time
+ m_Timer += m_BonusTime;
+
+ SendUpdateWorldState(TB_WS_TIME_BATTLE_END, uint32(time(NULL) + (m_Timer / 1000)));
+
+ SendWarning(TBTowers[tbTowerId].textDamaged);
+
+ SetData(BATTLEFIELD_TB_DATA_TOWERS_DESTROYED, GetData(BATTLEFIELD_TB_DATA_TOWERS_DESTROYED) + 1);
+ SendUpdateWorldState(uint32(TB_WS_TOWERS_DESTROYED), int32(GetData(BATTLEFIELD_TB_DATA_TOWERS_DESTROYED)));
+
+ SendUpdateWorldState(uint32(TBTowers[tbTowerId].wsDamaged[GetDefenderTeam()]), int32(0));
+ SendUpdateWorldState(uint32(TBTowers[tbTowerId].wsDestroyed), int32(1));
+
+ // Attack bonus buff
+ for (GuidSet::const_iterator itr = m_PlayersInWar[GetAttackerTeam()].begin(); itr != m_PlayersInWar[GetAttackerTeam()].end(); ++itr)
+ if (Player* player = ObjectAccessor::FindPlayer(*itr))
+ player->CastCustomSpell(SPELL_TOWER_ATTACK_BONUS, SPELLVALUE_AURA_STACK, GetData(BATTLEFIELD_TB_DATA_TOWERS_DESTROYED), player, TRIGGERED_FULL_MASK);
+
+ // Honor reward
+ TeamCastSpell(GetAttackerTeam(), SPELL_REWARD_TOWER_DESTROYED);
+}
+
+void BattlefieldTB::UpdateCapturedBaseCount()
+{
+ uint32 numCapturedBases = 0; // How many bases attacker has captured
+
+ for (BfCapturePointMap::iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr)
+ if (itr->second->GetTeamId() == GetAttackerTeam())
+ numCapturedBases += 1;
+
+ SetData(BATTLEFIELD_TB_DATA_BUILDINGS_CAPTURED, numCapturedBases);
+ SendUpdateWorldState(TB_WS_BUILDINGS_CAPTURED, uint32(numCapturedBases));
+
+ // Check if attackers won
+ if (numCapturedBases == TB_BASE_COUNT)
+ EndBattle(false);
+}
+
+// Called when player kill a unit in wg zone
+void BattlefieldTB::HandleKill(Player* killer, Unit* victim)
+{
+ if (killer == victim || victim->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ TeamId killerTeam = killer->GetTeamId();
+ for (GuidSet::const_iterator itr = m_PlayersInWar[killerTeam].begin(); itr != m_PlayersInWar[killerTeam].end(); ++itr)
+ if (Player* player = ObjectAccessor::FindPlayer(*itr))
+ if (player->GetDistance2d(killer) < 40.0f)
+ PromotePlayer(player);
+}
+
+void BattlefieldTB::PromotePlayer(Player* killer)
+{
+ if (!m_isActive || killer->HasAura(SPELL_TB_VETERAN))
+ return;
+
+ killer->CastSpell(killer, SPELL_TB_VETERAN, true);
+}
+
+TolBaradCapturePoint::TolBaradCapturePoint(BattlefieldTB* battlefield, TeamId teamInControl) : BfCapturePoint(battlefield)
+{
+ m_Bf = battlefield;
+ m_team = teamInControl;
+ m_value = teamInControl == TEAM_ALLIANCE ? m_maxValue : -m_maxValue;
+ m_State = teamInControl == TEAM_ALLIANCE ? BF_CAPTUREPOINT_OBJECTIVESTATE_ALLIANCE : BF_CAPTUREPOINT_OBJECTIVESTATE_HORDE;
+}
+
+void TolBaradCapturePoint::ChangeTeam(TeamId /*oldTeam*/)
+{
+ // Find out index
+ uint8 iBase = TB_BASE_COUNT;
+ for (uint8 i = 0; i < TB_BASE_COUNT; i++)
+ if (GetCapturePointEntry() == TBCapturePoints[i].entryFlagPole[m_Bf->GetDefenderTeam()])
+ iBase = i;
+
+ if (iBase == TB_BASE_COUNT)
+ return;
+
+ // Turn off previous world state icon
+ switch (m_OldState)
+ {
+ case BF_CAPTUREPOINT_OBJECTIVESTATE_ALLIANCE:
+ case BF_CAPTUREPOINT_OBJECTIVESTATE_HORDE:
+ SendUpdateWorldState(TBCapturePoints[iBase].wsControlled[GetTeamId()], uint32(0));
+ break;
+ case BF_CAPTUREPOINT_OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE:
+ case BF_CAPTUREPOINT_OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE:
+ SendUpdateWorldState(TBCapturePoints[iBase].wsCapturing[TEAM_ALLIANCE], uint32(0));
+ break;
+ case BF_CAPTUREPOINT_OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE:
+ case BF_CAPTUREPOINT_OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE:
+ SendUpdateWorldState(TBCapturePoints[iBase].wsCapturing[TEAM_HORDE], uint32(0));
+ break;
+ default:
+ break;
+ }
+
+ // Turn on new world state icon and send warning
+ switch (m_State)
+ {
+ case BF_CAPTUREPOINT_OBJECTIVESTATE_ALLIANCE:
+ case BF_CAPTUREPOINT_OBJECTIVESTATE_HORDE:
+ m_Bf->SendWarning(TBCapturePoints[iBase].textGained[GetTeamId()]);
+ SendUpdateWorldState(TBCapturePoints[iBase].wsControlled[GetTeamId()], uint32(1));
+ GetCapturePointGo()->SetGoArtKit(GetTeamId() == TEAM_ALLIANCE ? TB_GO_ARTKIT_FLAG_ALLIANCE : TB_GO_ARTKIT_FLAG_HORDE);
+ break;
+ case BF_CAPTUREPOINT_OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE:
+ m_Bf->SendWarning(TBCapturePoints[iBase].textLost[TEAM_HORDE]);
+ //no break here!
+ case BF_CAPTUREPOINT_OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE:
+ SendUpdateWorldState(TBCapturePoints[iBase].wsCapturing[TEAM_ALLIANCE], uint32(1));
+ GetCapturePointGo()->SetGoArtKit(TB_GO_ARTKIT_FLAG_NONE);
+ break;
+ case BF_CAPTUREPOINT_OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE:
+ m_Bf->SendWarning(TBCapturePoints[iBase].textLost[TEAM_ALLIANCE]);
+ //no break here!
+ case BF_CAPTUREPOINT_OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE:
+ SendUpdateWorldState(TBCapturePoints[iBase].wsCapturing[TEAM_HORDE], uint32(1));
+ GetCapturePointGo()->SetGoArtKit(TB_GO_ARTKIT_FLAG_NONE);
+ break;
+ default:
+ break;
+ }
+
+ // Update counter
+ m_Bf->ProcessEvent(NULL, EVENT_COUNT_CAPTURED_BASE);
+}
diff --git a/src/server/game/Battlefield/Zones/BattlefieldTB.h b/src/server/game/Battlefield/Zones/BattlefieldTB.h
new file mode 100644
index 00000000000..06182c78e61
--- /dev/null
+++ b/src/server/game/Battlefield/Zones/BattlefieldTB.h
@@ -0,0 +1,728 @@
+/*
+* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
+*
+* 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 BATTLEFIELD_TB_
+#define BATTLEFIELD_TB_
+
+#include "Battlefield.h"
+
+class BattlefieldTB;
+class TolBaradCapturePoint;
+
+enum TolBaradInfo
+{
+ BATTLEFIELD_TB_MAPID = 732, // Tol Barad
+ BATTLEFIELD_TB_ZONEID = 5095, // Tol Barad
+};
+
+enum TolBaradData
+{
+ BATTLEFIELD_TB_DATA_BUILDINGS_CAPTURED,
+ BATTLEFIELD_TB_DATA_TOWERS_INTACT,
+ BATTLEFIELD_TB_DATA_TOWERS_DESTROYED,
+ BATTLEFIELD_TB_DATA_MAX,
+};
+
+enum TolBaradSpells
+{
+ // Quest completion
+ SPELL_VICTORY_ALLIANCE = 94665,
+ SPELL_VICTORY_HORDE = 94763,
+
+ // Rewards
+ SPELL_REWARD_VICTORY_ALLIANCE = 89789,
+ SPELL_REWARD_VICTORY_HORDE = 89791,
+ SPELL_REWARD_DEFEAT = 89793,
+
+ SPELL_REWARD_TOWER_INTACT = 89794,
+ SPELL_REWARD_TOWER_DAMAGED = 89795,
+ SPELL_REWARD_TOWER_DESTROYED = 89796,
+
+ // Player buffs
+ SPELL_TB_SLOW_FALL = 88473,
+ SPELL_TB_VETERAN = 84655,
+ SPELL_TOWER_ATTACK_BONUS = 82629,
+ SPELL_TB_SPIRIT_HEAL_CHANNEL = 22011, // this spell replaces m_LastResurrectTimer in Battlefield.cpp?
+ SPELL_TB_SPIRITUAL_IMMUNITY = 95332,
+
+ // Vehicle
+ SPELL_THICK_LAYER_OF_RUST = 95330,
+ SPELL_RIDE_TOL_BARAD_VEHICLE = 84754,
+ SPELL_DEPLOY_SIEGE_MODE = 84974,
+ SPELL_SIEGE_CANNON_AURA = 85167, // aura, periodically triggers spell 85122
+// SPELL_SIEGE_CANNON_EFFECT = 85122, // targets random
+// SPELL_SIEGE_CANNON_DAMAGE = 85125,
+ SPELL_LEAVE_SIEGE_MODE = 85078,
+
+ SPELL_TOWER_RANGE_FINDER_PERIODIC = 85671,
+ SPELL_TOWER_RANGE_FINDER = 84979,
+
+ // Teleportation spells
+ SPELL_TB_THE_HOLE_TELEPORT = 89035,
+ SPELL_TB_D_BLOCK_TELEPORT = 89037,
+ SPELL_TB_CURSED_DEPTHS_TELEPORT = 89038,
+};
+
+enum TolBaradNpcs
+{
+ // Cursed Depths area
+ NPC_TOLBARAD_CAPTIVE_SPIRIT = 47531,
+ NPC_TOLBARAD_CELLBLOCK_OOZE = 47534,
+ NPC_TOLBARAD_ARCHMAGE_GALUS = 47537,
+ NPC_TOLBARAD_GHASTLY_CONVICT = 47590,
+
+ // D-Block area
+ NPC_TOLBARAD_SHIVARRA_DESTROYER = 47540,
+ NPC_TOLBARAD_CELL_WATCHER = 47542,
+ NPC_TOLBARAD_SVARNOS = 47544,
+ NPC_TOLBARAD_JAILED_WRATHGUARD = 47548,
+ NPC_TOLBARAD_IMPRISONED_IMP = 47549,
+
+ // The Hole area
+ NPC_TOLBARAD_WARDEN_SILVA = 48036,
+ NPC_TOLBARAD_WARDEN_GUARD = 47561,
+ NPC_TOLBARAD_IMPRISONED_WORKER = 47550,
+ NPC_TOLBARAD_EXILED_MAGE = 47552,
+
+ // Other
+ NPC_CROCOLISK = 47591,
+ NPC_PROBLIM = 47593,
+
+ // Graveyard spirits
+ NPC_TB_GY_SPIRIT_BARADIN_HOLD_A = 45066,
+ NPC_TB_GY_SPIRIT_BARADIN_HOLD_H = 45067,
+ NPC_TB_GY_SPIRIT_IRONCLAD_GARRISON_A = 45068,
+ NPC_TB_GY_SPIRIT_WARDENS_VIGIL_A = 45069,
+ NPC_TB_GY_SPIRIT_EAST_SPIRE_A = 45070,
+ NPC_TB_GY_SPIRIT_SOUTH_SPIRE_A = 45071,
+ NPC_TB_GY_SPIRIT_WEST_SPIRE_A = 45072,
+ NPC_TB_GY_SPIRIT_SLAGWORKS_A = 45073,
+ NPC_TB_GY_SPIRIT_IRONCLAD_GARRISON_H = 45074,
+ NPC_TB_GY_SPIRIT_WARDENS_VIGIL_H = 45075,
+ NPC_TB_GY_SPIRIT_SLAGWORKS_H = 45076,
+ NPC_TB_GY_SPIRIT_WEST_SPIRE_H = 45077,
+ NPC_TB_GY_SPIRIT_EAST_SPIRE_H = 45078,
+ NPC_TB_GY_SPIRIT_SOUTH_SPIRE_H = 45079,
+
+ // Stalker, dummies
+ NPC_DEBUG_ANNOUNCER = 43679,
+ NPC_TOWER_RANGE_FINDER = 45492,
+ NPC_TOWER_CANNON_TARGET = 45561,
+ NPC_SIEGE_ENGINE_TURRET = 45564,
+};
+
+enum TolBaradGOs
+{
+ // Towers
+ GO_WEST_SPIRE = 204588,
+ GO_EAST_SPIRE = 204589,
+ GO_SOUTH_SPIRE = 204590,
+
+ GO_CAPTURE_POINT_NORTH_A_DEFENDING = 205068,
+ GO_CAPTURE_POINT_NORTH_H_DEFENDING = 205096,
+ GO_CAPTURE_POINT_EAST_A_DEFENDING = 205138,
+ GO_CAPTURE_POINT_EAST_H_DEFENDING = 205139,
+ GO_CAPTURE_POINT_WEST_A_DEFENDING = 205101,
+ GO_CAPTURE_POINT_WEST_H_DEFENDING = 205103,
+
+ // Entrance gates and instance door
+ GO_TOLBARAD_GATES = 206598,
+ GO_TOLBARAD_DOOR = 206576,
+
+ // Other
+ GO_TB_MEETING_STONE = 206668,
+
+ GO_TB_INSTANCE_VISUAL_1 = 207746,
+ GO_TB_INSTANCE_VISUAL_2 = 207747,
+ GO_TB_INSTANCE_VISUAL_3 = 210114,
+ GO_TB_INSTANCE_VISUAL_4 = 210115,
+};
+
+enum TolBaradGOArtKit
+{
+ TB_GO_ARTKIT_FLAG_NONE = 0,
+ TB_GO_ARTKIT_FLAG_HORDE = 1,
+ TB_GO_ARTKIT_FLAG_ALLIANCE = 2,
+};
+
+enum TolBaradWorldStates
+{
+ TB_WS_ALLIANCE_CONTROLS_SHOW = 5385,
+ TB_WS_HORDE_CONTROLS_SHOW = 5384,
+ TB_WS_ALLIANCE_ATTACKING_SHOW = 5546,
+ TB_WS_HORDE_ATTACKING_SHOW = 5547,
+
+ TB_WS_BUILDINGS_CAPTURED = 5348,
+ TB_WS_BUILDINGS_CAPTURED_SHOW = 5349,
+ TB_WS_TOWERS_DESTROYED = 5347,
+ TB_WS_TOWERS_DESTROYED_SHOW = 5350,
+
+ TB_WS_FACTION_CONTROLLING = 5334, // 1 -> Alliance, 2 -> Horde
+
+ TB_WS_TIME_NEXT_BATTLE = 5332,
+ TB_WS_TIME_NEXT_BATTLE_SHOW = 5387,
+ TB_WS_TIME_BATTLE_END = 5333,
+ TB_WS_TIME_BATTLE_END_SHOW = 5346,
+
+ TB_WS_STATE_PREPARATIONS = 5684,
+ TB_WS_STATE_BATTLE = 5344,
+
+ /* Not Sure if TB
+ TB_WS_0_UNKNOWN = 5587,
+ TB_WS_9_UNKNOWN = 5508,
+ TB_WS_35_UNKNOWN = 5679,
+ TB_WS_36_UNKNOWN = 5678,
+ TB_WS_37_UNKNOWN = 5677,
+ TB_WS_60_UNKNOWN = 5361,
+ TB_WS_61_UNKNOWN = 5360,
+ TB_WS_65_UNKNOWN = 5195,
+ TB_WS_66_UNKNOWN = 5193,
+ */
+
+ TB_WS_PROGRESS_SHOW = 5376,
+ TB_WS_PROGRESS = 5377, // 0 horde, 100 alliance
+ TB_WS_PROGRESS_PERCENT_GREY = 5378,
+
+ TB_WS_KEEP_HORDE = 5469,
+ TB_WS_KEEP_ALLIANCE = 5470,
+
+ TB_WS_GARRISON_HORDE_CONTROLLED = 5418,
+ TB_WS_GARRISON_HORDE_CAPTURING = 5419,
+ TB_WS_GARRISON_NEUTRAL = 5420, // unused
+ TB_WS_GARRISON_ALLIANCE_CAPTURING = 5421,
+ TB_WS_GARRISON_ALLIANCE_CONTROLLED = 5422,
+
+ TB_WS_VIGIL_HORDE_CONTROLLED = 5423,
+ TB_WS_VIGIL_HORDE_CAPTURING = 5424,
+ TB_WS_VIGIL_NEUTRAL = 5425, // unused
+ TB_WS_VIGIL_ALLIANCE_CAPTURING = 5426,
+ TB_WS_VIGIL_ALLIANCE_CONTROLLED = 5427,
+
+ TB_WS_SLAGWORKS_HORDE_CONTROLLED = 5428,
+ TB_WS_SLAGWORKS_HORDE_CAPTURING = 5429,
+ TB_WS_SLAGWORKS_NEUTRAL = 5430, // unused
+ TB_WS_SLAGWORKS_ALLIANCE_CAPTURING = 5431,
+ TB_WS_SLAGWORKS_ALLIANCE_CONTROLLED = 5432,
+
+ TB_WS_WEST_INTACT_HORDE = 5433,
+ TB_WS_WEST_DAMAGED_HORDE = 5434,
+ TB_WS_WEST_DESTROYED_NEUTRAL = 5435,
+ TB_WS_WEST_INTACT_ALLIANCE = 5436,
+ TB_WS_WEST_DAMAGED_ALLIANCE = 5437,
+ TB_WS_WEST_INTACT_NEUTRAL = 5453, // unused
+ TB_WS_WEST_DAMAGED_NEUTRAL = 5454, // unused
+
+ TB_WS_SOUTH_INTACT_HORDE = 5438,
+ TB_WS_SOUTH_DAMAGED_HORDE = 5439,
+ TB_WS_SOUTH_DESTROYED_NEUTRAL = 5440,
+ TB_WS_SOUTH_INTACT_ALLIANCE = 5441,
+ TB_WS_SOUTH_DAMAGED_ALLIANCE = 5442,
+ TB_WS_SOUTH_INTACT_NEUTRAL = 5455, // unused
+ TB_WS_SOUTH_DAMAGED_NEUTRAL = 5456, // unused
+
+ TB_WS_EAST_INTACT_HORDE = 5443,
+ TB_WS_EAST_DAMAGED_HORDE = 5444,
+ TB_WS_EAST_DESTROYED_NEUTRAL = 5445,
+ TB_WS_EAST_INTACT_ALLIANCE = 5446,
+ TB_WS_EAST_DAMAGED_ALLIANCE = 5447,
+ TB_WS_EAST_INTACT_NEUTRAL = 5451,
+ TB_WS_EAST_DAMAGED_NEUTRAL = 5452,
+};
+
+enum TolBaradText
+{
+ // DEBUG Announcer
+ TB_TEXT_EAST_SPIRE_DAMAGED = 1,
+ TB_TEXT_EAST_SPIRE_DESTROYED = 2,
+ TB_TEXT_WEST_SPIRE_DAMAGED = 3,
+ TB_TEXT_WEST_SPIRE_DESTROYED = 4,
+ TB_TEXT_SOUTH_SPIRE_DAMAGED = 5,
+ TB_TEXT_SOUTH_SPIRE_DESTROYED = 6,
+ TB_TEXT_GARRISON_ALLIANCE_GAINED = 7,
+ TB_TEXT_GARRISON_ALLIANCE_LOST = 8,
+ TB_TEXT_GARRISON_HORDE_GAINED = 9,
+ TB_TEXT_GARRISON_HORDE_LOST = 10,
+ TB_TEXT_VIGIL_ALLIANCE_GAINED = 11,
+ TB_TEXT_VIGIL_ALLIANCE_LOST = 12,
+ TB_TEXT_VIGIL_HORDE_GAINED = 13,
+ TB_TEXT_VIGIL_HORDE_LOST = 14,
+ TB_TEXT_SLAGWORKS_ALLIANCE_GAINED = 15,
+ TB_TEXT_SLAGWORKS_ALLIANCE_LOST = 16,
+ TB_TEXT_SLAGWORKS_HORDE_GAINED = 17,
+ TB_TEXT_SLAGWORKS_HORDE_LOST = 18,
+ TB_TEXT_FORTRESS_DEFEND_ALLIANCE = 19,
+ TB_TEXT_FORTRESS_DEFEND_HORDE = 20,
+ TB_TEXT_FORTRESS_CAPTURE_ALLIANCE = 21,
+ TB_TEXT_FORTRESS_CAPTURE_HORDE = 22,
+ TB_TEXT_VEHICLE_OUTSIDE_WARNING = 23,
+ TB_TEXT_PREPARATIONS_IN_5_MIN = 24,
+ TB_TEXT_PREPARATIONS_IN_2_MIN = 25,
+ TB_TEXT_PREPARATIONS_IN_1_MIN = 26,
+};
+
+enum TolBaradEvent
+{
+ EVENT_COUNT_CAPTURED_BASE = 1,
+};
+
+const uint32 TBFactions[BG_TEAMS_COUNT] = { 1610, 1732 };
+
+// Stalker
+Position const TolBaradDebugAnnouncerPos = { -1234.25f, 961.903f, 159.4913f, 0.0f };
+
+// Quest Infantry NPCs
+enum TBQuestInfantryEntry
+{
+ NPC_ALLIANCE_WARRIOR_INFANTRY = 47599,
+ NPC_ALLIANCE_PALADIN_INFANTRY = 47600,
+ NPC_ALLIANCE_HUNTER_INFANTRY = 47595,
+ NPC_ALLIANCE_MAGE_INFANTRY = 47598,
+
+ NPC_HORDE_DRUID_INFANTRY = 47607,
+ NPC_HORDE_MAGE_INFANTRY = 47608,
+ NPC_HORDE_ROGUE_INFANTRY = 47609,
+ NPC_HORDE_SHAMAN_INFANTRY = 47610,
+};
+
+uint32 const TB_QUEST_INFANTRY[BG_TEAMS_COUNT][4] =
+{
+ { NPC_HORDE_DRUID_INFANTRY, NPC_HORDE_MAGE_INFANTRY, NPC_HORDE_ROGUE_INFANTRY, NPC_HORDE_SHAMAN_INFANTRY },
+ { NPC_ALLIANCE_WARRIOR_INFANTRY, NPC_ALLIANCE_PALADIN_INFANTRY, NPC_ALLIANCE_HUNTER_INFANTRY, NPC_ALLIANCE_MAGE_INFANTRY },
+};
+
+uint8 const TB_QUEST_INFANTRY_MAX = 37;
+Position const TBQuestInfantrySpawnData[TB_QUEST_INFANTRY_MAX] =
+{
+ { -930.4685f, 1020.178f, 121.5658f, 0.1537642f },
+ { -831.5157f, 975.816f, 121.5255f, 5.022717f },
+ { -837.0773f, 943.9008f, 121.5055f, 5.461119f },
+ { -839.1646f, 1024.046f, 121.5505f, 4.782219f },
+ { -881.283f, 1033.25f, 121.5243f, 0.0f },
+ { -883.038f, 924.955f, 121.5243f, 0.0f },
+ { -883.913f, 978.059f, 121.5243f, 3.388291f },
+ { -883.6224f, 950.8459f, 121.5122f, 0.8307042f },
+ { -895.181f, 1015.2f, 121.5505f, 2.652318f },
+ { -943.4023f, 961.7462f, 121.5658f, 5.258394f },
+ { -958.649f, 926.877f, 121.5243f, 0.0f },
+ { -959.743f, 1029.09f, 121.5243f, 0.0f },
+ { -964.6652f, 978.5373f, 121.5257f, 0.02025719f },
+ { -1407.14f, 721.42f, 123.5033f, 0.0f },
+ { -1414.46f, 671.66f, 123.5043f, 0.0f },
+ { -1431.7f, 623.073f, 123.5043f, 0.0f },
+ { -1434.162f, 655.8566f, 123.5051f, 4.84886f },
+ { -1445.19f, 739.729f, 123.5457f, 5.767949f },
+ { -1460.954f, 718.418f, 123.6453f, 5.178094f },
+ { -1462.48f, 694.378f, 123.5463f, 0.3441857f },
+ { -1372.23f, 683.707f, 123.5043f, 0.0f },
+ { -1479.46f, 635.799f, 123.5043f, 0.0f },
+ { -1491.259f, 734.5692f, 123.4525f, 1.529741f },
+ { -1509.024f, 688.8625f, 123.5463f, 6.243045f },
+ { -1419.311f, 1310.25f, 133.8389f, 0.0f },
+ { -1444.24f, 1266.439f, 133.8229f, 0.0f },
+ { -1450.569f, 1337.351f, 133.914f, 0.0f },
+ { -1479.819f, 1331.34f, 153.2f, 0.0f },
+ { -1497.62f, 1276.429f, 133.6676f, 3.147845f },
+ { -1498.37f, 1379.689f, 133.827f, 0.0f },
+ { -1499.97f, 1232.87f, 133.8239f, 0.0f },
+ { -1505.7f, 1261.99f, 133.7089f, 0.6167698f },
+ { -1531.84f, 1316.569f, 153.2f, 0.0f },
+ { -1533.141f, 1267.66f, 133.836f, 0.0f },
+ { -1547.59f, 1300.21f, 133.7094f, 1.908187f },
+ { -1563.3f, 1325.79f, 133.6673f, 0.0f },
+};
+
+// Guard NPCs
+enum TBGuardEntry
+{
+ NPC_BARADIN_GUARD = 51165,
+ NPC_HELLSCREAMS_SENTRY = 51166,
+};
+
+uint8 const TB_GUARDS_MAX = 8;
+Position const GuardNPCSpawns[TB_GUARDS_MAX] =
+{
+// { -837.3768f, 1196.082f, 114.2994f, 3.036873f },
+// { -762.118f, 1195.259f, 107.2007f, 3.036873f },
+// { -837.809f, 1179.842f, 114.1356f, 3.159046f },
+// { -762.5504f, 1179.019f, 107.2137f, 3.159046f },
+ { -1272.951f, 964.8854f, 119.5782f, 3.193953f },
+ { -1274.394f, 997.6511f, 119.5743f, 3.193953f },
+ { -1248.226f, 1018.476f, 119.8113f, 1.605703f },
+ { -1218.948f, 943.5695f, 119.5994f, 4.625123f },
+ { -1195.417f, 965.5364f, 119.8113f, 0.0f },
+ { -1220.832f, 1018.497f, 119.8113f, 1.605703f },
+ { -1196.151f, 999.5121f, 119.5966f, 0.0f },
+ { -1249.304f, 942.9063f, 119.5782f, 4.625123f },
+};
+
+enum TBFactionNPCEntry
+{
+ // Guards
+ NPC_BARADIN_GUARD_1 = 47324,
+ NPC_BARADIN_GUARD_2 = 47325,
+ NPC_BARADIN_GRUNT_1 = 47335,
+ NPC_BARADIN_GRUNT_2 = 47336,
+
+ // Questgivers
+ NPC_SERGEANT_PARKER = 48066, // Everytime
+ NPC_COMMANDER_STEVENS = 48039, // One of these three
+ NPC_2ND_LIEUTENANT_WANSWORTH = 48061,
+ NPC_MARSHAL_FALLOWS = 48074,
+
+ NPC_COMMANDER_ZANOTH = 48069, // Everytime!
+ NPC_STAFF_SERGEANT_LAZGAR = 48062, // One of these three
+ NPC_DRILLMASTER_RAZGOTH = 48070,
+ NPC_PRIVATE_GARNOTH = 48071,
+
+ // Portal summoners
+ NPC_MAVEN_ZARA = 50173,
+ NPC_RHAGHA = 50167,
+};
+
+struct TBFactionNPCInfo
+{
+ float x;
+ float y;
+ float z;
+ float o;
+ uint32 entryAlliance;
+ uint32 entryHorde;
+};
+
+uint8 const TB_FACTION_NPC_MAX = 4;
+TBFactionNPCInfo const FactionNPCSpawns[TB_FACTION_NPC_MAX] =
+{
+ { -1259.356f, 1057.108f, 107.0786f, 4.956735f, NPC_BARADIN_GUARD_1, NPC_BARADIN_GRUNT_1 },
+ { -1254.174f, 1061.094f, 107.0772f, 5.445427f, NPC_BARADIN_GUARD_2, NPC_BARADIN_GRUNT_2 },
+ { -1256.365f, 1058.47f, 107.0776f, 2.216568f, NPC_MAVEN_ZARA, NPC_RHAGHA },
+ { -1231.38f, 985.681f, 121.2403f, 0.6108652f, NPC_SERGEANT_PARKER, NPC_COMMANDER_ZANOTH },
+};
+
+// Questing
+enum TBQuesting
+{
+ CELLBLOCK_THE_HOLE = 0, // The Hole area
+ CELLBLOCK_D_BLOCK = 1, // D-Block area
+ CELLBLOCK_CURSED_DEPTHS = 2, // Cursed Depths area
+ CELLBLOCK_MAX = 3,
+ CELLBLOCK_NONE,
+
+ AREA_THE_HOLE = 5659,
+ AREA_D_BLOCK = 5657,
+ AREA_CURSED_DEPTHS = 5658,
+
+ GO_GATE_TO_THE_HOLE = 206845,
+ GO_GATE_D_BLOCK = 206844,
+ GO_CURSED_DEPTHS_GATE = 206843,
+
+ GO_CRATE_OF_CELLBLOCK_RATIONS = 206996,
+ GO_CURSED_SHACKLES = 206905,
+ GO_DUSTY_PRISON_JOURNAL = 206890,
+};
+
+Position const RandomQuestgiverPos = { -1228.93f, 975.038f, 121.7153f, 5.969026f };
+
+struct TBQuestAreaInfo
+{
+ uint32 entry;
+ uint32 teleportSpell;
+};
+TBQuestAreaInfo const TBQuestAreas[CELLBLOCK_MAX] =
+{
+ { AREA_THE_HOLE, SPELL_TB_THE_HOLE_TELEPORT },
+ { AREA_D_BLOCK, SPELL_TB_D_BLOCK_TELEPORT },
+ { AREA_CURSED_DEPTHS, SPELL_TB_CURSED_DEPTHS_TELEPORT },
+};
+uint32 const RandomQuestgivers[BG_TEAMS_COUNT][CELLBLOCK_MAX] =
+{
+ { NPC_MARSHAL_FALLOWS, NPC_2ND_LIEUTENANT_WANSWORTH, NPC_COMMANDER_STEVENS },
+ { NPC_DRILLMASTER_RAZGOTH, NPC_STAFF_SERGEANT_LAZGAR, NPC_PRIVATE_GARNOTH },
+};
+
+// Capture Points
+enum TBCapturePointId
+{
+ TB_BASE_IRONCLAD_GARRISON = 0,
+ TB_BASE_WARDENS_VIGIL = 1,
+ TB_BASE_SLAGWORKS = 2,
+ TB_BASE_COUNT = 3,
+};
+
+struct TBCapturePointSpawnData
+{
+ float x;
+ float y;
+ float z;
+ float o;
+ TBCapturePointId id;
+ uint32 entryFlagPole[2];
+ uint32 wsControlled[2];
+ uint32 wsCapturing[2];
+ uint32 wsNeutral;
+ uint32 textGained[2];
+ uint32 textLost[2];
+};
+
+TBCapturePointSpawnData const TBCapturePoints[TB_BASE_COUNT] =
+{
+ { -896.96f, 979.497f, 121.441f, 3.124123f, TB_BASE_IRONCLAD_GARRISON, { GO_CAPTURE_POINT_NORTH_A_DEFENDING, GO_CAPTURE_POINT_NORTH_H_DEFENDING }, { TB_WS_GARRISON_ALLIANCE_CONTROLLED, TB_WS_GARRISON_HORDE_CONTROLLED }, { TB_WS_GARRISON_ALLIANCE_CAPTURING, TB_WS_GARRISON_HORDE_CAPTURING }, TB_WS_GARRISON_NEUTRAL, { TB_TEXT_GARRISON_ALLIANCE_GAINED, TB_TEXT_GARRISON_HORDE_GAINED }, { TB_TEXT_GARRISON_ALLIANCE_LOST, TB_TEXT_GARRISON_HORDE_LOST } },
+ { -1492.34f, 1309.87f, 152.961f, 5.462882f, TB_BASE_WARDENS_VIGIL, { GO_CAPTURE_POINT_WEST_A_DEFENDING, GO_CAPTURE_POINT_WEST_H_DEFENDING }, { TB_WS_VIGIL_ALLIANCE_CONTROLLED, TB_WS_VIGIL_HORDE_CONTROLLED }, { TB_WS_VIGIL_ALLIANCE_CAPTURING, TB_WS_VIGIL_HORDE_CAPTURING }, TB_WS_VIGIL_NEUTRAL, { TB_TEXT_VIGIL_ALLIANCE_GAINED, TB_TEXT_VIGIL_HORDE_GAINED }, { TB_TEXT_VIGIL_ALLIANCE_LOST, TB_TEXT_VIGIL_HORDE_LOST } },
+ { -1437.f, 685.556f, 123.421f, 0.802851f, TB_BASE_SLAGWORKS, { GO_CAPTURE_POINT_EAST_A_DEFENDING, GO_CAPTURE_POINT_EAST_H_DEFENDING }, { TB_WS_SLAGWORKS_ALLIANCE_CONTROLLED, TB_WS_SLAGWORKS_HORDE_CONTROLLED }, { TB_WS_SLAGWORKS_ALLIANCE_CAPTURING, TB_WS_SLAGWORKS_HORDE_CAPTURING }, TB_WS_SLAGWORKS_NEUTRAL, { TB_TEXT_SLAGWORKS_ALLIANCE_GAINED, TB_TEXT_SLAGWORKS_HORDE_GAINED }, { TB_TEXT_SLAGWORKS_ALLIANCE_LOST, TB_TEXT_SLAGWORKS_HORDE_LOST } },
+};
+
+// Towers
+enum TBTowerId
+{
+ TB_TOWER_EAST_SPIRE = 0,
+ TB_TOWER_SOUTH_SPIRE = 1,
+ TB_TOWER_WEST_SPIRE = 2,
+ TB_TOWERS_COUNT = 3,
+};
+
+struct TBTowerInfo
+{
+ float x;
+ float y;
+ float z;
+ float o;
+ uint32 entry;
+ uint32 textDamaged;
+ uint32 textDestroyed;
+ uint32 wsIntact[BG_TEAMS_COUNT];
+ uint32 wsDamaged[BG_TEAMS_COUNT];
+ uint32 wsDestroyed;
+};
+
+TBTowerInfo const TBTowers[TB_TOWERS_COUNT] =
+{
+ { -1013.279f, 529.5382f, 146.427f, 1.97222f, GO_EAST_SPIRE, TB_TEXT_EAST_SPIRE_DAMAGED, TB_TEXT_EAST_SPIRE_DESTROYED, { TB_WS_EAST_INTACT_ALLIANCE, TB_WS_EAST_INTACT_HORDE }, { TB_WS_EAST_DAMAGED_ALLIANCE, TB_WS_EAST_DAMAGED_HORDE }, TB_WS_EAST_DESTROYED_NEUTRAL },
+ { -1618.91f, 954.5417f, 168.601f, 0.06981169f, GO_SOUTH_SPIRE, TB_TEXT_SOUTH_SPIRE_DAMAGED, TB_TEXT_SOUTH_SPIRE_DESTROYED, { TB_WS_SOUTH_INTACT_ALLIANCE, TB_WS_SOUTH_INTACT_HORDE }, { TB_WS_SOUTH_DAMAGED_ALLIANCE, TB_WS_SOUTH_DAMAGED_HORDE }, TB_WS_SOUTH_DESTROYED_NEUTRAL },
+ { -950.4097f, 1469.101f, 176.596f, 4.180066f, GO_WEST_SPIRE, TB_TEXT_WEST_SPIRE_DAMAGED, TB_TEXT_WEST_SPIRE_DESTROYED, { TB_WS_WEST_INTACT_ALLIANCE, TB_WS_WEST_INTACT_HORDE }, { TB_WS_WEST_DAMAGED_ALLIANCE, TB_WS_WEST_DAMAGED_HORDE }, TB_WS_WEST_DESTROYED_NEUTRAL },
+};
+
+// Vehicles
+enum TBVehicles
+{
+ NPC_ABANDONED_SIEGE_ENGINE = 45344,
+};
+
+int8 const TB_ABANDONED_SIEGE_ENGINE_COUNT = 6;
+Position const TBAbandonedSiegeEngineSpawnData[TB_ABANDONED_SIEGE_ENGINE_COUNT] =
+{
+ { -1106.57f, 1196.34f, 121.8023f, 0.4014257f },
+ { -1108.52f, 1111.33f, 121.2783f, 1.37881f },
+ { -1213.01f, 782.236f, 121.4473f, 1.675516f },
+ { -1258.26f, 780.497f, 122.4413f, 1.48353f },
+ { -1438.3f, 1095.24f, 121.1363f, 5.288348f },
+ { -1442.3f, 1141.07f, 123.6323f, 4.24115f },
+};
+
+// Banners
+enum TBFactionBannerEntry
+{
+ GO_BARADINS_WARDEN_BANNER = 207391, // Alliance banner
+ GO_HELLSCREAM_REACH_BANNER = 207400, // Horde banner
+};
+
+uint32 const TBBannerEntry[BG_TEAMS_COUNT] = { GO_BARADINS_WARDEN_BANNER, GO_HELLSCREAM_REACH_BANNER };
+
+uint8 const TB_BANNER_MAX = 23;
+Position const TBBanners[TB_BANNER_MAX] =
+{
+ { -987.6129f, 963.9861f, 121.4506f, 2.617989f },
+ { -988.118f, 993.0087f, 121.6746f, 3.612838f },
+ { -1195.941f, 964.342f, 119.728f, 0.8901166f },
+ { -1196.892f, 1000.957f, 119.8211f, 5.445428f },
+ { -1198.236f, 1081.898f, 120.2007f, 1.06465f },
+ { -1089.337f, 1157.161f, 120.2749f, 3.036838f },
+ { -1090.033f, 1143.476f, 120.2656f, 3.036838f },
+ { -1217.495f, 944.0261f, 119.4949f, 1.989672f },
+ { -1219.226f, 1018.168f, 119.728f, 2.251473f },
+ { -1210.319f, 1081.885f, 120.2396f, 2.007128f },
+ { -1226.903f, 786.7656f, 119.4592f, 1.553341f },
+ { -1228.464f, 979.7379f, 119.3814f, 0.03490625f },
+ { -1239.668f, 786.7899f, 119.4271f, 1.553341f },
+ { -1250.262f, 1017.887f, 119.728f, 0.8377575f },
+ { -1250.693f, 943.4496f, 119.4949f, 5.305802f },
+ { -1272.29f, 963.5208f, 119.4949f, 2.617989f },
+ { -1273.997f, 998.7934f, 119.4884f, 3.665196f },
+ { -1378.363f, 725.0087f, 124.2978f, 1.326448f },
+ { -1401.97f, 747.0972f, 123.2302f, 0.2443456f },
+ { -1421.953f, 1263.559f, 133.6141f, 5.009095f },
+ { -1446.497f, 1238.964f, 133.7601f, 5.969027f },
+ { -1488.908f, 1118.747f, 124.9255f, 6.248279f },
+ { -1488.533f, 1131.608f, 124.6363f, 6.248279f },
+};
+
+// Portals
+enum TBPortalEntry
+{
+ TB_PORTAL_ALLIANCE = 208227, // Portal to Stormwind
+ TB_PORTAL_HORDE = 208226, // Portal to Orgrimmar
+};
+
+uint32 const TBPortalEntry[BG_TEAMS_COUNT] = { TB_PORTAL_ALLIANCE, TB_PORTAL_HORDE };
+
+uint8 const TB_PORTAL_MAX = 2;
+Position const TBPortals[TB_PORTAL_MAX] =
+{
+ { -598.7656f, 1377.974f, 21.91898f, 0.0f },
+ { -1257.729f, 1060.365f, 106.9938f, 5.462882f },
+};
+
+/* ################### *
+ * Tol Barad graveyard *
+ * ################### */
+
+enum TBGraveyardAreaId
+{
+ // Tol Barad
+ TB_GY_BARADIN_HOLD = 1789,
+ TB_GY_IRONCLAD_GARRISON = 1783,
+ TB_GY_WARDENS_VIGIL = 1785,
+ TB_GY_SLAGWORKS = 1787,
+ TB_GY_WEST_SPIRE = 1784,
+ TB_GY_SOUTH_SPIRE = 1786,
+ TB_GY_EAST_SPIRE = 1788,
+ BATTLEFIELD_TB_GRAVEYARD_MAX = 7,
+
+ // Tol Barad Peninsula
+ TBP_GY_ALLIANCE_DAILY = 1808,
+ TBP_GY_HORDE_DAILY = 1807,
+};
+
+struct TBGraveyardInfo
+{
+ float x;
+ float y;
+ float z;
+ float o;
+ uint32 phaseId;
+ uint32 gyid;
+ uint32 spiritEntry[BG_TEAMS_COUNT];
+ bool defenderControls;
+};
+
+TBGraveyardInfo const TBGraveyards[BATTLEFIELD_TB_GRAVEYARD_MAX] =
+{
+ { -1247.42f, 981.25f, 155.35f, 6.28f, 128, TB_GY_BARADIN_HOLD, { NPC_TB_GY_SPIRIT_BARADIN_HOLD_A, NPC_TB_GY_SPIRIT_BARADIN_HOLD_H }, true },
+ { -974.28f, 1089.47f, 132.99f, 5.90f, 64, TB_GY_IRONCLAD_GARRISON, { NPC_TB_GY_SPIRIT_IRONCLAD_GARRISON_A, NPC_TB_GY_SPIRIT_IRONCLAD_GARRISON_H }, false },
+ { -1570.44f, 1167.57f, 159.50f, 2.20f, 64, TB_GY_WARDENS_VIGIL, { NPC_TB_GY_SPIRIT_WARDENS_VIGIL_A, NPC_TB_GY_SPIRIT_WARDENS_VIGIL_H }, false },
+ { -1343.32f, 565.24f, 139.04f, 1.66f, 64, TB_GY_SLAGWORKS, { NPC_TB_GY_SPIRIT_SLAGWORKS_A, NPC_TB_GY_SPIRIT_SLAGWORKS_H }, false },
+ { -1052.02f, 1494.05f, 191.41f, 4.13f, 64, TB_GY_WEST_SPIRE, { NPC_TB_GY_SPIRIT_WEST_SPIRE_A, NPC_TB_GY_SPIRIT_WEST_SPIRE_H }, false },
+ { -1603.34f, 874.29f, 193.69f, 5.27f, 64, TB_GY_SOUTH_SPIRE, { NPC_TB_GY_SPIRIT_SOUTH_SPIRE_A, NPC_TB_GY_SPIRIT_SOUTH_SPIRE_H }, false },
+ { -943.66f, 572.36f, 157.54f, 1.74f, 64, TB_GY_EAST_SPIRE, { NPC_TB_GY_SPIRIT_EAST_SPIRE_A, NPC_TB_GY_SPIRIT_EAST_SPIRE_H }, false },
+};
+
+/* ####################### *
+ * Tol Barad capture point *
+ * ####################### */
+
+class TolBaradCapturePoint : public BfCapturePoint
+{
+ public:
+ TolBaradCapturePoint(BattlefieldTB* battlefield, TeamId teamInControl);
+
+ void ChangeTeam(TeamId /*oldteam*/) override;
+};
+
+/* ##################### *
+ * Tol Barad battlefield *
+ * ##################### */
+
+class TC_GAME_API BattlefieldTB : public Battlefield
+{
+ public:
+ ~BattlefieldTB();
+
+ void OnStartGrouping() override;
+ void OnBattleStart() override;
+ void OnBattleEnd(bool endByTimer) override;
+
+ void OnPlayerEnterZone(Player* player) override;
+ void OnPlayerLeaveZone(Player* player) override;
+
+ void OnPlayerJoinWar(Player* player) override;
+ void OnPlayerLeaveWar(Player* player) override;
+
+ bool Update(uint32 diff) override;
+
+ void OnCreatureCreate(Creature* creature) override;
+ //void OnCreatureRemove(Creature* creature) override;
+
+ void OnGameObjectCreate(GameObject* go) override;
+
+ void UpdateCapturedBaseCount();
+ //void UpdatedDestroyedTowerCount(TeamId team);
+
+ //void DoCompleteOrIncrementAchievement(uint32 achievement, Player* player, uint8 incrementNumber = 1) override;
+
+ bool SetupBattlefield() override;
+
+ void SendInitWorldStatesTo(Player* player);
+ void SendInitWorldStatesToAll() override;
+ void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override;
+ void UpdateWorldStates();
+
+ void HandleKill(Player* killer, Unit* victim) override;
+ //void OnUnitDeath(Unit* unit) override;
+ void PromotePlayer(Player* killer);
+ void RemoveAurasFromPlayer(Player* player);
+
+ void ProcessEvent(WorldObject* obj, uint32 eventId) override;
+
+ void TowerDamaged(TBTowerId tbTowerId);
+ void TowerDestroyed(TBTowerId tbTowerId);
+
+ // returns the graveyardId in the specified area.
+ //uint8 GetSpiritGraveyardId(uint32 areaId) const;
+
+ void UpdateNPCsAndGameObjects();
+ void CreateCapturePoints();
+
+ protected:
+ // Minutes till battle preparation warnings
+ bool warnedFiveMinutes;
+ bool warnedTwoMinutes;
+ bool warnedOneMinute;
+
+ uint32 m_saveTimer;
+
+ bool updatedNPCAndObjects;
+ uint32 m_updateObjectsTimer;
+
+ uint32 m_BonusTime;
+
+ GuidSet BattleInactiveNPCs;
+ GuidSet BattleInactiveGOs;
+
+ GuidSet TemporaryNPCs;
+ GuidSet TemporaryGOs;
+
+ GuidSet Towers;
+
+ uint8 m_iCellblockRandom;
+
+ ObjectGuid TBGatesGUID;
+ ObjectGuid TBDoorGUID;
+
+ ObjectGuid m_gateToTheHoleGUID;
+ ObjectGuid m_gateDBlockGUID;
+ ObjectGuid m_gateCursedDepthsGUID;
+};
+
+#endif
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 59584744a2a..0c71134359e 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -24,6 +24,7 @@
#include "Battlefield.h"
#include "BattlefieldMgr.h"
#include "BattlefieldWG.h"
+#include "BattlefieldTB.h"
#include "Battleground.h"
#include "BattlegroundMgr.h"
#include "BattlegroundScore.h"
@@ -8946,6 +8947,22 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
if (bg && bg->GetTypeID(true) == BATTLEGROUND_BFG)
bg->FillInitialWorldStates(packet);
break;
+ // Tol Barad Peninsula
+ case 5389:
+ if (sWorld->getBoolConfig(CONFIG_TOLBARAD_ENABLE))
+ {
+ packet.Worldstates.emplace_back(5385, sWorld->getWorldState(5385)); // TB_WS_ALLIANCE_CONTROLS_SHOW
+ packet.Worldstates.emplace_back(5384, sWorld->getWorldState(5384)); // TB_WS_HORDE_CONTROLS_SHOW
+ packet.Worldstates.emplace_back(5387, sWorld->getWorldState(5387)); // TB_WS_TIME_NEXT_BATTLE_SHOW
+ packet.Worldstates.emplace_back(5546, sWorld->getWorldState(5546)); // TB_WS_ALLIANCE_ATTACKING_SHOW
+ packet.Worldstates.emplace_back(5547, sWorld->getWorldState(5547)); // TB_WS_HORDE_ATTACKING_SHOW
+ }
+ break;
+ // Tol Barad
+ case 5095:
+ if (bf && bf->GetTypeId() == BATTLEFIELD_TB)
+ bf->FillInitialWorldStates(packet);
+ break;
// Wintergrasp
case 4197:
if (bf && bf->GetTypeId() == BATTLEFIELD_WG)
@@ -8991,6 +9008,17 @@ void Player::SendBattlefieldWorldStates() const
SendUpdateWorldState(ClockWorldState[1], uint32(time(nullptr) + timer));
}
}
+
+ if (sWorld->getBoolConfig(CONFIG_TOLBARAD_ENABLE))
+ {
+ if (Battlefield* tb = sBattlefieldMgr->GetBattlefieldByBattleId(BATTLEFIELD_BATTLEID_TB))
+ {
+ SendUpdateWorldState(TB_WS_FACTION_CONTROLLING, uint32(tb->GetDefenderTeam() + 1));
+ uint32 timer = tb->GetTimer() / 1000;
+ SendUpdateWorldState(TB_WS_TIME_BATTLE_END, uint32(tb->IsWarTime() ? uint32(time(nullptr) + timer) : 0));
+ SendUpdateWorldState(TB_WS_TIME_NEXT_BATTLE, uint32(!tb->IsWarTime() ? uint32(time(nullptr) + timer) : 0));
+ }
+ }
}
uint32 Player::GetXPRestBonus(uint32 xp)
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 6768eb10b46..dc785f3bddf 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -3111,6 +3111,10 @@ void SpellMgr::LoadSpellInfoCorrections()
//! HACK: This spell break quest complete for alliance and on retail not used °_O
const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->Effect = 0;
break;
+ case 85123: // Siege Cannon (Tol Barad)
+ const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS);
+ const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetA = SpellImplicitTargetInfo(TARGET_UNIT_SRC_AREA_ENTRY);
+ break;
// VIOLET HOLD SPELLS
//
case 54258: // Water Globule (Ichoron)
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 5513c8e94dd..37d35e5b46d 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1413,6 +1413,16 @@ void World::LoadConfigSettings(bool reload)
m_int_configs[CONFIG_WINTERGRASP_NOBATTLETIME] = sConfigMgr->GetIntDefault("Wintergrasp.NoBattleTimer", 150);
m_int_configs[CONFIG_WINTERGRASP_RESTART_AFTER_CRASH] = sConfigMgr->GetIntDefault("Wintergrasp.CrashRestartTimer", 10);
+ // Tol Barad battlefield
+ m_bool_configs[CONFIG_TOLBARAD_ENABLE] = sConfigMgr->GetBoolDefault("TolBarad.Enable", true);
+ m_int_configs[CONFIG_TOLBARAD_PLR_MAX] = sConfigMgr->GetIntDefault("TolBarad.PlayerMax", 100);
+ m_int_configs[CONFIG_TOLBARAD_PLR_MIN] = sConfigMgr->GetIntDefault("TolBarad.PlayerMin", 0);
+ m_int_configs[CONFIG_TOLBARAD_PLR_MIN_LVL] = sConfigMgr->GetIntDefault("TolBarad.PlayerMinLvl", 85);
+ m_int_configs[CONFIG_TOLBARAD_BATTLETIME] = sConfigMgr->GetIntDefault("TolBarad.BattleTimer", 15);
+ m_int_configs[CONFIG_TOLBARAD_BONUSTIME] = sConfigMgr->GetIntDefault("TolBarad.BonusTime", 5);
+ m_int_configs[CONFIG_TOLBARAD_NOBATTLETIME] = sConfigMgr->GetIntDefault("TolBarad.NoBattleTimer", 150);
+ m_int_configs[CONFIG_TOLBARAD_RESTART_AFTER_CRASH] = sConfigMgr->GetIntDefault("TolBarad.CrashRestartTimer", 10);
+
// Stats limits
m_bool_configs[CONFIG_STATS_LIMITS_ENABLE] = sConfigMgr->GetBoolDefault("Stats.Limits.Enable", false);
m_float_configs[CONFIG_STATS_LIMITS_DODGE] = sConfigMgr->GetFloatDefault("Stats.Limits.Dodge", 95.0f);
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index 1cbcb747279..ef8668f2aa7 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -167,6 +167,7 @@ enum WorldBoolConfigs
CONFIG_WARDEN_ENABLED,
CONFIG_ENABLE_MMAPS,
CONFIG_WINTERGRASP_ENABLE,
+ CONFIG_TOLBARAD_ENABLE,
CONFIG_UI_QUESTLEVELS_IN_DIALOGS, // Should we add quest levels to the title in the NPC dialogs?
CONFIG_EVENT_ANNOUNCE,
CONFIG_STATS_LIMITS_ENABLE,
@@ -363,6 +364,13 @@ enum WorldIntConfigs
CONFIG_WINTERGRASP_BATTLETIME,
CONFIG_WINTERGRASP_NOBATTLETIME,
CONFIG_WINTERGRASP_RESTART_AFTER_CRASH,
+ CONFIG_TOLBARAD_PLR_MAX,
+ CONFIG_TOLBARAD_PLR_MIN,
+ CONFIG_TOLBARAD_PLR_MIN_LVL,
+ CONFIG_TOLBARAD_BATTLETIME,
+ CONFIG_TOLBARAD_BONUSTIME,
+ CONFIG_TOLBARAD_NOBATTLETIME,
+ CONFIG_TOLBARAD_RESTART_AFTER_CRASH,
CONFIG_GUILD_SAVE_INTERVAL,
CONFIG_GUILD_UNDELETABLE_LEVEL,
CONFIG_PACKET_SPOOF_POLICY,
diff --git a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp
index adf7219d2a3..123d4102794 100644
--- a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp
+++ b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp
@@ -193,6 +193,7 @@ void AddSC_stormwind_city();
void AddSC_stranglethorn_vale();
void AddSC_swamp_of_sorrows();
void AddSC_tirisfal_glades();
+void AddSC_tol_barad();
void AddSC_undercity();
void AddSC_western_plaguelands();
void AddSC_wetlands();
@@ -379,6 +380,7 @@ void AddEasternKingdomsScripts()
AddSC_stranglethorn_vale();
AddSC_swamp_of_sorrows();
AddSC_tirisfal_glades();
+ AddSC_tol_barad();
AddSC_undercity();
AddSC_western_plaguelands();
AddSC_wetlands();
diff --git a/src/server/scripts/EasternKingdoms/zone_tol_barad.cpp b/src/server/scripts/EasternKingdoms/zone_tol_barad.cpp
new file mode 100644
index 00000000000..54534a3d301
--- /dev/null
+++ b/src/server/scripts/EasternKingdoms/zone_tol_barad.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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 "BattlefieldMgr.h"
+#include "BattlefieldTB.h"
+#include "Battlefield.h"
+#include "ScriptSystem.h"
+#include "WorldSession.h"
+#include "ScriptedCreature.h"
+#include "ScriptedGossip.h"
+#include "SpellScript.h"
+#include "Player.h"
+
+enum TBSpiritGuide
+{
+ SPELL_CHANNEL_SPIRIT_HEAL = 22011,
+
+ GOSSIP_OPTION_ID_SLAGWORKS = 0,
+ GOSSIP_OPTION_ID_IRONCLAD_GARRISON = 1,
+ GOSSIP_OPTION_ID_WARDENS_VIGIL = 2,
+ GOSSIP_OPTION_ID_EAST_SPIRE = 3,
+ GOSSIP_OPTION_ID_WEST_SPIRE = 4,
+ GOSSIP_OPTION_ID_SOUTH_SPIRE = 5,
+};
+
+class npc_tb_spirit_guide : public CreatureScript
+{
+ public:
+ npc_tb_spirit_guide() : CreatureScript("npc_tb_spirit_guide") { }
+
+ struct npc_tb_spirit_guideAI : public ScriptedAI
+ {
+ npc_tb_spirit_guideAI(Creature* creature) : ScriptedAI(creature) { }
+
+ void UpdateAI(uint32 /*diff*/) override
+ {
+ if (!me->HasUnitState(UNIT_STATE_CASTING))
+ DoCast(me, SPELL_CHANNEL_SPIRIT_HEAL);
+ }
+
+ void sGossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
+ {
+ player->PlayerTalkClass->SendCloseGossip();
+
+ uint32 areaId = 0;
+ switch (gossipListId)
+ {
+ case GOSSIP_OPTION_ID_SLAGWORKS:
+ areaId = TB_GY_SLAGWORKS;
+ break;
+ case GOSSIP_OPTION_ID_IRONCLAD_GARRISON:
+ areaId = TB_GY_IRONCLAD_GARRISON;
+ break;
+ case GOSSIP_OPTION_ID_WARDENS_VIGIL:
+ areaId = TB_GY_WARDENS_VIGIL;
+ break;
+ case GOSSIP_OPTION_ID_EAST_SPIRE:
+ areaId = TB_GY_EAST_SPIRE;
+ break;
+ case GOSSIP_OPTION_ID_WEST_SPIRE:
+ areaId = TB_GY_WEST_SPIRE;
+ break;
+ case GOSSIP_OPTION_ID_SOUTH_SPIRE:
+ areaId = TB_GY_SOUTH_SPIRE;
+ break;
+ default:
+ return;
+ }
+
+ if (WorldSafeLocsEntry const* safeLoc = sWorldSafeLocsStore.LookupEntry(areaId))
+ player->TeleportTo(safeLoc->MapID, safeLoc->Loc.X, safeLoc->Loc.Y, safeLoc->Loc.Z, 0);
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return new npc_tb_spirit_guideAI(creature);
+ }
+};
+
+// 85123 - Siege Cannon - selects random target
+class spell_siege_cannon : public SpellScriptLoader
+{
+public:
+ spell_siege_cannon() : SpellScriptLoader("spell_siege_cannon") { }
+
+ class spell_siege_cannon_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_siege_cannon_SpellScript);
+
+ void SelectRandomTarget(std::list<WorldObject*>& targets)
+ {
+ if (targets.empty())
+ return;
+
+ WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets);
+ targets.clear();
+ targets.push_back(target);
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_siege_cannon_SpellScript::SelectRandomTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_siege_cannon_SpellScript();
+ }
+};
+
+void AddSC_tol_barad()
+{
+ new npc_tb_spirit_guide();
+ new spell_siege_cannon();
+}
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
index eeb2be26a23..20de1aac57f 100644
--- a/src/server/worldserver/worldserver.conf.dist
+++ b/src/server/worldserver/worldserver.conf.dist
@@ -2532,6 +2532,64 @@ Wintergrasp.NoBattleTimer = 150
Wintergrasp.CrashRestartTimer = 10
#
+# TolBarad.Enable
+# Description: Enable the Tol Barad battlefield.
+# Default: 0 - (Disabled)
+# 1 - (Enabled, Experimental as in incomplete, bugged and with crashes)
+
+TolBarad.Enable = 0
+
+#
+# TolBarad.PlayerMax
+# Description: Maximum number of players allowed in Tol Barad.
+# Default: 100
+
+TolBarad.PlayerMax = 100
+
+#
+# TolBarad.PlayerMin
+# Description: Minimum number of players required for Tol Barad.
+# Default: 0
+
+TolBarad.PlayerMin = 0
+
+#
+# TolBarad.PlayerMinLvl
+# Description: Required character level for the Tol Barad battle.
+# Default: 85
+
+TolBarad.PlayerMinLvl = 85
+
+#
+# TolBarad.BattleTimer
+# Description: Time (in minutes) for the Tol Barad battle to last.
+# Default: 15
+
+TolBarad.BattleTimer = 15
+
+#
+# TolBarad.BonusTime
+# Description: Bonus time (in minutes) for each tower destroyed in Tol Barad battle.
+# Default: 5
+
+TolBarad.BonusTime = 5
+
+#
+# TolBarad.NoBattleTimer
+# Description: Time (in minutes) between TolBarad battles.
+# Default: 150
+
+TolBarad.NoBattleTimer = 150
+
+#
+# TolBarad.CrashRestartTimer
+# Description: Time (in minutes) to delay the restart of TolBarad if the world server
+# crashed during a running battle.
+# Default: 10
+
+TolBarad.CrashRestartTimer = 10
+
+#
###################################################################################################
###################################################################################################