diff options
author | Mihapro <Mihapro@users.noreply.github.com> | 2016-07-15 14:39:41 +0200 |
---|---|---|
committer | Aokromes <Aokromes@users.noreply.github.com> | 2016-07-15 14:39:41 +0200 |
commit | b7c2d309e666a21877977597e17ab9b4728fff0b (patch) | |
tree | 7cb6f1033ce0d451d8e275d59c11cdfc7b23744c /src | |
parent | a5b6d1992a50d4eaf4a7e13dc27e4c876467341a (diff) |
[6.x] Core/Battlefield: Tol Barad (#17124)
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Battlefield/Battlefield.h | 4 | ||||
-rw-r--r-- | src/server/game/Battlefield/BattlefieldMgr.cpp | 4 | ||||
-rw-r--r-- | src/server/game/Battlefield/Zones/BattlefieldTB.cpp | 869 | ||||
-rw-r--r-- | src/server/game/Battlefield/Zones/BattlefieldTB.h | 728 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 28 | ||||
-rw-r--r-- | src/server/game/Spells/SpellMgr.cpp | 4 | ||||
-rw-r--r-- | src/server/game/World/World.cpp | 10 | ||||
-rw-r--r-- | src/server/game/World/World.h | 8 | ||||
-rw-r--r-- | src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp | 2 | ||||
-rw-r--r-- | src/server/scripts/EasternKingdoms/zone_tol_barad.cpp | 131 | ||||
-rw-r--r-- | src/server/worldserver/worldserver.conf.dist | 58 |
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 + +# ################################################################################################### ################################################################################################### |