From 49523a74a4c28e5ae17f9a8352aa8224b765b7d8 Mon Sep 17 00:00:00 2001 From: Carbenium Date: Mon, 22 Jun 2020 16:10:34 +0200 Subject: Battlefields: Move BF scripts out of game This commit introduces the usual script interface for battlefields. (cherry picked from commit f7faf20254a120a90b8ee8eb55a284a6351aabc3) --- src/server/game/Battlefield/Battlefield.h | 5 +- src/server/game/Battlefield/BattlefieldMgr.cpp | 62 +- .../game/Battlefield/Zones/BattlefieldTB.cpp | 872 --------- src/server/game/Battlefield/Zones/BattlefieldTB.h | 716 -------- .../game/Battlefield/Zones/BattlefieldWG.cpp | 1853 ------------------- src/server/game/Battlefield/Zones/BattlefieldWG.h | 581 ------ src/server/game/Entities/Player/Player.cpp | 20 +- src/server/game/Miscellaneous/SharedDefines.h | 70 + src/server/game/Scripting/ScriptMgr.cpp | 22 + src/server/game/Scripting/ScriptMgr.h | 16 + src/server/game/Spells/SpellMgr.cpp | 1 - src/server/scripts/Battlefield/BattlefieldTB.cpp | 889 ++++++++++ src/server/scripts/Battlefield/BattlefieldTB.h | 632 +++++++ src/server/scripts/Battlefield/BattlefieldWG.cpp | 1870 ++++++++++++++++++++ src/server/scripts/Battlefield/BattlefieldWG.h | 575 ++++++ .../Battlefield/battlefield_script_loader.cpp | 25 + .../scripts/EasternKingdoms/zone_tol_barad.cpp | 2 +- src/server/scripts/Northrend/zone_wintergrasp.cpp | 6 +- 18 files changed, 4153 insertions(+), 4064 deletions(-) delete mode 100644 src/server/game/Battlefield/Zones/BattlefieldTB.cpp delete mode 100644 src/server/game/Battlefield/Zones/BattlefieldTB.h delete mode 100644 src/server/game/Battlefield/Zones/BattlefieldWG.cpp delete mode 100644 src/server/game/Battlefield/Zones/BattlefieldWG.h create mode 100644 src/server/scripts/Battlefield/BattlefieldTB.cpp create mode 100644 src/server/scripts/Battlefield/BattlefieldTB.h create mode 100644 src/server/scripts/Battlefield/BattlefieldWG.cpp create mode 100644 src/server/scripts/Battlefield/BattlefieldWG.h create mode 100644 src/server/scripts/Battlefield/battlefield_script_loader.cpp (limited to 'src') diff --git a/src/server/game/Battlefield/Battlefield.h b/src/server/game/Battlefield/Battlefield.h index 192340e7e31..f1013ae7365 100644 --- a/src/server/game/Battlefield/Battlefield.h +++ b/src/server/game/Battlefield/Battlefield.h @@ -25,8 +25,9 @@ enum BattlefieldTypes { - BATTLEFIELD_WG, // Wintergrasp - BATTLEFIELD_TB // Tol Barad (cataclysm) + BATTLEFIELD_WG = 1, // Wintergrasp + BATTLEFIELD_TB = 2, // Tol Barad (cataclysm) + BATTLEFIELD_MAX }; enum BattlefieldIDs diff --git a/src/server/game/Battlefield/BattlefieldMgr.cpp b/src/server/game/Battlefield/BattlefieldMgr.cpp index 2498678c3e2..5f42b90b22b 100644 --- a/src/server/game/Battlefield/BattlefieldMgr.cpp +++ b/src/server/game/Battlefield/BattlefieldMgr.cpp @@ -16,10 +16,11 @@ */ #include "BattlefieldMgr.h" -#include "BattlefieldWG.h" -#include "BattlefieldTB.h" +#include "DatabaseEnv.h" +#include "ObjectMgr.h" #include "Log.h" #include "Player.h" +#include "ScriptMgr.h" BattlefieldMgr::BattlefieldMgr() { @@ -42,31 +43,44 @@ BattlefieldMgr* BattlefieldMgr::instance() void BattlefieldMgr::InitBattlefield() { - Battlefield* wg = new BattlefieldWG(); - // respawn, init variables - if (!wg->SetupBattlefield()) - { - TC_LOG_INFO("bg.battlefield", "Battlefield: Wintergrasp init failed."); - delete wg; - } - else - { - _battlefieldSet.push_back(wg); - TC_LOG_INFO("bg.battlefield", "Battlefield: Wintergrasp successfully initiated."); - } + uint32 oldMSTime = getMSTime(); - Battlefield* tb = new BattlefieldTB; - // respawn, init variables - if (!tb->SetupBattlefield()) - { - TC_LOG_DEBUG("bg.battlefield", "Battlefield: Tol Barad init failed."); - delete tb; - } - else + uint32 count = 0; + + if (QueryResult result = WorldDatabase.Query("SELECT TypeId, ScriptName FROM battlefield_template")) { - _battlefieldSet.push_back(tb); - TC_LOG_DEBUG("bg.battlefield", "Battlefield: Tol Barad successfully initiated."); + do + { + Field* fields = result->Fetch(); + + uint32 typeId = fields[0].GetUInt8(); + + if (typeId >= BATTLEFIELD_MAX) + { + TC_LOG_ERROR("sql.sql", "BattlefieldMgr::InitBattlefield: Invalid TypeId value %u in battlefield_template, skipped.", typeId); + continue; + } + + uint32 scriptId = sObjectMgr->GetScriptId(fields[1].GetString()); + + Battlefield* bf = sScriptMgr->CreateBattlefield(scriptId); + + if (!bf->SetupBattlefield()) + { + TC_LOG_INFO("bg.battlefield", "Setting up battlefield with TypeId %u failed.", typeId); + delete bf; + } + else + { + _battlefieldSet.push_back(bf); + TC_LOG_INFO("bg.battlefield", "Setting up battlefield with TypeId %u succeeded.", typeId); + } + + ++count; + } while (result->NextRow()); } + + TC_LOG_INFO("server.loading", ">> Loaded %u battlefields in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } 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 deleted file mode 100644 index d40d794506d..00000000000 --- a/src/server/game/Battlefield/Zones/BattlefieldTB.cpp +++ /dev/null @@ -1,872 +0,0 @@ -/* -* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information -* -* This program is free software; you can redistribute it and/or modify it -* under the terms of the GNU General Public License as published by the -* Free Software Foundation; either version 2 of the License, or (at your -* option) any later version. -* -* This program is distributed in the hope that it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along -* with this program. If not, see . -*/ - -// 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 "Battleground.h" -#include "CreatureTextMgr.h" -#include "GameObject.h" -#include "GameTime.h" -#include "MapManager.h" -#include "ObjectAccessor.h" -#include "Player.h" -#include "Random.h" -#include "SpellAuras.h" -#include "TemporarySummon.h" -#include "World.h" -#include "WorldStatePackets.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, uint32(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].pos, QuaternionData::fromEulerAnglesZYX(TBCapturePoints[i].pos.GetOrientation(), 0.0f, 0.0f))) - { - 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].pos, QuaternionData::fromEulerAnglesZYX(TBTowers[i].pos.GetOrientation(), 0.0f, 0.0f))) - 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].pos)) - 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->GetTeamId() == GetAttackerTeam() && GetData(BATTLEFIELD_TB_DATA_TOWERS_DESTROYED) > 0) - player->CastSpell(player, SPELL_TOWER_ATTACK_BONUS, CastSpellExtraArgs(TRIGGERED_FULL_MASK).AddSpellMod(SPELLVALUE_AURA_STACK, GetData(BATTLEFIELD_TB_DATA_TOWERS_DESTROYED))); -} - - -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() ? GameTime::GetGameTime() + (m_Timer / 1000) : 0)); - packet.Worldstates.emplace_back(uint32(TB_WS_TIME_NEXT_BATTLE), int32(!IsWarTime() ? GameTime::GetGameTime() + (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, uint32(IsWarTime() ? 1 : 0)); - sWorld->setWorldState(TB_WS_ALLIANCE_CONTROLS_SHOW, uint32(!IsWarTime() && GetDefenderTeam() == TEAM_ALLIANCE ? 1 : 0)); - sWorld->setWorldState(TB_WS_HORDE_CONTROLS_SHOW, uint32(!IsWarTime() && GetDefenderTeam() == TEAM_HORDE ? 1 : 0)); - sWorld->setWorldState(TB_WS_ALLIANCE_ATTACKING_SHOW, uint32(IsWarTime() && GetAttackerTeam() == TEAM_ALLIANCE ? 1 : 0)); - sWorld->setWorldState(TB_WS_HORDE_ATTACKING_SHOW, uint32(IsWarTime() && GetAttackerTeam() == TEAM_HORDE ? 1 : 0)); - sWorld->setWorldState(TB_WS_TIME_NEXT_BATTLE, uint32(!IsWarTime() ? m_Timer : 0)); - sWorld->setWorldState(TB_WS_TIME_NEXT_BATTLE_SHOW, uint32(!IsWarTime() ? 1 : 0)); - - // Tol Barad - for (uint8 team = 0; team < PVP_TEAMS_COUNT; team++) - for (ObjectGuid const& guid : m_players[team]) - if (Player* player = ObjectAccessor::FindPlayer(guid)) - 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 < PVP_TEAMS_COUNT; ++team) - for (ObjectGuid const& guid : m_players[team]) - if (Player* player = ObjectAccessor::FindPlayer(guid)) - 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 (ObjectGuid const& guid : m_PlayersInWar[team]) - if (Player* player = ObjectAccessor::FindPlayer(guid)) - 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(CELLBLOCK_THE_HOLE, CELLBLOCK_CURSED_DEPTHS) : uint8(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].pos, QuaternionData::fromEulerAnglesZYX(TBCapturePoints[i].pos.GetOrientation(), 0.0f, 0.0f))) - { - 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])) - 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])) - 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].pos)) - TemporaryNPCs.insert(creature->GetGUID()); - - if (Creature* creature = SpawnCreature(RandomQuestgivers[GetDefenderTeam()][m_iCellblockRandom], RandomQuestgiverPos)) - TemporaryNPCs.insert(creature->GetGUID()); - - // Spawn portals - for (uint8 i = 0; i < TB_PORTAL_MAX; i++) - if (GameObject* go = SpawnGameObject(TBPortalEntry[GetDefenderTeam()], TBPortals[i], QuaternionData::fromEulerAnglesZYX(TBPortals[i].GetOrientation(), 0.0f, 0.0f))) - 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])) - 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], QuaternionData::fromEulerAnglesZYX(TBBanners[i].GetOrientation(), 0.0f, 0.0f))) - 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, WorldObject* /*invoker*/) -{ - 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(GameTime::GetGameTime() + (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 (ObjectGuid const& guid : m_PlayersInWar[GetAttackerTeam()]) - if (Player* player = ObjectAccessor::FindPlayer(guid)) - player->CastSpell(player, SPELL_TOWER_ATTACK_BONUS, CastSpellExtraArgs(TRIGGERED_FULL_MASK).AddSpellMod(SPELLVALUE_AURA_STACK, GetData(BATTLEFIELD_TB_DATA_TOWERS_DESTROYED))); - - // 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 (ObjectGuid const& guid : m_PlayersInWar[killerTeam]) - if (Player* player = ObjectAccessor::FindPlayer(guid)) - 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]); - /* fallthrough */ - 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]); - /* fallthrough */ - 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(nullptr, EVENT_COUNT_CAPTURED_BASE, nullptr); -} diff --git a/src/server/game/Battlefield/Zones/BattlefieldTB.h b/src/server/game/Battlefield/Zones/BattlefieldTB.h deleted file mode 100644 index f74a1d2f608..00000000000 --- a/src/server/game/Battlefield/Zones/BattlefieldTB.h +++ /dev/null @@ -1,716 +0,0 @@ -/* -* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information -* -* This program is free software; you can redistribute it and/or modify it -* under the terms of the GNU General Public License as published by the -* Free Software Foundation; either version 2 of the License, or (at your -* option) any later version. -* -* This program is distributed in the hope that it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along -* with this program. If not, see . -*/ - -#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[PVP_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[PVP_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 -{ - Position pos; - 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[PVP_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 -{ - Position pos; - 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 -{ - Position pos; - uint32 entry; - uint32 textDamaged; - uint32 textDestroyed; - uint32 wsIntact[PVP_TEAMS_COUNT]; - uint32 wsDamaged[PVP_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[PVP_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[PVP_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 -{ - Position pos; - uint32 phaseId; - uint32 gyid; - uint32 spiritEntry[PVP_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, WorldObject* invoker) 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/Battlefield/Zones/BattlefieldWG.cpp b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp deleted file mode 100644 index daedc0e1958..00000000000 --- a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp +++ /dev/null @@ -1,1853 +0,0 @@ -/* - * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - */ - -/// @todo Implement proper support for vehicle+player teleportation -/// @todo Use spell victory/defeat in wg instead of RewardMarkOfHonor() && RewardHonor -/// @todo Add proper implement of achievement - -#include "BattlefieldWG.h" -#include "AchievementMgr.h" -#include "Battleground.h" -#include "CreatureTextMgr.h" -#include "GameObject.h" -#include "GameTime.h" -#include "DB2Stores.h" -#include "Log.h" -#include "MapManager.h" -#include "ObjectAccessor.h" -#include "Player.h" -#include "Random.h" -#include "SpellAuras.h" -#include "TemporarySummon.h" -#include "World.h" -#include "WorldSession.h" -#include "WorldStatePackets.h" - -struct BfWGCoordGY -{ - Position Pos; - uint32 GraveyardID; - uint32 TextID; // for gossip menu - TeamId StartControl; -}; - -// 7 in sql, 7 in header -BfWGCoordGY const WGGraveyard[BATTLEFIELD_WG_GRAVEYARD_MAX] = -{ - { { 5104.750f, 2300.940f, 368.579f, 0.733038f }, 1329, BATTLEFIELD_WG_GOSSIPTEXT_GY_NE, TEAM_NEUTRAL }, - { { 5099.120f, 3466.036f, 368.484f, 5.317802f }, 1330, BATTLEFIELD_WG_GOSSIPTEXT_GY_NW, TEAM_NEUTRAL }, - { { 4314.648f, 2408.522f, 392.642f, 6.268125f }, 1333, BATTLEFIELD_WG_GOSSIPTEXT_GY_SE, TEAM_NEUTRAL }, - { { 4331.716f, 3235.695f, 390.251f, 0.008500f }, 1334, BATTLEFIELD_WG_GOSSIPTEXT_GY_SW, TEAM_NEUTRAL }, - { { 5537.986f, 2897.493f, 517.057f, 4.819249f }, 1285, BATTLEFIELD_WG_GOSSIPTEXT_GY_KEEP, TEAM_NEUTRAL }, - { { 5032.454f, 3711.382f, 372.468f, 3.971623f }, 1331, BATTLEFIELD_WG_GOSSIPTEXT_GY_HORDE, TEAM_HORDE }, - { { 5140.790f, 2179.120f, 390.950f, 1.972220f }, 1332, BATTLEFIELD_WG_GOSSIPTEXT_GY_ALLIANCE, TEAM_ALLIANCE }, -}; - -uint32 const ClockWorldState[] = { WS_BATTLEFIELD_WG_TIME_BATTLE_END, WS_BATTLEFIELD_WG_TIME_NEXT_BATTLE }; -uint32 const WintergraspFaction[] = { FACTION_ALLIANCE_GENERIC_WG, FACTION_HORDE_GENERIC_WG, FACTION_FRIENDLY }; - -Position const WintergraspStalkerPos = { 4948.985f, 2937.789f, 550.5172f, 1.815142f }; - -Position const WintergraspRelicPos = { 5440.379f, 2840.493f, 430.2816f, -1.832595f }; -QuaternionData const WintergraspRelicRot = { 0.f, 0.f, -0.7933531f, 0.6087617f }; - -uint8 const WG_MAX_OBJ = 32; -uint8 const WG_MAX_TURRET = 15; -uint8 const WG_MAX_TELEPORTER = 12; -uint8 const WG_MAX_WORKSHOP = 6; -uint8 const WG_MAX_TOWER = 7; - -// ***************************************************** -// ************ Destructible (Wall, Tower..) *********** -// ***************************************************** - -struct WintergraspBuildingSpawnData -{ - uint32 entry; - uint32 WorldState; - Position pos; - QuaternionData rot; - WintergraspGameObjectBuildingType type; -}; - -WintergraspBuildingSpawnData const WGGameObjectBuilding[WG_MAX_OBJ] = -{ - // Wall (Not spawned in db) - // Entry WS X Y Z O rX rY rZ rW Type - { 190219, 3749, { 5371.457f, 3047.472f, 407.5710f, 3.14159300f }, { 0.f, 0.f, -1.000000000f, 0.00000000f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, - { 190220, 3750, { 5331.264f, 3047.105f, 407.9228f, 0.05235888f }, { 0.f, 0.f, 0.026176450f, 0.99965730f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, - { 191795, 3764, { 5385.841f, 2909.490f, 409.7127f, 0.00872424f }, { 0.f, 0.f, 0.004362106f, 0.99999050f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, - { 191796, 3772, { 5384.452f, 2771.835f, 410.2704f, 3.14159300f }, { 0.f, 0.f, -1.000000000f, 0.00000000f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, - { 191799, 3762, { 5371.436f, 2630.610f, 408.8163f, 3.13285800f }, { 0.f, 0.f, 0.999990500f, 0.00436732f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, - { 191800, 3766, { 5301.838f, 2909.089f, 409.8661f, 0.00872424f }, { 0.f, 0.f, 0.004362106f, 0.99999050f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, - { 191801, 3770, { 5301.063f, 2771.411f, 409.9014f, 3.14159300f }, { 0.f, 0.f, -1.000000000f, 0.00000000f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, - { 191802, 3751, { 5280.197f, 2995.583f, 408.8249f, 1.61442800f }, { 0.f, 0.f, 0.722363500f, 0.69151360f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, - { 191803, 3752, { 5279.136f, 2956.023f, 408.6041f, 1.57079600f }, { 0.f, 0.f, 0.707106600f, 0.70710690f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, - { 191804, 3767, { 5278.685f, 2882.513f, 409.5388f, 1.57079600f }, { 0.f, 0.f, 0.707106600f, 0.70710690f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, - { 191806, 3769, { 5279.502f, 2798.945f, 409.9983f, 1.57079600f }, { 0.f, 0.f, 0.707106600f, 0.70710690f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, - { 191807, 3759, { 5279.937f, 2724.766f, 409.9452f, 1.56207000f }, { 0.f, 0.f, 0.704014800f, 0.71018530f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, - { 191808, 3760, { 5279.601f, 2683.786f, 409.8488f, 1.55334100f }, { 0.f, 0.f, 0.700908700f, 0.71325110f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, - { 191809, 3761, { 5330.955f, 2630.777f, 409.2826f, 3.13285800f }, { 0.f, 0.f, 0.999990500f, 0.00436732f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, - { 190369, 3753, { 5256.085f, 2933.963f, 409.3571f, 3.13285800f }, { 0.f, 0.f, 0.999990500f, 0.00436732f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, - { 190370, 3758, { 5257.463f, 2747.327f, 409.7427f, -3.13285800f }, { 0.f, 0.f, -0.999990500f, 0.00436732f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, - { 190371, 3754, { 5214.960f, 2934.089f, 409.1905f, -0.00872424f }, { 0.f, 0.f, -0.004362106f, 0.99999050f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, - { 190372, 3757, { 5215.821f, 2747.566f, 409.1884f, -3.13285800f }, { 0.f, 0.f, -0.999990500f, 0.00436732f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, - { 190374, 3755, { 5162.273f, 2883.043f, 410.2556f, 1.57952200f }, { 0.f, 0.f, 0.710185100f, 0.70401500f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, - { 190376, 3756, { 5163.724f, 2799.838f, 409.2270f, 1.57952200f }, { 0.f, 0.f, 0.710185100f, 0.70401500f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, - - // Tower of keep (Not spawned in db) - { 190221, 3711, { 5281.154f, 3044.588f, 407.8434f, 3.115388f }, { 0.f, 0.f, 0.9999142f, 0.013101960f }, BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER }, // NW - { 190373, 3713, { 5163.757f, 2932.228f, 409.1904f, 3.124123f }, { 0.f, 0.f, 0.9999619f, 0.008734641f }, BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER }, // SW - { 190377, 3714, { 5166.397f, 2748.368f, 409.1884f, -1.570796f }, { 0.f, 0.f, -0.7071066f, 0.707106900f }, BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER }, // SE - { 190378, 3712, { 5281.192f, 2632.479f, 409.0985f, -1.588246f }, { 0.f, 0.f, -0.7132492f, 0.700910500f }, BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER }, // NE - - // Wall (with passage) (Not spawned in db) - { 191797, 3765, { 5343.290f, 2908.860f, 409.5757f, 0.00872424f }, { 0.f, 0.f, 0.004362106f, 0.9999905f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, - { 191798, 3771, { 5342.719f, 2771.386f, 409.6249f, 3.14159300f }, { 0.f, 0.f, -1.000000000f, 0.0000000f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, - { 191805, 3768, { 5279.126f, 2840.797f, 409.7826f, 1.57952200f }, { 0.f, 0.f, 0.710185100f, 0.7040150f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, - - // South tower (Not spawned in db) - { 190356, 3704, { 4557.173f, 3623.943f, 395.8828f, 1.675516f }, { 0.f, 0.f, 0.7431450f, 0.669130400f }, BATTLEFIELD_WG_OBJECTTYPE_TOWER }, // W - { 190357, 3705, { 4398.172f, 2822.497f, 405.6270f, -3.124123f }, { 0.f, 0.f, -0.9999619f, 0.008734641f }, BATTLEFIELD_WG_OBJECTTYPE_TOWER }, // S - { 190358, 3706, { 4459.105f, 1944.326f, 434.9912f, -2.002762f }, { 0.f, 0.f, -0.8422165f, 0.539139500f }, BATTLEFIELD_WG_OBJECTTYPE_TOWER }, // E - - // Door of forteress (Not spawned in db) - { GO_WINTERGRASP_FORTRESS_GATE, 3763, { 5162.991f, 2841.232f, 410.1892f, -3.132858f }, { 0.f, 0.f, -0.9999905f, 0.00436732f }, BATTLEFIELD_WG_OBJECTTYPE_DOOR }, - - // Last door (Not spawned in db) - { GO_WINTERGRASP_VAULT_GATE, 3773, { 5397.108f, 2841.54f, 425.9014f, 3.141593f }, { 0.f, 0.f, -1.f, 0.f }, BATTLEFIELD_WG_OBJECTTYPE_DOOR_LAST }, -}; - -struct StaticWintergraspTowerInfo -{ - uint8 TowerId; - - struct - { - uint8 Damaged; - uint8 Destroyed; - } TextIds; -}; - -StaticWintergraspTowerInfo const TowerData[WG_MAX_TOWER] = -{ - { BATTLEFIELD_WG_TOWER_FORTRESS_NW, { BATTLEFIELD_WG_TEXT_NW_KEEPTOWER_DAMAGE, BATTLEFIELD_WG_TEXT_NW_KEEPTOWER_DESTROY } }, - { BATTLEFIELD_WG_TOWER_FORTRESS_SW, { BATTLEFIELD_WG_TEXT_SW_KEEPTOWER_DAMAGE, BATTLEFIELD_WG_TEXT_SW_KEEPTOWER_DESTROY } }, - { BATTLEFIELD_WG_TOWER_FORTRESS_SE, { BATTLEFIELD_WG_TEXT_SE_KEEPTOWER_DAMAGE, BATTLEFIELD_WG_TEXT_SE_KEEPTOWER_DESTROY } }, - { BATTLEFIELD_WG_TOWER_FORTRESS_NE, { BATTLEFIELD_WG_TEXT_NE_KEEPTOWER_DAMAGE, BATTLEFIELD_WG_TEXT_NE_KEEPTOWER_DESTROY } }, - { BATTLEFIELD_WG_TOWER_SHADOWSIGHT, { BATTLEFIELD_WG_TEXT_WESTERN_TOWER_DAMAGE, BATTLEFIELD_WG_TEXT_WESTERN_TOWER_DESTROY } }, - { BATTLEFIELD_WG_TOWER_WINTER_S_EDGE, { BATTLEFIELD_WG_TEXT_SOUTHERN_TOWER_DAMAGE, BATTLEFIELD_WG_TEXT_SOUTHERN_TOWER_DESTROY } }, - { BATTLEFIELD_WG_TOWER_FLAMEWATCH, { BATTLEFIELD_WG_TEXT_EASTERN_TOWER_DAMAGE, BATTLEFIELD_WG_TEXT_EASTERN_TOWER_DESTROY } } -}; - -Position const WGTurret[WG_MAX_TURRET] = -{ - { 5391.19f, 3060.8f, 419.616f, 1.69557f }, - { 5266.75f, 2976.5f, 421.067f, 3.20354f }, - { 5234.86f, 2948.8f, 420.88f, 1.61311f }, - { 5323.05f, 2923.7f, 421.645f, 1.5817f }, - { 5363.82f, 2923.87f, 421.709f, 1.60527f }, - { 5264.04f, 2861.34f, 421.587f, 3.21142f }, - { 5264.68f, 2819.78f, 421.656f, 3.15645f }, - { 5322.16f, 2756.69f, 421.646f, 4.69978f }, - { 5363.78f, 2756.77f, 421.629f, 4.78226f }, - { 5236.2f, 2732.68f, 421.649f, 4.72336f }, - { 5265.02f, 2704.63f, 421.7f, 3.12507f }, - { 5350.87f, 2616.03f, 421.243f, 4.72729f }, - { 5390.95f, 2615.5f, 421.126f, 4.6409f }, - { 5148.8f, 2820.24f, 421.621f, 3.16043f }, - { 5147.98f, 2861.93f, 421.63f, 3.18792f }, -}; - -struct WintergraspObjectPositionData -{ - Position Pos; - uint32 HordeEntry; - uint32 AllianceEntry; -}; - -struct WintergraspGameObjectData -{ - Position Pos; - QuaternionData Rot; - uint32 HordeEntry; - uint32 AllianceEntry; -}; - -WintergraspGameObjectData const WGPortalDefenderData[WG_MAX_TELEPORTER] = -{ - // Player teleporter - { { 5153.408f, 2901.349f, 409.1913f, -0.06981169f }, { 0.f, 0.f, -0.03489876f, 0.9993908f }, 190763, 191575 }, - { { 5268.698f, 2666.421f, 409.0985f, -0.71558490f }, { 0.f, 0.f, -0.35020730f, 0.9366722f }, 190763, 191575 }, - { { 5197.050f, 2944.814f, 409.1913f, 2.33874000f }, { 0.f, 0.f, 0.92050460f, 0.3907318f }, 190763, 191575 }, - { { 5196.671f, 2737.345f, 409.1892f, -2.93213900f }, { 0.f, 0.f, -0.99452110f, 0.1045355f }, 190763, 191575 }, - { { 5314.580f, 3055.852f, 408.8620f, 0.54105060f }, { 0.f, 0.f, 0.26723770f, 0.9636307f }, 190763, 191575 }, - { { 5391.277f, 2828.094f, 418.6752f, -2.16420600f }, { 0.f, 0.f, -0.88294700f, 0.4694727f }, 190763, 191575 }, - { { 5153.931f, 2781.671f, 409.2455f, 1.65806200f }, { 0.f, 0.f, 0.73727700f, 0.6755905f }, 190763, 191575 }, - { { 5311.445f, 2618.931f, 409.0916f, -2.37364400f }, { 0.f, 0.f, -0.92718320f, 0.3746083f }, 190763, 191575 }, - { { 5269.208f, 3013.838f, 408.8276f, -1.76278200f }, { 0.f, 0.f, -0.77162460f, 0.6360782f }, 190763, 191575 }, - - { { 5401.634f, 2853.667f, 418.6748f, 2.63544400f }, { 0.f, 0.f, 0.96814730f, 0.2503814f }, 192819, 192819 }, // return portal inside fortress, neutral - // Vehicle teleporter - { { 5314.515f, 2703.687f, 408.5502f, -0.89011660f }, { 0.f, 0.f, -0.43051050f, 0.9025856f }, 192951, 192951 }, - { { 5316.252f, 2977.042f, 408.5385f, -0.82030330f }, { 0.f, 0.f, -0.39874840f, 0.9170604f }, 192951, 192951 } -}; - -// ********************************************************* -// **********Tower Element(GameObject, Creature)************ -// ********************************************************* - -struct WintergraspTowerData -{ - uint32 towerEntry; // Gameobject id of tower - std::vector GameObject; // Gameobject position and entry (Horde/Alliance) - - // Creature: Turrets and Guard /// @todo: Killed on Tower destruction ? Tower damage ? Requires confirming - std::vector CreatureBottom; -}; - -uint8 const WG_MAX_ATTACKTOWERS = 3; -// 192414 : 0 in sql, 1 in header -// 192278 : 0 in sql, 3 in header -WintergraspTowerData const AttackTowers[WG_MAX_ATTACKTOWERS] = -{ - // West tower - { - 190356, - { - { { 4559.113f, 3606.216f, 419.9992f, 4.799657f }, { 0.f, 0.f, -0.67558960f, 0.73727790f }, 192488, 192501 }, // Flag on tower - { { 4539.420f, 3622.490f, 420.0342f, 3.211419f }, { 0.f, 0.f, -0.99939060f, 0.03490613f }, 192488, 192501 }, // Flag on tower - { { 4555.258f, 3641.648f, 419.9740f, 1.675514f }, { 0.f, 0.f, 0.74314400f, 0.66913150f }, 192488, 192501 }, // Flag on tower - { { 4574.872f, 3625.911f, 420.0792f, 0.087266f }, { 0.f, 0.f, 0.04361916f, 0.99904820f }, 192488, 192501 }, // Flag on tower - { { 4433.899f, 3534.142f, 360.2750f, 4.433136f }, { 0.f, 0.f, -0.79863550f, 0.60181500f }, 192269, 192278 }, // Flag near workshop - { { 4572.933f, 3475.519f, 363.0090f, 1.422443f }, { 0.f, 0.f, 0.65275960f, 0.75756520f }, 192269, 192277 } // Flag near bridge - }, - { - { { 4418.688477f, 3506.251709f, 358.975494f, 4.293305f }, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A } // Roaming Guard - } - }, - // South Tower - { - 190357, - { - { { 4416.004f, 2822.666f, 429.8512f, 6.2657330f }, { 0.f, 0.f, -0.00872612f, 0.99996190f }, 192488, 192501 }, // Flag on tower - { { 4398.819f, 2804.698f, 429.7920f, 4.6949370f }, { 0.f, 0.f, -0.71325020f, 0.70090960f }, 192488, 192501 }, // Flag on tower - { { 4387.622f, 2719.566f, 389.9351f, 4.7385700f }, { 0.f, 0.f, -0.69779010f, 0.71630230f }, 192366, 192414 }, // Flag near tower - { { 4464.124f, 2855.453f, 406.1106f, 0.8290324f }, { 0.f, 0.f, 0.40274720f, 0.91531130f }, 192366, 192429 }, // Flag near tower - { { 4526.457f, 2810.181f, 391.1997f, 3.2899610f }, { 0.f, 0.f, -0.99724960f, 0.07411628f }, 192269, 192278 } // Flag near bridge - }, - { - { { 4452.859863f, 2808.870117f, 402.604004f, 6.056290f }, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard - { { 4455.899902f, 2835.958008f, 401.122559f, 0.034907f }, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard - { { 4412.649414f, 2953.792236f, 374.799957f, 0.980838f }, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Roaming Guard - { { 4362.089844f, 2811.510010f, 407.337006f, 3.193950f }, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard - { { 4412.290039f, 2753.790039f, 401.015015f, 5.829400f }, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard - { { 4421.939941f, 2773.189941f, 400.894989f, 5.707230f }, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A } // Standing Guard - } - }, - // East Tower - { - 190358, - { - { { 4466.793f, 1960.418f, 459.1437f, 1.151916f }, { 0.f, 0.f, 0.5446386f, 0.8386708f }, 192488, 192501 }, // Flag on tower - { { 4475.351f, 1937.031f, 459.0702f, 5.846854f }, { 0.f, 0.f, -0.2164392f, 0.9762961f }, 192488, 192501 }, // Flag on tower - { { 4451.758f, 1928.104f, 459.0759f, 4.276057f }, { 0.f, 0.f, -0.8433914f, 0.5372996f }, 192488, 192501 }, // Flag on tower - { { 4442.987f, 1951.898f, 459.0930f, 2.740162f }, { 0.f, 0.f, 0.9799242f, 0.1993704f }, 192488, 192501 } // Flag on tower - }, - { - { { 4501.060059f, 1990.280029f, 431.157013f, 1.029740f }, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard - { { 4463.830078f, 2015.180054f, 430.299988f, 1.431170f }, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard - { { 4494.580078f, 1943.760010f, 435.627014f, 6.195920f }, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard - { { 4450.149902f, 1897.579956f, 435.045013f, 4.398230f }, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard - { { 4428.870117f, 1906.869995f, 432.648010f, 3.996800f }, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A } // Standing Guard - } - } -}; - -struct WintergraspTowerCannonData -{ - uint32 towerEntry; - std::vector TowerCannonBottom; - std::vector TurretTop; -}; - -uint8 const WG_MAX_TOWER_CANNON = 7; - -WintergraspTowerCannonData const TowerCannon[WG_MAX_TOWER_CANNON] = -{ - { - 190221, - { - // no cannons at bottom - }, - { - { 5255.88f, 3047.63f, 438.499f, 3.13677f }, - { 5280.90f, 3071.32f, 438.499f, 1.62879f } - } - }, - { - 190373, - { - // no cannons at bottom - }, - { - { 5138.59f, 2935.16f, 439.845f, 3.11723f }, - { 5163.06f, 2959.52f, 439.846f, 1.47258f } - } - }, - { - 190377, - { - // no cannons at bottom - }, - { - { 5163.84f, 2723.74f, 439.844f, 1.39940f }, - { 5139.69f, 2747.40f, 439.844f, 3.17221f } - } - }, - { - 190378, - { - // no cannons at bottom - }, - { - { 5278.21f, 2607.23f, 439.755f, 4.71944f }, - { 5255.01f, 2631.98f, 439.755f, 3.15257f } - } - }, - { - 190356, - { - { 4537.380371f, 3599.531738f, 402.886993f, 3.998462f }, - { 4581.497559f, 3604.087158f, 402.886963f, 5.651723f } - }, - { - { 4469.448242f, 1966.623779f, 465.647217f, 1.153573f }, - { 4581.895996f, 3626.438477f, 426.539062f, 0.117806f } - } - }, - { - 190357, - { - { 4421.640137f, 2799.935791f, 412.630920f, 5.459298f }, - { 4420.263184f, 2845.340332f, 412.630951f, 0.742197f } - }, - { - { 4423.430664f, 2822.762939f, 436.283142f, 6.223487f }, - { 4397.825684f, 2847.629639f, 436.283325f, 1.579430f }, - { 4398.814941f, 2797.266357f, 436.283051f, 4.703747f } - } - }, - { - 190358, - { - { 4448.138184f, 1974.998779f, 441.995911f, 1.967238f }, - { 4448.713379f, 1955.148682f, 441.995178f, 0.380733f } - }, - { - { 4469.448242f, 1966.623779f, 465.647217f, 1.153573f }, - { 4481.996582f, 1933.658325f, 465.647186f, 5.873029f } - } - } -}; - -// ********************************************************* -// *****************WorkShop Data & Element***************** -// ********************************************************* - -struct StaticWintergraspWorkshopInfo -{ - uint8 WorkshopId; - uint32 WorldStateId; - - struct - { - uint8 AllianceCapture; - uint8 AllianceAttack; - uint8 HordeCapture; - uint8 HordeAttack; - } TextIds; -}; - -StaticWintergraspWorkshopInfo const WorkshopData[WG_MAX_WORKSHOP] = -{ - { BATTLEFIELD_WG_WORKSHOP_NE, WS_BATTLEFIELD_WG_WORKSHOP_NE, { BATTLEFIELD_WG_TEXT_SUNKEN_RING_CAPTURE_ALLIANCE, BATTLEFIELD_WG_TEXT_SUNKEN_RING_ATTACK_ALLIANCE, BATTLEFIELD_WG_TEXT_SUNKEN_RING_CAPTURE_HORDE, BATTLEFIELD_WG_TEXT_SUNKEN_RING_ATTACK_HORDE } }, - { BATTLEFIELD_WG_WORKSHOP_NW, WS_BATTLEFIELD_WG_WORKSHOP_NW, { BATTLEFIELD_WG_TEXT_BROKEN_TEMPLE_CAPTURE_ALLIANCE, BATTLEFIELD_WG_TEXT_BROKEN_TEMPLE_ATTACK_ALLIANCE, BATTLEFIELD_WG_TEXT_BROKEN_TEMPLE_CAPTURE_HORDE, BATTLEFIELD_WG_TEXT_BROKEN_TEMPLE_ATTACK_HORDE } }, - { BATTLEFIELD_WG_WORKSHOP_SE, WS_BATTLEFIELD_WG_WORKSHOP_SE, { BATTLEFIELD_WG_TEXT_EASTSPARK_CAPTURE_ALLIANCE, BATTLEFIELD_WG_TEXT_EASTSPARK_ATTACK_ALLIANCE, BATTLEFIELD_WG_TEXT_EASTSPARK_CAPTURE_HORDE, BATTLEFIELD_WG_TEXT_EASTSPARK_ATTACK_HORDE } }, - { BATTLEFIELD_WG_WORKSHOP_SW, WS_BATTLEFIELD_WG_WORKSHOP_SW, { BATTLEFIELD_WG_TEXT_WESTSPARK_CAPTURE_ALLIANCE, BATTLEFIELD_WG_TEXT_WESTSPARK_ATTACK_ALLIANCE, BATTLEFIELD_WG_TEXT_WESTSPARK_CAPTURE_HORDE, BATTLEFIELD_WG_TEXT_WESTSPARK_ATTACK_HORDE } }, - // KEEP WORKSHOPS - It can't be taken, so it doesn't have a textids - { BATTLEFIELD_WG_WORKSHOP_KEEP_WEST, WS_BATTLEFIELD_WG_WORKSHOP_K_W, { 0, 0, 0, 0 } }, - { BATTLEFIELD_WG_WORKSHOP_KEEP_EAST, WS_BATTLEFIELD_WG_WORKSHOP_K_E, { 0, 0, 0, 0 } } -}; - -BattlefieldWG::~BattlefieldWG() -{ - for (WintergraspWorkshop* workshop : Workshops) - delete workshop; - - for (BfWGGameObjectBuilding* building : BuildingsInZone) - delete building; -} - -bool BattlefieldWG::SetupBattlefield() -{ - m_TypeId = BATTLEFIELD_WG; // See enum BattlefieldTypes - m_BattleId = BATTLEFIELD_BATTLEID_WG; - m_ZoneId = AREA_WINTERGRASP; - m_MapId = BATTLEFIELD_WG_MAPID; - m_Map = sMapMgr->CreateBaseMap(m_MapId); - - InitStalker(BATTLEFIELD_WG_NPC_STALKER, WintergraspStalkerPos); - - m_MaxPlayer = sWorld->getIntConfig(CONFIG_WINTERGRASP_PLR_MAX); - m_IsEnabled = sWorld->getBoolConfig(CONFIG_WINTERGRASP_ENABLE); - m_MinPlayer = sWorld->getIntConfig(CONFIG_WINTERGRASP_PLR_MIN); - m_MinLevel = sWorld->getIntConfig(CONFIG_WINTERGRASP_PLR_MIN_LVL); - m_BattleTime = sWorld->getIntConfig(CONFIG_WINTERGRASP_BATTLETIME) * MINUTE * IN_MILLISECONDS; - m_NoWarBattleTime = sWorld->getIntConfig(CONFIG_WINTERGRASP_NOBATTLETIME) * MINUTE * IN_MILLISECONDS; - m_RestartAfterCrash = sWorld->getIntConfig(CONFIG_WINTERGRASP_RESTART_AFTER_CRASH) * MINUTE * IN_MILLISECONDS; - - m_TimeForAcceptInvite = 20; - m_StartGroupingTimer = 15 * MINUTE * IN_MILLISECONDS; - m_StartGrouping = false; - - m_tenacityTeam = TEAM_NEUTRAL; - m_tenacityStack = 0; - - KickPosition.Relocate(5728.117f, 2714.346f, 697.733f, 0); - KickPosition.m_mapId = m_MapId; - - RegisterZone(m_ZoneId); - - m_Data32.resize(BATTLEFIELD_WG_DATA_MAX); - - m_saveTimer = 60000; - - // Init Graveyards - SetGraveyardNumber(BATTLEFIELD_WG_GRAVEYARD_MAX); - - // Load from db - if ((sWorld->getWorldState(WS_BATTLEFIELD_WG_ACTIVE) == 0) && (sWorld->getWorldState(WS_BATTLEFIELD_WG_DEFENDER) == 0) - && (sWorld->getWorldState(ClockWorldState[0]) == 0)) - { - sWorld->setWorldState(WS_BATTLEFIELD_WG_ACTIVE, uint64(false)); - sWorld->setWorldState(WS_BATTLEFIELD_WG_DEFENDER, uint64(urand(0, 1))); - sWorld->setWorldState(ClockWorldState[0], uint64(m_NoWarBattleTime)); - } - - m_isActive = sWorld->getWorldState(WS_BATTLEFIELD_WG_ACTIVE) != 0; - m_DefenderTeam = TeamId(sWorld->getWorldState(WS_BATTLEFIELD_WG_DEFENDER)); - - m_Timer = sWorld->getWorldState(ClockWorldState[0]); - if (m_isActive) - { - m_isActive = false; - m_Timer = m_RestartAfterCrash; - } - - SetData(BATTLEFIELD_WG_DATA_WON_A, uint32(sWorld->getWorldState(WS_BATTLEFIELD_WG_ATTACKED_A))); - SetData(BATTLEFIELD_WG_DATA_DEF_A, uint32(sWorld->getWorldState(WS_BATTLEFIELD_WG_DEFENDED_A))); - SetData(BATTLEFIELD_WG_DATA_WON_H, uint32(sWorld->getWorldState(WS_BATTLEFIELD_WG_ATTACKED_H))); - SetData(BATTLEFIELD_WG_DATA_DEF_H, uint32(sWorld->getWorldState(WS_BATTLEFIELD_WG_DEFENDED_H))); - - for (uint8 i = 0; i < BATTLEFIELD_WG_GRAVEYARD_MAX; i++) - { - BfGraveyardWG* graveyard = new BfGraveyardWG(this); - - // When between games, the graveyard is controlled by the defending team - if (WGGraveyard[i].StartControl == TEAM_NEUTRAL) - graveyard->Initialize(m_DefenderTeam, WGGraveyard[i].GraveyardID); - else - graveyard->Initialize(WGGraveyard[i].StartControl, WGGraveyard[i].GraveyardID); - - graveyard->SetTextId(WGGraveyard[i].TextID); - m_GraveyardList[i] = graveyard; - } - - - Workshops.resize(WG_MAX_WORKSHOP); - // Spawn workshop creatures and gameobjects - for (uint8 i = 0; i < WG_MAX_WORKSHOP; i++) - { - WintergraspWorkshop* workshop = new WintergraspWorkshop(this, i); - if (i < BATTLEFIELD_WG_WORKSHOP_NE) - workshop->GiveControlTo(GetAttackerTeam(), true); - else - workshop->GiveControlTo(GetDefenderTeam(), true); - - // Note: Capture point is added once the gameobject is created. - Workshops[i] = workshop; - } - - // Spawn turrets and hide them per default - for (uint8 i = 0; i < WG_MAX_TURRET; i++) - { - Position towerCannonPos = WGTurret[i].GetPosition(); - if (Creature* creature = SpawnCreature(NPC_WINTERGRASP_TOWER_CANNON, towerCannonPos)) - { - CanonList.push_back(creature->GetGUID()); - HideNpc(creature); - } - } - - BuildingsInZone.resize(WG_MAX_OBJ); - // Spawn all gameobjects - for (uint8 i = 0; i < WG_MAX_OBJ; i++) - { - if (GameObject* go = SpawnGameObject(WGGameObjectBuilding[i].entry, WGGameObjectBuilding[i].pos, WGGameObjectBuilding[i].rot)) - { - BfWGGameObjectBuilding* b = new BfWGGameObjectBuilding(this, WGGameObjectBuilding[i].type, WGGameObjectBuilding[i].WorldState); - b->Init(go); - if (!IsEnabled() && go->GetEntry() == GO_WINTERGRASP_VAULT_GATE) - go->SetDestructibleState(GO_DESTRUCTIBLE_DESTROYED); - - BuildingsInZone[i] = b; - } - } - - // Spawning portal defender - for (uint8 i = 0; i < WG_MAX_TELEPORTER; ++i) - { - WintergraspGameObjectData const& teleporter = WGPortalDefenderData[i]; - if (GameObject* go = SpawnGameObject(teleporter.AllianceEntry, teleporter.Pos, teleporter.Rot)) - { - DefenderPortalList[TEAM_ALLIANCE].push_back(go->GetGUID()); - go->SetRespawnTime(GetDefenderTeam() == TEAM_ALLIANCE ? RESPAWN_IMMEDIATELY : RESPAWN_ONE_DAY); - } - - if (GameObject* go = SpawnGameObject(teleporter.HordeEntry, teleporter.Pos, teleporter.Rot)) - { - DefenderPortalList[TEAM_HORDE].push_back(go->GetGUID()); - go->SetRespawnTime(GetDefenderTeam() == TEAM_HORDE ? RESPAWN_IMMEDIATELY : RESPAWN_ONE_DAY); - } - } - - UpdateCounterVehicle(true); - return true; -} - -bool BattlefieldWG::Update(uint32 diff) -{ - bool m_return = Battlefield::Update(diff); - if (m_saveTimer <= diff) - { - sWorld->setWorldState(WS_BATTLEFIELD_WG_ACTIVE, m_isActive); - sWorld->setWorldState(WS_BATTLEFIELD_WG_DEFENDER, m_DefenderTeam); - sWorld->setWorldState(ClockWorldState[0], m_Timer); - sWorld->setWorldState(WS_BATTLEFIELD_WG_ATTACKED_A, GetData(BATTLEFIELD_WG_DATA_WON_A)); - sWorld->setWorldState(WS_BATTLEFIELD_WG_DEFENDED_A, GetData(BATTLEFIELD_WG_DATA_DEF_A)); - sWorld->setWorldState(WS_BATTLEFIELD_WG_ATTACKED_H, GetData(BATTLEFIELD_WG_DATA_WON_H)); - sWorld->setWorldState(WS_BATTLEFIELD_WG_DEFENDED_H, GetData(BATTLEFIELD_WG_DATA_DEF_H)); - m_saveTimer = 60 * IN_MILLISECONDS; - } - else - m_saveTimer -= diff; - - return m_return; -} - -void BattlefieldWG::OnBattleStart() -{ - // Spawn titan relic - if (GameObject* relic = SpawnGameObject(GO_WINTERGRASP_TITAN_S_RELIC, WintergraspRelicPos, WintergraspRelicRot)) - { - // Update faction of relic, only attacker can click on - relic->SetFaction(WintergraspFaction[GetAttackerTeam()]); - // Set in use (not allow to click on before last door is broken) - relic->AddFlag(GameObjectFlags(GO_FLAG_IN_USE | GO_FLAG_NOT_SELECTABLE)); - m_titansRelicGUID = relic->GetGUID(); - } - else - TC_LOG_ERROR("bg.battlefield", "WG: Failed to spawn titan relic."); - - - // Update tower visibility and update faction - for (auto itr = CanonList.begin(); itr != CanonList.end(); ++itr) - { - if (Creature* creature = GetCreature(*itr)) - { - ShowNpc(creature, true); - creature->SetFaction(WintergraspFaction[GetDefenderTeam()]); - } - } - - // Rebuild all wall - for (BfWGGameObjectBuilding* building : BuildingsInZone) - { - building->Rebuild(); - building->UpdateTurretAttack(false); - } - - SetData(BATTLEFIELD_WG_DATA_BROKEN_TOWER_ATT, 0); - SetData(BATTLEFIELD_WG_DATA_BROKEN_TOWER_DEF, 0); - SetData(BATTLEFIELD_WG_DATA_DAMAGED_TOWER_ATT, 0); - SetData(BATTLEFIELD_WG_DATA_DAMAGED_TOWER_DEF, 0); - - // Update graveyard (in no war time all graveyard is to deffender, in war time, depend of base) - for (WintergraspWorkshop* workshop : Workshops) - workshop->UpdateGraveyardAndWorkshop(); - - for (uint8 team = 0; team < PVP_TEAMS_COUNT; ++team) - { - for (auto itr = m_players[team].begin(); itr != m_players[team].end(); ++itr) - { - // Kick player in orb room, TODO: offline player ? - if (Player* player = ObjectAccessor::FindPlayer(*itr)) - { - float x, y, z; - player->GetPosition(x, y, z); - if (5500 > x && x > 5392 && y < 2880 && y > 2800 && z < 480) - player->TeleportTo(571, 5349.8686f, 2838.481f, 409.240f, 0.046328f); - SendInitWorldStatesTo(player); - } - } - } - - // Initialize vehicle counter - UpdateCounterVehicle(true); - // Send start warning to all players - SendWarning(BATTLEFIELD_WG_TEXT_START_BATTLE); -} - -void BattlefieldWG::UpdateCounterVehicle(bool init) -{ - if (init) - { - SetData(BATTLEFIELD_WG_DATA_VEHICLE_H, 0); - SetData(BATTLEFIELD_WG_DATA_VEHICLE_A, 0); - } - SetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_H, 0); - SetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_A, 0); - - for (WintergraspWorkshop* workshop : Workshops) - { - if (workshop->GetTeamControl() == TEAM_ALLIANCE) - UpdateData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_A, 4); - else if (workshop->GetTeamControl() == TEAM_HORDE) - UpdateData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_H, 4); - } - - UpdateVehicleCountWG(); -} - -void BattlefieldWG::OnBattleEnd(bool endByTimer) -{ - // Remove relic - if (!m_titansRelicGUID.IsEmpty()) - if (GameObject* relic = GetGameObject(m_titansRelicGUID)) - relic->RemoveFromWorld(); - m_titansRelicGUID.Clear(); - - // change collision wall state closed - for (BfWGGameObjectBuilding* building : BuildingsInZone) - { - building->RebuildGate(); - } - - // successful defense - if (endByTimer) - UpdateData(GetDefenderTeam() == TEAM_HORDE ? BATTLEFIELD_WG_DATA_DEF_H : BATTLEFIELD_WG_DATA_DEF_A, 1); - // successful attack (note that teams have already been swapped, so defender team is the one who won) - else - UpdateData(GetDefenderTeam() == TEAM_HORDE ? BATTLEFIELD_WG_DATA_WON_H : BATTLEFIELD_WG_DATA_WON_A, 1); - - // Remove turret - for (auto itr = CanonList.begin(); itr != CanonList.end(); ++itr) - { - if (Creature* creature = GetCreature(*itr)) - { - if (!endByTimer) - creature->SetFaction(WintergraspFaction[GetDefenderTeam()]); - HideNpc(creature); - } - } - - // Update all graveyard, control is to defender when no wartime - for (uint8 i = 0; i < BATTLEFIELD_WG_GY_HORDE; i++) - if (BfGraveyard* graveyard = GetGraveyardById(i)) - graveyard->GiveControlTo(GetDefenderTeam()); - - // Update portals - for (auto itr = DefenderPortalList[GetDefenderTeam()].begin(); itr != DefenderPortalList[GetDefenderTeam()].end(); ++itr) - if (GameObject* portal = GetGameObject(*itr)) - portal->SetRespawnTime(RESPAWN_IMMEDIATELY); - - for (auto itr = DefenderPortalList[GetAttackerTeam()].begin(); itr != DefenderPortalList[GetAttackerTeam()].end(); ++itr) - if (GameObject* portal = GetGameObject(*itr)) - portal->SetRespawnTime(RESPAWN_ONE_DAY); - - // Saving data - for (BfWGGameObjectBuilding* building : BuildingsInZone) - building->Save(); - - for (WintergraspWorkshop* workshop : Workshops) - workshop->Save(); - - for (auto itr = m_PlayersInWar[GetDefenderTeam()].begin(); itr != m_PlayersInWar[GetDefenderTeam()].end(); ++itr) - { - if (Player* player = ObjectAccessor::FindPlayer(*itr)) - { - player->CastSpell(player, SPELL_ESSENCE_OF_WINTERGRASP, true); - player->CastSpell(player, SPELL_VICTORY_REWARD, true); - // Complete victory quests - player->AreaExploredOrEventHappens(QUEST_VICTORY_WINTERGRASP_A); - player->AreaExploredOrEventHappens(QUEST_VICTORY_WINTERGRASP_H); - // Send Wintergrasp victory achievement - DoCompleteOrIncrementAchievement(ACHIEVEMENTS_WIN_WG, player); - // Award achievement for succeeding in Wintergrasp in 10 minutes or less - if (!endByTimer && GetTimer() <= 10000) - DoCompleteOrIncrementAchievement(ACHIEVEMENTS_WIN_WG_TIMER_10, player); - } - } - - for (auto itr = m_PlayersInWar[GetAttackerTeam()].begin(); itr != m_PlayersInWar[GetAttackerTeam()].end(); ++itr) - if (Player* player = ObjectAccessor::FindPlayer(*itr)) - player->CastSpell(player, SPELL_DEFEAT_REWARD, true); - - for (uint8 team = 0; team < PVP_TEAMS_COUNT; ++team) - { - for (auto itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr) - if (Player* player = ObjectAccessor::FindPlayer(*itr)) - RemoveAurasFromPlayer(player); - - m_PlayersInWar[team].clear(); - - for (auto itr = m_vehicles[team].begin(); itr != m_vehicles[team].end(); ++itr) - if (Creature* creature = GetCreature(*itr)) - if (creature->IsVehicle()) - creature->DespawnOrUnsummon(); - - m_vehicles[team].clear(); - } - - if (!endByTimer) - { - for (uint8 team = 0; team < PVP_TEAMS_COUNT; ++team) - { - for (auto itr = m_players[team].begin(); itr != m_players[team].end(); ++itr) - { - if (Player* player = ObjectAccessor::FindPlayer(*itr)) - { - player->RemoveAurasDueToSpell(m_DefenderTeam == TEAM_ALLIANCE ? SPELL_HORDE_CONTROL_PHASE_SHIFT : SPELL_ALLIANCE_CONTROL_PHASE_SHIFT, player->GetGUID()); - player->AddAura(m_DefenderTeam == TEAM_HORDE ? SPELL_HORDE_CONTROL_PHASE_SHIFT : SPELL_ALLIANCE_CONTROL_PHASE_SHIFT, player); - } - } - } - } - - if (!endByTimer) // win alli/horde - SendWarning(GetDefenderTeam() == TEAM_ALLIANCE ? BATTLEFIELD_WG_TEXT_FORTRESS_CAPTURE_ALLIANCE : BATTLEFIELD_WG_TEXT_FORTRESS_CAPTURE_HORDE); - else // defend alli/horde - SendWarning(GetDefenderTeam() == TEAM_ALLIANCE ? BATTLEFIELD_WG_TEXT_FORTRESS_DEFEND_ALLIANCE : BATTLEFIELD_WG_TEXT_FORTRESS_DEFEND_HORDE); -} - -// ******************************************************* -// ******************* Reward System ********************* -// ******************************************************* -void BattlefieldWG::DoCompleteOrIncrementAchievement(uint32 achievement, Player* player, uint8 /*incrementNumber*/) -{ - AchievementEntry const* achievementEntry = sAchievementStore.LookupEntry(achievement); - - if (!achievementEntry) - return; - - switch (achievement) - { - case ACHIEVEMENTS_WIN_WG_100: - { - // player->UpdateCriteria(); - } - default: - { - if (player) - player->CompletedAchievement(achievementEntry); - break; - } - } - -} - -void BattlefieldWG::OnStartGrouping() -{ - SendWarning(BATTLEFIELD_WG_TEXT_START_GROUPING); -} - -uint8 BattlefieldWG::GetSpiritGraveyardId(uint32 areaId) const -{ - switch (areaId) - { - case AREA_WINTERGRASP_FORTRESS: - return BATTLEFIELD_WG_GY_KEEP; - case AREA_THE_SUNKEN_RING: - return BATTLEFIELD_WG_GY_WORKSHOP_NE; - case AREA_THE_BROKEN_TEMPLATE: - return BATTLEFIELD_WG_GY_WORKSHOP_NW; - case AREA_WESTPARK_WORKSHOP: - return BATTLEFIELD_WG_GY_WORKSHOP_SW; - case AREA_EASTPARK_WORKSHOP: - return BATTLEFIELD_WG_GY_WORKSHOP_SE; - case AREA_WINTERGRASP: - return BATTLEFIELD_WG_GY_ALLIANCE; - case AREA_THE_CHILLED_QUAGMIRE: - return BATTLEFIELD_WG_GY_HORDE; - default: - TC_LOG_ERROR("bg.battlefield", "BattlefieldWG::GetSpiritGraveyardId: Unexpected Area Id %u", areaId); - break; - } - - return 0; -} - -void BattlefieldWG::OnCreatureCreate(Creature* creature) -{ - // Accessing to db spawned creatures - switch (creature->GetEntry()) - { - case NPC_DWARVEN_SPIRIT_GUIDE: - case NPC_TAUNKA_SPIRIT_GUIDE: - { - TeamId teamId = (creature->GetEntry() == NPC_DWARVEN_SPIRIT_GUIDE ? TEAM_ALLIANCE : TEAM_HORDE); - uint8 graveyardId = GetSpiritGraveyardId(creature->GetAreaId()); - if (m_GraveyardList[graveyardId]) - m_GraveyardList[graveyardId]->SetSpirit(creature, teamId); - break; - } - } - - // untested code - not sure if it is valid. - if (IsWarTime()) - { - switch (creature->GetEntry()) - { - case NPC_WINTERGRASP_SIEGE_ENGINE_ALLIANCE: - case NPC_WINTERGRASP_SIEGE_ENGINE_HORDE: - case NPC_WINTERGRASP_CATAPULT: - case NPC_WINTERGRASP_DEMOLISHER: - { - if (!creature->ToTempSummon() || !creature->ToTempSummon()->GetSummonerGUID() || !ObjectAccessor::FindPlayer(creature->ToTempSummon()->GetSummonerGUID())) - { - creature->DespawnOrUnsummon(); - return; - } - - Player* creator = ObjectAccessor::FindPlayer(creature->ToTempSummon()->GetSummonerGUID()); - TeamId team = creator->GetTeamId(); - - if (team == TEAM_HORDE) - { - if (GetData(BATTLEFIELD_WG_DATA_VEHICLE_H) < GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_H)) - { - UpdateData(BATTLEFIELD_WG_DATA_VEHICLE_H, 1); - creature->AddAura(SPELL_HORDE_FLAG, creature); - m_vehicles[team].insert(creature->GetGUID()); - UpdateVehicleCountWG(); - } - else - { - creature->DespawnOrUnsummon(); - return; - } - } - else - { - if (GetData(BATTLEFIELD_WG_DATA_VEHICLE_A) < GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_A)) - { - UpdateData(BATTLEFIELD_WG_DATA_VEHICLE_A, 1); - creature->AddAura(SPELL_ALLIANCE_FLAG, creature); - m_vehicles[team].insert(creature->GetGUID()); - UpdateVehicleCountWG(); - } - else - { - creature->DespawnOrUnsummon(); - return; - } - } - - creature->CastSpell(creator, SPELL_GRAB_PASSENGER, true); - break; - } - } - } -} - -void BattlefieldWG::OnCreatureRemove(Creature* /*creature*/) -{ -/* possibly can be used later - if (IsWarTime()) - { - switch (creature->GetEntry()) - { - case NPC_WINTERGRASP_SIEGE_ENGINE_ALLIANCE: - case NPC_WINTERGRASP_SIEGE_ENGINE_HORDE: - case NPC_WINTERGRASP_CATAPULT: - case NPC_WINTERGRASP_DEMOLISHER: - { - uint8 team; - if (creature->GetFaction() == WintergraspFaction[TEAM_ALLIANCE]) - team = TEAM_ALLIANCE; - else if (creature->GetFaction() == WintergraspFaction[TEAM_HORDE]) - team = TEAM_HORDE; - else - return; - - m_vehicles[team].erase(creature->GetGUID()); - if (team == TEAM_HORDE) - UpdateData(BATTLEFIELD_WG_DATA_VEHICLE_H, -1); - else - UpdateData(BATTLEFIELD_WG_DATA_VEHICLE_A, -1); - UpdateVehicleCountWG(); - - break; - } - } - }*/ -} - -void BattlefieldWG::OnGameObjectCreate(GameObject* go) -{ - uint8 workshopId = 0; - - switch (go->GetEntry()) - { - case GO_WINTERGRASP_FACTORY_BANNER_NE: - workshopId = BATTLEFIELD_WG_WORKSHOP_NE; - break; - case GO_WINTERGRASP_FACTORY_BANNER_NW: - workshopId = BATTLEFIELD_WG_WORKSHOP_NW; - break; - case GO_WINTERGRASP_FACTORY_BANNER_SE: - workshopId = BATTLEFIELD_WG_WORKSHOP_SE; - break; - case GO_WINTERGRASP_FACTORY_BANNER_SW: - workshopId = BATTLEFIELD_WG_WORKSHOP_SW; - break; - default: - return; - } - - for (WintergraspWorkshop* workshop : Workshops) - { - if (workshop->GetId() == workshopId) - { - WintergraspCapturePoint* capturePoint = new WintergraspCapturePoint(this, GetAttackerTeam()); - - capturePoint->SetCapturePointData(go); - capturePoint->LinkToWorkshop(workshop); - AddCapturePoint(capturePoint); - break; - } - } -} - -// Called when player kill a unit in wg zone -void BattlefieldWG::HandleKill(Player* killer, Unit* victim) -{ - if (killer == victim) - return; - - if (victim->GetTypeId() == TYPEID_PLAYER) - { - HandlePromotion(killer, victim); - - // Allow to Skin non-released corpse - victim->AddUnitFlag(UNIT_FLAG_SKINNABLE); - } - - /// @todoRecent PvP activity worldstate -} - -bool BattlefieldWG::FindAndRemoveVehicleFromList(Unit* vehicle) -{ - for (uint32 team = 0; team < PVP_TEAMS_COUNT; ++team) - { - auto itr = m_vehicles[team].find(vehicle->GetGUID()); - if (itr != m_vehicles[team].end()) - { - m_vehicles[team].erase(itr); - - if (team == TEAM_HORDE) - UpdateData(BATTLEFIELD_WG_DATA_VEHICLE_H, -1); - else - UpdateData(BATTLEFIELD_WG_DATA_VEHICLE_A, -1); - return true; - } - } - - return false; -} - -void BattlefieldWG::OnUnitDeath(Unit* unit) -{ - if (IsWarTime()) - if (unit->IsVehicle()) - if (FindAndRemoveVehicleFromList(unit)) - UpdateVehicleCountWG(); -} - -void BattlefieldWG::HandlePromotion(Player* playerKiller, Unit* unitKilled) -{ - uint32 teamId = playerKiller->GetTeamId(); - - for (auto iter = m_PlayersInWar[teamId].begin(); iter != m_PlayersInWar[teamId].end(); ++iter) - if (Player* player = ObjectAccessor::FindPlayer(*iter)) - if (player->GetDistance2d(unitKilled) < 40.0f) - PromotePlayer(player); -} - -// Update rank for player -void BattlefieldWG::PromotePlayer(Player* killer) -{ - if (!m_isActive) - return; - // Updating rank of player - if (Aura* auraRecruit = killer->GetAura(SPELL_RECRUIT)) - { - if (auraRecruit->GetStackAmount() >= 5) - { - killer->RemoveAura(SPELL_RECRUIT); - killer->CastSpell(killer, SPELL_CORPORAL, true); - if (Creature* stalker = GetCreature(StalkerGuid)) - sCreatureTextMgr->SendChat(stalker, BATTLEFIELD_WG_TEXT_RANK_CORPORAL, killer, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_NORMAL, 0, SoundKitPlayType::Normal, TEAM_OTHER, false, killer); - } - else - killer->CastSpell(killer, SPELL_RECRUIT, true); - } - else if (Aura* auraCorporal = killer->GetAura(SPELL_CORPORAL)) - { - if (auraCorporal->GetStackAmount() >= 5) - { - killer->RemoveAura(SPELL_CORPORAL); - killer->CastSpell(killer, SPELL_LIEUTENANT, true); - if (Creature* stalker = GetCreature(StalkerGuid)) - sCreatureTextMgr->SendChat(stalker, BATTLEFIELD_WG_TEXT_RANK_FIRST_LIEUTENANT, killer, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_NORMAL, 0, SoundKitPlayType::Normal, TEAM_OTHER, false, killer); - } - else - killer->CastSpell(killer, SPELL_CORPORAL, true); - } -} - -void BattlefieldWG::RemoveAurasFromPlayer(Player* player) -{ - player->RemoveAurasDueToSpell(SPELL_RECRUIT); - player->RemoveAurasDueToSpell(SPELL_CORPORAL); - player->RemoveAurasDueToSpell(SPELL_LIEUTENANT); - player->RemoveAurasDueToSpell(SPELL_TOWER_CONTROL); - player->RemoveAurasDueToSpell(SPELL_SPIRITUAL_IMMUNITY); - player->RemoveAurasDueToSpell(SPELL_TENACITY); - player->RemoveAurasDueToSpell(SPELL_ESSENCE_OF_WINTERGRASP); - player->RemoveAurasDueToSpell(SPELL_WINTERGRASP_RESTRICTED_FLIGHT_AREA); -} - -void BattlefieldWG::OnPlayerJoinWar(Player* player) -{ - RemoveAurasFromPlayer(player); - - player->CastSpell(player, SPELL_RECRUIT, true); - - if (player->GetZoneId() != m_ZoneId) - { - if (player->GetTeamId() == GetDefenderTeam()) - player->TeleportTo(571, 5345, 2842, 410, 3.14f); - else - { - if (player->GetTeamId() == TEAM_HORDE) - player->TeleportTo(571, 5025.857422f, 3674.628906f, 362.737122f, 4.135169f); - else - player->TeleportTo(571, 5101.284f, 2186.564f, 373.549f, 3.812f); - } - } - - UpdateTenacity(); - - if (player->GetTeamId() == GetAttackerTeam()) - { - if (GetData(BATTLEFIELD_WG_DATA_BROKEN_TOWER_ATT) < 3) - player->SetAuraStack(SPELL_TOWER_CONTROL, player, 3 - GetData(BATTLEFIELD_WG_DATA_BROKEN_TOWER_ATT)); - } - else - { - if (GetData(BATTLEFIELD_WG_DATA_BROKEN_TOWER_ATT) > 0) - player->SetAuraStack(SPELL_TOWER_CONTROL, player, GetData(BATTLEFIELD_WG_DATA_BROKEN_TOWER_ATT)); - } - SendInitWorldStatesTo(player); -} - -void BattlefieldWG::OnPlayerLeaveWar(Player* player) -{ - // Remove all aura from WG /// @todo false we can go out of this zone on retail and keep Rank buff, remove on end of WG - if (!player->GetSession()->PlayerLogout()) - { - if (Creature* vehicle = player->GetVehicleCreatureBase()) // Remove vehicle of player if he go out. - vehicle->DespawnOrUnsummon(); - - RemoveAurasFromPlayer(player); - } - - player->RemoveAurasDueToSpell(SPELL_HORDE_CONTROLS_FACTORY_PHASE_SHIFT); - player->RemoveAurasDueToSpell(SPELL_ALLIANCE_CONTROLS_FACTORY_PHASE_SHIFT); - player->RemoveAurasDueToSpell(SPELL_HORDE_CONTROL_PHASE_SHIFT); - player->RemoveAurasDueToSpell(SPELL_ALLIANCE_CONTROL_PHASE_SHIFT); - UpdateTenacity(); -} - -void BattlefieldWG::OnPlayerLeaveZone(Player* player) -{ - if (!m_isActive) - RemoveAurasFromPlayer(player); - - player->RemoveAurasDueToSpell(SPELL_HORDE_CONTROLS_FACTORY_PHASE_SHIFT); - player->RemoveAurasDueToSpell(SPELL_ALLIANCE_CONTROLS_FACTORY_PHASE_SHIFT); - player->RemoveAurasDueToSpell(SPELL_HORDE_CONTROL_PHASE_SHIFT); - player->RemoveAurasDueToSpell(SPELL_ALLIANCE_CONTROL_PHASE_SHIFT); -} - -void BattlefieldWG::OnPlayerEnterZone(Player* player) -{ - if (!m_isActive) - RemoveAurasFromPlayer(player); - - player->AddAura(m_DefenderTeam == TEAM_HORDE ? SPELL_HORDE_CONTROL_PHASE_SHIFT : SPELL_ALLIANCE_CONTROL_PHASE_SHIFT, player); - // Send worldstate to player - SendInitWorldStatesTo(player); -} - -uint32 BattlefieldWG::GetData(uint32 data) const -{ - switch (data) - { - // Used to determine when the phasing spells must be cast - // See: SpellArea::IsFitToRequirements - case AREA_THE_SUNKEN_RING: - case AREA_THE_BROKEN_TEMPLATE: - case AREA_WESTPARK_WORKSHOP: - case AREA_EASTPARK_WORKSHOP: - // Graveyards and Workshops are controlled by the same team. - if (BfGraveyard const* graveyard = GetGraveyardById(GetSpiritGraveyardId(data))) - return graveyard->GetControlTeamId(); - break; - default: - break; - } - - return Battlefield::GetData(data); -} - - -void BattlefieldWG::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) -{ - packet.Worldstates.emplace_back(WS_BATTLEFIELD_WG_DEFENDED_A, GetData(BATTLEFIELD_WG_DATA_DEF_A)); - packet.Worldstates.emplace_back(WS_BATTLEFIELD_WG_DEFENDED_H, GetData(BATTLEFIELD_WG_DATA_DEF_H)); - packet.Worldstates.emplace_back(WS_BATTLEFIELD_WG_ATTACKED_A, GetData(BATTLEFIELD_WG_DATA_WON_A)); - packet.Worldstates.emplace_back(WS_BATTLEFIELD_WG_ATTACKED_H, GetData(BATTLEFIELD_WG_DATA_WON_H)); - packet.Worldstates.emplace_back(WS_BATTLEFIELD_WG_ATTACKER, GetAttackerTeam()); - packet.Worldstates.emplace_back(WS_BATTLEFIELD_WG_DEFENDER, GetDefenderTeam()); - - // Note: cleanup these two, their names look awkward - packet.Worldstates.emplace_back(WS_BATTLEFIELD_WG_ACTIVE, IsWarTime() ? 0 : 1); - packet.Worldstates.emplace_back(WS_BATTLEFIELD_WG_SHOW_WORLDSTATE, IsWarTime() ? 1 : 0); - - for (uint32 itr = 0; itr < 2; ++itr) - packet.Worldstates.emplace_back(ClockWorldState[itr], int32(GameTime::GetGameTime()) + int32(m_Timer) / int32(1000)); - - packet.Worldstates.emplace_back(WS_BATTLEFIELD_WG_VEHICLE_H, GetData(BATTLEFIELD_WG_DATA_VEHICLE_H)); - packet.Worldstates.emplace_back(WS_BATTLEFIELD_WG_MAX_VEHICLE_H, GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_H)); - packet.Worldstates.emplace_back(WS_BATTLEFIELD_WG_VEHICLE_A, GetData(BATTLEFIELD_WG_DATA_VEHICLE_A)); - packet.Worldstates.emplace_back(WS_BATTLEFIELD_WG_MAX_VEHICLE_A, GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_A)); - - for (BfWGGameObjectBuilding* building : BuildingsInZone) - building->FillInitialWorldStates(packet); - - for (WintergraspWorkshop* workshop : Workshops) - workshop->FillInitialWorldStates(packet); -} - -void BattlefieldWG::SendInitWorldStatesTo(Player* player) -{ - WorldPackets::WorldState::InitWorldStates packet; - packet.MapID = m_MapId; - packet.AreaID = m_ZoneId; - packet.SubareaID = player->GetAreaId(); - FillInitialWorldStates(packet); - - player->SendDirectMessage(packet.Write()); -} - -void BattlefieldWG::SendInitWorldStatesToAll() -{ - for (uint8 team = 0; team < PVP_TEAMS_COUNT; ++team) - for (auto itr = m_players[team].begin(); itr != m_players[team].end(); ++itr) - if (Player* player = ObjectAccessor::FindPlayer(*itr)) - SendInitWorldStatesTo(player); -} - -void BattlefieldWG::BrokenWallOrTower(TeamId team, BfWGGameObjectBuilding* building) -{ - if (team == GetDefenderTeam()) - { - for (auto itr = m_PlayersInWar[GetAttackerTeam()].begin(); itr != m_PlayersInWar[GetAttackerTeam()].end(); ++itr) - { - if (Player* player = ObjectAccessor::FindPlayer(*itr)) - if (player->GetDistance2d(ASSERT_NOTNULL(GetGameObject(building->GetGUID()))) < 50.0f) - player->KilledMonsterCredit(QUEST_CREDIT_DEFEND_SIEGE); - } - } -} - -// Called when a tower is broke -void BattlefieldWG::UpdatedDestroyedTowerCount(TeamId team) -{ - // Southern tower - if (team == GetAttackerTeam()) - { - // Update counter - UpdateData(BATTLEFIELD_WG_DATA_DAMAGED_TOWER_ATT, -1); - UpdateData(BATTLEFIELD_WG_DATA_BROKEN_TOWER_ATT, 1); - - // Remove buff stack on attackers - for (auto itr = m_PlayersInWar[GetAttackerTeam()].begin(); itr != m_PlayersInWar[GetAttackerTeam()].end(); ++itr) - if (Player* player = ObjectAccessor::FindPlayer(*itr)) - player->RemoveAuraFromStack(SPELL_TOWER_CONTROL); - - // Add buff stack to defenders and give achievement/quest credit - for (auto itr = m_PlayersInWar[GetDefenderTeam()].begin(); itr != m_PlayersInWar[GetDefenderTeam()].end(); ++itr) - { - if (Player* player = ObjectAccessor::FindPlayer(*itr)) - { - player->CastSpell(player, SPELL_TOWER_CONTROL, true); - player->KilledMonsterCredit(QUEST_CREDIT_TOWERS_DESTROYED); - DoCompleteOrIncrementAchievement(ACHIEVEMENTS_WG_TOWER_DESTROY, player); - } - } - - // If all three south towers are destroyed (ie. all attack towers), remove ten minutes from battle time - if (GetData(BATTLEFIELD_WG_DATA_BROKEN_TOWER_ATT) == 3) - { - if (int32(m_Timer - 600000) < 0) - m_Timer = 0; - else - m_Timer -= 600000; - SendInitWorldStatesToAll(); - } - } - else // Keep tower - { - UpdateData(BATTLEFIELD_WG_DATA_DAMAGED_TOWER_DEF, -1); - UpdateData(BATTLEFIELD_WG_DATA_BROKEN_TOWER_DEF, 1); - } -} - -void BattlefieldWG::ProcessEvent(WorldObject* obj, uint32 eventId, WorldObject* /*invoker*/) -{ - if (!obj || !IsWarTime()) - return; - - // We handle only gameobjects here - GameObject* go = obj->ToGameObject(); - if (!go) - return; - - // On click on titan relic - if (go->GetEntry() == GO_WINTERGRASP_TITAN_S_RELIC) - { - if (CanInteractWithRelic()) - EndBattle(false); - else if (GameObject* relic = GetRelic()) - relic->SetRespawnTime(RESPAWN_IMMEDIATELY); - } - - // if destroy or damage event, search the wall/tower and update worldstate/send warning message - for (BfWGGameObjectBuilding* building : BuildingsInZone) - { - if (go->GetGUID() == building->GetGUID()) - { - if (GameObject* buildingGo = GetGameObject(building->GetGUID())) - { - if (buildingGo->GetGOInfo()->destructibleBuilding.DamagedEvent == eventId) - building->Damaged(); - else if (buildingGo->GetGOInfo()->destructibleBuilding.DestroyedEvent == eventId) - building->Destroyed(); - break; - } - } - } -} - -// Called when a tower is damaged, used for honor reward calcul -void BattlefieldWG::UpdateDamagedTowerCount(TeamId team) -{ - if (team == GetAttackerTeam()) - UpdateData(BATTLEFIELD_WG_DATA_DAMAGED_TOWER_ATT, 1); - else - UpdateData(BATTLEFIELD_WG_DATA_DAMAGED_TOWER_DEF, 1); -} - -// Update vehicle count WorldState to player -void BattlefieldWG::UpdateVehicleCountWG() -{ - SendUpdateWorldState(WS_BATTLEFIELD_WG_VEHICLE_H, GetData(BATTLEFIELD_WG_DATA_VEHICLE_H)); - SendUpdateWorldState(WS_BATTLEFIELD_WG_MAX_VEHICLE_H, GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_H)); - SendUpdateWorldState(WS_BATTLEFIELD_WG_VEHICLE_A, GetData(BATTLEFIELD_WG_DATA_VEHICLE_A)); - SendUpdateWorldState(WS_BATTLEFIELD_WG_MAX_VEHICLE_A, GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_A)); -} - -void BattlefieldWG::UpdateTenacity() -{ - uint32 alliancePlayers = m_PlayersInWar[TEAM_ALLIANCE].size(); - uint32 hordePlayers = m_PlayersInWar[TEAM_HORDE].size(); - int32 newStack = 0; - - if (alliancePlayers && hordePlayers) - { - if (alliancePlayers < hordePlayers) - newStack = int32((float(hordePlayers / alliancePlayers) - 1) * 4); // positive, should cast on alliance - else if (alliancePlayers > hordePlayers) - newStack = int32((1 - float(alliancePlayers / hordePlayers)) * 4); // negative, should cast on horde - } - - if (newStack == int32(m_tenacityStack)) - return; - - m_tenacityStack = newStack; - // Remove old buff - if (m_tenacityTeam != TEAM_NEUTRAL) - { - for (auto itr = m_players[m_tenacityTeam].begin(); itr != m_players[m_tenacityTeam].end(); ++itr) - if (Player* player = ObjectAccessor::FindPlayer(*itr)) - if (player->GetLevel() >= m_MinLevel) - player->RemoveAurasDueToSpell(SPELL_TENACITY); - - for (auto itr = m_vehicles[m_tenacityTeam].begin(); itr != m_vehicles[m_tenacityTeam].end(); ++itr) - if (Creature* creature = GetCreature(*itr)) - creature->RemoveAurasDueToSpell(SPELL_TENACITY_VEHICLE); - } - - // Apply new buff - if (newStack) - { - m_tenacityTeam = newStack > 0 ? TEAM_ALLIANCE : TEAM_HORDE; - - if (newStack < 0) - newStack = -newStack; - if (newStack > 20) - newStack = 20; - - uint32 buff_honor = SPELL_GREATEST_HONOR; - if (newStack < 15) - buff_honor = SPELL_GREATER_HONOR; - if (newStack < 10) - buff_honor = SPELL_GREAT_HONOR; - if (newStack < 5) - buff_honor = 0; - - for (auto itr = m_PlayersInWar[m_tenacityTeam].begin(); itr != m_PlayersInWar[m_tenacityTeam].end(); ++itr) - if (Player* player = ObjectAccessor::FindPlayer(*itr)) - player->SetAuraStack(SPELL_TENACITY, player, newStack); - - for (auto itr = m_vehicles[m_tenacityTeam].begin(); itr != m_vehicles[m_tenacityTeam].end(); ++itr) - if (Creature* creature = GetCreature(*itr)) - creature->SetAuraStack(SPELL_TENACITY_VEHICLE, creature, newStack); - - if (buff_honor != 0) - { - for (auto itr = m_PlayersInWar[m_tenacityTeam].begin(); itr != m_PlayersInWar[m_tenacityTeam].end(); ++itr) - if (Player* player = ObjectAccessor::FindPlayer(*itr)) - player->CastSpell(player, buff_honor, true); - - for (auto itr = m_vehicles[m_tenacityTeam].begin(); itr != m_vehicles[m_tenacityTeam].end(); ++itr) - if (Creature* creature = GetCreature(*itr)) - creature->CastSpell(creature, buff_honor, true); - } - } - else - m_tenacityTeam = TEAM_NEUTRAL; -} - -WintergraspCapturePoint::WintergraspCapturePoint(BattlefieldWG* battlefield, TeamId teamInControl) : BfCapturePoint(battlefield) -{ - m_Bf = battlefield; - m_team = teamInControl; - m_Workshop = nullptr; -} - -void WintergraspCapturePoint::ChangeTeam(TeamId /*oldTeam*/) -{ - ASSERT(m_Workshop); - m_Workshop->GiveControlTo(m_team); -} - -BfGraveyardWG::BfGraveyardWG(BattlefieldWG* battlefield) : BfGraveyard(battlefield) -{ - m_Bf = battlefield; - m_GossipTextId = 0; -} - -BfWGGameObjectBuilding::BfWGGameObjectBuilding(BattlefieldWG* wg, WintergraspGameObjectBuildingType type, uint32 worldState) -{ - ASSERT(wg); - - _wg = wg; - _teamControl = TEAM_NEUTRAL; - _type = type; - _worldState = worldState; - _state = BATTLEFIELD_WG_OBJECTSTATE_NONE; - _staticTowerInfo = nullptr; -} - -void BfWGGameObjectBuilding::Rebuild() -{ - switch (_type) - { - case BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER: - case BATTLEFIELD_WG_OBJECTTYPE_DOOR_LAST: - case BATTLEFIELD_WG_OBJECTTYPE_DOOR: - case BATTLEFIELD_WG_OBJECTTYPE_WALL: - _teamControl = _wg->GetDefenderTeam(); // Objects that are part of the keep should be the defender's - break; - case BATTLEFIELD_WG_OBJECTTYPE_TOWER: - _teamControl = _wg->GetAttackerTeam(); // The towers in the south should be the attacker's - break; - default: - _teamControl = TEAM_NEUTRAL; - break; - } - - if (GameObject* build = _wg->GetGameObject(_buildGUID)) - { - // Rebuild gameobject - if (build->IsDestructibleBuilding()) - { - build->SetDestructibleState(GO_DESTRUCTIBLE_REBUILDING, nullptr, true); - if (build->GetEntry() == GO_WINTERGRASP_VAULT_GATE) - if (GameObject* go = build->FindNearestGameObject(GO_WINTERGRASP_KEEP_COLLISION_WALL, 50.0f)) - go->SetGoState(GO_STATE_ACTIVE); - - // Update worldstate - _state = WintergraspGameObjectState(BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_INTACT - (_teamControl * 3)); - _wg->SendUpdateWorldState(_worldState, _state); - } - UpdateCreatureAndGo(); - build->SetFaction(WintergraspFaction[_teamControl]); - } -} - -void BfWGGameObjectBuilding::RebuildGate() -{ - if (GameObject* build = _wg->GetGameObject(_buildGUID)) - { - if (build->IsDestructibleBuilding() && build->GetEntry() == GO_WINTERGRASP_VAULT_GATE) - { - if (GameObject* go = build->FindNearestGameObject(GO_WINTERGRASP_KEEP_COLLISION_WALL, 50.0f)) - go->SetGoState(GO_STATE_READY); //not GO_STATE_ACTIVE - } - } -} - -void BfWGGameObjectBuilding::Damaged() -{ - // Update worldstate - _state = WintergraspGameObjectState(BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_DAMAGE - (_teamControl * 3)); - _wg->SendUpdateWorldState(_worldState, _state); - - // Send warning message - if (_staticTowerInfo) - _wg->SendWarning(_staticTowerInfo->TextIds.Damaged); - - for (ObjectGuid guid : m_CreatureTopList[_wg->GetAttackerTeam()]) - if (Creature* creature = _wg->GetCreature(guid)) - _wg->HideNpc(creature); - - for (ObjectGuid guid : m_TurretTopList) - if (Creature* creature = _wg->GetCreature(guid)) - _wg->HideNpc(creature); - - if (_type == BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER) - _wg->UpdateDamagedTowerCount(_wg->GetDefenderTeam()); - else if (_type == BATTLEFIELD_WG_OBJECTTYPE_TOWER) - _wg->UpdateDamagedTowerCount(_wg->GetAttackerTeam()); -} - -void BfWGGameObjectBuilding::Destroyed() -{ - // Update worldstate - _state = WintergraspGameObjectState(BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_DESTROY - (_teamControl * 3)); - _wg->SendUpdateWorldState(_worldState, _state); - - // Warn players - if (_staticTowerInfo) - _wg->SendWarning(_staticTowerInfo->TextIds.Destroyed); - - switch (_type) - { - // Inform the global wintergrasp script of the destruction of this object - case BATTLEFIELD_WG_OBJECTTYPE_TOWER: - case BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER: - _wg->UpdatedDestroyedTowerCount(_teamControl); - break; - case BATTLEFIELD_WG_OBJECTTYPE_DOOR_LAST: - if (GameObject* build = _wg->GetGameObject(_buildGUID)) - if (GameObject* go = build->FindNearestGameObject(GO_WINTERGRASP_KEEP_COLLISION_WALL, 50.0f)) - go->SetGoState(GO_STATE_ACTIVE); - _wg->SetRelicInteractible(true); - if (_wg->GetRelic()) - _wg->GetRelic()->RemoveFlag(GameObjectFlags(GO_FLAG_IN_USE | GO_FLAG_NOT_SELECTABLE)); - else - TC_LOG_ERROR("bg.battlefield.wg", "Titan Relic not found."); - break; - default: - break; - } - - _wg->BrokenWallOrTower(_teamControl, this); -} - -void BfWGGameObjectBuilding::Init(GameObject* go) -{ - if (!go) - return; - - // GameObject associated to object - _buildGUID = go->GetGUID(); - - switch (_type) - { - case BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER: - case BATTLEFIELD_WG_OBJECTTYPE_DOOR_LAST: - case BATTLEFIELD_WG_OBJECTTYPE_DOOR: - case BATTLEFIELD_WG_OBJECTTYPE_WALL: - _teamControl = _wg->GetDefenderTeam(); // Objects that are part of the keep should be the defender's - break; - case BATTLEFIELD_WG_OBJECTTYPE_TOWER: - _teamControl = _wg->GetAttackerTeam(); // The towers in the south should be the attacker's - break; - default: - _teamControl = TEAM_NEUTRAL; - break; - } - - _state = WintergraspGameObjectState(sWorld->getWorldState(_worldState)); - switch (_state) - { - case BATTLEFIELD_WG_OBJECTSTATE_NEUTRAL_INTACT: - case BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_INTACT: - case BATTLEFIELD_WG_OBJECTSTATE_HORDE_INTACT: - go->SetDestructibleState(GO_DESTRUCTIBLE_REBUILDING, nullptr, true); - break; - case BATTLEFIELD_WG_OBJECTSTATE_NEUTRAL_DESTROY: - case BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_DESTROY: - case BATTLEFIELD_WG_OBJECTSTATE_HORDE_DESTROY: - go->SetDestructibleState(GO_DESTRUCTIBLE_DESTROYED); - break; - case BATTLEFIELD_WG_OBJECTSTATE_NEUTRAL_DAMAGE: - case BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_DAMAGE: - case BATTLEFIELD_WG_OBJECTSTATE_HORDE_DAMAGE: - go->SetDestructibleState(GO_DESTRUCTIBLE_DAMAGED); - break; - default: - break; - } - - int32 towerId = -1; - switch (go->GetEntry()) - { - case GO_WINTERGRASP_FORTRESS_TOWER_1: - towerId = BATTLEFIELD_WG_TOWER_FORTRESS_NW; - break; - case GO_WINTERGRASP_FORTRESS_TOWER_2: - towerId = BATTLEFIELD_WG_TOWER_FORTRESS_SW; - break; - case GO_WINTERGRASP_FORTRESS_TOWER_3: - towerId = BATTLEFIELD_WG_TOWER_FORTRESS_SE; - break; - case GO_WINTERGRASP_FORTRESS_TOWER_4: - towerId = BATTLEFIELD_WG_TOWER_FORTRESS_NE; - break; - case GO_WINTERGRASP_SHADOWSIGHT_TOWER: - towerId = BATTLEFIELD_WG_TOWER_SHADOWSIGHT; - break; - case GO_WINTERGRASP_WINTER_S_EDGE_TOWER: - towerId = BATTLEFIELD_WG_TOWER_WINTER_S_EDGE; - break; - case GO_WINTERGRASP_FLAMEWATCH_TOWER: - towerId = BATTLEFIELD_WG_TOWER_FLAMEWATCH; - break; - } - - if (towerId >= BATTLEFIELD_WG_TOWER_SHADOWSIGHT) // Attacker towers - { - // Spawn associate gameobjects - for (WintergraspGameObjectData const& gobData : AttackTowers[towerId - 4].GameObject) - { - if (GameObject* goHorde = _wg->SpawnGameObject(gobData.HordeEntry, gobData.Pos, gobData.Rot)) - m_GameObjectList[TEAM_HORDE].push_back(goHorde->GetGUID()); - - if (GameObject* goAlliance = _wg->SpawnGameObject(gobData.AllianceEntry, gobData.Pos, gobData.Rot)) - m_GameObjectList[TEAM_ALLIANCE].push_back(goAlliance->GetGUID()); - } - - // Spawn associate npc bottom - for (WintergraspObjectPositionData const& creatureData : AttackTowers[towerId - 4].CreatureBottom) - { - if (Creature* creature = _wg->SpawnCreature(creatureData.HordeEntry, creatureData.Pos)) - m_CreatureBottomList[TEAM_HORDE].push_back(creature->GetGUID()); - - if (Creature* creature = _wg->SpawnCreature(creatureData.AllianceEntry, creatureData.Pos)) - m_CreatureBottomList[TEAM_ALLIANCE].push_back(creature->GetGUID()); - } - } - - if (towerId >= 0) - { - ASSERT(towerId < WG_MAX_TOWER); - _staticTowerInfo = &TowerData[towerId]; - - // Spawn Turret bottom - for (Position const& turretPos : TowerCannon[towerId].TowerCannonBottom) - { - if (Creature* turret = _wg->SpawnCreature(NPC_WINTERGRASP_TOWER_CANNON, turretPos)) - { - m_TowerCannonBottomList.push_back(turret->GetGUID()); - switch (go->GetEntry()) - { - case GO_WINTERGRASP_FORTRESS_TOWER_1: - case GO_WINTERGRASP_FORTRESS_TOWER_2: - case GO_WINTERGRASP_FORTRESS_TOWER_3: - case GO_WINTERGRASP_FORTRESS_TOWER_4: - turret->SetFaction(WintergraspFaction[_wg->GetDefenderTeam()]); - break; - case GO_WINTERGRASP_SHADOWSIGHT_TOWER: - case GO_WINTERGRASP_WINTER_S_EDGE_TOWER: - case GO_WINTERGRASP_FLAMEWATCH_TOWER: - turret->SetFaction(WintergraspFaction[_wg->GetAttackerTeam()]); - break; - } - - _wg->HideNpc(turret); - } - } - - // Spawn Turret top - for (Position const& towerCannonPos : TowerCannon[towerId].TurretTop) - { - if (Creature* turret = _wg->SpawnCreature(NPC_WINTERGRASP_TOWER_CANNON, towerCannonPos)) - { - m_TurretTopList.push_back(turret->GetGUID()); - switch (go->GetEntry()) - { - case GO_WINTERGRASP_FORTRESS_TOWER_1: - case GO_WINTERGRASP_FORTRESS_TOWER_2: - case GO_WINTERGRASP_FORTRESS_TOWER_3: - case GO_WINTERGRASP_FORTRESS_TOWER_4: - turret->SetFaction(WintergraspFaction[_wg->GetDefenderTeam()]); - break; - case GO_WINTERGRASP_SHADOWSIGHT_TOWER: - case GO_WINTERGRASP_WINTER_S_EDGE_TOWER: - case GO_WINTERGRASP_FLAMEWATCH_TOWER: - turret->SetFaction(WintergraspFaction[_wg->GetAttackerTeam()]); - break; - } - _wg->HideNpc(turret); - } - } - UpdateCreatureAndGo(); - } -} - -void BfWGGameObjectBuilding::UpdateCreatureAndGo() -{ - for (ObjectGuid guid : m_CreatureTopList[_wg->GetDefenderTeam()]) - if (Creature* creature = _wg->GetCreature(guid)) - _wg->HideNpc(creature); - - for (ObjectGuid guid : m_CreatureTopList[_wg->GetAttackerTeam()]) - if (Creature* creature = _wg->GetCreature(guid)) - _wg->ShowNpc(creature, true); - - for (ObjectGuid guid : m_CreatureBottomList[_wg->GetDefenderTeam()]) - if (Creature* creature = _wg->GetCreature(guid)) - _wg->HideNpc(creature); - - for (ObjectGuid guid : m_CreatureBottomList[_wg->GetAttackerTeam()]) - if (Creature* creature = _wg->GetCreature(guid)) - _wg->ShowNpc(creature, true); - - for (ObjectGuid guid : m_GameObjectList[_wg->GetDefenderTeam()]) - if (GameObject* go = _wg->GetGameObject(guid)) - go->SetRespawnTime(RESPAWN_ONE_DAY); - - for (ObjectGuid guid : m_GameObjectList[_wg->GetAttackerTeam()]) - if (GameObject* go = _wg->GetGameObject(guid)) - go->SetRespawnTime(RESPAWN_IMMEDIATELY); -} - -void BfWGGameObjectBuilding::UpdateTurretAttack(bool disable) -{ - for (ObjectGuid guid : m_TowerCannonBottomList) - { - if (Creature* creature = _wg->GetCreature(guid)) - { - if (disable) - _wg->HideNpc(creature); - else - _wg->ShowNpc(creature, true); - - switch (_buildGUID.GetEntry()) - { - case GO_WINTERGRASP_FORTRESS_TOWER_1: - case GO_WINTERGRASP_FORTRESS_TOWER_2: - case GO_WINTERGRASP_FORTRESS_TOWER_3: - case GO_WINTERGRASP_FORTRESS_TOWER_4: - { - creature->SetFaction(WintergraspFaction[_wg->GetDefenderTeam()]); - break; - } - case GO_WINTERGRASP_SHADOWSIGHT_TOWER: - case GO_WINTERGRASP_WINTER_S_EDGE_TOWER: - case GO_WINTERGRASP_FLAMEWATCH_TOWER: - { - creature->SetFaction(WintergraspFaction[_wg->GetAttackerTeam()]); - break; - } - } - } - } - - for (ObjectGuid guid : m_TurretTopList) - { - if (Creature* creature = _wg->GetCreature(guid)) - { - if (disable) - _wg->HideNpc(creature); - else - _wg->ShowNpc(creature, true); - - switch (_buildGUID.GetEntry()) - { - case GO_WINTERGRASP_FORTRESS_TOWER_1: - case GO_WINTERGRASP_FORTRESS_TOWER_2: - case GO_WINTERGRASP_FORTRESS_TOWER_3: - case GO_WINTERGRASP_FORTRESS_TOWER_4: - { - creature->SetFaction(WintergraspFaction[_wg->GetDefenderTeam()]); - break; - } - case GO_WINTERGRASP_SHADOWSIGHT_TOWER: - case GO_WINTERGRASP_WINTER_S_EDGE_TOWER: - case GO_WINTERGRASP_FLAMEWATCH_TOWER: - { - creature->SetFaction(WintergraspFaction[_wg->GetAttackerTeam()]); - break; - } - } - } - } -} - -void BfWGGameObjectBuilding::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) -{ - packet.Worldstates.emplace_back(_worldState, _state); -} - -void BfWGGameObjectBuilding::Save() -{ - sWorld->setWorldState(_worldState, _state); -} - -WintergraspWorkshop::WintergraspWorkshop(BattlefieldWG* wg, uint8 type) -{ - ASSERT(wg && type < WG_MAX_WORKSHOP); - - _wg = wg; - _state = BATTLEFIELD_WG_OBJECTSTATE_NONE; - _teamControl = TEAM_NEUTRAL; - _staticInfo = &WorkshopData[type]; -} - -uint8 WintergraspWorkshop::GetId() const -{ - return _staticInfo->WorkshopId; -} - -void WintergraspWorkshop::GiveControlTo(TeamId teamId, bool init /*= false*/) -{ - switch (teamId) - { - case TEAM_NEUTRAL: - { - // Send warning message to all player for inform a faction attack a workshop - // alliance / horde attacking workshop - _wg->SendWarning(_teamControl == TEAM_ALLIANCE ? _staticInfo->TextIds.HordeAttack : _staticInfo->TextIds.AllianceAttack); - break; - } - case TEAM_ALLIANCE: - { - // Updating worldstate - _state = BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_INTACT; - _wg->SendUpdateWorldState(_staticInfo->WorldStateId, _state); - - // Warning message - if (!init) - _wg->SendWarning(_staticInfo->TextIds.AllianceCapture); // workshop taken - alliance - - // Found associate graveyard and update it - if (_staticInfo->WorkshopId < BATTLEFIELD_WG_WORKSHOP_KEEP_WEST) - if (BfGraveyard* gy = _wg->GetGraveyardById(_staticInfo->WorkshopId)) - gy->GiveControlTo(TEAM_ALLIANCE); - - _teamControl = teamId; - break; - } - case TEAM_HORDE: - { - // Update worldstate - _state = BATTLEFIELD_WG_OBJECTSTATE_HORDE_INTACT; - _wg->SendUpdateWorldState(_staticInfo->WorldStateId, _state); - - // Warning message - if (!init) - _wg->SendWarning(_staticInfo->TextIds.HordeCapture); // workshop taken - horde - - // Update graveyard control - if (_staticInfo->WorkshopId < BATTLEFIELD_WG_WORKSHOP_KEEP_WEST) - if (BfGraveyard* gy = _wg->GetGraveyardById(_staticInfo->WorkshopId)) - gy->GiveControlTo(TEAM_HORDE); - - _teamControl = teamId; - break; - } - } - if (!init) - _wg->UpdateCounterVehicle(false); -} - -void WintergraspWorkshop::UpdateGraveyardAndWorkshop() -{ - if (_staticInfo->WorkshopId < BATTLEFIELD_WG_WORKSHOP_NE) - GiveControlTo(_wg->GetAttackerTeam(), true); - else - GiveControlTo(_wg->GetDefenderTeam(), true); -} - -void WintergraspWorkshop::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) -{ - packet.Worldstates.emplace_back(_staticInfo->WorldStateId, _state); -} - -void WintergraspWorkshop::Save() -{ - sWorld->setWorldState(_staticInfo->WorldStateId, _state); -} diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.h b/src/server/game/Battlefield/Zones/BattlefieldWG.h deleted file mode 100644 index 2c126ae01f4..00000000000 --- a/src/server/game/Battlefield/Zones/BattlefieldWG.h +++ /dev/null @@ -1,581 +0,0 @@ -/* - * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - */ - -#ifndef BATTLEFIELD_WG_ -#define BATTLEFIELD_WG_ - -#include "Battlefield.h" - -class Group; -class BattlefieldWG; -class WintergraspCapturePoint; - -struct BfWGGameObjectBuilding; -struct WintergraspWorkshop; -struct StaticWintergraspTowerInfo; -struct StaticWintergraspWorkshopInfo; -struct WintergraspObjectPositionData; - -typedef std::vector GameObjectBuildingVect; -typedef std::vector WorkshopVect; - -// used in Player.cpp -extern uint32 const ClockWorldState[]; - -// used in zone_wintergrasp.cpp -TC_GAME_API extern uint32 const WintergraspFaction[]; - -enum WintergraspSpells -{ - // Wartime auras - SPELL_RECRUIT = 37795, - SPELL_CORPORAL = 33280, - SPELL_LIEUTENANT = 55629, - SPELL_TENACITY = 58549, - SPELL_TENACITY_VEHICLE = 59911, - SPELL_TOWER_CONTROL = 62064, - SPELL_SPIRITUAL_IMMUNITY = 58729, - SPELL_GREAT_HONOR = 58555, - SPELL_GREATER_HONOR = 58556, - SPELL_GREATEST_HONOR = 58557, - SPELL_ALLIANCE_FLAG = 14268, - SPELL_HORDE_FLAG = 14267, - SPELL_GRAB_PASSENGER = 61178, - - // Reward spells - SPELL_VICTORY_REWARD = 56902, - SPELL_DEFEAT_REWARD = 58494, - SPELL_DAMAGED_TOWER = 59135, - SPELL_DESTROYED_TOWER = 59136, - SPELL_DAMAGED_BUILDING = 59201, - SPELL_INTACT_BUILDING = 59203, - - SPELL_TELEPORT_BRIDGE = 59096, - SPELL_TELEPORT_FORTRESS = 60035, - - SPELL_TELEPORT_DALARAN = 53360, - SPELL_VICTORY_AURA = 60044, - - // Other spells - SPELL_WINTERGRASP_WATER = 36444, - SPELL_ESSENCE_OF_WINTERGRASP = 58045, - SPELL_WINTERGRASP_RESTRICTED_FLIGHT_AREA = 91604, - - // Phasing spells - SPELL_HORDE_CONTROLS_FACTORY_PHASE_SHIFT = 56618, // ADDS PHASE 16 - SPELL_ALLIANCE_CONTROLS_FACTORY_PHASE_SHIFT = 56617, // ADDS PHASE 32 - - SPELL_HORDE_CONTROL_PHASE_SHIFT = 55773, // ADDS PHASE 64 - SPELL_ALLIANCE_CONTROL_PHASE_SHIFT = 55774 // ADDS PHASE 128 -}; - -enum WintergraspData -{ - BATTLEFIELD_WG_DATA_DAMAGED_TOWER_DEF, - BATTLEFIELD_WG_DATA_BROKEN_TOWER_DEF, - BATTLEFIELD_WG_DATA_DAMAGED_TOWER_ATT, - BATTLEFIELD_WG_DATA_BROKEN_TOWER_ATT, - BATTLEFIELD_WG_DATA_MAX_VEHICLE_A, - BATTLEFIELD_WG_DATA_MAX_VEHICLE_H, - BATTLEFIELD_WG_DATA_VEHICLE_A, - BATTLEFIELD_WG_DATA_VEHICLE_H, - BATTLEFIELD_WG_DATA_WON_A, - BATTLEFIELD_WG_DATA_DEF_A, - BATTLEFIELD_WG_DATA_WON_H, - BATTLEFIELD_WG_DATA_DEF_H, - BATTLEFIELD_WG_DATA_MAX, - - BATTLEFIELD_WG_MAPID = 571 // Northrend -}; - -enum WintergraspAchievements -{ - ACHIEVEMENTS_WIN_WG = 1717, - ACHIEVEMENTS_WIN_WG_100 = 1718, /// @todo: Has to be implemented - ACHIEVEMENTS_WG_GNOMESLAUGHTER = 1723, /// @todo: Has to be implemented - ACHIEVEMENTS_WG_TOWER_DESTROY = 1727, - ACHIEVEMENTS_DESTRUCTION_DERBY_A = 1737, /// @todo: Has to be implemented - ACHIEVEMENTS_WG_TOWER_CANNON_KILL = 1751, /// @todo: Has to be implemented - ACHIEVEMENTS_WG_MASTER_A = 1752, /// @todo: Has to be implemented - ACHIEVEMENTS_WIN_WG_TIMER_10 = 1755, - ACHIEVEMENTS_STONE_KEEPER_50 = 2085, /// @todo: Has to be implemented - ACHIEVEMENTS_STONE_KEEPER_100 = 2086, /// @todo: Has to be implemented - ACHIEVEMENTS_STONE_KEEPER_250 = 2087, /// @todo: Has to be implemented - ACHIEVEMENTS_STONE_KEEPER_500 = 2088, /// @todo: Has to be implemented - ACHIEVEMENTS_STONE_KEEPER_1000 = 2089, /// @todo: Has to be implemented - ACHIEVEMENTS_WG_RANGER = 2199, /// @todo: Has to be implemented - ACHIEVEMENTS_DESTRUCTION_DERBY_H = 2476, /// @todo: Has to be implemented - ACHIEVEMENTS_WG_MASTER_H = 2776 /// @todo: Has to be implemented -}; - -enum WintergraspQuests -{ - QUEST_VICTORY_WINTERGRASP_A = 13181, - QUEST_VICTORY_WINTERGRASP_H = 13183, - QUEST_CREDIT_TOWERS_DESTROYED = 35074, - QUEST_CREDIT_DEFEND_SIEGE = 31284 -}; - -/*######################### - *####### Graveyards ###### - *#########################*/ - -class BfGraveyardWG : public BfGraveyard -{ - public: - BfGraveyardWG(BattlefieldWG* Bf); - - void SetTextId(uint32 textId) { m_GossipTextId = textId; } - uint32 GetTextId() const { return m_GossipTextId; } - - protected: - uint32 m_GossipTextId; -}; - -enum WGGraveyardId -{ - BATTLEFIELD_WG_GY_WORKSHOP_NE, - BATTLEFIELD_WG_GY_WORKSHOP_NW, - BATTLEFIELD_WG_GY_WORKSHOP_SE, - BATTLEFIELD_WG_GY_WORKSHOP_SW, - BATTLEFIELD_WG_GY_KEEP, - BATTLEFIELD_WG_GY_HORDE, - BATTLEFIELD_WG_GY_ALLIANCE, - BATTLEFIELD_WG_GRAVEYARD_MAX -}; - -enum WGGossipText -{ - BATTLEFIELD_WG_GOSSIPTEXT_GY_NE = 20071, - BATTLEFIELD_WG_GOSSIPTEXT_GY_NW = 20072, - BATTLEFIELD_WG_GOSSIPTEXT_GY_SE = 20074, - BATTLEFIELD_WG_GOSSIPTEXT_GY_SW = 20073, - BATTLEFIELD_WG_GOSSIPTEXT_GY_KEEP = 20070, - BATTLEFIELD_WG_GOSSIPTEXT_GY_HORDE = 20075, - BATTLEFIELD_WG_GOSSIPTEXT_GY_ALLIANCE = 20076 -}; - -enum WintergraspNpcs -{ - BATTLEFIELD_WG_NPC_GUARD_H = 30739, - BATTLEFIELD_WG_NPC_GUARD_A = 30740, - BATTLEFIELD_WG_NPC_STALKER = 15214, - - NPC_TAUNKA_SPIRIT_GUIDE = 31841, // Horde spirit guide for Wintergrasp - NPC_DWARVEN_SPIRIT_GUIDE = 31842, // Alliance spirit guide for Wintergrasp - - NPC_WINTERGRASP_SIEGE_ENGINE_ALLIANCE = 28312, - NPC_WINTERGRASP_SIEGE_ENGINE_HORDE = 32627, - NPC_WINTERGRASP_CATAPULT = 27881, - NPC_WINTERGRASP_DEMOLISHER = 28094, - NPC_WINTERGRASP_TOWER_CANNON = 28366 -}; - -/* ######################### * - * WintergraspCapturePoint * - * ######################### */ - -class WintergraspCapturePoint : public BfCapturePoint -{ - public: - WintergraspCapturePoint(BattlefieldWG* battlefield, TeamId teamInControl); - - void LinkToWorkshop(WintergraspWorkshop* workshop) { m_Workshop = workshop; } - - void ChangeTeam(TeamId oldteam) override; - TeamId GetTeam() const { return m_team; } - - protected: - WintergraspWorkshop* m_Workshop; -}; - -/* ######################### * - * WinterGrasp Battlefield * - * ######################### */ - -class TC_GAME_API BattlefieldWG : public Battlefield -{ - public: - ~BattlefieldWG(); - /** - * \brief Called when the battle start - * - Spawn relic and turret - * - Rebuild tower and wall - * - Invite player to war - */ - void OnBattleStart() override; - - /** - * \brief Called when battle end - * - Remove relic and turret - * - Change banner/npc in keep if it needed - * - Saving battlestate - * - Reward honor/mark to player - * - Remove vehicle - * \param endByTimer : true if battle ended when timer is at 00:00, false if battle ended by clicking on relic - */ - void OnBattleEnd(bool endByTimer) override; - - /** - * \brief Called when grouping starts (15 minutes before battlestart) - * - Invite all player in zone to join queue - */ - void OnStartGrouping() override; - - /** - * \brief Called when player accept invite to join battle - * - Update aura - * - Teleport if it needed - * - Update worldstate - * - Update tenacity - * \param player: Player who accepted invite - */ - void OnPlayerJoinWar(Player* player) override; - - /** - * \brief Called when player left the battle - * - Update player aura - * \param player : Player who left the battle - */ - void OnPlayerLeaveWar(Player* player) override; - - /** - * \brief Called when player left the WG zone - * \param player : Player who left the zone - */ - void OnPlayerLeaveZone(Player* player) override; - - /** - * \brief Called when player enters in WG zone - * - Update aura - * - Update worldstate - * \param player : Player who enters the zone - */ - void OnPlayerEnterZone(Player* player) override; - - /** - * \brief Called for update battlefield data - * - Save battle timer in database every minutes - * - Update imunity aura from graveyard - * \param diff : time elapsed since the last call (in ms) - */ - bool Update(uint32 diff) override; - - /** - * \brief Called when a creature is created - * - Update vehicle count - */ - void OnCreatureCreate(Creature* creature) override; - - /** - * \brief Called when a creature is removed - * - Update vehicle count - */ - void OnCreatureRemove(Creature* creature) override; - - /** - * \brief Called when a gameobject is created - */ - void OnGameObjectCreate(GameObject* go) override; - - /** - * \brief Called when a wall/tower is broken - * - Update quest - */ - void BrokenWallOrTower(TeamId team, BfWGGameObjectBuilding* building); - - /** - * \brief Called when a tower is damaged - * - Update tower count (for reward calcul) - */ - void UpdateDamagedTowerCount(TeamId team); - - /** - * \brief Called when tower is broken - * - Update tower buff - * - check if three south tower is down for remove 10 minutes to wg - */ - void UpdatedDestroyedTowerCount(TeamId team); - - void DoCompleteOrIncrementAchievement(uint32 achievement, Player* player, uint8 incrementNumber = 1) override; - - void RemoveAurasFromPlayer(Player* player); - - /** - * \brief Called when battlefield is setup, at server start - */ - bool SetupBattlefield() override; - - /// Return pointer to relic object - GameObject* GetRelic() { return GetGameObject(m_titansRelicGUID); } - - /// Define relic object - void SetRelic(ObjectGuid relicGUID) { m_titansRelicGUID = relicGUID; } - - /// Check if players can interact with the relic (Only if the last door has been broken) - bool CanInteractWithRelic() { return m_isRelicInteractible; } - - /// Define if player can interact with the relic - void SetRelicInteractible(bool allow) { m_isRelicInteractible = allow; } - - void UpdateVehicleCountWG(); - void UpdateCounterVehicle(bool init); - - void SendInitWorldStatesTo(Player* player); - void SendInitWorldStatesToAll() override; - void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; - - void HandleKill(Player* killer, Unit* victim) override; - void OnUnitDeath(Unit* unit) override; - void HandlePromotion(Player* killer, Unit* killed); - void PromotePlayer(Player* killer); - - void UpdateTenacity(); - void ProcessEvent(WorldObject* obj, uint32 eventId, WorldObject* invoker) override; - - bool FindAndRemoveVehicleFromList(Unit* vehicle); - - // returns the graveyardId in the specified area. - uint8 GetSpiritGraveyardId(uint32 areaId) const; - - uint32 GetData(uint32 data) const override; - - protected: - bool m_isRelicInteractible; - - WorkshopVect Workshops; - - GuidVector DefenderPortalList[PVP_TEAMS_COUNT]; - GameObjectBuildingVect BuildingsInZone; - - GuidUnorderedSet m_vehicles[PVP_TEAMS_COUNT]; - GuidVector CanonList; - - TeamId m_tenacityTeam; - uint32 m_tenacityStack; - uint32 m_saveTimer; - - ObjectGuid m_titansRelicGUID; -}; - -enum WintergraspGameObjectBuildingType -{ - BATTLEFIELD_WG_OBJECTTYPE_DOOR, - BATTLEFIELD_WG_OBJECTTYPE_TITANRELIC, - BATTLEFIELD_WG_OBJECTTYPE_WALL, - BATTLEFIELD_WG_OBJECTTYPE_DOOR_LAST, - BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER, - BATTLEFIELD_WG_OBJECTTYPE_TOWER -}; - -enum WintergraspGameObjectState -{ - BATTLEFIELD_WG_OBJECTSTATE_NONE, - BATTLEFIELD_WG_OBJECTSTATE_NEUTRAL_INTACT, - BATTLEFIELD_WG_OBJECTSTATE_NEUTRAL_DAMAGE, - BATTLEFIELD_WG_OBJECTSTATE_NEUTRAL_DESTROY, - BATTLEFIELD_WG_OBJECTSTATE_HORDE_INTACT, - BATTLEFIELD_WG_OBJECTSTATE_HORDE_DAMAGE, - BATTLEFIELD_WG_OBJECTSTATE_HORDE_DESTROY, - BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_INTACT, - BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_DAMAGE, - BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_DESTROY -}; - -enum WintergraspTowerIds -{ - BATTLEFIELD_WG_TOWER_FORTRESS_NW, - BATTLEFIELD_WG_TOWER_FORTRESS_SW, - BATTLEFIELD_WG_TOWER_FORTRESS_SE, - BATTLEFIELD_WG_TOWER_FORTRESS_NE, - BATTLEFIELD_WG_TOWER_SHADOWSIGHT, - BATTLEFIELD_WG_TOWER_WINTER_S_EDGE, - BATTLEFIELD_WG_TOWER_FLAMEWATCH -}; - -enum WintergraspWorkshopIds -{ - BATTLEFIELD_WG_WORKSHOP_SE, - BATTLEFIELD_WG_WORKSHOP_SW, - BATTLEFIELD_WG_WORKSHOP_NE, - BATTLEFIELD_WG_WORKSHOP_NW, - BATTLEFIELD_WG_WORKSHOP_KEEP_WEST, - BATTLEFIELD_WG_WORKSHOP_KEEP_EAST -}; - -enum WintergraspTeamControl -{ - BATTLEFIELD_WG_TEAM_ALLIANCE, - BATTLEFIELD_WG_TEAM_HORDE, - BATTLEFIELD_WG_TEAM_NEUTRAL -}; - -enum WintergraspText -{ - // Invisible Stalker - BATTLEFIELD_WG_TEXT_SOUTHERN_TOWER_DAMAGE = 1, - BATTLEFIELD_WG_TEXT_SOUTHERN_TOWER_DESTROY = 2, - BATTLEFIELD_WG_TEXT_EASTERN_TOWER_DAMAGE = 3, - BATTLEFIELD_WG_TEXT_EASTERN_TOWER_DESTROY = 4, - BATTLEFIELD_WG_TEXT_WESTERN_TOWER_DAMAGE = 5, - BATTLEFIELD_WG_TEXT_WESTERN_TOWER_DESTROY = 6, - BATTLEFIELD_WG_TEXT_NW_KEEPTOWER_DAMAGE = 7, - BATTLEFIELD_WG_TEXT_NW_KEEPTOWER_DESTROY = 8, - BATTLEFIELD_WG_TEXT_SE_KEEPTOWER_DAMAGE = 9, - BATTLEFIELD_WG_TEXT_SE_KEEPTOWER_DESTROY = 10, - BATTLEFIELD_WG_TEXT_BROKEN_TEMPLE_ATTACK_ALLIANCE = 11, - BATTLEFIELD_WG_TEXT_BROKEN_TEMPLE_CAPTURE_ALLIANCE = 12, - BATTLEFIELD_WG_TEXT_BROKEN_TEMPLE_ATTACK_HORDE = 13, - BATTLEFIELD_WG_TEXT_BROKEN_TEMPLE_CAPTURE_HORDE = 14, - BATTLEFIELD_WG_TEXT_EASTSPARK_ATTACK_ALLIANCE = 15, - BATTLEFIELD_WG_TEXT_EASTSPARK_CAPTURE_ALLIANCE = 16, - BATTLEFIELD_WG_TEXT_EASTSPARK_ATTACK_HORDE = 17, - BATTLEFIELD_WG_TEXT_EASTSPARK_CAPTURE_HORDE = 18, - BATTLEFIELD_WG_TEXT_SUNKEN_RING_ATTACK_ALLIANCE = 19, - BATTLEFIELD_WG_TEXT_SUNKEN_RING_CAPTURE_ALLIANCE = 20, - BATTLEFIELD_WG_TEXT_SUNKEN_RING_ATTACK_HORDE = 21, - BATTLEFIELD_WG_TEXT_SUNKEN_RING_CAPTURE_HORDE = 22, - BATTLEFIELD_WG_TEXT_WESTSPARK_ATTACK_ALLIANCE = 23, - BATTLEFIELD_WG_TEXT_WESTSPARK_CAPTURE_ALLIANCE = 24, - BATTLEFIELD_WG_TEXT_WESTSPARK_ATTACK_HORDE = 25, - BATTLEFIELD_WG_TEXT_WESTSPARK_CAPTURE_HORDE = 26, - - BATTLEFIELD_WG_TEXT_START_GROUPING = 27, - BATTLEFIELD_WG_TEXT_START_BATTLE = 28, - BATTLEFIELD_WG_TEXT_FORTRESS_DEFEND_ALLIANCE = 29, - BATTLEFIELD_WG_TEXT_FORTRESS_CAPTURE_ALLIANCE = 30, - BATTLEFIELD_WG_TEXT_FORTRESS_DEFEND_HORDE = 31, - BATTLEFIELD_WG_TEXT_FORTRESS_CAPTURE_HORDE = 32, - - BATTLEFIELD_WG_TEXT_NE_KEEPTOWER_DAMAGE = 33, - BATTLEFIELD_WG_TEXT_NE_KEEPTOWER_DESTROY = 34, - BATTLEFIELD_WG_TEXT_SW_KEEPTOWER_DAMAGE = 35, - BATTLEFIELD_WG_TEXT_SW_KEEPTOWER_DESTROY = 36, - - BATTLEFIELD_WG_TEXT_RANK_CORPORAL = 37, - BATTLEFIELD_WG_TEXT_RANK_FIRST_LIEUTENANT = 38 -}; - -enum WintergraspGameObject -{ - GO_WINTERGRASP_FACTORY_BANNER_NE = 190475, - GO_WINTERGRASP_FACTORY_BANNER_NW = 190487, - GO_WINTERGRASP_FACTORY_BANNER_SE = 194959, - GO_WINTERGRASP_FACTORY_BANNER_SW = 194962, - - GO_WINTERGRASP_TITAN_S_RELIC = 192829, - - GO_WINTERGRASP_FORTRESS_TOWER_1 = 190221, - GO_WINTERGRASP_FORTRESS_TOWER_2 = 190373, - GO_WINTERGRASP_FORTRESS_TOWER_3 = 190377, - GO_WINTERGRASP_FORTRESS_TOWER_4 = 190378, - - GO_WINTERGRASP_SHADOWSIGHT_TOWER = 190356, - GO_WINTERGRASP_WINTER_S_EDGE_TOWER = 190357, - GO_WINTERGRASP_FLAMEWATCH_TOWER = 190358, - - GO_WINTERGRASP_FORTRESS_GATE = 190375, - GO_WINTERGRASP_VAULT_GATE = 191810, - - GO_WINTERGRASP_KEEP_COLLISION_WALL = 194323 -}; - -// ******************************************************************** -// * Structs using for Building, Graveyard, Workshop * -// ******************************************************************** - -// Structure for different buildings that can be destroyed during battle -struct TC_GAME_API BfWGGameObjectBuilding -{ -private: - // WG object - BattlefieldWG* _wg; - - // Linked gameobject - ObjectGuid _buildGUID; - - // the team that controls this point - TeamId _teamControl; - - WintergraspGameObjectBuildingType _type; - uint32 _worldState; - - WintergraspGameObjectState _state; - - StaticWintergraspTowerInfo const* _staticTowerInfo; - - // GameObject associations - GuidVector m_GameObjectList[PVP_TEAMS_COUNT]; - - // Creature associations - GuidVector m_CreatureBottomList[PVP_TEAMS_COUNT]; - GuidVector m_CreatureTopList[PVP_TEAMS_COUNT]; - GuidVector m_TowerCannonBottomList; - GuidVector m_TurretTopList; - -public: - BfWGGameObjectBuilding(BattlefieldWG* wg, WintergraspGameObjectBuildingType type, uint32 worldState); - void Init(GameObject* go); - - ObjectGuid const& GetGUID() const { return _buildGUID; } - - void Rebuild(); - void RebuildGate(); - - // Called when associated gameobject is damaged - void Damaged(); - - // Called when associated gameobject is destroyed - void Destroyed(); - - void UpdateCreatureAndGo(); - - void UpdateTurretAttack(bool disable); - - void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet); - - void Save(); -}; - -// Structure for the 6 workshop -struct TC_GAME_API WintergraspWorkshop -{ -private: - BattlefieldWG* _wg; // Pointer to wintergrasp - ObjectGuid _buildGUID; - WintergraspGameObjectState _state; // For worldstate - TeamId _teamControl; // Team witch control the workshop - - StaticWintergraspWorkshopInfo const* _staticInfo; - -public: - WintergraspWorkshop(BattlefieldWG* wg, uint8 type); - - uint8 GetId() const; - TeamId GetTeamControl() const { return _teamControl; } - - // Called on change faction in CapturePoint class - void GiveControlTo(TeamId teamId, bool init = false); - - void UpdateGraveyardAndWorkshop(); - - void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet); - - void Save(); -}; - -#endif diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index ff8711ade2c..70ca1340b31 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -26,8 +26,6 @@ #include "Bag.h" #include "Battlefield.h" #include "BattlefieldMgr.h" -#include "BattlefieldTB.h" -#include "BattlefieldWG.h" #include "Battleground.h" #include "BattlegroundMgr.h" #include "BattlegroundPackets.h" @@ -9747,11 +9745,11 @@ void Player::SendInitWorldStates(uint32 zoneId, uint32 areaId) case 5389: // Tol Barad Peninsula if (sWorld->getBoolConfig(CONFIG_TOLBARAD_ENABLE)) { - packet.Worldstates.emplace_back(5385u, sWorld->getWorldState(5385)); // TB_WS_ALLIANCE_CONTROLS_SHOW - packet.Worldstates.emplace_back(5384u, sWorld->getWorldState(5384)); // TB_WS_HORDE_CONTROLS_SHOW - packet.Worldstates.emplace_back(5387u, sWorld->getWorldState(5387)); // TB_WS_TIME_NEXT_BATTLE_SHOW - packet.Worldstates.emplace_back(5546u, sWorld->getWorldState(5546)); // TB_WS_ALLIANCE_ATTACKING_SHOW - packet.Worldstates.emplace_back(5547u, sWorld->getWorldState(5547)); // TB_WS_HORDE_ATTACKING_SHOW + packet.Worldstates.emplace_back(WS_BATTLEFIELD_TB_ALLIANCE_CONTROLS_SHOW, sWorld->getWorldState(WS_BATTLEFIELD_TB_ALLIANCE_CONTROLS_SHOW)); + packet.Worldstates.emplace_back(WS_BATTLEFIELD_TB_HORDE_CONTROLS_SHOW, sWorld->getWorldState(WS_BATTLEFIELD_TB_HORDE_CONTROLS_SHOW)); + packet.Worldstates.emplace_back(WS_BATTLEFIELD_TB_TIME_NEXT_BATTLE_SHOW, sWorld->getWorldState(WS_BATTLEFIELD_TB_TIME_NEXT_BATTLE_SHOW)); + packet.Worldstates.emplace_back(WS_BATTLEFIELD_TB_ALLIANCE_ATTACKING_SHOW, sWorld->getWorldState(WS_BATTLEFIELD_TB_ALLIANCE_ATTACKING_SHOW)); + packet.Worldstates.emplace_back(WS_BATTLEFIELD_TB_HORDE_ATTACKING_SHOW, sWorld->getWorldState(WS_BATTLEFIELD_TB_HORDE_ATTACKING_SHOW)); } break; case 5095: // Tol Barad @@ -9791,7 +9789,7 @@ void Player::SendBattlefieldWorldStates() const { SendUpdateWorldState(WS_BATTLEFIELD_WG_ACTIVE, wg->IsWarTime() ? 0 : 1); uint32 timer = wg->IsWarTime() ? 0 : (wg->GetTimer() / 1000); // 0 - Time to next battle - SendUpdateWorldState(ClockWorldState[1], uint32(GameTime::GetGameTime() + timer)); + SendUpdateWorldState(WS_BATTLEFIELD_WG_TIME_NEXT_BATTLE, uint32(GameTime::GetGameTime() + timer)); } } @@ -9799,10 +9797,10 @@ void Player::SendBattlefieldWorldStates() const { if (Battlefield* tb = sBattlefieldMgr->GetBattlefieldByBattleId(BATTLEFIELD_BATTLEID_TB)) { - SendUpdateWorldState(TB_WS_FACTION_CONTROLLING, uint32(tb->GetDefenderTeam() + 1)); + SendUpdateWorldState(WS_BATTLEFIELD_TB_FACTION_CONTROLLING, uint32(tb->GetDefenderTeam() + 1)); uint32 timer = tb->GetTimer() / 1000; - SendUpdateWorldState(TB_WS_TIME_BATTLE_END, uint32(tb->IsWarTime() ? uint32(GameTime::GetGameTime() + timer) : 0)); - SendUpdateWorldState(TB_WS_TIME_NEXT_BATTLE, uint32(!tb->IsWarTime() ? uint32(GameTime::GetGameTime() + timer) : 0)); + SendUpdateWorldState(WS_BATTLEFIELD_TB_TIME_BATTLE_END, uint32(tb->IsWarTime() ? uint32(GameTime::GetGameTime() + timer) : 0)); + SendUpdateWorldState(WS_BATTLEFIELD_TB_TIME_NEXT_BATTLE, uint32(!tb->IsWarTime() ? uint32(GameTime::GetGameTime() + timer) : 0)); } } } diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 7093f1831aa..585a8a252d1 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -7719,6 +7719,76 @@ enum WorldState : uint32 WS_BATTLEFIELD_WG_DEFENDED_A = 4025, WS_BATTLEFIELD_WG_TIME_NEXT_BATTLE = 4354, + WS_BATTLEFIELD_TB_ALLIANCE_CONTROLS_SHOW = 5385, + WS_BATTLEFIELD_TB_HORDE_CONTROLS_SHOW = 5384, + WS_BATTLEFIELD_TB_ALLIANCE_ATTACKING_SHOW = 5546, + WS_BATTLEFIELD_TB_HORDE_ATTACKING_SHOW = 5547, + + WS_BATTLEFIELD_TB_BUILDINGS_CAPTURED = 5348, + WS_BATTLEFIELD_TB_BUILDINGS_CAPTURED_SHOW = 5349, + WS_BATTLEFIELD_TB_TOWERS_DESTROYED = 5347, + WS_BATTLEFIELD_TB_TOWERS_DESTROYED_SHOW = 5350, + + WS_BATTLEFIELD_TB_FACTION_CONTROLLING = 5334, // 1 -> Alliance, 2 -> Horde + + WS_BATTLEFIELD_TB_TIME_NEXT_BATTLE = 5332, + WS_BATTLEFIELD_TB_TIME_NEXT_BATTLE_SHOW = 5387, + WS_BATTLEFIELD_TB_TIME_BATTLE_END = 5333, + WS_BATTLEFIELD_TB_TIME_BATTLE_END_SHOW = 5346, + + WS_BATTLEFIELD_TB_STATE_PREPARATIONS = 5684, + WS_BATTLEFIELD_TB_STATE_BATTLE = 5344, + + WS_BATTLEFIELD_TB_PROGRESS_SHOW = 5376, + WS_BATTLEFIELD_TB_PROGRESS = 5377, // 0 horde, 100 alliance + WS_BATTLEFIELD_TB_PROGRESS_PERCENT_GREY = 5378, + + WS_BATTLEFIELD_TB_KEEP_HORDE = 5469, + WS_BATTLEFIELD_TB_KEEP_ALLIANCE = 5470, + + WS_BATTLEFIELD_TB_GARRISON_HORDE_CONTROLLED = 5418, + WS_BATTLEFIELD_TB_GARRISON_HORDE_CAPTURING = 5419, + WS_BATTLEFIELD_TB_GARRISON_NEUTRAL = 5420, // unused + WS_BATTLEFIELD_TB_GARRISON_ALLIANCE_CAPTURING = 5421, + WS_BATTLEFIELD_TB_GARRISON_ALLIANCE_CONTROLLED = 5422, + + WS_BATTLEFIELD_TB_VIGIL_HORDE_CONTROLLED = 5423, + WS_BATTLEFIELD_TB_VIGIL_HORDE_CAPTURING = 5424, + WS_BATTLEFIELD_TB_VIGIL_NEUTRAL = 5425, // unused + WS_BATTLEFIELD_TB_VIGIL_ALLIANCE_CAPTURING = 5426, + WS_BATTLEFIELD_TB_VIGIL_ALLIANCE_CONTROLLED = 5427, + + WS_BATTLEFIELD_TB_SLAGWORKS_HORDE_CONTROLLED = 5428, + WS_BATTLEFIELD_TB_SLAGWORKS_HORDE_CAPTURING = 5429, + WS_BATTLEFIELD_TB_SLAGWORKS_NEUTRAL = 5430, // unused + WS_BATTLEFIELD_TB_SLAGWORKS_ALLIANCE_CAPTURING = 5431, + WS_BATTLEFIELD_TB_SLAGWORKS_ALLIANCE_CONTROLLED = 5432, + + WS_BATTLEFIELD_TB_WEST_INTACT_HORDE = 5433, + WS_BATTLEFIELD_TB_WEST_DAMAGED_HORDE = 5434, + WS_BATTLEFIELD_TB_WEST_DESTROYED_NEUTRAL = 5435, + WS_BATTLEFIELD_TB_WEST_INTACT_ALLIANCE = 5436, + WS_BATTLEFIELD_TB_WEST_DAMAGED_ALLIANCE = 5437, + WS_BATTLEFIELD_TB_WEST_INTACT_NEUTRAL = 5453, // unused + WS_BATTLEFIELD_TB_WEST_DAMAGED_NEUTRAL = 5454, // unused + + WS_BATTLEFIELD_TB_SOUTH_INTACT_HORDE = 5438, + WS_BATTLEFIELD_TB_SOUTH_DAMAGED_HORDE = 5439, + WS_BATTLEFIELD_TB_SOUTH_DESTROYED_NEUTRAL = 5440, + WS_BATTLEFIELD_TB_SOUTH_INTACT_ALLIANCE = 5441, + WS_BATTLEFIELD_TB_SOUTH_DAMAGED_ALLIANCE = 5442, + WS_BATTLEFIELD_TB_SOUTH_INTACT_NEUTRAL = 5455, // unused + WS_BATTLEFIELD_TB_SOUTH_DAMAGED_NEUTRAL = 5456, // unused + + WS_BATTLEFIELD_TB_EAST_INTACT_HORDE = 5443, + WS_BATTLEFIELD_TB_EAST_DAMAGED_HORDE = 5444, + WS_BATTLEFIELD_TB_EAST_DESTROYED_NEUTRAL = 5445, + WS_BATTLEFIELD_TB_EAST_INTACT_ALLIANCE = 5446, + WS_BATTLEFIELD_TB_EAST_DAMAGED_ALLIANCE = 5447, + WS_BATTLEFIELD_TB_EAST_INTACT_NEUTRAL = 5451, + WS_BATTLEFIELD_TB_EAST_DAMAGED_NEUTRAL = 5452, + + WS_CURRENCY_RESET_TIME = 20001, // Next arena distribution time WS_WEEKLY_QUEST_RESET_TIME = 20002, // Next weekly quest reset time WS_BG_DAILY_RESET_TIME = 20003, // Next daily BG reset time diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp index 038aa13a952..6eb82ae349a 100644 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -84,6 +84,10 @@ template<> struct is_script_database_bound : std::true_type { }; +template<> +struct is_script_database_bound + : std::true_type { }; + template<> struct is_script_database_bound : std::true_type { }; @@ -724,6 +728,11 @@ class ScriptRegistrySwapHooks AreaTrigger, AreaTriggerEntityScript, Base > { }; +/// This hook is responsible for swapping BattlefieldScripts +template +class ScriptRegistrySwapHooks + : public UnsupportedScriptRegistrySwapHooks { }; + /// This hook is responsible for swapping BattlegroundScript's template class ScriptRegistrySwapHooks @@ -1720,6 +1729,12 @@ bool ScriptMgr::OnAreaTrigger(Player* player, AreaTriggerEntry const* trigger, b return entered ? tmpscript->OnTrigger(player, trigger) : tmpscript->OnExit(player, trigger); } +Battlefield* ScriptMgr::CreateBattlefield(uint32 scriptId) +{ + GET_SCRIPT_RET(BattlefieldScript, scriptId, tmpscript, nullptr); + return tmpscript->GetBattlefield(); +} + Battleground* ScriptMgr::CreateBattleground(BattlegroundTypeId /*typeId*/) { /// @todo Implement script-side battlegrounds. @@ -2437,6 +2452,12 @@ bool OnlyOnceAreaTriggerScript::OnTrigger(Player* player, AreaTriggerEntry const void OnlyOnceAreaTriggerScript::ResetAreaTriggerDone(InstanceScript* script, uint32 triggerId) { script->ResetAreaTriggerDone(triggerId); } void OnlyOnceAreaTriggerScript::ResetAreaTriggerDone(Player const* player, AreaTriggerEntry const* trigger) { if (InstanceScript* instance = player->GetInstanceScript()) ResetAreaTriggerDone(instance, trigger->ID); } +BattlefieldScript::BattlefieldScript(char const* name) + : ScriptObject(name) +{ + ScriptRegistry::Instance()->AddScript(this); +} + BattlegroundScript::BattlegroundScript(char const* name) : ScriptObject(name) { @@ -2557,6 +2578,7 @@ template class TC_GAME_API ScriptRegistry; template class TC_GAME_API ScriptRegistry; template class TC_GAME_API ScriptRegistry; template class TC_GAME_API ScriptRegistry; +template class TC_GAME_API ScriptRegistry; template class TC_GAME_API ScriptRegistry; template class TC_GAME_API ScriptRegistry; template class TC_GAME_API ScriptRegistry; diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index 20f7ca37715..e8694f64f70 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -28,6 +28,7 @@ class AreaTriggerAI; class AuctionHouseObject; class Aura; class AuraScript; +class Battlefield; class Battleground; class BattlegroundMap; class Channel; @@ -470,6 +471,17 @@ class TC_GAME_API OnlyOnceAreaTriggerScript : public AreaTriggerScript void ResetAreaTriggerDone(Player const* player, AreaTriggerEntry const* trigger); }; +class TC_GAME_API BattlefieldScript : public ScriptObject +{ + protected: + + BattlefieldScript(char const* name); + + public: + + virtual Battlefield* GetBattlefield() const = 0; +}; + class TC_GAME_API BattlegroundScript : public ScriptObject { protected: @@ -1016,6 +1028,10 @@ class TC_GAME_API ScriptMgr bool OnAreaTrigger(Player* player, AreaTriggerEntry const* trigger, bool entered); + public: /* BattlefieldScript */ + + Battlefield* CreateBattlefield(uint32 scriptId); + public: /* BattlegroundScript */ Battleground* CreateBattleground(BattlegroundTypeId typeId); diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index cc830ac492a..f04b788fd70 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -17,7 +17,6 @@ #include "SpellMgr.h" #include "BattlefieldMgr.h" -#include "BattlefieldWG.h" #include "BattlegroundMgr.h" #include "Chat.h" #include "Containers.h" diff --git a/src/server/scripts/Battlefield/BattlefieldTB.cpp b/src/server/scripts/Battlefield/BattlefieldTB.cpp new file mode 100644 index 00000000000..e147689d610 --- /dev/null +++ b/src/server/scripts/Battlefield/BattlefieldTB.cpp @@ -0,0 +1,889 @@ +/* +* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along +* with this program. If not, see . +*/ + +// 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 "Battleground.h" +#include "CreatureTextMgr.h" +#include "GameObject.h" +#include "GameTime.h" +#include "MapManager.h" +#include "ObjectAccessor.h" +#include "Player.h" +#include "Random.h" +#include "ScriptMgr.h" +#include "SpellAuras.h" +#include "TemporarySummon.h" +#include "World.h" +#include "WorldStatePackets.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(WS_BATTLEFIELD_TB_STATE_BATTLE) == 1 || sWorld->getWorldState(WS_BATTLEFIELD_TB_TIME_NEXT_BATTLE) == 0) + sWorld->setWorldState(WS_BATTLEFIELD_TB_TIME_NEXT_BATTLE, m_RestartAfterCrash); + + // Set timer + m_Timer = sWorld->getWorldState(WS_BATTLEFIELD_TB_TIME_NEXT_BATTLE); + + // Defending team isn't set yet? Choose randomly. + if (sWorld->getWorldState(WS_BATTLEFIELD_TB_FACTION_CONTROLLING) == 0) + sWorld->setWorldState(WS_BATTLEFIELD_TB_FACTION_CONTROLLING, uint32(urand(1, 2))); + + // Set defender team + SetDefenderTeam(TeamId(sWorld->getWorldState(WS_BATTLEFIELD_TB_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].pos, QuaternionData::fromEulerAnglesZYX(TBCapturePoints[i].pos.GetOrientation(), 0.0f, 0.0f))) + { + 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].pos, QuaternionData::fromEulerAnglesZYX(TBTowers[i].pos.GetOrientation(), 0.0f, 0.0f))) + 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].pos)) + 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(WS_BATTLEFIELD_TB_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->GetTeamId() == GetAttackerTeam() && GetData(BATTLEFIELD_TB_DATA_TOWERS_DESTROYED) > 0) + player->CastSpell(player, SPELL_TOWER_ATTACK_BONUS, CastSpellExtraArgs(TRIGGERED_FULL_MASK).AddSpellMod(SPELLVALUE_AURA_STACK, GetData(BATTLEFIELD_TB_DATA_TOWERS_DESTROYED))); +} + + +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(WS_BATTLEFIELD_TB_ALLIANCE_ATTACKING_SHOW), int32(IsWarTime() && GetAttackerTeam() == TEAM_ALLIANCE ? 1 : 0)); + packet.Worldstates.emplace_back(uint32(WS_BATTLEFIELD_TB_HORDE_ATTACKING_SHOW), int32(IsWarTime() && GetAttackerTeam() == TEAM_HORDE ? 1 : 0)); + + // Not sure if TB + //packet.Worldstates.emplace_back(uint32(WS_BATTLEFIELD_TB_9_UNKNOWN), int32(1)); + + packet.Worldstates.emplace_back(uint32(WS_BATTLEFIELD_TB_SOUTH_DAMAGED_NEUTRAL), int32(0)); + packet.Worldstates.emplace_back(uint32(WS_BATTLEFIELD_TB_SOUTH_INTACT_NEUTRAL), int32(0)); + + packet.Worldstates.emplace_back(uint32(WS_BATTLEFIELD_TB_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(WS_BATTLEFIELD_TB_TOWERS_DESTROYED_SHOW), int32(GetData(BATTLEFIELD_TB_DATA_TOWERS_DESTROYED))); + packet.Worldstates.emplace_back(uint32(WS_BATTLEFIELD_TB_BUILDINGS_CAPTURED_SHOW), int32(IsWarTime() ? 1 : 0)); + packet.Worldstates.emplace_back(uint32(WS_BATTLEFIELD_TB_BUILDINGS_CAPTURED), int32(GetData(BATTLEFIELD_TB_DATA_BUILDINGS_CAPTURED))); + packet.Worldstates.emplace_back(uint32(WS_BATTLEFIELD_TB_TOWERS_DESTROYED), int32(0)); + + packet.Worldstates.emplace_back(uint32(WS_BATTLEFIELD_TB_TIME_BATTLE_END_SHOW), int32(IsWarTime() ? 1 : 0)); + + packet.Worldstates.emplace_back(uint32(WS_BATTLEFIELD_TB_STATE_BATTLE), int32(IsWarTime() ? 1 : 0)); + packet.Worldstates.emplace_back(uint32(WS_BATTLEFIELD_TB_STATE_PREPARATIONS), int32(GetState() == BATTLEFIELD_WARMUP ? 1 : 0)); + + // Not sure if TB + //packet.Worldstates.emplace_back(uint32(WS_BATTLEFIELD_TB_35_UNKNOWN), int32(0)); + //packet.Worldstates.emplace_back(uint32(WS_BATTLEFIELD_TB_36_UNKNOWN), int32(0)); + //packet.Worldstates.emplace_back(uint32(WS_BATTLEFIELD_TB_37_UNKNOWN), int32(0)); + + // Unused tower icons + packet.Worldstates.emplace_back(uint32(WS_BATTLEFIELD_TB_WEST_DAMAGED_NEUTRAL), int32(0)); + packet.Worldstates.emplace_back(uint32(WS_BATTLEFIELD_TB_WEST_INTACT_NEUTRAL), int32(0)); + packet.Worldstates.emplace_back(uint32(WS_BATTLEFIELD_TB_EAST_DAMAGED_NEUTRAL), int32(0)); + packet.Worldstates.emplace_back(uint32(WS_BATTLEFIELD_TB_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(WS_BATTLEFIELD_TB_TIME_NEXT_BATTLE_SHOW), int32(!IsWarTime() ? 1 : 0)); + + packet.Worldstates.emplace_back(uint32(WS_BATTLEFIELD_TB_ALLIANCE_CONTROLS_SHOW), int32(!IsWarTime() && GetDefenderTeam() == TEAM_ALLIANCE ? 1 : 0)); + packet.Worldstates.emplace_back(uint32(WS_BATTLEFIELD_TB_HORDE_CONTROLS_SHOW), int32(!IsWarTime() && GetDefenderTeam() == TEAM_HORDE ? 1 : 0)); + + packet.Worldstates.emplace_back(uint32(WS_BATTLEFIELD_TB_TIME_BATTLE_END), int32(IsWarTime() ? GameTime::GetGameTime() + (m_Timer / 1000) : 0)); + packet.Worldstates.emplace_back(uint32(WS_BATTLEFIELD_TB_TIME_NEXT_BATTLE), int32(!IsWarTime() ? GameTime::GetGameTime() + (m_Timer / 1000) : 0)); + + // Not sure if TB + //packet.Worldstates.emplace_back(uint32(WS_BATTLEFIELD_TB_65_UNKNOWN), int32(0)); + //packet.Worldstates.emplace_back(uint32(WS_BATTLEFIELD_TB_66_UNKNOWN), int32(0)); + + packet.Worldstates.emplace_back(uint32(WS_BATTLEFIELD_TB_KEEP_ALLIANCE), int32(GetDefenderTeam() == TEAM_ALLIANCE ? 1 : 0)); + packet.Worldstates.emplace_back(uint32(WS_BATTLEFIELD_TB_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(WS_BATTLEFIELD_TB_STATE_BATTLE, uint32(IsWarTime() ? 1 : 0)); + sWorld->setWorldState(WS_BATTLEFIELD_TB_ALLIANCE_CONTROLS_SHOW, uint32(!IsWarTime() && GetDefenderTeam() == TEAM_ALLIANCE ? 1 : 0)); + sWorld->setWorldState(WS_BATTLEFIELD_TB_HORDE_CONTROLS_SHOW, uint32(!IsWarTime() && GetDefenderTeam() == TEAM_HORDE ? 1 : 0)); + sWorld->setWorldState(WS_BATTLEFIELD_TB_ALLIANCE_ATTACKING_SHOW, uint32(IsWarTime() && GetAttackerTeam() == TEAM_ALLIANCE ? 1 : 0)); + sWorld->setWorldState(WS_BATTLEFIELD_TB_HORDE_ATTACKING_SHOW, uint32(IsWarTime() && GetAttackerTeam() == TEAM_HORDE ? 1 : 0)); + sWorld->setWorldState(WS_BATTLEFIELD_TB_TIME_NEXT_BATTLE, uint32(!IsWarTime() ? m_Timer : 0)); + sWorld->setWorldState(WS_BATTLEFIELD_TB_TIME_NEXT_BATTLE_SHOW, uint32(!IsWarTime() ? 1 : 0)); + + // Tol Barad + for (uint8 team = 0; team < PVP_TEAMS_COUNT; team++) + for (ObjectGuid const& guid : m_players[team]) + if (Player* player = ObjectAccessor::FindPlayer(guid)) + 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(WS_BATTLEFIELD_TB_STATE_PREPARATIONS, uint32(1)); + + // Teleport players out of questing area + for (uint8 team = 0; team < PVP_TEAMS_COUNT; ++team) + for (ObjectGuid const& guid : m_players[team]) + if (Player* player = ObjectAccessor::FindPlayer(guid)) + 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 (ObjectGuid const& guid : m_PlayersInWar[team]) + if (Player* player = ObjectAccessor::FindPlayer(guid)) + 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(CELLBLOCK_THE_HOLE, CELLBLOCK_CURSED_DEPTHS) : uint8(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].pos, QuaternionData::fromEulerAnglesZYX(TBCapturePoints[i].pos.GetOrientation(), 0.0f, 0.0f))) + { + 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])) + 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])) + 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].pos)) + TemporaryNPCs.insert(creature->GetGUID()); + + if (Creature* creature = SpawnCreature(RandomQuestgivers[GetDefenderTeam()][m_iCellblockRandom], RandomQuestgiverPos)) + TemporaryNPCs.insert(creature->GetGUID()); + + // Spawn portals + for (uint8 i = 0; i < TB_PORTAL_MAX; i++) + if (GameObject* go = SpawnGameObject(TBPortalEntry[GetDefenderTeam()], TBPortals[i], QuaternionData::fromEulerAnglesZYX(TBPortals[i].GetOrientation(), 0.0f, 0.0f))) + 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])) + 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], QuaternionData::fromEulerAnglesZYX(TBBanners[i].GetOrientation(), 0.0f, 0.0f))) + 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, WorldObject* /*invoker*/) +{ + 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(WS_BATTLEFIELD_TB_TIME_BATTLE_END, uint32(GameTime::GetGameTime() + (m_Timer / 1000))); + + SendWarning(TBTowers[tbTowerId].textDamaged); + + SetData(BATTLEFIELD_TB_DATA_TOWERS_DESTROYED, GetData(BATTLEFIELD_TB_DATA_TOWERS_DESTROYED) + 1); + SendUpdateWorldState(uint32(WS_BATTLEFIELD_TB_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 (ObjectGuid const& guid : m_PlayersInWar[GetAttackerTeam()]) + if (Player* player = ObjectAccessor::FindPlayer(guid)) + player->CastSpell(player, SPELL_TOWER_ATTACK_BONUS, CastSpellExtraArgs(TRIGGERED_FULL_MASK).AddSpellMod(SPELLVALUE_AURA_STACK, GetData(BATTLEFIELD_TB_DATA_TOWERS_DESTROYED))); + + // 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(WS_BATTLEFIELD_TB_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 (ObjectGuid const& guid : m_PlayersInWar[killerTeam]) + if (Player* player = ObjectAccessor::FindPlayer(guid)) + 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]); + /* fallthrough */ + 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]); + /* fallthrough */ + 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(nullptr, EVENT_COUNT_CAPTURED_BASE, nullptr); +} + +class Battlefield_tol_barad : public BattlefieldScript +{ +public: + Battlefield_tol_barad() : BattlefieldScript("battlefield_tb") { } + + Battlefield* GetBattlefield() const override + { + return new BattlefieldTB(); + } +}; + +void AddSC_BF_tol_barad() +{ + new Battlefield_tol_barad(); +} diff --git a/src/server/scripts/Battlefield/BattlefieldTB.h b/src/server/scripts/Battlefield/BattlefieldTB.h new file mode 100644 index 00000000000..e8250d2bb36 --- /dev/null +++ b/src/server/scripts/Battlefield/BattlefieldTB.h @@ -0,0 +1,632 @@ +/* +* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along +* with this program. If not, see . +*/ + +#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 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[PVP_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[PVP_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 +{ + Position pos; + 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[PVP_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 +{ + Position pos; + 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 }, { WS_BATTLEFIELD_TB_GARRISON_ALLIANCE_CONTROLLED, WS_BATTLEFIELD_TB_GARRISON_HORDE_CONTROLLED }, { WS_BATTLEFIELD_TB_GARRISON_ALLIANCE_CAPTURING, WS_BATTLEFIELD_TB_GARRISON_HORDE_CAPTURING }, WS_BATTLEFIELD_TB_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 }, { WS_BATTLEFIELD_TB_VIGIL_ALLIANCE_CONTROLLED, WS_BATTLEFIELD_TB_VIGIL_HORDE_CONTROLLED }, { WS_BATTLEFIELD_TB_VIGIL_ALLIANCE_CAPTURING, WS_BATTLEFIELD_TB_VIGIL_HORDE_CAPTURING }, WS_BATTLEFIELD_TB_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 }, { WS_BATTLEFIELD_TB_SLAGWORKS_ALLIANCE_CONTROLLED, WS_BATTLEFIELD_TB_SLAGWORKS_HORDE_CONTROLLED }, { WS_BATTLEFIELD_TB_SLAGWORKS_ALLIANCE_CAPTURING, WS_BATTLEFIELD_TB_SLAGWORKS_HORDE_CAPTURING }, WS_BATTLEFIELD_TB_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 +{ + Position pos; + uint32 entry; + uint32 textDamaged; + uint32 textDestroyed; + uint32 wsIntact[PVP_TEAMS_COUNT]; + uint32 wsDamaged[PVP_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, { WS_BATTLEFIELD_TB_EAST_INTACT_ALLIANCE, WS_BATTLEFIELD_TB_EAST_INTACT_HORDE }, { WS_BATTLEFIELD_TB_EAST_DAMAGED_ALLIANCE, WS_BATTLEFIELD_TB_EAST_DAMAGED_HORDE }, WS_BATTLEFIELD_TB_EAST_DESTROYED_NEUTRAL }, + { { -1618.91f, 954.5417f, 168.601f, 0.06981169f }, GO_SOUTH_SPIRE, TB_TEXT_SOUTH_SPIRE_DAMAGED, TB_TEXT_SOUTH_SPIRE_DESTROYED, { WS_BATTLEFIELD_TB_SOUTH_INTACT_ALLIANCE, WS_BATTLEFIELD_TB_SOUTH_INTACT_HORDE }, { WS_BATTLEFIELD_TB_SOUTH_DAMAGED_ALLIANCE, WS_BATTLEFIELD_TB_SOUTH_DAMAGED_HORDE }, WS_BATTLEFIELD_TB_SOUTH_DESTROYED_NEUTRAL }, + { { -950.4097f, 1469.101f, 176.596f, 4.180066f }, GO_WEST_SPIRE, TB_TEXT_WEST_SPIRE_DAMAGED, TB_TEXT_WEST_SPIRE_DESTROYED, { WS_BATTLEFIELD_TB_WEST_INTACT_ALLIANCE, WS_BATTLEFIELD_TB_WEST_INTACT_HORDE }, { WS_BATTLEFIELD_TB_WEST_DAMAGED_ALLIANCE, WS_BATTLEFIELD_TB_WEST_DAMAGED_HORDE }, WS_BATTLEFIELD_TB_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[PVP_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[PVP_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 +{ + Position pos; + uint32 phaseId; + uint32 gyid; + uint32 spiritEntry[PVP_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 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, WorldObject* invoker) 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/scripts/Battlefield/BattlefieldWG.cpp b/src/server/scripts/Battlefield/BattlefieldWG.cpp new file mode 100644 index 00000000000..a8f3d135ebd --- /dev/null +++ b/src/server/scripts/Battlefield/BattlefieldWG.cpp @@ -0,0 +1,1870 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +/// @todo Implement proper support for vehicle+player teleportation +/// @todo Use spell victory/defeat in wg instead of RewardMarkOfHonor() && RewardHonor +/// @todo Add proper implement of achievement + +#include "BattlefieldWG.h" +#include "AchievementMgr.h" +#include "Battleground.h" +#include "CreatureTextMgr.h" +#include "GameObject.h" +#include "GameTime.h" +#include "DB2Stores.h" +#include "Log.h" +#include "MapManager.h" +#include "ObjectAccessor.h" +#include "Player.h" +#include "Random.h" +#include "ScriptMgr.h" +#include "SpellAuras.h" +#include "TemporarySummon.h" +#include "World.h" +#include "WorldSession.h" +#include "WorldStatePackets.h" + +struct BfWGCoordGY +{ + Position Pos; + uint32 GraveyardID; + uint32 TextID; // for gossip menu + TeamId StartControl; +}; + +// 7 in sql, 7 in header +BfWGCoordGY const WGGraveyard[BATTLEFIELD_WG_GRAVEYARD_MAX] = +{ + { { 5104.750f, 2300.940f, 368.579f, 0.733038f }, 1329, BATTLEFIELD_WG_GOSSIPTEXT_GY_NE, TEAM_NEUTRAL }, + { { 5099.120f, 3466.036f, 368.484f, 5.317802f }, 1330, BATTLEFIELD_WG_GOSSIPTEXT_GY_NW, TEAM_NEUTRAL }, + { { 4314.648f, 2408.522f, 392.642f, 6.268125f }, 1333, BATTLEFIELD_WG_GOSSIPTEXT_GY_SE, TEAM_NEUTRAL }, + { { 4331.716f, 3235.695f, 390.251f, 0.008500f }, 1334, BATTLEFIELD_WG_GOSSIPTEXT_GY_SW, TEAM_NEUTRAL }, + { { 5537.986f, 2897.493f, 517.057f, 4.819249f }, 1285, BATTLEFIELD_WG_GOSSIPTEXT_GY_KEEP, TEAM_NEUTRAL }, + { { 5032.454f, 3711.382f, 372.468f, 3.971623f }, 1331, BATTLEFIELD_WG_GOSSIPTEXT_GY_HORDE, TEAM_HORDE }, + { { 5140.790f, 2179.120f, 390.950f, 1.972220f }, 1332, BATTLEFIELD_WG_GOSSIPTEXT_GY_ALLIANCE, TEAM_ALLIANCE }, +}; + +uint32 const ClockWorldState[] = { WS_BATTLEFIELD_WG_TIME_BATTLE_END, WS_BATTLEFIELD_WG_TIME_NEXT_BATTLE }; +uint32 const WintergraspFaction[] = { FACTION_ALLIANCE_GENERIC_WG, FACTION_HORDE_GENERIC_WG, FACTION_FRIENDLY }; + +Position const WintergraspStalkerPos = { 4948.985f, 2937.789f, 550.5172f, 1.815142f }; + +Position const WintergraspRelicPos = { 5440.379f, 2840.493f, 430.2816f, -1.832595f }; +QuaternionData const WintergraspRelicRot = { 0.f, 0.f, -0.7933531f, 0.6087617f }; + +uint8 const WG_MAX_OBJ = 32; +uint8 const WG_MAX_TURRET = 15; +uint8 const WG_MAX_TELEPORTER = 12; +uint8 const WG_MAX_WORKSHOP = 6; +uint8 const WG_MAX_TOWER = 7; + +// ***************************************************** +// ************ Destructible (Wall, Tower..) *********** +// ***************************************************** + +struct WintergraspBuildingSpawnData +{ + uint32 entry; + uint32 WorldState; + Position pos; + QuaternionData rot; + WintergraspGameObjectBuildingType type; +}; + +WintergraspBuildingSpawnData const WGGameObjectBuilding[WG_MAX_OBJ] = +{ + // Wall (Not spawned in db) + // Entry WS X Y Z O rX rY rZ rW Type + { 190219, 3749, { 5371.457f, 3047.472f, 407.5710f, 3.14159300f }, { 0.f, 0.f, -1.000000000f, 0.00000000f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, + { 190220, 3750, { 5331.264f, 3047.105f, 407.9228f, 0.05235888f }, { 0.f, 0.f, 0.026176450f, 0.99965730f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, + { 191795, 3764, { 5385.841f, 2909.490f, 409.7127f, 0.00872424f }, { 0.f, 0.f, 0.004362106f, 0.99999050f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, + { 191796, 3772, { 5384.452f, 2771.835f, 410.2704f, 3.14159300f }, { 0.f, 0.f, -1.000000000f, 0.00000000f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, + { 191799, 3762, { 5371.436f, 2630.610f, 408.8163f, 3.13285800f }, { 0.f, 0.f, 0.999990500f, 0.00436732f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, + { 191800, 3766, { 5301.838f, 2909.089f, 409.8661f, 0.00872424f }, { 0.f, 0.f, 0.004362106f, 0.99999050f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, + { 191801, 3770, { 5301.063f, 2771.411f, 409.9014f, 3.14159300f }, { 0.f, 0.f, -1.000000000f, 0.00000000f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, + { 191802, 3751, { 5280.197f, 2995.583f, 408.8249f, 1.61442800f }, { 0.f, 0.f, 0.722363500f, 0.69151360f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, + { 191803, 3752, { 5279.136f, 2956.023f, 408.6041f, 1.57079600f }, { 0.f, 0.f, 0.707106600f, 0.70710690f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, + { 191804, 3767, { 5278.685f, 2882.513f, 409.5388f, 1.57079600f }, { 0.f, 0.f, 0.707106600f, 0.70710690f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, + { 191806, 3769, { 5279.502f, 2798.945f, 409.9983f, 1.57079600f }, { 0.f, 0.f, 0.707106600f, 0.70710690f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, + { 191807, 3759, { 5279.937f, 2724.766f, 409.9452f, 1.56207000f }, { 0.f, 0.f, 0.704014800f, 0.71018530f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, + { 191808, 3760, { 5279.601f, 2683.786f, 409.8488f, 1.55334100f }, { 0.f, 0.f, 0.700908700f, 0.71325110f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, + { 191809, 3761, { 5330.955f, 2630.777f, 409.2826f, 3.13285800f }, { 0.f, 0.f, 0.999990500f, 0.00436732f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, + { 190369, 3753, { 5256.085f, 2933.963f, 409.3571f, 3.13285800f }, { 0.f, 0.f, 0.999990500f, 0.00436732f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, + { 190370, 3758, { 5257.463f, 2747.327f, 409.7427f, -3.13285800f }, { 0.f, 0.f, -0.999990500f, 0.00436732f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, + { 190371, 3754, { 5214.960f, 2934.089f, 409.1905f, -0.00872424f }, { 0.f, 0.f, -0.004362106f, 0.99999050f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, + { 190372, 3757, { 5215.821f, 2747.566f, 409.1884f, -3.13285800f }, { 0.f, 0.f, -0.999990500f, 0.00436732f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, + { 190374, 3755, { 5162.273f, 2883.043f, 410.2556f, 1.57952200f }, { 0.f, 0.f, 0.710185100f, 0.70401500f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, + { 190376, 3756, { 5163.724f, 2799.838f, 409.2270f, 1.57952200f }, { 0.f, 0.f, 0.710185100f, 0.70401500f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, + + // Tower of keep (Not spawned in db) + { 190221, 3711, { 5281.154f, 3044.588f, 407.8434f, 3.115388f }, { 0.f, 0.f, 0.9999142f, 0.013101960f }, BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER }, // NW + { 190373, 3713, { 5163.757f, 2932.228f, 409.1904f, 3.124123f }, { 0.f, 0.f, 0.9999619f, 0.008734641f }, BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER }, // SW + { 190377, 3714, { 5166.397f, 2748.368f, 409.1884f, -1.570796f }, { 0.f, 0.f, -0.7071066f, 0.707106900f }, BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER }, // SE + { 190378, 3712, { 5281.192f, 2632.479f, 409.0985f, -1.588246f }, { 0.f, 0.f, -0.7132492f, 0.700910500f }, BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER }, // NE + + // Wall (with passage) (Not spawned in db) + { 191797, 3765, { 5343.290f, 2908.860f, 409.5757f, 0.00872424f }, { 0.f, 0.f, 0.004362106f, 0.9999905f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, + { 191798, 3771, { 5342.719f, 2771.386f, 409.6249f, 3.14159300f }, { 0.f, 0.f, -1.000000000f, 0.0000000f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, + { 191805, 3768, { 5279.126f, 2840.797f, 409.7826f, 1.57952200f }, { 0.f, 0.f, 0.710185100f, 0.7040150f }, BATTLEFIELD_WG_OBJECTTYPE_WALL }, + + // South tower (Not spawned in db) + { 190356, 3704, { 4557.173f, 3623.943f, 395.8828f, 1.675516f }, { 0.f, 0.f, 0.7431450f, 0.669130400f }, BATTLEFIELD_WG_OBJECTTYPE_TOWER }, // W + { 190357, 3705, { 4398.172f, 2822.497f, 405.6270f, -3.124123f }, { 0.f, 0.f, -0.9999619f, 0.008734641f }, BATTLEFIELD_WG_OBJECTTYPE_TOWER }, // S + { 190358, 3706, { 4459.105f, 1944.326f, 434.9912f, -2.002762f }, { 0.f, 0.f, -0.8422165f, 0.539139500f }, BATTLEFIELD_WG_OBJECTTYPE_TOWER }, // E + + // Door of forteress (Not spawned in db) + { GO_WINTERGRASP_FORTRESS_GATE, 3763, { 5162.991f, 2841.232f, 410.1892f, -3.132858f }, { 0.f, 0.f, -0.9999905f, 0.00436732f }, BATTLEFIELD_WG_OBJECTTYPE_DOOR }, + + // Last door (Not spawned in db) + { GO_WINTERGRASP_VAULT_GATE, 3773, { 5397.108f, 2841.54f, 425.9014f, 3.141593f }, { 0.f, 0.f, -1.f, 0.f }, BATTLEFIELD_WG_OBJECTTYPE_DOOR_LAST }, +}; + +struct StaticWintergraspTowerInfo +{ + uint8 TowerId; + + struct + { + uint8 Damaged; + uint8 Destroyed; + } TextIds; +}; + +StaticWintergraspTowerInfo const TowerData[WG_MAX_TOWER] = +{ + { BATTLEFIELD_WG_TOWER_FORTRESS_NW, { BATTLEFIELD_WG_TEXT_NW_KEEPTOWER_DAMAGE, BATTLEFIELD_WG_TEXT_NW_KEEPTOWER_DESTROY } }, + { BATTLEFIELD_WG_TOWER_FORTRESS_SW, { BATTLEFIELD_WG_TEXT_SW_KEEPTOWER_DAMAGE, BATTLEFIELD_WG_TEXT_SW_KEEPTOWER_DESTROY } }, + { BATTLEFIELD_WG_TOWER_FORTRESS_SE, { BATTLEFIELD_WG_TEXT_SE_KEEPTOWER_DAMAGE, BATTLEFIELD_WG_TEXT_SE_KEEPTOWER_DESTROY } }, + { BATTLEFIELD_WG_TOWER_FORTRESS_NE, { BATTLEFIELD_WG_TEXT_NE_KEEPTOWER_DAMAGE, BATTLEFIELD_WG_TEXT_NE_KEEPTOWER_DESTROY } }, + { BATTLEFIELD_WG_TOWER_SHADOWSIGHT, { BATTLEFIELD_WG_TEXT_WESTERN_TOWER_DAMAGE, BATTLEFIELD_WG_TEXT_WESTERN_TOWER_DESTROY } }, + { BATTLEFIELD_WG_TOWER_WINTER_S_EDGE, { BATTLEFIELD_WG_TEXT_SOUTHERN_TOWER_DAMAGE, BATTLEFIELD_WG_TEXT_SOUTHERN_TOWER_DESTROY } }, + { BATTLEFIELD_WG_TOWER_FLAMEWATCH, { BATTLEFIELD_WG_TEXT_EASTERN_TOWER_DAMAGE, BATTLEFIELD_WG_TEXT_EASTERN_TOWER_DESTROY } } +}; + +Position const WGTurret[WG_MAX_TURRET] = +{ + { 5391.19f, 3060.8f, 419.616f, 1.69557f }, + { 5266.75f, 2976.5f, 421.067f, 3.20354f }, + { 5234.86f, 2948.8f, 420.88f, 1.61311f }, + { 5323.05f, 2923.7f, 421.645f, 1.5817f }, + { 5363.82f, 2923.87f, 421.709f, 1.60527f }, + { 5264.04f, 2861.34f, 421.587f, 3.21142f }, + { 5264.68f, 2819.78f, 421.656f, 3.15645f }, + { 5322.16f, 2756.69f, 421.646f, 4.69978f }, + { 5363.78f, 2756.77f, 421.629f, 4.78226f }, + { 5236.2f, 2732.68f, 421.649f, 4.72336f }, + { 5265.02f, 2704.63f, 421.7f, 3.12507f }, + { 5350.87f, 2616.03f, 421.243f, 4.72729f }, + { 5390.95f, 2615.5f, 421.126f, 4.6409f }, + { 5148.8f, 2820.24f, 421.621f, 3.16043f }, + { 5147.98f, 2861.93f, 421.63f, 3.18792f }, +}; + +struct WintergraspObjectPositionData +{ + Position Pos; + uint32 HordeEntry; + uint32 AllianceEntry; +}; + +struct WintergraspGameObjectData +{ + Position Pos; + QuaternionData Rot; + uint32 HordeEntry; + uint32 AllianceEntry; +}; + +WintergraspGameObjectData const WGPortalDefenderData[WG_MAX_TELEPORTER] = +{ + // Player teleporter + { { 5153.408f, 2901.349f, 409.1913f, -0.06981169f }, { 0.f, 0.f, -0.03489876f, 0.9993908f }, 190763, 191575 }, + { { 5268.698f, 2666.421f, 409.0985f, -0.71558490f }, { 0.f, 0.f, -0.35020730f, 0.9366722f }, 190763, 191575 }, + { { 5197.050f, 2944.814f, 409.1913f, 2.33874000f }, { 0.f, 0.f, 0.92050460f, 0.3907318f }, 190763, 191575 }, + { { 5196.671f, 2737.345f, 409.1892f, -2.93213900f }, { 0.f, 0.f, -0.99452110f, 0.1045355f }, 190763, 191575 }, + { { 5314.580f, 3055.852f, 408.8620f, 0.54105060f }, { 0.f, 0.f, 0.26723770f, 0.9636307f }, 190763, 191575 }, + { { 5391.277f, 2828.094f, 418.6752f, -2.16420600f }, { 0.f, 0.f, -0.88294700f, 0.4694727f }, 190763, 191575 }, + { { 5153.931f, 2781.671f, 409.2455f, 1.65806200f }, { 0.f, 0.f, 0.73727700f, 0.6755905f }, 190763, 191575 }, + { { 5311.445f, 2618.931f, 409.0916f, -2.37364400f }, { 0.f, 0.f, -0.92718320f, 0.3746083f }, 190763, 191575 }, + { { 5269.208f, 3013.838f, 408.8276f, -1.76278200f }, { 0.f, 0.f, -0.77162460f, 0.6360782f }, 190763, 191575 }, + + { { 5401.634f, 2853.667f, 418.6748f, 2.63544400f }, { 0.f, 0.f, 0.96814730f, 0.2503814f }, 192819, 192819 }, // return portal inside fortress, neutral + // Vehicle teleporter + { { 5314.515f, 2703.687f, 408.5502f, -0.89011660f }, { 0.f, 0.f, -0.43051050f, 0.9025856f }, 192951, 192951 }, + { { 5316.252f, 2977.042f, 408.5385f, -0.82030330f }, { 0.f, 0.f, -0.39874840f, 0.9170604f }, 192951, 192951 } +}; + +// ********************************************************* +// **********Tower Element(GameObject, Creature)************ +// ********************************************************* + +struct WintergraspTowerData +{ + uint32 towerEntry; // Gameobject id of tower + std::vector GameObject; // Gameobject position and entry (Horde/Alliance) + + // Creature: Turrets and Guard /// @todo: Killed on Tower destruction ? Tower damage ? Requires confirming + std::vector CreatureBottom; +}; + +uint8 const WG_MAX_ATTACKTOWERS = 3; +// 192414 : 0 in sql, 1 in header +// 192278 : 0 in sql, 3 in header +WintergraspTowerData const AttackTowers[WG_MAX_ATTACKTOWERS] = +{ + // West tower + { + 190356, + { + { { 4559.113f, 3606.216f, 419.9992f, 4.799657f }, { 0.f, 0.f, -0.67558960f, 0.73727790f }, 192488, 192501 }, // Flag on tower + { { 4539.420f, 3622.490f, 420.0342f, 3.211419f }, { 0.f, 0.f, -0.99939060f, 0.03490613f }, 192488, 192501 }, // Flag on tower + { { 4555.258f, 3641.648f, 419.9740f, 1.675514f }, { 0.f, 0.f, 0.74314400f, 0.66913150f }, 192488, 192501 }, // Flag on tower + { { 4574.872f, 3625.911f, 420.0792f, 0.087266f }, { 0.f, 0.f, 0.04361916f, 0.99904820f }, 192488, 192501 }, // Flag on tower + { { 4433.899f, 3534.142f, 360.2750f, 4.433136f }, { 0.f, 0.f, -0.79863550f, 0.60181500f }, 192269, 192278 }, // Flag near workshop + { { 4572.933f, 3475.519f, 363.0090f, 1.422443f }, { 0.f, 0.f, 0.65275960f, 0.75756520f }, 192269, 192277 } // Flag near bridge + }, + { + { { 4418.688477f, 3506.251709f, 358.975494f, 4.293305f }, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A } // Roaming Guard + } + }, + // South Tower + { + 190357, + { + { { 4416.004f, 2822.666f, 429.8512f, 6.2657330f }, { 0.f, 0.f, -0.00872612f, 0.99996190f }, 192488, 192501 }, // Flag on tower + { { 4398.819f, 2804.698f, 429.7920f, 4.6949370f }, { 0.f, 0.f, -0.71325020f, 0.70090960f }, 192488, 192501 }, // Flag on tower + { { 4387.622f, 2719.566f, 389.9351f, 4.7385700f }, { 0.f, 0.f, -0.69779010f, 0.71630230f }, 192366, 192414 }, // Flag near tower + { { 4464.124f, 2855.453f, 406.1106f, 0.8290324f }, { 0.f, 0.f, 0.40274720f, 0.91531130f }, 192366, 192429 }, // Flag near tower + { { 4526.457f, 2810.181f, 391.1997f, 3.2899610f }, { 0.f, 0.f, -0.99724960f, 0.07411628f }, 192269, 192278 } // Flag near bridge + }, + { + { { 4452.859863f, 2808.870117f, 402.604004f, 6.056290f }, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard + { { 4455.899902f, 2835.958008f, 401.122559f, 0.034907f }, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard + { { 4412.649414f, 2953.792236f, 374.799957f, 0.980838f }, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Roaming Guard + { { 4362.089844f, 2811.510010f, 407.337006f, 3.193950f }, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard + { { 4412.290039f, 2753.790039f, 401.015015f, 5.829400f }, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard + { { 4421.939941f, 2773.189941f, 400.894989f, 5.707230f }, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A } // Standing Guard + } + }, + // East Tower + { + 190358, + { + { { 4466.793f, 1960.418f, 459.1437f, 1.151916f }, { 0.f, 0.f, 0.5446386f, 0.8386708f }, 192488, 192501 }, // Flag on tower + { { 4475.351f, 1937.031f, 459.0702f, 5.846854f }, { 0.f, 0.f, -0.2164392f, 0.9762961f }, 192488, 192501 }, // Flag on tower + { { 4451.758f, 1928.104f, 459.0759f, 4.276057f }, { 0.f, 0.f, -0.8433914f, 0.5372996f }, 192488, 192501 }, // Flag on tower + { { 4442.987f, 1951.898f, 459.0930f, 2.740162f }, { 0.f, 0.f, 0.9799242f, 0.1993704f }, 192488, 192501 } // Flag on tower + }, + { + { { 4501.060059f, 1990.280029f, 431.157013f, 1.029740f }, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard + { { 4463.830078f, 2015.180054f, 430.299988f, 1.431170f }, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard + { { 4494.580078f, 1943.760010f, 435.627014f, 6.195920f }, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard + { { 4450.149902f, 1897.579956f, 435.045013f, 4.398230f }, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard + { { 4428.870117f, 1906.869995f, 432.648010f, 3.996800f }, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A } // Standing Guard + } + } +}; + +struct WintergraspTowerCannonData +{ + uint32 towerEntry; + std::vector TowerCannonBottom; + std::vector TurretTop; +}; + +uint8 const WG_MAX_TOWER_CANNON = 7; + +WintergraspTowerCannonData const TowerCannon[WG_MAX_TOWER_CANNON] = +{ + { + 190221, + { + // no cannons at bottom + }, + { + { 5255.88f, 3047.63f, 438.499f, 3.13677f }, + { 5280.90f, 3071.32f, 438.499f, 1.62879f } + } + }, + { + 190373, + { + // no cannons at bottom + }, + { + { 5138.59f, 2935.16f, 439.845f, 3.11723f }, + { 5163.06f, 2959.52f, 439.846f, 1.47258f } + } + }, + { + 190377, + { + // no cannons at bottom + }, + { + { 5163.84f, 2723.74f, 439.844f, 1.39940f }, + { 5139.69f, 2747.40f, 439.844f, 3.17221f } + } + }, + { + 190378, + { + // no cannons at bottom + }, + { + { 5278.21f, 2607.23f, 439.755f, 4.71944f }, + { 5255.01f, 2631.98f, 439.755f, 3.15257f } + } + }, + { + 190356, + { + { 4537.380371f, 3599.531738f, 402.886993f, 3.998462f }, + { 4581.497559f, 3604.087158f, 402.886963f, 5.651723f } + }, + { + { 4469.448242f, 1966.623779f, 465.647217f, 1.153573f }, + { 4581.895996f, 3626.438477f, 426.539062f, 0.117806f } + } + }, + { + 190357, + { + { 4421.640137f, 2799.935791f, 412.630920f, 5.459298f }, + { 4420.263184f, 2845.340332f, 412.630951f, 0.742197f } + }, + { + { 4423.430664f, 2822.762939f, 436.283142f, 6.223487f }, + { 4397.825684f, 2847.629639f, 436.283325f, 1.579430f }, + { 4398.814941f, 2797.266357f, 436.283051f, 4.703747f } + } + }, + { + 190358, + { + { 4448.138184f, 1974.998779f, 441.995911f, 1.967238f }, + { 4448.713379f, 1955.148682f, 441.995178f, 0.380733f } + }, + { + { 4469.448242f, 1966.623779f, 465.647217f, 1.153573f }, + { 4481.996582f, 1933.658325f, 465.647186f, 5.873029f } + } + } +}; + +// ********************************************************* +// *****************WorkShop Data & Element***************** +// ********************************************************* + +struct StaticWintergraspWorkshopInfo +{ + uint8 WorkshopId; + uint32 WorldStateId; + + struct + { + uint8 AllianceCapture; + uint8 AllianceAttack; + uint8 HordeCapture; + uint8 HordeAttack; + } TextIds; +}; + +StaticWintergraspWorkshopInfo const WorkshopData[WG_MAX_WORKSHOP] = +{ + { BATTLEFIELD_WG_WORKSHOP_NE, WS_BATTLEFIELD_WG_WORKSHOP_NE, { BATTLEFIELD_WG_TEXT_SUNKEN_RING_CAPTURE_ALLIANCE, BATTLEFIELD_WG_TEXT_SUNKEN_RING_ATTACK_ALLIANCE, BATTLEFIELD_WG_TEXT_SUNKEN_RING_CAPTURE_HORDE, BATTLEFIELD_WG_TEXT_SUNKEN_RING_ATTACK_HORDE } }, + { BATTLEFIELD_WG_WORKSHOP_NW, WS_BATTLEFIELD_WG_WORKSHOP_NW, { BATTLEFIELD_WG_TEXT_BROKEN_TEMPLE_CAPTURE_ALLIANCE, BATTLEFIELD_WG_TEXT_BROKEN_TEMPLE_ATTACK_ALLIANCE, BATTLEFIELD_WG_TEXT_BROKEN_TEMPLE_CAPTURE_HORDE, BATTLEFIELD_WG_TEXT_BROKEN_TEMPLE_ATTACK_HORDE } }, + { BATTLEFIELD_WG_WORKSHOP_SE, WS_BATTLEFIELD_WG_WORKSHOP_SE, { BATTLEFIELD_WG_TEXT_EASTSPARK_CAPTURE_ALLIANCE, BATTLEFIELD_WG_TEXT_EASTSPARK_ATTACK_ALLIANCE, BATTLEFIELD_WG_TEXT_EASTSPARK_CAPTURE_HORDE, BATTLEFIELD_WG_TEXT_EASTSPARK_ATTACK_HORDE } }, + { BATTLEFIELD_WG_WORKSHOP_SW, WS_BATTLEFIELD_WG_WORKSHOP_SW, { BATTLEFIELD_WG_TEXT_WESTSPARK_CAPTURE_ALLIANCE, BATTLEFIELD_WG_TEXT_WESTSPARK_ATTACK_ALLIANCE, BATTLEFIELD_WG_TEXT_WESTSPARK_CAPTURE_HORDE, BATTLEFIELD_WG_TEXT_WESTSPARK_ATTACK_HORDE } }, + // KEEP WORKSHOPS - It can't be taken, so it doesn't have a textids + { BATTLEFIELD_WG_WORKSHOP_KEEP_WEST, WS_BATTLEFIELD_WG_WORKSHOP_K_W, { 0, 0, 0, 0 } }, + { BATTLEFIELD_WG_WORKSHOP_KEEP_EAST, WS_BATTLEFIELD_WG_WORKSHOP_K_E, { 0, 0, 0, 0 } } +}; + +BattlefieldWG::~BattlefieldWG() +{ + for (WintergraspWorkshop* workshop : Workshops) + delete workshop; + + for (BfWGGameObjectBuilding* building : BuildingsInZone) + delete building; +} + +bool BattlefieldWG::SetupBattlefield() +{ + m_TypeId = BATTLEFIELD_WG; // See enum BattlefieldTypes + m_BattleId = BATTLEFIELD_BATTLEID_WG; + m_ZoneId = AREA_WINTERGRASP; + m_MapId = BATTLEFIELD_WG_MAPID; + m_Map = sMapMgr->CreateBaseMap(m_MapId); + + InitStalker(BATTLEFIELD_WG_NPC_STALKER, WintergraspStalkerPos); + + m_MaxPlayer = sWorld->getIntConfig(CONFIG_WINTERGRASP_PLR_MAX); + m_IsEnabled = sWorld->getBoolConfig(CONFIG_WINTERGRASP_ENABLE); + m_MinPlayer = sWorld->getIntConfig(CONFIG_WINTERGRASP_PLR_MIN); + m_MinLevel = sWorld->getIntConfig(CONFIG_WINTERGRASP_PLR_MIN_LVL); + m_BattleTime = sWorld->getIntConfig(CONFIG_WINTERGRASP_BATTLETIME) * MINUTE * IN_MILLISECONDS; + m_NoWarBattleTime = sWorld->getIntConfig(CONFIG_WINTERGRASP_NOBATTLETIME) * MINUTE * IN_MILLISECONDS; + m_RestartAfterCrash = sWorld->getIntConfig(CONFIG_WINTERGRASP_RESTART_AFTER_CRASH) * MINUTE * IN_MILLISECONDS; + + m_TimeForAcceptInvite = 20; + m_StartGroupingTimer = 15 * MINUTE * IN_MILLISECONDS; + m_StartGrouping = false; + + m_tenacityTeam = TEAM_NEUTRAL; + m_tenacityStack = 0; + + KickPosition.Relocate(5728.117f, 2714.346f, 697.733f, 0); + KickPosition.m_mapId = m_MapId; + + RegisterZone(m_ZoneId); + + m_Data32.resize(BATTLEFIELD_WG_DATA_MAX); + + m_saveTimer = 60000; + + // Init Graveyards + SetGraveyardNumber(BATTLEFIELD_WG_GRAVEYARD_MAX); + + // Load from db + if ((sWorld->getWorldState(WS_BATTLEFIELD_WG_ACTIVE) == 0) && (sWorld->getWorldState(WS_BATTLEFIELD_WG_DEFENDER) == 0) + && (sWorld->getWorldState(ClockWorldState[0]) == 0)) + { + sWorld->setWorldState(WS_BATTLEFIELD_WG_ACTIVE, uint64(false)); + sWorld->setWorldState(WS_BATTLEFIELD_WG_DEFENDER, uint64(urand(0, 1))); + sWorld->setWorldState(ClockWorldState[0], uint64(m_NoWarBattleTime)); + } + + m_isActive = sWorld->getWorldState(WS_BATTLEFIELD_WG_ACTIVE) != 0; + m_DefenderTeam = TeamId(sWorld->getWorldState(WS_BATTLEFIELD_WG_DEFENDER)); + + m_Timer = sWorld->getWorldState(ClockWorldState[0]); + if (m_isActive) + { + m_isActive = false; + m_Timer = m_RestartAfterCrash; + } + + SetData(BATTLEFIELD_WG_DATA_WON_A, uint32(sWorld->getWorldState(WS_BATTLEFIELD_WG_ATTACKED_A))); + SetData(BATTLEFIELD_WG_DATA_DEF_A, uint32(sWorld->getWorldState(WS_BATTLEFIELD_WG_DEFENDED_A))); + SetData(BATTLEFIELD_WG_DATA_WON_H, uint32(sWorld->getWorldState(WS_BATTLEFIELD_WG_ATTACKED_H))); + SetData(BATTLEFIELD_WG_DATA_DEF_H, uint32(sWorld->getWorldState(WS_BATTLEFIELD_WG_DEFENDED_H))); + + for (uint8 i = 0; i < BATTLEFIELD_WG_GRAVEYARD_MAX; i++) + { + BfGraveyardWG* graveyard = new BfGraveyardWG(this); + + // When between games, the graveyard is controlled by the defending team + if (WGGraveyard[i].StartControl == TEAM_NEUTRAL) + graveyard->Initialize(m_DefenderTeam, WGGraveyard[i].GraveyardID); + else + graveyard->Initialize(WGGraveyard[i].StartControl, WGGraveyard[i].GraveyardID); + + graveyard->SetTextId(WGGraveyard[i].TextID); + m_GraveyardList[i] = graveyard; + } + + + Workshops.resize(WG_MAX_WORKSHOP); + // Spawn workshop creatures and gameobjects + for (uint8 i = 0; i < WG_MAX_WORKSHOP; i++) + { + WintergraspWorkshop* workshop = new WintergraspWorkshop(this, i); + if (i < BATTLEFIELD_WG_WORKSHOP_NE) + workshop->GiveControlTo(GetAttackerTeam(), true); + else + workshop->GiveControlTo(GetDefenderTeam(), true); + + // Note: Capture point is added once the gameobject is created. + Workshops[i] = workshop; + } + + // Spawn turrets and hide them per default + for (uint8 i = 0; i < WG_MAX_TURRET; i++) + { + Position towerCannonPos = WGTurret[i].GetPosition(); + if (Creature* creature = SpawnCreature(NPC_WINTERGRASP_TOWER_CANNON, towerCannonPos)) + { + CanonList.push_back(creature->GetGUID()); + HideNpc(creature); + } + } + + BuildingsInZone.resize(WG_MAX_OBJ); + // Spawn all gameobjects + for (uint8 i = 0; i < WG_MAX_OBJ; i++) + { + if (GameObject* go = SpawnGameObject(WGGameObjectBuilding[i].entry, WGGameObjectBuilding[i].pos, WGGameObjectBuilding[i].rot)) + { + BfWGGameObjectBuilding* b = new BfWGGameObjectBuilding(this, WGGameObjectBuilding[i].type, WGGameObjectBuilding[i].WorldState); + b->Init(go); + if (!IsEnabled() && go->GetEntry() == GO_WINTERGRASP_VAULT_GATE) + go->SetDestructibleState(GO_DESTRUCTIBLE_DESTROYED); + + BuildingsInZone[i] = b; + } + } + + // Spawning portal defender + for (uint8 i = 0; i < WG_MAX_TELEPORTER; ++i) + { + WintergraspGameObjectData const& teleporter = WGPortalDefenderData[i]; + if (GameObject* go = SpawnGameObject(teleporter.AllianceEntry, teleporter.Pos, teleporter.Rot)) + { + DefenderPortalList[TEAM_ALLIANCE].push_back(go->GetGUID()); + go->SetRespawnTime(GetDefenderTeam() == TEAM_ALLIANCE ? RESPAWN_IMMEDIATELY : RESPAWN_ONE_DAY); + } + + if (GameObject* go = SpawnGameObject(teleporter.HordeEntry, teleporter.Pos, teleporter.Rot)) + { + DefenderPortalList[TEAM_HORDE].push_back(go->GetGUID()); + go->SetRespawnTime(GetDefenderTeam() == TEAM_HORDE ? RESPAWN_IMMEDIATELY : RESPAWN_ONE_DAY); + } + } + + UpdateCounterVehicle(true); + return true; +} + +bool BattlefieldWG::Update(uint32 diff) +{ + bool m_return = Battlefield::Update(diff); + if (m_saveTimer <= diff) + { + sWorld->setWorldState(WS_BATTLEFIELD_WG_ACTIVE, m_isActive); + sWorld->setWorldState(WS_BATTLEFIELD_WG_DEFENDER, m_DefenderTeam); + sWorld->setWorldState(ClockWorldState[0], m_Timer); + sWorld->setWorldState(WS_BATTLEFIELD_WG_ATTACKED_A, GetData(BATTLEFIELD_WG_DATA_WON_A)); + sWorld->setWorldState(WS_BATTLEFIELD_WG_DEFENDED_A, GetData(BATTLEFIELD_WG_DATA_DEF_A)); + sWorld->setWorldState(WS_BATTLEFIELD_WG_ATTACKED_H, GetData(BATTLEFIELD_WG_DATA_WON_H)); + sWorld->setWorldState(WS_BATTLEFIELD_WG_DEFENDED_H, GetData(BATTLEFIELD_WG_DATA_DEF_H)); + m_saveTimer = 60 * IN_MILLISECONDS; + } + else + m_saveTimer -= diff; + + return m_return; +} + +void BattlefieldWG::OnBattleStart() +{ + // Spawn titan relic + if (GameObject* relic = SpawnGameObject(GO_WINTERGRASP_TITAN_S_RELIC, WintergraspRelicPos, WintergraspRelicRot)) + { + // Update faction of relic, only attacker can click on + relic->SetFaction(WintergraspFaction[GetAttackerTeam()]); + // Set in use (not allow to click on before last door is broken) + relic->AddFlag(GameObjectFlags(GO_FLAG_IN_USE | GO_FLAG_NOT_SELECTABLE)); + m_titansRelicGUID = relic->GetGUID(); + } + else + TC_LOG_ERROR("bg.battlefield", "WG: Failed to spawn titan relic."); + + + // Update tower visibility and update faction + for (auto itr = CanonList.begin(); itr != CanonList.end(); ++itr) + { + if (Creature* creature = GetCreature(*itr)) + { + ShowNpc(creature, true); + creature->SetFaction(WintergraspFaction[GetDefenderTeam()]); + } + } + + // Rebuild all wall + for (BfWGGameObjectBuilding* building : BuildingsInZone) + { + building->Rebuild(); + building->UpdateTurretAttack(false); + } + + SetData(BATTLEFIELD_WG_DATA_BROKEN_TOWER_ATT, 0); + SetData(BATTLEFIELD_WG_DATA_BROKEN_TOWER_DEF, 0); + SetData(BATTLEFIELD_WG_DATA_DAMAGED_TOWER_ATT, 0); + SetData(BATTLEFIELD_WG_DATA_DAMAGED_TOWER_DEF, 0); + + // Update graveyard (in no war time all graveyard is to deffender, in war time, depend of base) + for (WintergraspWorkshop* workshop : Workshops) + workshop->UpdateGraveyardAndWorkshop(); + + for (uint8 team = 0; team < PVP_TEAMS_COUNT; ++team) + { + for (auto itr = m_players[team].begin(); itr != m_players[team].end(); ++itr) + { + // Kick player in orb room, TODO: offline player ? + if (Player* player = ObjectAccessor::FindPlayer(*itr)) + { + float x, y, z; + player->GetPosition(x, y, z); + if (5500 > x && x > 5392 && y < 2880 && y > 2800 && z < 480) + player->TeleportTo(571, 5349.8686f, 2838.481f, 409.240f, 0.046328f); + SendInitWorldStatesTo(player); + } + } + } + + // Initialize vehicle counter + UpdateCounterVehicle(true); + // Send start warning to all players + SendWarning(BATTLEFIELD_WG_TEXT_START_BATTLE); +} + +void BattlefieldWG::UpdateCounterVehicle(bool init) +{ + if (init) + { + SetData(BATTLEFIELD_WG_DATA_VEHICLE_H, 0); + SetData(BATTLEFIELD_WG_DATA_VEHICLE_A, 0); + } + SetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_H, 0); + SetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_A, 0); + + for (WintergraspWorkshop* workshop : Workshops) + { + if (workshop->GetTeamControl() == TEAM_ALLIANCE) + UpdateData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_A, 4); + else if (workshop->GetTeamControl() == TEAM_HORDE) + UpdateData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_H, 4); + } + + UpdateVehicleCountWG(); +} + +void BattlefieldWG::OnBattleEnd(bool endByTimer) +{ + // Remove relic + if (!m_titansRelicGUID.IsEmpty()) + if (GameObject* relic = GetGameObject(m_titansRelicGUID)) + relic->RemoveFromWorld(); + m_titansRelicGUID.Clear(); + + // change collision wall state closed + for (BfWGGameObjectBuilding* building : BuildingsInZone) + { + building->RebuildGate(); + } + + // successful defense + if (endByTimer) + UpdateData(GetDefenderTeam() == TEAM_HORDE ? BATTLEFIELD_WG_DATA_DEF_H : BATTLEFIELD_WG_DATA_DEF_A, 1); + // successful attack (note that teams have already been swapped, so defender team is the one who won) + else + UpdateData(GetDefenderTeam() == TEAM_HORDE ? BATTLEFIELD_WG_DATA_WON_H : BATTLEFIELD_WG_DATA_WON_A, 1); + + // Remove turret + for (auto itr = CanonList.begin(); itr != CanonList.end(); ++itr) + { + if (Creature* creature = GetCreature(*itr)) + { + if (!endByTimer) + creature->SetFaction(WintergraspFaction[GetDefenderTeam()]); + HideNpc(creature); + } + } + + // Update all graveyard, control is to defender when no wartime + for (uint8 i = 0; i < BATTLEFIELD_WG_GY_HORDE; i++) + if (BfGraveyard* graveyard = GetGraveyardById(i)) + graveyard->GiveControlTo(GetDefenderTeam()); + + // Update portals + for (auto itr = DefenderPortalList[GetDefenderTeam()].begin(); itr != DefenderPortalList[GetDefenderTeam()].end(); ++itr) + if (GameObject* portal = GetGameObject(*itr)) + portal->SetRespawnTime(RESPAWN_IMMEDIATELY); + + for (auto itr = DefenderPortalList[GetAttackerTeam()].begin(); itr != DefenderPortalList[GetAttackerTeam()].end(); ++itr) + if (GameObject* portal = GetGameObject(*itr)) + portal->SetRespawnTime(RESPAWN_ONE_DAY); + + // Saving data + for (BfWGGameObjectBuilding* building : BuildingsInZone) + building->Save(); + + for (WintergraspWorkshop* workshop : Workshops) + workshop->Save(); + + for (auto itr = m_PlayersInWar[GetDefenderTeam()].begin(); itr != m_PlayersInWar[GetDefenderTeam()].end(); ++itr) + { + if (Player* player = ObjectAccessor::FindPlayer(*itr)) + { + player->CastSpell(player, SPELL_ESSENCE_OF_WINTERGRASP, true); + player->CastSpell(player, SPELL_VICTORY_REWARD, true); + // Complete victory quests + player->AreaExploredOrEventHappens(QUEST_VICTORY_WINTERGRASP_A); + player->AreaExploredOrEventHappens(QUEST_VICTORY_WINTERGRASP_H); + // Send Wintergrasp victory achievement + DoCompleteOrIncrementAchievement(ACHIEVEMENTS_WIN_WG, player); + // Award achievement for succeeding in Wintergrasp in 10 minutes or less + if (!endByTimer && GetTimer() <= 10000) + DoCompleteOrIncrementAchievement(ACHIEVEMENTS_WIN_WG_TIMER_10, player); + } + } + + for (auto itr = m_PlayersInWar[GetAttackerTeam()].begin(); itr != m_PlayersInWar[GetAttackerTeam()].end(); ++itr) + if (Player* player = ObjectAccessor::FindPlayer(*itr)) + player->CastSpell(player, SPELL_DEFEAT_REWARD, true); + + for (uint8 team = 0; team < PVP_TEAMS_COUNT; ++team) + { + for (auto itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr) + if (Player* player = ObjectAccessor::FindPlayer(*itr)) + RemoveAurasFromPlayer(player); + + m_PlayersInWar[team].clear(); + + for (auto itr = m_vehicles[team].begin(); itr != m_vehicles[team].end(); ++itr) + if (Creature* creature = GetCreature(*itr)) + if (creature->IsVehicle()) + creature->DespawnOrUnsummon(); + + m_vehicles[team].clear(); + } + + if (!endByTimer) + { + for (uint8 team = 0; team < PVP_TEAMS_COUNT; ++team) + { + for (auto itr = m_players[team].begin(); itr != m_players[team].end(); ++itr) + { + if (Player* player = ObjectAccessor::FindPlayer(*itr)) + { + player->RemoveAurasDueToSpell(m_DefenderTeam == TEAM_ALLIANCE ? SPELL_HORDE_CONTROL_PHASE_SHIFT : SPELL_ALLIANCE_CONTROL_PHASE_SHIFT, player->GetGUID()); + player->AddAura(m_DefenderTeam == TEAM_HORDE ? SPELL_HORDE_CONTROL_PHASE_SHIFT : SPELL_ALLIANCE_CONTROL_PHASE_SHIFT, player); + } + } + } + } + + if (!endByTimer) // win alli/horde + SendWarning(GetDefenderTeam() == TEAM_ALLIANCE ? BATTLEFIELD_WG_TEXT_FORTRESS_CAPTURE_ALLIANCE : BATTLEFIELD_WG_TEXT_FORTRESS_CAPTURE_HORDE); + else // defend alli/horde + SendWarning(GetDefenderTeam() == TEAM_ALLIANCE ? BATTLEFIELD_WG_TEXT_FORTRESS_DEFEND_ALLIANCE : BATTLEFIELD_WG_TEXT_FORTRESS_DEFEND_HORDE); +} + +// ******************************************************* +// ******************* Reward System ********************* +// ******************************************************* +void BattlefieldWG::DoCompleteOrIncrementAchievement(uint32 achievement, Player* player, uint8 /*incrementNumber*/) +{ + AchievementEntry const* achievementEntry = sAchievementStore.LookupEntry(achievement); + + if (!achievementEntry) + return; + + switch (achievement) + { + case ACHIEVEMENTS_WIN_WG_100: + { + // player->UpdateCriteria(); + } + default: + { + if (player) + player->CompletedAchievement(achievementEntry); + break; + } + } + +} + +void BattlefieldWG::OnStartGrouping() +{ + SendWarning(BATTLEFIELD_WG_TEXT_START_GROUPING); +} + +uint8 BattlefieldWG::GetSpiritGraveyardId(uint32 areaId) const +{ + switch (areaId) + { + case AREA_WINTERGRASP_FORTRESS: + return BATTLEFIELD_WG_GY_KEEP; + case AREA_THE_SUNKEN_RING: + return BATTLEFIELD_WG_GY_WORKSHOP_NE; + case AREA_THE_BROKEN_TEMPLATE: + return BATTLEFIELD_WG_GY_WORKSHOP_NW; + case AREA_WESTPARK_WORKSHOP: + return BATTLEFIELD_WG_GY_WORKSHOP_SW; + case AREA_EASTPARK_WORKSHOP: + return BATTLEFIELD_WG_GY_WORKSHOP_SE; + case AREA_WINTERGRASP: + return BATTLEFIELD_WG_GY_ALLIANCE; + case AREA_THE_CHILLED_QUAGMIRE: + return BATTLEFIELD_WG_GY_HORDE; + default: + TC_LOG_ERROR("bg.battlefield", "BattlefieldWG::GetSpiritGraveyardId: Unexpected Area Id %u", areaId); + break; + } + + return 0; +} + +void BattlefieldWG::OnCreatureCreate(Creature* creature) +{ + // Accessing to db spawned creatures + switch (creature->GetEntry()) + { + case NPC_DWARVEN_SPIRIT_GUIDE: + case NPC_TAUNKA_SPIRIT_GUIDE: + { + TeamId teamId = (creature->GetEntry() == NPC_DWARVEN_SPIRIT_GUIDE ? TEAM_ALLIANCE : TEAM_HORDE); + uint8 graveyardId = GetSpiritGraveyardId(creature->GetAreaId()); + if (m_GraveyardList[graveyardId]) + m_GraveyardList[graveyardId]->SetSpirit(creature, teamId); + break; + } + } + + // untested code - not sure if it is valid. + if (IsWarTime()) + { + switch (creature->GetEntry()) + { + case NPC_WINTERGRASP_SIEGE_ENGINE_ALLIANCE: + case NPC_WINTERGRASP_SIEGE_ENGINE_HORDE: + case NPC_WINTERGRASP_CATAPULT: + case NPC_WINTERGRASP_DEMOLISHER: + { + if (!creature->ToTempSummon() || !creature->ToTempSummon()->GetSummonerGUID() || !ObjectAccessor::FindPlayer(creature->ToTempSummon()->GetSummonerGUID())) + { + creature->DespawnOrUnsummon(); + return; + } + + Player* creator = ObjectAccessor::FindPlayer(creature->ToTempSummon()->GetSummonerGUID()); + TeamId team = creator->GetTeamId(); + + if (team == TEAM_HORDE) + { + if (GetData(BATTLEFIELD_WG_DATA_VEHICLE_H) < GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_H)) + { + UpdateData(BATTLEFIELD_WG_DATA_VEHICLE_H, 1); + creature->AddAura(SPELL_HORDE_FLAG, creature); + m_vehicles[team].insert(creature->GetGUID()); + UpdateVehicleCountWG(); + } + else + { + creature->DespawnOrUnsummon(); + return; + } + } + else + { + if (GetData(BATTLEFIELD_WG_DATA_VEHICLE_A) < GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_A)) + { + UpdateData(BATTLEFIELD_WG_DATA_VEHICLE_A, 1); + creature->AddAura(SPELL_ALLIANCE_FLAG, creature); + m_vehicles[team].insert(creature->GetGUID()); + UpdateVehicleCountWG(); + } + else + { + creature->DespawnOrUnsummon(); + return; + } + } + + creature->CastSpell(creator, SPELL_GRAB_PASSENGER, true); + break; + } + } + } +} + +void BattlefieldWG::OnCreatureRemove(Creature* /*creature*/) +{ +/* possibly can be used later + if (IsWarTime()) + { + switch (creature->GetEntry()) + { + case NPC_WINTERGRASP_SIEGE_ENGINE_ALLIANCE: + case NPC_WINTERGRASP_SIEGE_ENGINE_HORDE: + case NPC_WINTERGRASP_CATAPULT: + case NPC_WINTERGRASP_DEMOLISHER: + { + uint8 team; + if (creature->GetFaction() == WintergraspFaction[TEAM_ALLIANCE]) + team = TEAM_ALLIANCE; + else if (creature->GetFaction() == WintergraspFaction[TEAM_HORDE]) + team = TEAM_HORDE; + else + return; + + m_vehicles[team].erase(creature->GetGUID()); + if (team == TEAM_HORDE) + UpdateData(BATTLEFIELD_WG_DATA_VEHICLE_H, -1); + else + UpdateData(BATTLEFIELD_WG_DATA_VEHICLE_A, -1); + UpdateVehicleCountWG(); + + break; + } + } + }*/ +} + +void BattlefieldWG::OnGameObjectCreate(GameObject* go) +{ + uint8 workshopId = 0; + + switch (go->GetEntry()) + { + case GO_WINTERGRASP_FACTORY_BANNER_NE: + workshopId = BATTLEFIELD_WG_WORKSHOP_NE; + break; + case GO_WINTERGRASP_FACTORY_BANNER_NW: + workshopId = BATTLEFIELD_WG_WORKSHOP_NW; + break; + case GO_WINTERGRASP_FACTORY_BANNER_SE: + workshopId = BATTLEFIELD_WG_WORKSHOP_SE; + break; + case GO_WINTERGRASP_FACTORY_BANNER_SW: + workshopId = BATTLEFIELD_WG_WORKSHOP_SW; + break; + default: + return; + } + + for (WintergraspWorkshop* workshop : Workshops) + { + if (workshop->GetId() == workshopId) + { + WintergraspCapturePoint* capturePoint = new WintergraspCapturePoint(this, GetAttackerTeam()); + + capturePoint->SetCapturePointData(go); + capturePoint->LinkToWorkshop(workshop); + AddCapturePoint(capturePoint); + break; + } + } +} + +// Called when player kill a unit in wg zone +void BattlefieldWG::HandleKill(Player* killer, Unit* victim) +{ + if (killer == victim) + return; + + if (victim->GetTypeId() == TYPEID_PLAYER) + { + HandlePromotion(killer, victim); + + // Allow to Skin non-released corpse + victim->AddUnitFlag(UNIT_FLAG_SKINNABLE); + } + + /// @todoRecent PvP activity worldstate +} + +bool BattlefieldWG::FindAndRemoveVehicleFromList(Unit* vehicle) +{ + for (uint32 team = 0; team < PVP_TEAMS_COUNT; ++team) + { + auto itr = m_vehicles[team].find(vehicle->GetGUID()); + if (itr != m_vehicles[team].end()) + { + m_vehicles[team].erase(itr); + + if (team == TEAM_HORDE) + UpdateData(BATTLEFIELD_WG_DATA_VEHICLE_H, -1); + else + UpdateData(BATTLEFIELD_WG_DATA_VEHICLE_A, -1); + return true; + } + } + + return false; +} + +void BattlefieldWG::OnUnitDeath(Unit* unit) +{ + if (IsWarTime()) + if (unit->IsVehicle()) + if (FindAndRemoveVehicleFromList(unit)) + UpdateVehicleCountWG(); +} + +void BattlefieldWG::HandlePromotion(Player* playerKiller, Unit* unitKilled) +{ + uint32 teamId = playerKiller->GetTeamId(); + + for (auto iter = m_PlayersInWar[teamId].begin(); iter != m_PlayersInWar[teamId].end(); ++iter) + if (Player* player = ObjectAccessor::FindPlayer(*iter)) + if (player->GetDistance2d(unitKilled) < 40.0f) + PromotePlayer(player); +} + +// Update rank for player +void BattlefieldWG::PromotePlayer(Player* killer) +{ + if (!m_isActive) + return; + // Updating rank of player + if (Aura* auraRecruit = killer->GetAura(SPELL_RECRUIT)) + { + if (auraRecruit->GetStackAmount() >= 5) + { + killer->RemoveAura(SPELL_RECRUIT); + killer->CastSpell(killer, SPELL_CORPORAL, true); + if (Creature* stalker = GetCreature(StalkerGuid)) + sCreatureTextMgr->SendChat(stalker, BATTLEFIELD_WG_TEXT_RANK_CORPORAL, killer, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_NORMAL, 0, SoundKitPlayType::Normal, TEAM_OTHER, false, killer); + } + else + killer->CastSpell(killer, SPELL_RECRUIT, true); + } + else if (Aura* auraCorporal = killer->GetAura(SPELL_CORPORAL)) + { + if (auraCorporal->GetStackAmount() >= 5) + { + killer->RemoveAura(SPELL_CORPORAL); + killer->CastSpell(killer, SPELL_LIEUTENANT, true); + if (Creature* stalker = GetCreature(StalkerGuid)) + sCreatureTextMgr->SendChat(stalker, BATTLEFIELD_WG_TEXT_RANK_FIRST_LIEUTENANT, killer, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_NORMAL, 0, SoundKitPlayType::Normal, TEAM_OTHER, false, killer); + } + else + killer->CastSpell(killer, SPELL_CORPORAL, true); + } +} + +void BattlefieldWG::RemoveAurasFromPlayer(Player* player) +{ + player->RemoveAurasDueToSpell(SPELL_RECRUIT); + player->RemoveAurasDueToSpell(SPELL_CORPORAL); + player->RemoveAurasDueToSpell(SPELL_LIEUTENANT); + player->RemoveAurasDueToSpell(SPELL_TOWER_CONTROL); + player->RemoveAurasDueToSpell(SPELL_SPIRITUAL_IMMUNITY); + player->RemoveAurasDueToSpell(SPELL_TENACITY); + player->RemoveAurasDueToSpell(SPELL_ESSENCE_OF_WINTERGRASP); + player->RemoveAurasDueToSpell(SPELL_WINTERGRASP_RESTRICTED_FLIGHT_AREA); +} + +void BattlefieldWG::OnPlayerJoinWar(Player* player) +{ + RemoveAurasFromPlayer(player); + + player->CastSpell(player, SPELL_RECRUIT, true); + + if (player->GetZoneId() != m_ZoneId) + { + if (player->GetTeamId() == GetDefenderTeam()) + player->TeleportTo(571, 5345, 2842, 410, 3.14f); + else + { + if (player->GetTeamId() == TEAM_HORDE) + player->TeleportTo(571, 5025.857422f, 3674.628906f, 362.737122f, 4.135169f); + else + player->TeleportTo(571, 5101.284f, 2186.564f, 373.549f, 3.812f); + } + } + + UpdateTenacity(); + + if (player->GetTeamId() == GetAttackerTeam()) + { + if (GetData(BATTLEFIELD_WG_DATA_BROKEN_TOWER_ATT) < 3) + player->SetAuraStack(SPELL_TOWER_CONTROL, player, 3 - GetData(BATTLEFIELD_WG_DATA_BROKEN_TOWER_ATT)); + } + else + { + if (GetData(BATTLEFIELD_WG_DATA_BROKEN_TOWER_ATT) > 0) + player->SetAuraStack(SPELL_TOWER_CONTROL, player, GetData(BATTLEFIELD_WG_DATA_BROKEN_TOWER_ATT)); + } + SendInitWorldStatesTo(player); +} + +void BattlefieldWG::OnPlayerLeaveWar(Player* player) +{ + // Remove all aura from WG /// @todo false we can go out of this zone on retail and keep Rank buff, remove on end of WG + if (!player->GetSession()->PlayerLogout()) + { + if (Creature* vehicle = player->GetVehicleCreatureBase()) // Remove vehicle of player if he go out. + vehicle->DespawnOrUnsummon(); + + RemoveAurasFromPlayer(player); + } + + player->RemoveAurasDueToSpell(SPELL_HORDE_CONTROLS_FACTORY_PHASE_SHIFT); + player->RemoveAurasDueToSpell(SPELL_ALLIANCE_CONTROLS_FACTORY_PHASE_SHIFT); + player->RemoveAurasDueToSpell(SPELL_HORDE_CONTROL_PHASE_SHIFT); + player->RemoveAurasDueToSpell(SPELL_ALLIANCE_CONTROL_PHASE_SHIFT); + UpdateTenacity(); +} + +void BattlefieldWG::OnPlayerLeaveZone(Player* player) +{ + if (!m_isActive) + RemoveAurasFromPlayer(player); + + player->RemoveAurasDueToSpell(SPELL_HORDE_CONTROLS_FACTORY_PHASE_SHIFT); + player->RemoveAurasDueToSpell(SPELL_ALLIANCE_CONTROLS_FACTORY_PHASE_SHIFT); + player->RemoveAurasDueToSpell(SPELL_HORDE_CONTROL_PHASE_SHIFT); + player->RemoveAurasDueToSpell(SPELL_ALLIANCE_CONTROL_PHASE_SHIFT); +} + +void BattlefieldWG::OnPlayerEnterZone(Player* player) +{ + if (!m_isActive) + RemoveAurasFromPlayer(player); + + player->AddAura(m_DefenderTeam == TEAM_HORDE ? SPELL_HORDE_CONTROL_PHASE_SHIFT : SPELL_ALLIANCE_CONTROL_PHASE_SHIFT, player); + // Send worldstate to player + SendInitWorldStatesTo(player); +} + +uint32 BattlefieldWG::GetData(uint32 data) const +{ + switch (data) + { + // Used to determine when the phasing spells must be cast + // See: SpellArea::IsFitToRequirements + case AREA_THE_SUNKEN_RING: + case AREA_THE_BROKEN_TEMPLATE: + case AREA_WESTPARK_WORKSHOP: + case AREA_EASTPARK_WORKSHOP: + // Graveyards and Workshops are controlled by the same team. + if (BfGraveyard const* graveyard = GetGraveyardById(GetSpiritGraveyardId(data))) + return graveyard->GetControlTeamId(); + break; + default: + break; + } + + return Battlefield::GetData(data); +} + + +void BattlefieldWG::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) +{ + packet.Worldstates.emplace_back(WS_BATTLEFIELD_WG_DEFENDED_A, GetData(BATTLEFIELD_WG_DATA_DEF_A)); + packet.Worldstates.emplace_back(WS_BATTLEFIELD_WG_DEFENDED_H, GetData(BATTLEFIELD_WG_DATA_DEF_H)); + packet.Worldstates.emplace_back(WS_BATTLEFIELD_WG_ATTACKED_A, GetData(BATTLEFIELD_WG_DATA_WON_A)); + packet.Worldstates.emplace_back(WS_BATTLEFIELD_WG_ATTACKED_H, GetData(BATTLEFIELD_WG_DATA_WON_H)); + packet.Worldstates.emplace_back(WS_BATTLEFIELD_WG_ATTACKER, GetAttackerTeam()); + packet.Worldstates.emplace_back(WS_BATTLEFIELD_WG_DEFENDER, GetDefenderTeam()); + + // Note: cleanup these two, their names look awkward + packet.Worldstates.emplace_back(WS_BATTLEFIELD_WG_ACTIVE, IsWarTime() ? 0 : 1); + packet.Worldstates.emplace_back(WS_BATTLEFIELD_WG_SHOW_WORLDSTATE, IsWarTime() ? 1 : 0); + + for (uint32 itr = 0; itr < 2; ++itr) + packet.Worldstates.emplace_back(ClockWorldState[itr], int32(GameTime::GetGameTime()) + int32(m_Timer) / int32(1000)); + + packet.Worldstates.emplace_back(WS_BATTLEFIELD_WG_VEHICLE_H, GetData(BATTLEFIELD_WG_DATA_VEHICLE_H)); + packet.Worldstates.emplace_back(WS_BATTLEFIELD_WG_MAX_VEHICLE_H, GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_H)); + packet.Worldstates.emplace_back(WS_BATTLEFIELD_WG_VEHICLE_A, GetData(BATTLEFIELD_WG_DATA_VEHICLE_A)); + packet.Worldstates.emplace_back(WS_BATTLEFIELD_WG_MAX_VEHICLE_A, GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_A)); + + for (BfWGGameObjectBuilding* building : BuildingsInZone) + building->FillInitialWorldStates(packet); + + for (WintergraspWorkshop* workshop : Workshops) + workshop->FillInitialWorldStates(packet); +} + +void BattlefieldWG::SendInitWorldStatesTo(Player* player) +{ + WorldPackets::WorldState::InitWorldStates packet; + packet.MapID = m_MapId; + packet.AreaID = m_ZoneId; + packet.SubareaID = player->GetAreaId(); + FillInitialWorldStates(packet); + + player->SendDirectMessage(packet.Write()); +} + +void BattlefieldWG::SendInitWorldStatesToAll() +{ + for (uint8 team = 0; team < PVP_TEAMS_COUNT; ++team) + for (auto itr = m_players[team].begin(); itr != m_players[team].end(); ++itr) + if (Player* player = ObjectAccessor::FindPlayer(*itr)) + SendInitWorldStatesTo(player); +} + +void BattlefieldWG::BrokenWallOrTower(TeamId team, BfWGGameObjectBuilding* building) +{ + if (team == GetDefenderTeam()) + { + for (auto itr = m_PlayersInWar[GetAttackerTeam()].begin(); itr != m_PlayersInWar[GetAttackerTeam()].end(); ++itr) + { + if (Player* player = ObjectAccessor::FindPlayer(*itr)) + if (player->GetDistance2d(ASSERT_NOTNULL(GetGameObject(building->GetGUID()))) < 50.0f) + player->KilledMonsterCredit(QUEST_CREDIT_DEFEND_SIEGE); + } + } +} + +// Called when a tower is broke +void BattlefieldWG::UpdatedDestroyedTowerCount(TeamId team) +{ + // Southern tower + if (team == GetAttackerTeam()) + { + // Update counter + UpdateData(BATTLEFIELD_WG_DATA_DAMAGED_TOWER_ATT, -1); + UpdateData(BATTLEFIELD_WG_DATA_BROKEN_TOWER_ATT, 1); + + // Remove buff stack on attackers + for (auto itr = m_PlayersInWar[GetAttackerTeam()].begin(); itr != m_PlayersInWar[GetAttackerTeam()].end(); ++itr) + if (Player* player = ObjectAccessor::FindPlayer(*itr)) + player->RemoveAuraFromStack(SPELL_TOWER_CONTROL); + + // Add buff stack to defenders and give achievement/quest credit + for (auto itr = m_PlayersInWar[GetDefenderTeam()].begin(); itr != m_PlayersInWar[GetDefenderTeam()].end(); ++itr) + { + if (Player* player = ObjectAccessor::FindPlayer(*itr)) + { + player->CastSpell(player, SPELL_TOWER_CONTROL, true); + player->KilledMonsterCredit(QUEST_CREDIT_TOWERS_DESTROYED); + DoCompleteOrIncrementAchievement(ACHIEVEMENTS_WG_TOWER_DESTROY, player); + } + } + + // If all three south towers are destroyed (ie. all attack towers), remove ten minutes from battle time + if (GetData(BATTLEFIELD_WG_DATA_BROKEN_TOWER_ATT) == 3) + { + if (int32(m_Timer - 600000) < 0) + m_Timer = 0; + else + m_Timer -= 600000; + SendInitWorldStatesToAll(); + } + } + else // Keep tower + { + UpdateData(BATTLEFIELD_WG_DATA_DAMAGED_TOWER_DEF, -1); + UpdateData(BATTLEFIELD_WG_DATA_BROKEN_TOWER_DEF, 1); + } +} + +void BattlefieldWG::ProcessEvent(WorldObject* obj, uint32 eventId, WorldObject* /*invoker*/) +{ + if (!obj || !IsWarTime()) + return; + + // We handle only gameobjects here + GameObject* go = obj->ToGameObject(); + if (!go) + return; + + // On click on titan relic + if (go->GetEntry() == GO_WINTERGRASP_TITAN_S_RELIC) + { + if (CanInteractWithRelic()) + EndBattle(false); + else if (GameObject* relic = GetRelic()) + relic->SetRespawnTime(RESPAWN_IMMEDIATELY); + } + + // if destroy or damage event, search the wall/tower and update worldstate/send warning message + for (BfWGGameObjectBuilding* building : BuildingsInZone) + { + if (go->GetGUID() == building->GetGUID()) + { + if (GameObject* buildingGo = GetGameObject(building->GetGUID())) + { + if (buildingGo->GetGOInfo()->destructibleBuilding.DamagedEvent == eventId) + building->Damaged(); + else if (buildingGo->GetGOInfo()->destructibleBuilding.DestroyedEvent == eventId) + building->Destroyed(); + break; + } + } + } +} + +// Called when a tower is damaged, used for honor reward calcul +void BattlefieldWG::UpdateDamagedTowerCount(TeamId team) +{ + if (team == GetAttackerTeam()) + UpdateData(BATTLEFIELD_WG_DATA_DAMAGED_TOWER_ATT, 1); + else + UpdateData(BATTLEFIELD_WG_DATA_DAMAGED_TOWER_DEF, 1); +} + +// Update vehicle count WorldState to player +void BattlefieldWG::UpdateVehicleCountWG() +{ + SendUpdateWorldState(WS_BATTLEFIELD_WG_VEHICLE_H, GetData(BATTLEFIELD_WG_DATA_VEHICLE_H)); + SendUpdateWorldState(WS_BATTLEFIELD_WG_MAX_VEHICLE_H, GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_H)); + SendUpdateWorldState(WS_BATTLEFIELD_WG_VEHICLE_A, GetData(BATTLEFIELD_WG_DATA_VEHICLE_A)); + SendUpdateWorldState(WS_BATTLEFIELD_WG_MAX_VEHICLE_A, GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_A)); +} + +void BattlefieldWG::UpdateTenacity() +{ + uint32 alliancePlayers = m_PlayersInWar[TEAM_ALLIANCE].size(); + uint32 hordePlayers = m_PlayersInWar[TEAM_HORDE].size(); + int32 newStack = 0; + + if (alliancePlayers && hordePlayers) + { + if (alliancePlayers < hordePlayers) + newStack = int32((float(hordePlayers / alliancePlayers) - 1) * 4); // positive, should cast on alliance + else if (alliancePlayers > hordePlayers) + newStack = int32((1 - float(alliancePlayers / hordePlayers)) * 4); // negative, should cast on horde + } + + if (newStack == int32(m_tenacityStack)) + return; + + m_tenacityStack = newStack; + // Remove old buff + if (m_tenacityTeam != TEAM_NEUTRAL) + { + for (auto itr = m_players[m_tenacityTeam].begin(); itr != m_players[m_tenacityTeam].end(); ++itr) + if (Player* player = ObjectAccessor::FindPlayer(*itr)) + if (player->GetLevel() >= m_MinLevel) + player->RemoveAurasDueToSpell(SPELL_TENACITY); + + for (auto itr = m_vehicles[m_tenacityTeam].begin(); itr != m_vehicles[m_tenacityTeam].end(); ++itr) + if (Creature* creature = GetCreature(*itr)) + creature->RemoveAurasDueToSpell(SPELL_TENACITY_VEHICLE); + } + + // Apply new buff + if (newStack) + { + m_tenacityTeam = newStack > 0 ? TEAM_ALLIANCE : TEAM_HORDE; + + if (newStack < 0) + newStack = -newStack; + if (newStack > 20) + newStack = 20; + + uint32 buff_honor = SPELL_GREATEST_HONOR; + if (newStack < 15) + buff_honor = SPELL_GREATER_HONOR; + if (newStack < 10) + buff_honor = SPELL_GREAT_HONOR; + if (newStack < 5) + buff_honor = 0; + + for (auto itr = m_PlayersInWar[m_tenacityTeam].begin(); itr != m_PlayersInWar[m_tenacityTeam].end(); ++itr) + if (Player* player = ObjectAccessor::FindPlayer(*itr)) + player->SetAuraStack(SPELL_TENACITY, player, newStack); + + for (auto itr = m_vehicles[m_tenacityTeam].begin(); itr != m_vehicles[m_tenacityTeam].end(); ++itr) + if (Creature* creature = GetCreature(*itr)) + creature->SetAuraStack(SPELL_TENACITY_VEHICLE, creature, newStack); + + if (buff_honor != 0) + { + for (auto itr = m_PlayersInWar[m_tenacityTeam].begin(); itr != m_PlayersInWar[m_tenacityTeam].end(); ++itr) + if (Player* player = ObjectAccessor::FindPlayer(*itr)) + player->CastSpell(player, buff_honor, true); + + for (auto itr = m_vehicles[m_tenacityTeam].begin(); itr != m_vehicles[m_tenacityTeam].end(); ++itr) + if (Creature* creature = GetCreature(*itr)) + creature->CastSpell(creature, buff_honor, true); + } + } + else + m_tenacityTeam = TEAM_NEUTRAL; +} + +WintergraspCapturePoint::WintergraspCapturePoint(BattlefieldWG* battlefield, TeamId teamInControl) : BfCapturePoint(battlefield) +{ + m_Bf = battlefield; + m_team = teamInControl; + m_Workshop = nullptr; +} + +void WintergraspCapturePoint::ChangeTeam(TeamId /*oldTeam*/) +{ + ASSERT(m_Workshop); + m_Workshop->GiveControlTo(m_team); +} + +BfGraveyardWG::BfGraveyardWG(BattlefieldWG* battlefield) : BfGraveyard(battlefield) +{ + m_Bf = battlefield; + m_GossipTextId = 0; +} + +BfWGGameObjectBuilding::BfWGGameObjectBuilding(BattlefieldWG* wg, WintergraspGameObjectBuildingType type, uint32 worldState) +{ + ASSERT(wg); + + _wg = wg; + _teamControl = TEAM_NEUTRAL; + _type = type; + _worldState = worldState; + _state = BATTLEFIELD_WG_OBJECTSTATE_NONE; + _staticTowerInfo = nullptr; +} + +void BfWGGameObjectBuilding::Rebuild() +{ + switch (_type) + { + case BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER: + case BATTLEFIELD_WG_OBJECTTYPE_DOOR_LAST: + case BATTLEFIELD_WG_OBJECTTYPE_DOOR: + case BATTLEFIELD_WG_OBJECTTYPE_WALL: + _teamControl = _wg->GetDefenderTeam(); // Objects that are part of the keep should be the defender's + break; + case BATTLEFIELD_WG_OBJECTTYPE_TOWER: + _teamControl = _wg->GetAttackerTeam(); // The towers in the south should be the attacker's + break; + default: + _teamControl = TEAM_NEUTRAL; + break; + } + + if (GameObject* build = _wg->GetGameObject(_buildGUID)) + { + // Rebuild gameobject + if (build->IsDestructibleBuilding()) + { + build->SetDestructibleState(GO_DESTRUCTIBLE_REBUILDING, nullptr, true); + if (build->GetEntry() == GO_WINTERGRASP_VAULT_GATE) + if (GameObject* go = build->FindNearestGameObject(GO_WINTERGRASP_KEEP_COLLISION_WALL, 50.0f)) + go->SetGoState(GO_STATE_ACTIVE); + + // Update worldstate + _state = WintergraspGameObjectState(BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_INTACT - (_teamControl * 3)); + _wg->SendUpdateWorldState(_worldState, _state); + } + UpdateCreatureAndGo(); + build->SetFaction(WintergraspFaction[_teamControl]); + } +} + +void BfWGGameObjectBuilding::RebuildGate() +{ + if (GameObject* build = _wg->GetGameObject(_buildGUID)) + { + if (build->IsDestructibleBuilding() && build->GetEntry() == GO_WINTERGRASP_VAULT_GATE) + { + if (GameObject* go = build->FindNearestGameObject(GO_WINTERGRASP_KEEP_COLLISION_WALL, 50.0f)) + go->SetGoState(GO_STATE_READY); //not GO_STATE_ACTIVE + } + } +} + +void BfWGGameObjectBuilding::Damaged() +{ + // Update worldstate + _state = WintergraspGameObjectState(BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_DAMAGE - (_teamControl * 3)); + _wg->SendUpdateWorldState(_worldState, _state); + + // Send warning message + if (_staticTowerInfo) + _wg->SendWarning(_staticTowerInfo->TextIds.Damaged); + + for (ObjectGuid guid : m_CreatureTopList[_wg->GetAttackerTeam()]) + if (Creature* creature = _wg->GetCreature(guid)) + _wg->HideNpc(creature); + + for (ObjectGuid guid : m_TurretTopList) + if (Creature* creature = _wg->GetCreature(guid)) + _wg->HideNpc(creature); + + if (_type == BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER) + _wg->UpdateDamagedTowerCount(_wg->GetDefenderTeam()); + else if (_type == BATTLEFIELD_WG_OBJECTTYPE_TOWER) + _wg->UpdateDamagedTowerCount(_wg->GetAttackerTeam()); +} + +void BfWGGameObjectBuilding::Destroyed() +{ + // Update worldstate + _state = WintergraspGameObjectState(BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_DESTROY - (_teamControl * 3)); + _wg->SendUpdateWorldState(_worldState, _state); + + // Warn players + if (_staticTowerInfo) + _wg->SendWarning(_staticTowerInfo->TextIds.Destroyed); + + switch (_type) + { + // Inform the global wintergrasp script of the destruction of this object + case BATTLEFIELD_WG_OBJECTTYPE_TOWER: + case BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER: + _wg->UpdatedDestroyedTowerCount(_teamControl); + break; + case BATTLEFIELD_WG_OBJECTTYPE_DOOR_LAST: + if (GameObject* build = _wg->GetGameObject(_buildGUID)) + if (GameObject* go = build->FindNearestGameObject(GO_WINTERGRASP_KEEP_COLLISION_WALL, 50.0f)) + go->SetGoState(GO_STATE_ACTIVE); + _wg->SetRelicInteractible(true); + if (_wg->GetRelic()) + _wg->GetRelic()->RemoveFlag(GameObjectFlags(GO_FLAG_IN_USE | GO_FLAG_NOT_SELECTABLE)); + else + TC_LOG_ERROR("bg.battlefield.wg", "Titan Relic not found."); + break; + default: + break; + } + + _wg->BrokenWallOrTower(_teamControl, this); +} + +void BfWGGameObjectBuilding::Init(GameObject* go) +{ + if (!go) + return; + + // GameObject associated to object + _buildGUID = go->GetGUID(); + + switch (_type) + { + case BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER: + case BATTLEFIELD_WG_OBJECTTYPE_DOOR_LAST: + case BATTLEFIELD_WG_OBJECTTYPE_DOOR: + case BATTLEFIELD_WG_OBJECTTYPE_WALL: + _teamControl = _wg->GetDefenderTeam(); // Objects that are part of the keep should be the defender's + break; + case BATTLEFIELD_WG_OBJECTTYPE_TOWER: + _teamControl = _wg->GetAttackerTeam(); // The towers in the south should be the attacker's + break; + default: + _teamControl = TEAM_NEUTRAL; + break; + } + + _state = WintergraspGameObjectState(sWorld->getWorldState(_worldState)); + switch (_state) + { + case BATTLEFIELD_WG_OBJECTSTATE_NEUTRAL_INTACT: + case BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_INTACT: + case BATTLEFIELD_WG_OBJECTSTATE_HORDE_INTACT: + go->SetDestructibleState(GO_DESTRUCTIBLE_REBUILDING, nullptr, true); + break; + case BATTLEFIELD_WG_OBJECTSTATE_NEUTRAL_DESTROY: + case BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_DESTROY: + case BATTLEFIELD_WG_OBJECTSTATE_HORDE_DESTROY: + go->SetDestructibleState(GO_DESTRUCTIBLE_DESTROYED); + break; + case BATTLEFIELD_WG_OBJECTSTATE_NEUTRAL_DAMAGE: + case BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_DAMAGE: + case BATTLEFIELD_WG_OBJECTSTATE_HORDE_DAMAGE: + go->SetDestructibleState(GO_DESTRUCTIBLE_DAMAGED); + break; + default: + break; + } + + int32 towerId = -1; + switch (go->GetEntry()) + { + case GO_WINTERGRASP_FORTRESS_TOWER_1: + towerId = BATTLEFIELD_WG_TOWER_FORTRESS_NW; + break; + case GO_WINTERGRASP_FORTRESS_TOWER_2: + towerId = BATTLEFIELD_WG_TOWER_FORTRESS_SW; + break; + case GO_WINTERGRASP_FORTRESS_TOWER_3: + towerId = BATTLEFIELD_WG_TOWER_FORTRESS_SE; + break; + case GO_WINTERGRASP_FORTRESS_TOWER_4: + towerId = BATTLEFIELD_WG_TOWER_FORTRESS_NE; + break; + case GO_WINTERGRASP_SHADOWSIGHT_TOWER: + towerId = BATTLEFIELD_WG_TOWER_SHADOWSIGHT; + break; + case GO_WINTERGRASP_WINTER_S_EDGE_TOWER: + towerId = BATTLEFIELD_WG_TOWER_WINTER_S_EDGE; + break; + case GO_WINTERGRASP_FLAMEWATCH_TOWER: + towerId = BATTLEFIELD_WG_TOWER_FLAMEWATCH; + break; + } + + if (towerId >= BATTLEFIELD_WG_TOWER_SHADOWSIGHT) // Attacker towers + { + // Spawn associate gameobjects + for (WintergraspGameObjectData const& gobData : AttackTowers[towerId - 4].GameObject) + { + if (GameObject* goHorde = _wg->SpawnGameObject(gobData.HordeEntry, gobData.Pos, gobData.Rot)) + m_GameObjectList[TEAM_HORDE].push_back(goHorde->GetGUID()); + + if (GameObject* goAlliance = _wg->SpawnGameObject(gobData.AllianceEntry, gobData.Pos, gobData.Rot)) + m_GameObjectList[TEAM_ALLIANCE].push_back(goAlliance->GetGUID()); + } + + // Spawn associate npc bottom + for (WintergraspObjectPositionData const& creatureData : AttackTowers[towerId - 4].CreatureBottom) + { + if (Creature* creature = _wg->SpawnCreature(creatureData.HordeEntry, creatureData.Pos)) + m_CreatureBottomList[TEAM_HORDE].push_back(creature->GetGUID()); + + if (Creature* creature = _wg->SpawnCreature(creatureData.AllianceEntry, creatureData.Pos)) + m_CreatureBottomList[TEAM_ALLIANCE].push_back(creature->GetGUID()); + } + } + + if (towerId >= 0) + { + ASSERT(towerId < WG_MAX_TOWER); + _staticTowerInfo = &TowerData[towerId]; + + // Spawn Turret bottom + for (Position const& turretPos : TowerCannon[towerId].TowerCannonBottom) + { + if (Creature* turret = _wg->SpawnCreature(NPC_WINTERGRASP_TOWER_CANNON, turretPos)) + { + m_TowerCannonBottomList.push_back(turret->GetGUID()); + switch (go->GetEntry()) + { + case GO_WINTERGRASP_FORTRESS_TOWER_1: + case GO_WINTERGRASP_FORTRESS_TOWER_2: + case GO_WINTERGRASP_FORTRESS_TOWER_3: + case GO_WINTERGRASP_FORTRESS_TOWER_4: + turret->SetFaction(WintergraspFaction[_wg->GetDefenderTeam()]); + break; + case GO_WINTERGRASP_SHADOWSIGHT_TOWER: + case GO_WINTERGRASP_WINTER_S_EDGE_TOWER: + case GO_WINTERGRASP_FLAMEWATCH_TOWER: + turret->SetFaction(WintergraspFaction[_wg->GetAttackerTeam()]); + break; + } + + _wg->HideNpc(turret); + } + } + + // Spawn Turret top + for (Position const& towerCannonPos : TowerCannon[towerId].TurretTop) + { + if (Creature* turret = _wg->SpawnCreature(NPC_WINTERGRASP_TOWER_CANNON, towerCannonPos)) + { + m_TurretTopList.push_back(turret->GetGUID()); + switch (go->GetEntry()) + { + case GO_WINTERGRASP_FORTRESS_TOWER_1: + case GO_WINTERGRASP_FORTRESS_TOWER_2: + case GO_WINTERGRASP_FORTRESS_TOWER_3: + case GO_WINTERGRASP_FORTRESS_TOWER_4: + turret->SetFaction(WintergraspFaction[_wg->GetDefenderTeam()]); + break; + case GO_WINTERGRASP_SHADOWSIGHT_TOWER: + case GO_WINTERGRASP_WINTER_S_EDGE_TOWER: + case GO_WINTERGRASP_FLAMEWATCH_TOWER: + turret->SetFaction(WintergraspFaction[_wg->GetAttackerTeam()]); + break; + } + _wg->HideNpc(turret); + } + } + UpdateCreatureAndGo(); + } +} + +void BfWGGameObjectBuilding::UpdateCreatureAndGo() +{ + for (ObjectGuid guid : m_CreatureTopList[_wg->GetDefenderTeam()]) + if (Creature* creature = _wg->GetCreature(guid)) + _wg->HideNpc(creature); + + for (ObjectGuid guid : m_CreatureTopList[_wg->GetAttackerTeam()]) + if (Creature* creature = _wg->GetCreature(guid)) + _wg->ShowNpc(creature, true); + + for (ObjectGuid guid : m_CreatureBottomList[_wg->GetDefenderTeam()]) + if (Creature* creature = _wg->GetCreature(guid)) + _wg->HideNpc(creature); + + for (ObjectGuid guid : m_CreatureBottomList[_wg->GetAttackerTeam()]) + if (Creature* creature = _wg->GetCreature(guid)) + _wg->ShowNpc(creature, true); + + for (ObjectGuid guid : m_GameObjectList[_wg->GetDefenderTeam()]) + if (GameObject* go = _wg->GetGameObject(guid)) + go->SetRespawnTime(RESPAWN_ONE_DAY); + + for (ObjectGuid guid : m_GameObjectList[_wg->GetAttackerTeam()]) + if (GameObject* go = _wg->GetGameObject(guid)) + go->SetRespawnTime(RESPAWN_IMMEDIATELY); +} + +void BfWGGameObjectBuilding::UpdateTurretAttack(bool disable) +{ + for (ObjectGuid guid : m_TowerCannonBottomList) + { + if (Creature* creature = _wg->GetCreature(guid)) + { + if (disable) + _wg->HideNpc(creature); + else + _wg->ShowNpc(creature, true); + + switch (_buildGUID.GetEntry()) + { + case GO_WINTERGRASP_FORTRESS_TOWER_1: + case GO_WINTERGRASP_FORTRESS_TOWER_2: + case GO_WINTERGRASP_FORTRESS_TOWER_3: + case GO_WINTERGRASP_FORTRESS_TOWER_4: + { + creature->SetFaction(WintergraspFaction[_wg->GetDefenderTeam()]); + break; + } + case GO_WINTERGRASP_SHADOWSIGHT_TOWER: + case GO_WINTERGRASP_WINTER_S_EDGE_TOWER: + case GO_WINTERGRASP_FLAMEWATCH_TOWER: + { + creature->SetFaction(WintergraspFaction[_wg->GetAttackerTeam()]); + break; + } + } + } + } + + for (ObjectGuid guid : m_TurretTopList) + { + if (Creature* creature = _wg->GetCreature(guid)) + { + if (disable) + _wg->HideNpc(creature); + else + _wg->ShowNpc(creature, true); + + switch (_buildGUID.GetEntry()) + { + case GO_WINTERGRASP_FORTRESS_TOWER_1: + case GO_WINTERGRASP_FORTRESS_TOWER_2: + case GO_WINTERGRASP_FORTRESS_TOWER_3: + case GO_WINTERGRASP_FORTRESS_TOWER_4: + { + creature->SetFaction(WintergraspFaction[_wg->GetDefenderTeam()]); + break; + } + case GO_WINTERGRASP_SHADOWSIGHT_TOWER: + case GO_WINTERGRASP_WINTER_S_EDGE_TOWER: + case GO_WINTERGRASP_FLAMEWATCH_TOWER: + { + creature->SetFaction(WintergraspFaction[_wg->GetAttackerTeam()]); + break; + } + } + } + } +} + +void BfWGGameObjectBuilding::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) +{ + packet.Worldstates.emplace_back(_worldState, _state); +} + +void BfWGGameObjectBuilding::Save() +{ + sWorld->setWorldState(_worldState, _state); +} + +WintergraspWorkshop::WintergraspWorkshop(BattlefieldWG* wg, uint8 type) +{ + ASSERT(wg && type < WG_MAX_WORKSHOP); + + _wg = wg; + _state = BATTLEFIELD_WG_OBJECTSTATE_NONE; + _teamControl = TEAM_NEUTRAL; + _staticInfo = &WorkshopData[type]; +} + +uint8 WintergraspWorkshop::GetId() const +{ + return _staticInfo->WorkshopId; +} + +void WintergraspWorkshop::GiveControlTo(TeamId teamId, bool init /*= false*/) +{ + switch (teamId) + { + case TEAM_NEUTRAL: + { + // Send warning message to all player for inform a faction attack a workshop + // alliance / horde attacking workshop + _wg->SendWarning(_teamControl == TEAM_ALLIANCE ? _staticInfo->TextIds.HordeAttack : _staticInfo->TextIds.AllianceAttack); + break; + } + case TEAM_ALLIANCE: + { + // Updating worldstate + _state = BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_INTACT; + _wg->SendUpdateWorldState(_staticInfo->WorldStateId, _state); + + // Warning message + if (!init) + _wg->SendWarning(_staticInfo->TextIds.AllianceCapture); // workshop taken - alliance + + // Found associate graveyard and update it + if (_staticInfo->WorkshopId < BATTLEFIELD_WG_WORKSHOP_KEEP_WEST) + if (BfGraveyard* gy = _wg->GetGraveyardById(_staticInfo->WorkshopId)) + gy->GiveControlTo(TEAM_ALLIANCE); + + _teamControl = teamId; + break; + } + case TEAM_HORDE: + { + // Update worldstate + _state = BATTLEFIELD_WG_OBJECTSTATE_HORDE_INTACT; + _wg->SendUpdateWorldState(_staticInfo->WorldStateId, _state); + + // Warning message + if (!init) + _wg->SendWarning(_staticInfo->TextIds.HordeCapture); // workshop taken - horde + + // Update graveyard control + if (_staticInfo->WorkshopId < BATTLEFIELD_WG_WORKSHOP_KEEP_WEST) + if (BfGraveyard* gy = _wg->GetGraveyardById(_staticInfo->WorkshopId)) + gy->GiveControlTo(TEAM_HORDE); + + _teamControl = teamId; + break; + } + } + if (!init) + _wg->UpdateCounterVehicle(false); +} + +void WintergraspWorkshop::UpdateGraveyardAndWorkshop() +{ + if (_staticInfo->WorkshopId < BATTLEFIELD_WG_WORKSHOP_NE) + GiveControlTo(_wg->GetAttackerTeam(), true); + else + GiveControlTo(_wg->GetDefenderTeam(), true); +} + +void WintergraspWorkshop::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) +{ + packet.Worldstates.emplace_back(_staticInfo->WorldStateId, _state); +} + +void WintergraspWorkshop::Save() +{ + sWorld->setWorldState(_staticInfo->WorldStateId, _state); +} + +class Battlefield_wintergrasp : public BattlefieldScript +{ +public: + Battlefield_wintergrasp() : BattlefieldScript("battlefield_wg") { } + + Battlefield* GetBattlefield() const override + { + return new BattlefieldWG(); + } +}; + +void AddSC_BF_wintergrasp() +{ + new Battlefield_wintergrasp(); +} diff --git a/src/server/scripts/Battlefield/BattlefieldWG.h b/src/server/scripts/Battlefield/BattlefieldWG.h new file mode 100644 index 00000000000..fc3806427d9 --- /dev/null +++ b/src/server/scripts/Battlefield/BattlefieldWG.h @@ -0,0 +1,575 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#ifndef BATTLEFIELD_WG_ +#define BATTLEFIELD_WG_ + +#include "Battlefield.h" + +class Group; +class BattlefieldWG; +class WintergraspCapturePoint; + +struct BfWGGameObjectBuilding; +struct WintergraspWorkshop; +struct StaticWintergraspTowerInfo; +struct StaticWintergraspWorkshopInfo; +struct WintergraspObjectPositionData; + +typedef std::vector GameObjectBuildingVect; +typedef std::vector WorkshopVect; + +enum WintergraspSpells +{ + // Wartime auras + SPELL_RECRUIT = 37795, + SPELL_CORPORAL = 33280, + SPELL_LIEUTENANT = 55629, + SPELL_TENACITY = 58549, + SPELL_TENACITY_VEHICLE = 59911, + SPELL_TOWER_CONTROL = 62064, + SPELL_SPIRITUAL_IMMUNITY = 58729, + SPELL_GREAT_HONOR = 58555, + SPELL_GREATER_HONOR = 58556, + SPELL_GREATEST_HONOR = 58557, + SPELL_ALLIANCE_FLAG = 14268, + SPELL_HORDE_FLAG = 14267, + SPELL_GRAB_PASSENGER = 61178, + + // Reward spells + SPELL_VICTORY_REWARD = 56902, + SPELL_DEFEAT_REWARD = 58494, + SPELL_DAMAGED_TOWER = 59135, + SPELL_DESTROYED_TOWER = 59136, + SPELL_DAMAGED_BUILDING = 59201, + SPELL_INTACT_BUILDING = 59203, + + SPELL_TELEPORT_BRIDGE = 59096, + SPELL_TELEPORT_FORTRESS = 60035, + + SPELL_TELEPORT_DALARAN = 53360, + SPELL_VICTORY_AURA = 60044, + + // Other spells + SPELL_WINTERGRASP_WATER = 36444, + SPELL_ESSENCE_OF_WINTERGRASP = 58045, + SPELL_WINTERGRASP_RESTRICTED_FLIGHT_AREA = 91604, + + // Phasing spells + SPELL_HORDE_CONTROLS_FACTORY_PHASE_SHIFT = 56618, // ADDS PHASE 16 + SPELL_ALLIANCE_CONTROLS_FACTORY_PHASE_SHIFT = 56617, // ADDS PHASE 32 + + SPELL_HORDE_CONTROL_PHASE_SHIFT = 55773, // ADDS PHASE 64 + SPELL_ALLIANCE_CONTROL_PHASE_SHIFT = 55774 // ADDS PHASE 128 +}; + +enum WintergraspData +{ + BATTLEFIELD_WG_DATA_DAMAGED_TOWER_DEF, + BATTLEFIELD_WG_DATA_BROKEN_TOWER_DEF, + BATTLEFIELD_WG_DATA_DAMAGED_TOWER_ATT, + BATTLEFIELD_WG_DATA_BROKEN_TOWER_ATT, + BATTLEFIELD_WG_DATA_MAX_VEHICLE_A, + BATTLEFIELD_WG_DATA_MAX_VEHICLE_H, + BATTLEFIELD_WG_DATA_VEHICLE_A, + BATTLEFIELD_WG_DATA_VEHICLE_H, + BATTLEFIELD_WG_DATA_WON_A, + BATTLEFIELD_WG_DATA_DEF_A, + BATTLEFIELD_WG_DATA_WON_H, + BATTLEFIELD_WG_DATA_DEF_H, + BATTLEFIELD_WG_DATA_MAX, + + BATTLEFIELD_WG_MAPID = 571 // Northrend +}; + +enum WintergraspAchievements +{ + ACHIEVEMENTS_WIN_WG = 1717, + ACHIEVEMENTS_WIN_WG_100 = 1718, /// @todo: Has to be implemented + ACHIEVEMENTS_WG_GNOMESLAUGHTER = 1723, /// @todo: Has to be implemented + ACHIEVEMENTS_WG_TOWER_DESTROY = 1727, + ACHIEVEMENTS_DESTRUCTION_DERBY_A = 1737, /// @todo: Has to be implemented + ACHIEVEMENTS_WG_TOWER_CANNON_KILL = 1751, /// @todo: Has to be implemented + ACHIEVEMENTS_WG_MASTER_A = 1752, /// @todo: Has to be implemented + ACHIEVEMENTS_WIN_WG_TIMER_10 = 1755, + ACHIEVEMENTS_STONE_KEEPER_50 = 2085, /// @todo: Has to be implemented + ACHIEVEMENTS_STONE_KEEPER_100 = 2086, /// @todo: Has to be implemented + ACHIEVEMENTS_STONE_KEEPER_250 = 2087, /// @todo: Has to be implemented + ACHIEVEMENTS_STONE_KEEPER_500 = 2088, /// @todo: Has to be implemented + ACHIEVEMENTS_STONE_KEEPER_1000 = 2089, /// @todo: Has to be implemented + ACHIEVEMENTS_WG_RANGER = 2199, /// @todo: Has to be implemented + ACHIEVEMENTS_DESTRUCTION_DERBY_H = 2476, /// @todo: Has to be implemented + ACHIEVEMENTS_WG_MASTER_H = 2776 /// @todo: Has to be implemented +}; + +enum WintergraspQuests +{ + QUEST_VICTORY_WINTERGRASP_A = 13181, + QUEST_VICTORY_WINTERGRASP_H = 13183, + QUEST_CREDIT_TOWERS_DESTROYED = 35074, + QUEST_CREDIT_DEFEND_SIEGE = 31284 +}; + +/*######################### + *####### Graveyards ###### + *#########################*/ + +class BfGraveyardWG : public BfGraveyard +{ + public: + BfGraveyardWG(BattlefieldWG* Bf); + + void SetTextId(uint32 textId) { m_GossipTextId = textId; } + uint32 GetTextId() const { return m_GossipTextId; } + + protected: + uint32 m_GossipTextId; +}; + +enum WGGraveyardId +{ + BATTLEFIELD_WG_GY_WORKSHOP_NE, + BATTLEFIELD_WG_GY_WORKSHOP_NW, + BATTLEFIELD_WG_GY_WORKSHOP_SE, + BATTLEFIELD_WG_GY_WORKSHOP_SW, + BATTLEFIELD_WG_GY_KEEP, + BATTLEFIELD_WG_GY_HORDE, + BATTLEFIELD_WG_GY_ALLIANCE, + BATTLEFIELD_WG_GRAVEYARD_MAX +}; + +enum WGGossipText +{ + BATTLEFIELD_WG_GOSSIPTEXT_GY_NE = 20071, + BATTLEFIELD_WG_GOSSIPTEXT_GY_NW = 20072, + BATTLEFIELD_WG_GOSSIPTEXT_GY_SE = 20074, + BATTLEFIELD_WG_GOSSIPTEXT_GY_SW = 20073, + BATTLEFIELD_WG_GOSSIPTEXT_GY_KEEP = 20070, + BATTLEFIELD_WG_GOSSIPTEXT_GY_HORDE = 20075, + BATTLEFIELD_WG_GOSSIPTEXT_GY_ALLIANCE = 20076 +}; + +enum WintergraspNpcs +{ + BATTLEFIELD_WG_NPC_GUARD_H = 30739, + BATTLEFIELD_WG_NPC_GUARD_A = 30740, + BATTLEFIELD_WG_NPC_STALKER = 15214, + + NPC_TAUNKA_SPIRIT_GUIDE = 31841, // Horde spirit guide for Wintergrasp + NPC_DWARVEN_SPIRIT_GUIDE = 31842, // Alliance spirit guide for Wintergrasp + + NPC_WINTERGRASP_SIEGE_ENGINE_ALLIANCE = 28312, + NPC_WINTERGRASP_SIEGE_ENGINE_HORDE = 32627, + NPC_WINTERGRASP_CATAPULT = 27881, + NPC_WINTERGRASP_DEMOLISHER = 28094, + NPC_WINTERGRASP_TOWER_CANNON = 28366 +}; + +/* ######################### * + * WintergraspCapturePoint * + * ######################### */ + +class WintergraspCapturePoint : public BfCapturePoint +{ + public: + WintergraspCapturePoint(BattlefieldWG* battlefield, TeamId teamInControl); + + void LinkToWorkshop(WintergraspWorkshop* workshop) { m_Workshop = workshop; } + + void ChangeTeam(TeamId oldteam) override; + TeamId GetTeam() const { return m_team; } + + protected: + WintergraspWorkshop* m_Workshop; +}; + +/* ######################### * + * WinterGrasp Battlefield * + * ######################### */ + +class BattlefieldWG : public Battlefield +{ + public: + ~BattlefieldWG(); + /** + * \brief Called when the battle start + * - Spawn relic and turret + * - Rebuild tower and wall + * - Invite player to war + */ + void OnBattleStart() override; + + /** + * \brief Called when battle end + * - Remove relic and turret + * - Change banner/npc in keep if it needed + * - Saving battlestate + * - Reward honor/mark to player + * - Remove vehicle + * \param endByTimer : true if battle ended when timer is at 00:00, false if battle ended by clicking on relic + */ + void OnBattleEnd(bool endByTimer) override; + + /** + * \brief Called when grouping starts (15 minutes before battlestart) + * - Invite all player in zone to join queue + */ + void OnStartGrouping() override; + + /** + * \brief Called when player accept invite to join battle + * - Update aura + * - Teleport if it needed + * - Update worldstate + * - Update tenacity + * \param player: Player who accepted invite + */ + void OnPlayerJoinWar(Player* player) override; + + /** + * \brief Called when player left the battle + * - Update player aura + * \param player : Player who left the battle + */ + void OnPlayerLeaveWar(Player* player) override; + + /** + * \brief Called when player left the WG zone + * \param player : Player who left the zone + */ + void OnPlayerLeaveZone(Player* player) override; + + /** + * \brief Called when player enters in WG zone + * - Update aura + * - Update worldstate + * \param player : Player who enters the zone + */ + void OnPlayerEnterZone(Player* player) override; + + /** + * \brief Called for update battlefield data + * - Save battle timer in database every minutes + * - Update imunity aura from graveyard + * \param diff : time elapsed since the last call (in ms) + */ + bool Update(uint32 diff) override; + + /** + * \brief Called when a creature is created + * - Update vehicle count + */ + void OnCreatureCreate(Creature* creature) override; + + /** + * \brief Called when a creature is removed + * - Update vehicle count + */ + void OnCreatureRemove(Creature* creature) override; + + /** + * \brief Called when a gameobject is created + */ + void OnGameObjectCreate(GameObject* go) override; + + /** + * \brief Called when a wall/tower is broken + * - Update quest + */ + void BrokenWallOrTower(TeamId team, BfWGGameObjectBuilding* building); + + /** + * \brief Called when a tower is damaged + * - Update tower count (for reward calcul) + */ + void UpdateDamagedTowerCount(TeamId team); + + /** + * \brief Called when tower is broken + * - Update tower buff + * - check if three south tower is down for remove 10 minutes to wg + */ + void UpdatedDestroyedTowerCount(TeamId team); + + void DoCompleteOrIncrementAchievement(uint32 achievement, Player* player, uint8 incrementNumber = 1) override; + + void RemoveAurasFromPlayer(Player* player); + + /** + * \brief Called when battlefield is setup, at server start + */ + bool SetupBattlefield() override; + + /// Return pointer to relic object + GameObject* GetRelic() { return GetGameObject(m_titansRelicGUID); } + + /// Define relic object + void SetRelic(ObjectGuid relicGUID) { m_titansRelicGUID = relicGUID; } + + /// Check if players can interact with the relic (Only if the last door has been broken) + bool CanInteractWithRelic() { return m_isRelicInteractible; } + + /// Define if player can interact with the relic + void SetRelicInteractible(bool allow) { m_isRelicInteractible = allow; } + + void UpdateVehicleCountWG(); + void UpdateCounterVehicle(bool init); + + void SendInitWorldStatesTo(Player* player); + void SendInitWorldStatesToAll() override; + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; + + void HandleKill(Player* killer, Unit* victim) override; + void OnUnitDeath(Unit* unit) override; + void HandlePromotion(Player* killer, Unit* killed); + void PromotePlayer(Player* killer); + + void UpdateTenacity(); + void ProcessEvent(WorldObject* obj, uint32 eventId, WorldObject* invoker) override; + + bool FindAndRemoveVehicleFromList(Unit* vehicle); + + // returns the graveyardId in the specified area. + uint8 GetSpiritGraveyardId(uint32 areaId) const; + + uint32 GetData(uint32 data) const override; + + protected: + bool m_isRelicInteractible; + + WorkshopVect Workshops; + + GuidVector DefenderPortalList[PVP_TEAMS_COUNT]; + GameObjectBuildingVect BuildingsInZone; + + GuidUnorderedSet m_vehicles[PVP_TEAMS_COUNT]; + GuidVector CanonList; + + TeamId m_tenacityTeam; + uint32 m_tenacityStack; + uint32 m_saveTimer; + + ObjectGuid m_titansRelicGUID; +}; + +enum WintergraspGameObjectBuildingType +{ + BATTLEFIELD_WG_OBJECTTYPE_DOOR, + BATTLEFIELD_WG_OBJECTTYPE_TITANRELIC, + BATTLEFIELD_WG_OBJECTTYPE_WALL, + BATTLEFIELD_WG_OBJECTTYPE_DOOR_LAST, + BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER, + BATTLEFIELD_WG_OBJECTTYPE_TOWER +}; + +enum WintergraspGameObjectState +{ + BATTLEFIELD_WG_OBJECTSTATE_NONE, + BATTLEFIELD_WG_OBJECTSTATE_NEUTRAL_INTACT, + BATTLEFIELD_WG_OBJECTSTATE_NEUTRAL_DAMAGE, + BATTLEFIELD_WG_OBJECTSTATE_NEUTRAL_DESTROY, + BATTLEFIELD_WG_OBJECTSTATE_HORDE_INTACT, + BATTLEFIELD_WG_OBJECTSTATE_HORDE_DAMAGE, + BATTLEFIELD_WG_OBJECTSTATE_HORDE_DESTROY, + BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_INTACT, + BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_DAMAGE, + BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_DESTROY +}; + +enum WintergraspTowerIds +{ + BATTLEFIELD_WG_TOWER_FORTRESS_NW, + BATTLEFIELD_WG_TOWER_FORTRESS_SW, + BATTLEFIELD_WG_TOWER_FORTRESS_SE, + BATTLEFIELD_WG_TOWER_FORTRESS_NE, + BATTLEFIELD_WG_TOWER_SHADOWSIGHT, + BATTLEFIELD_WG_TOWER_WINTER_S_EDGE, + BATTLEFIELD_WG_TOWER_FLAMEWATCH +}; + +enum WintergraspWorkshopIds +{ + BATTLEFIELD_WG_WORKSHOP_SE, + BATTLEFIELD_WG_WORKSHOP_SW, + BATTLEFIELD_WG_WORKSHOP_NE, + BATTLEFIELD_WG_WORKSHOP_NW, + BATTLEFIELD_WG_WORKSHOP_KEEP_WEST, + BATTLEFIELD_WG_WORKSHOP_KEEP_EAST +}; + +enum WintergraspTeamControl +{ + BATTLEFIELD_WG_TEAM_ALLIANCE, + BATTLEFIELD_WG_TEAM_HORDE, + BATTLEFIELD_WG_TEAM_NEUTRAL +}; + +enum WintergraspText +{ + // Invisible Stalker + BATTLEFIELD_WG_TEXT_SOUTHERN_TOWER_DAMAGE = 1, + BATTLEFIELD_WG_TEXT_SOUTHERN_TOWER_DESTROY = 2, + BATTLEFIELD_WG_TEXT_EASTERN_TOWER_DAMAGE = 3, + BATTLEFIELD_WG_TEXT_EASTERN_TOWER_DESTROY = 4, + BATTLEFIELD_WG_TEXT_WESTERN_TOWER_DAMAGE = 5, + BATTLEFIELD_WG_TEXT_WESTERN_TOWER_DESTROY = 6, + BATTLEFIELD_WG_TEXT_NW_KEEPTOWER_DAMAGE = 7, + BATTLEFIELD_WG_TEXT_NW_KEEPTOWER_DESTROY = 8, + BATTLEFIELD_WG_TEXT_SE_KEEPTOWER_DAMAGE = 9, + BATTLEFIELD_WG_TEXT_SE_KEEPTOWER_DESTROY = 10, + BATTLEFIELD_WG_TEXT_BROKEN_TEMPLE_ATTACK_ALLIANCE = 11, + BATTLEFIELD_WG_TEXT_BROKEN_TEMPLE_CAPTURE_ALLIANCE = 12, + BATTLEFIELD_WG_TEXT_BROKEN_TEMPLE_ATTACK_HORDE = 13, + BATTLEFIELD_WG_TEXT_BROKEN_TEMPLE_CAPTURE_HORDE = 14, + BATTLEFIELD_WG_TEXT_EASTSPARK_ATTACK_ALLIANCE = 15, + BATTLEFIELD_WG_TEXT_EASTSPARK_CAPTURE_ALLIANCE = 16, + BATTLEFIELD_WG_TEXT_EASTSPARK_ATTACK_HORDE = 17, + BATTLEFIELD_WG_TEXT_EASTSPARK_CAPTURE_HORDE = 18, + BATTLEFIELD_WG_TEXT_SUNKEN_RING_ATTACK_ALLIANCE = 19, + BATTLEFIELD_WG_TEXT_SUNKEN_RING_CAPTURE_ALLIANCE = 20, + BATTLEFIELD_WG_TEXT_SUNKEN_RING_ATTACK_HORDE = 21, + BATTLEFIELD_WG_TEXT_SUNKEN_RING_CAPTURE_HORDE = 22, + BATTLEFIELD_WG_TEXT_WESTSPARK_ATTACK_ALLIANCE = 23, + BATTLEFIELD_WG_TEXT_WESTSPARK_CAPTURE_ALLIANCE = 24, + BATTLEFIELD_WG_TEXT_WESTSPARK_ATTACK_HORDE = 25, + BATTLEFIELD_WG_TEXT_WESTSPARK_CAPTURE_HORDE = 26, + + BATTLEFIELD_WG_TEXT_START_GROUPING = 27, + BATTLEFIELD_WG_TEXT_START_BATTLE = 28, + BATTLEFIELD_WG_TEXT_FORTRESS_DEFEND_ALLIANCE = 29, + BATTLEFIELD_WG_TEXT_FORTRESS_CAPTURE_ALLIANCE = 30, + BATTLEFIELD_WG_TEXT_FORTRESS_DEFEND_HORDE = 31, + BATTLEFIELD_WG_TEXT_FORTRESS_CAPTURE_HORDE = 32, + + BATTLEFIELD_WG_TEXT_NE_KEEPTOWER_DAMAGE = 33, + BATTLEFIELD_WG_TEXT_NE_KEEPTOWER_DESTROY = 34, + BATTLEFIELD_WG_TEXT_SW_KEEPTOWER_DAMAGE = 35, + BATTLEFIELD_WG_TEXT_SW_KEEPTOWER_DESTROY = 36, + + BATTLEFIELD_WG_TEXT_RANK_CORPORAL = 37, + BATTLEFIELD_WG_TEXT_RANK_FIRST_LIEUTENANT = 38 +}; + +enum WintergraspGameObject +{ + GO_WINTERGRASP_FACTORY_BANNER_NE = 190475, + GO_WINTERGRASP_FACTORY_BANNER_NW = 190487, + GO_WINTERGRASP_FACTORY_BANNER_SE = 194959, + GO_WINTERGRASP_FACTORY_BANNER_SW = 194962, + + GO_WINTERGRASP_TITAN_S_RELIC = 192829, + + GO_WINTERGRASP_FORTRESS_TOWER_1 = 190221, + GO_WINTERGRASP_FORTRESS_TOWER_2 = 190373, + GO_WINTERGRASP_FORTRESS_TOWER_3 = 190377, + GO_WINTERGRASP_FORTRESS_TOWER_4 = 190378, + + GO_WINTERGRASP_SHADOWSIGHT_TOWER = 190356, + GO_WINTERGRASP_WINTER_S_EDGE_TOWER = 190357, + GO_WINTERGRASP_FLAMEWATCH_TOWER = 190358, + + GO_WINTERGRASP_FORTRESS_GATE = 190375, + GO_WINTERGRASP_VAULT_GATE = 191810, + + GO_WINTERGRASP_KEEP_COLLISION_WALL = 194323 +}; + +// ******************************************************************** +// * Structs using for Building, Graveyard, Workshop * +// ******************************************************************** + +// Structure for different buildings that can be destroyed during battle +struct BfWGGameObjectBuilding +{ +private: + // WG object + BattlefieldWG* _wg; + + // Linked gameobject + ObjectGuid _buildGUID; + + // the team that controls this point + TeamId _teamControl; + + WintergraspGameObjectBuildingType _type; + uint32 _worldState; + + WintergraspGameObjectState _state; + + StaticWintergraspTowerInfo const* _staticTowerInfo; + + // GameObject associations + GuidVector m_GameObjectList[PVP_TEAMS_COUNT]; + + // Creature associations + GuidVector m_CreatureBottomList[PVP_TEAMS_COUNT]; + GuidVector m_CreatureTopList[PVP_TEAMS_COUNT]; + GuidVector m_TowerCannonBottomList; + GuidVector m_TurretTopList; + +public: + BfWGGameObjectBuilding(BattlefieldWG* wg, WintergraspGameObjectBuildingType type, uint32 worldState); + void Init(GameObject* go); + + ObjectGuid const& GetGUID() const { return _buildGUID; } + + void Rebuild(); + void RebuildGate(); + + // Called when associated gameobject is damaged + void Damaged(); + + // Called when associated gameobject is destroyed + void Destroyed(); + + void UpdateCreatureAndGo(); + + void UpdateTurretAttack(bool disable); + + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet); + + void Save(); +}; + +// Structure for the 6 workshop +struct WintergraspWorkshop +{ +private: + BattlefieldWG* _wg; // Pointer to wintergrasp + ObjectGuid _buildGUID; + WintergraspGameObjectState _state; // For worldstate + TeamId _teamControl; // Team witch control the workshop + + StaticWintergraspWorkshopInfo const* _staticInfo; + +public: + WintergraspWorkshop(BattlefieldWG* wg, uint8 type); + + uint8 GetId() const; + TeamId GetTeamControl() const { return _teamControl; } + + // Called on change faction in CapturePoint class + void GiveControlTo(TeamId teamId, bool init = false); + + void UpdateGraveyardAndWorkshop(); + + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet); + + void Save(); +}; + +#endif diff --git a/src/server/scripts/Battlefield/battlefield_script_loader.cpp b/src/server/scripts/Battlefield/battlefield_script_loader.cpp new file mode 100644 index 00000000000..fcfa06e9449 --- /dev/null +++ b/src/server/scripts/Battlefield/battlefield_script_loader.cpp @@ -0,0 +1,25 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +void AddSC_BF_wintergrasp(); +void AddSC_BF_tol_barad(); + +void AddBattlefieldScripts() +{ + AddSC_BF_wintergrasp(); + AddSC_BF_tol_barad(); +} diff --git a/src/server/scripts/EasternKingdoms/zone_tol_barad.cpp b/src/server/scripts/EasternKingdoms/zone_tol_barad.cpp index a30fb95d026..b8fe8a65f3f 100644 --- a/src/server/scripts/EasternKingdoms/zone_tol_barad.cpp +++ b/src/server/scripts/EasternKingdoms/zone_tol_barad.cpp @@ -18,7 +18,7 @@ #include "ScriptMgr.h" #include "Battlefield.h" #include "BattlefieldMgr.h" -#include "BattlefieldTB.h" +#include "Battlefield/BattlefieldTB.h" #include "DB2Stores.h" #include "ObjectMgr.h" #include "Player.h" diff --git a/src/server/scripts/Northrend/zone_wintergrasp.cpp b/src/server/scripts/Northrend/zone_wintergrasp.cpp index 5d2390b1ab7..d38c8c43aab 100644 --- a/src/server/scripts/Northrend/zone_wintergrasp.cpp +++ b/src/server/scripts/Northrend/zone_wintergrasp.cpp @@ -18,7 +18,7 @@ #include "ScriptMgr.h" #include "Battlefield.h" #include "BattlefieldMgr.h" -#include "BattlefieldWG.h" +#include "Battlefield/BattlefieldWG.h" #include "DB2Stores.h" #include "GameObject.h" #include "GameObjectAI.h" @@ -360,8 +360,8 @@ class go_wg_vehicle_teleporter : public GameObjectScript bool IsFriendly(Unit* passenger) { - return ((me->GetFaction() == WintergraspFaction[TEAM_HORDE] && passenger->GetFaction() == HORDE) || - (me->GetFaction() == WintergraspFaction[TEAM_ALLIANCE] && passenger->GetFaction() == ALLIANCE)); + return ((me->GetFaction() == FACTION_HORDE_GENERIC_WG && passenger->GetFaction() == HORDE) || + (me->GetFaction() == FACTION_ALLIANCE_GENERIC_WG && passenger->GetFaction() == ALLIANCE)); } Creature* GetValidVehicle(Creature* cVeh) -- cgit v1.2.3