diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp | 1184 | ||||
-rw-r--r-- | src/server/game/Battlegrounds/Zones/BattlegroundIC.h | 897 | ||||
-rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 14 | ||||
-rw-r--r-- | src/server/scripts/Northrend/IsleOfConquest/isle_of_conquest.cpp | 153 |
4 files changed, 763 insertions, 1485 deletions
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp index e34a0adaf52..639fa4510de 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp @@ -22,6 +22,7 @@ #include "Map.h" #include "ObjectMgr.h" #include "Player.h" +#include "TemporarySummon.h" #include "Transport.h" #include "UnitAI.h" #include "Vehicle.h" @@ -32,336 +33,173 @@ enum IsleOfConquestPvpStats PVP_STAT_BASES_DEFENDED = 246 }; -BattlegroundIC::BattlegroundIC(BattlegroundTemplate const* battlegroundTemplate) : Battleground(battlegroundTemplate) +enum IsleOfConquestGameObjects { - BgObjects.resize(MAX_NORMAL_GAMEOBJECTS_SPAWNS + MAX_AIRSHIPS_SPAWNS + MAX_HANGAR_TELEPORTERS_SPAWNS + MAX_FORTRESS_TELEPORTERS_SPAWNS + MAX_HANGAR_TELEPORTER_EFFECTS_SPAWNS + MAX_FORTRESS_TELEPORTER_EFFECTS_SPAWNS); - BgCreatures.resize(MAX_NORMAL_NPCS_SPAWNS + MAX_WORKSHOP_SPAWNS + MAX_DOCKS_SPAWNS + MAX_SPIRIT_GUIDES_SPAWNS + MAX_HANGAR_NPCS_SPAWNS); - - for (uint8 i = 0; i < 2; ++i) - factionReinforcements[i] = MAX_REINFORCEMENTS; - - for (uint8 i = 0; i < BG_IC_MAXDOOR; ++i) - GateStatus[i] = BG_IC_GATE_OK; + GO_TELEPORTER_1 = 195314, // 195314 H-OUT 66549 + GO_TELEPORTER_2 = 195313, // 195313 H-IN 66548 + + GO_TELEPORTER_3 = 195315, // 195315 A-OUT 66549 + GO_TELEPORTER_4 = 195316, // 195316 A-IN 66548 + + GO_TELEPORTER_EFFECTS_A = 195701, + GO_TELEPORTER_EFFECTS_H = 195702, + + GO_DOODAD_HU_PORTCULLIS01 = 195436, + GO_DOODAD_ND_HUMAN_GATE_CLOSEDFX_DOOR01 = 195703, + GO_DOODAD_PORTCULLISACTIVE02 = 195452, + GO_DOODAD_VR_PORTCULLIS01 = 195437, + + GO_HORDE_GATE_1 = 195494, + GO_HORDE_GATE_2 = 195495, + GO_HORDE_GATE_3 = 195496, + + GO_ALLIANCE_GATE_1 = 195699, + GO_ALLIANCE_GATE_2 = 195700, + GO_ALLIANCE_GATE_3 = 195698, + + GO_DOODAD_ND_WINTERORC_WALL_GATEFX_DOOR01 = 195491, + + // banners + GO_BANNER_WORKSHOP_CONTROLLED_H = 195130, + GO_BANNER_WORKSHOP_CONTROLLED_A = 195132, + GO_BANNER_WORKSHOP_CONTROLLED_N = 195133, + GO_BANNER_WORKSHOP_CONTESTED_A = 195144, + GO_BANNER_WORKSHOP_CONTESTED_H = 195145, + + GO_BANNER_DOCKS_CONTROLLED_A = 195149, + GO_BANNER_DOCKS_CONTESTED_A = 195150, + GO_BANNER_DOCKS_CONTROLLED_H = 195151, + GO_BANNER_DOCKS_CONTESTED_H = 195152, + GO_BANNER_DOCKS_CONTROLLED_N = 195157, + + GO_BANNER_HANGAR_CONTROLLED_A = 195153, + GO_BANNER_HANGAR_CONTESTED_A = 195154, + GO_BANNER_HANGAR_CONTROLLED_H = 195155, + GO_BANNER_HANGAR_CONTESTED_H = 195156, + GO_BANNER_HANGAR_CONTROLLED_N = 195158, + + GO_BANNER_QUARRY_CONTROLLED_A = 195334, + GO_BANNER_QUARRY_CONTROLLED_H = 195336, + GO_BANNER_QUARRY_CONTESTED_A = 195335, + GO_BANNER_QUARRY_CONTESTED_H = 195337, + GO_BANNER_QUARRY_CONTROLLED_N = 195338, + + GO_BANNER_REFINERY_CONTROLLED_A = 195339, + GO_BANNER_REFINERY_CONTROLLED_H = 195341, + GO_BANNER_REFINERY_CONTESTED_A = 195340, + GO_BANNER_REFINERY_CONTESTED_H = 195342, + GO_BANNER_REFINERY_CONTROLLED_N = 195343, + + GO_BANNER_HORDE_KEEP_CONTROLLED_A = 195391, + GO_BANNER_HORDE_KEEP_CONTROLLED_H = 195393, + GO_BANNER_HORDE_KEEP_CONTESTED_A = 195392, + GO_BANNER_HORDE_KEEP_CONTESTED_H = 195394, + + GO_BANNER_ALLIANCE_KEEP_CONTROLLED_A = 195396, + GO_BANNER_ALLIANCE_KEEP_CONTROLLED_H = 195398, + GO_BANNER_ALLIANCE_KEEP_CONTESTED_A = 195397, + GO_BANNER_ALLIANCE_KEEP_CONTESTED_H = 195399, + + GO_KEEP_GATE_H = 195223, + GO_KEEP_GATE_A = 195451, + GO_KEEP_GATE_2_A = 195452, + + GO_HORDE_GUNSHIP = 195276, + GO_ALLIANCE_GUNSHIP = 195121 +}; - closeFortressDoorsTimer = CLOSE_DOORS_TIME; // the doors are closed again... in a special way - doorsClosed = false; - docksTimer = DOCKS_UPDATE_TIME; - resourceTimer = IC_RESOURCE_TIME; +static constexpr Seconds IOC_RESOURCE_TIMER = 45s; - for (uint8 i = NODE_TYPE_REFINERY; i < MAX_NODE_TYPES; ++i) - nodePoint[i] = nodePointInitial[i]; +Position const GunshipTeleportTriggerPosition[2] = +{ + { 11.69964981079101562f, 0.034145999699831008f, 20.62075996398925781f, 3.211405754089355468f }, + { 7.30560922622680664f, -0.09524600207805633f, 34.51021575927734375f, 3.159045934677124023f } +}; - siegeEngineWorkshopTimer = WORKSHOP_UPDATE_TIME; +BattlegroundIC::BattlegroundIC(BattlegroundTemplate const* battlegroundTemplate) : Battleground(battlegroundTemplate) +{ + _factionReinforcements = { MAX_REINFORCEMENTS, MAX_REINFORCEMENTS }; - gunshipHorde = nullptr; - gunshipAlliance = nullptr; -} + _gateStatus = { BG_IC_GATE_OK, BG_IC_GATE_OK, BG_IC_GATE_OK, BG_IC_GATE_OK, BG_IC_GATE_OK, BG_IC_GATE_OK }; -BattlegroundIC::~BattlegroundIC() { } + _gunshipGUIDs = { }; + _cannonGUIDs = { }; + _nodePoints = { }; + _keepGateGUIDs = { }; + _keepBannerGUIDs = { }; -void BattlegroundIC::HandlePlayerResurrect(Player* player) -{ - if (nodePoint[NODE_TYPE_QUARRY].nodeState == (GetPlayerTeam(player->GetGUID()) == ALLIANCE ? NODE_STATE_CONTROLLED_A : NODE_STATE_CONTROLLED_H)) - player->CastSpell(player, SPELL_QUARRY, true); + _nodePoints[NODE_TYPE_REFINERY] = std::make_unique<ICNodePoint>(IsleOfConquestNodeState::Neutral, nodePointInitial[NODE_TYPE_REFINERY]); + _nodePoints[NODE_TYPE_QUARRY] = std::make_unique<ICNodePoint>(IsleOfConquestNodeState::Neutral, nodePointInitial[NODE_TYPE_QUARRY]); + _nodePoints[NODE_TYPE_DOCKS] = std::make_unique<ICNodePoint>(IsleOfConquestNodeState::Neutral, nodePointInitial[NODE_TYPE_DOCKS]); + _nodePoints[NODE_TYPE_HANGAR] = std::make_unique<ICNodePoint>(IsleOfConquestNodeState::Neutral, nodePointInitial[NODE_TYPE_HANGAR]); + _nodePoints[NODE_TYPE_WORKSHOP] = std::make_unique<ICNodePoint>(IsleOfConquestNodeState::Neutral, nodePointInitial[NODE_TYPE_WORKSHOP]); + _nodePoints[NODE_TYPE_GRAVEYARD_A] = std::make_unique<ICNodePoint>(IsleOfConquestNodeState::ControlledA, nodePointInitial[NODE_TYPE_GRAVEYARD_A]); + _nodePoints[NODE_TYPE_GRAVEYARD_H] = std::make_unique<ICNodePoint>(IsleOfConquestNodeState::ControlledH, nodePointInitial[NODE_TYPE_GRAVEYARD_H]); - if (nodePoint[NODE_TYPE_REFINERY].nodeState == (GetPlayerTeam(player->GetGUID()) == ALLIANCE ? NODE_STATE_CONTROLLED_A : NODE_STATE_CONTROLLED_H)) - player->CastSpell(player, SPELL_OIL_REFINERY, true); + _resourceTimer.Reset(IOC_RESOURCE_TIMER); } +BattlegroundIC::~BattlegroundIC() = default; + void BattlegroundIC::PostUpdateImpl(uint32 diff) { if (GetStatus() != STATUS_IN_PROGRESS) return; - if (!doorsClosed) - { - if (closeFortressDoorsTimer <= diff) - { - RemoveObjectFromWorld(BG_IC_GO_DOODAD_ND_HUMAN_GATE_CLOSEDFX_DOOR01); - RemoveObjectFromWorld(BG_IC_GO_DOODAD_ND_WINTERORC_WALL_GATEFX_DOOR01); - RemoveObjectFromWorld(BG_IC_GO_DOODAD_ND_HUMAN_GATE_CLOSEDFX_DOOR02); - RemoveObjectFromWorld(BG_IC_GO_DOODAD_ND_WINTERORC_WALL_GATEFX_DOOR02); - RemoveObjectFromWorld(BG_IC_GO_DOODAD_ND_HUMAN_GATE_CLOSEDFX_DOOR03); - RemoveObjectFromWorld(BG_IC_GO_DOODAD_ND_WINTERORC_WALL_GATEFX_DOOR03); - - GetBGObject(BG_IC_GO_ALLIANCE_GATE_1)->SetDestructibleState(GO_DESTRUCTIBLE_DAMAGED); - GetBGObject(BG_IC_GO_HORDE_GATE_1)->SetDestructibleState(GO_DESTRUCTIBLE_DAMAGED); - GetBGObject(BG_IC_GO_ALLIANCE_GATE_2)->SetDestructibleState(GO_DESTRUCTIBLE_DAMAGED); - GetBGObject(BG_IC_GO_HORDE_GATE_2)->SetDestructibleState(GO_DESTRUCTIBLE_DAMAGED); - GetBGObject(BG_IC_GO_ALLIANCE_GATE_3)->SetDestructibleState(GO_DESTRUCTIBLE_DAMAGED); - GetBGObject(BG_IC_GO_HORDE_GATE_3)->SetDestructibleState(GO_DESTRUCTIBLE_DAMAGED); - - doorsClosed = true; - } else closeFortressDoorsTimer -= diff; - } - - for (uint8 i = NODE_TYPE_REFINERY; i < MAX_NODE_TYPES; ++i) - { - if (nodePoint[i].nodeType == NODE_TYPE_DOCKS) - { - if (nodePoint[i].nodeState == NODE_STATE_CONTROLLED_A || - nodePoint[i].nodeState == NODE_STATE_CONTROLLED_H) - { - if (docksTimer <= diff) - { - // we need to confirm this, i am not sure if this every 3 minutes - for (uint8 u = (nodePoint[i].faction == TEAM_ALLIANCE ? BG_IC_NPC_CATAPULT_1_A : BG_IC_NPC_CATAPULT_1_H); u < (nodePoint[i].faction == TEAM_ALLIANCE ? BG_IC_NPC_CATAPULT_4_A : BG_IC_NPC_CATAPULT_4_H); ++u) - { - if (Creature* catapult = GetBGCreature(u)) - { - if (!catapult->IsAlive()) - catapult->Respawn(true); - } - } - - // we need to confirm this is blizzlike, not sure if it is every 3 minutes - for (uint8 u = (nodePoint[i].faction == TEAM_ALLIANCE ? BG_IC_NPC_GLAIVE_THROWER_1_A : BG_IC_NPC_GLAIVE_THROWER_1_H); u < (nodePoint[i].faction == TEAM_ALLIANCE ? BG_IC_NPC_GLAIVE_THROWER_2_A : BG_IC_NPC_GLAIVE_THROWER_2_H); ++u) - { - if (Creature* glaiveThrower = GetBGCreature(u)) - { - if (!glaiveThrower->IsAlive()) - glaiveThrower->Respawn(true); - } - } - - docksTimer = DOCKS_UPDATE_TIME; - } else docksTimer -= diff; - } - } - - if (nodePoint[i].nodeType == NODE_TYPE_WORKSHOP) - { - if (nodePoint[i].nodeState == NODE_STATE_CONTROLLED_A || - nodePoint[i].nodeState == NODE_STATE_CONTROLLED_H) - { - if (siegeEngineWorkshopTimer <= diff) - { - uint8 siegeType = (nodePoint[i].faction == TEAM_ALLIANCE ? BG_IC_NPC_SIEGE_ENGINE_A : BG_IC_NPC_SIEGE_ENGINE_H); - - if (Creature* siege = GetBGCreature(siegeType)) // this always should be true - { - if (siege->IsAlive()) - { - if (siege->HasUnitFlag(UNIT_FLAG_UNINTERACTIBLE | UNIT_FLAG_CANT_SWIM | UNIT_FLAG_IMMUNE_TO_PC)) - { - // following sniffs the vehicle always has UNIT_FLAG_CANNOT_SWIM - siege->SetUninteractible(false); - siege->SetImmuneToPC(false); - } - else - siege->SetHealth(siege->GetMaxHealth()); - } - else - siege->Respawn(true); - } - - // we need to confirm if it is every 3 minutes - for (uint8 u = (nodePoint[i].faction == TEAM_ALLIANCE ? BG_IC_NPC_DEMOLISHER_1_A : BG_IC_NPC_DEMOLISHER_1_H); u < (nodePoint[i].faction == TEAM_ALLIANCE ? BG_IC_NPC_DEMOLISHER_4_A : BG_IC_NPC_DEMOLISHER_4_H); ++u) - { - if (Creature* demolisher = GetBGCreature(u)) - { - if (!demolisher->IsAlive()) - demolisher->Respawn(true); - } - } - siegeEngineWorkshopTimer = WORKSHOP_UPDATE_TIME; - } else siegeEngineWorkshopTimer -= diff; - } - } - - // the point is waiting for a change on its banner - if (nodePoint[i].needChange) - { - if (nodePoint[i].timer <= diff) - { - uint32 nextBanner = GetNextBanner(&nodePoint[i], nodePoint[i].faction, true); - - nodePoint[i].last_entry = nodePoint[i].gameobject_entry; - nodePoint[i].gameobject_entry = nextBanner; - // nodePoint[i].faction = the faction should be the same one... - - GameObject* banner = GetBGObject(nodePoint[i].gameobject_type); - - if (!banner) // this should never happen - return; - - float cords[4] = {banner->GetPositionX(), banner->GetPositionY(), banner->GetPositionZ(), banner->GetOrientation() }; - - DelObject(nodePoint[i].gameobject_type); - AddObject(nodePoint[i].gameobject_type, nodePoint[i].gameobject_entry, cords[0], cords[1], cords[2], cords[3], 0, 0, 0, 0, RESPAWN_ONE_DAY); - - GetBGObject(nodePoint[i].gameobject_type)->SetFaction(nodePoint[i].faction == TEAM_ALLIANCE ? BG_IC_Factions[1] : BG_IC_Factions[0]); - - UpdateNodeWorldState(&nodePoint[i]); - HandleCapturedNodes(&nodePoint[i], false); - - if (nodePoint[i].faction == TEAM_ALLIANCE) - SendBroadcastText(ICNodes[i].TextAllianceTaken, CHAT_MSG_BG_SYSTEM_ALLIANCE); - else - SendBroadcastText(ICNodes[i].TextHordeTaken, CHAT_MSG_BG_SYSTEM_HORDE); - - nodePoint[i].needChange = false; - nodePoint[i].timer = BANNER_STATE_CHANGE_TIME; - } else nodePoint[i].timer -= diff; - } - } - - if (resourceTimer <= diff) + _scheduler.Update(diff); + _resourceTimer.Update(diff); + if (_resourceTimer.Passed()) { for (uint8 i = 0; i < NODE_TYPE_DOCKS; ++i) { - if (nodePoint[i].nodeState == NODE_STATE_CONTROLLED_A || - nodePoint[i].nodeState == NODE_STATE_CONTROLLED_H) + if (_nodePoints[i]->GetLastControlledTeam() != TEAM_NEUTRAL && !_nodePoints[i]->IsContested()) { - factionReinforcements[nodePoint[i].faction] += 1; - RewardHonorToTeam(RESOURCE_HONOR_AMOUNT, nodePoint[i].faction == TEAM_ALLIANCE ? ALLIANCE : HORDE); - UpdateWorldState((nodePoint[i].faction == TEAM_ALLIANCE ? BG_IC_ALLIANCE_REINFORCEMENTS : BG_IC_HORDE_REINFORCEMENTS), factionReinforcements[nodePoint[i].faction]); + _factionReinforcements[_nodePoints[i]->GetLastControlledTeam()] += 1; + RewardHonorToTeam(RESOURCE_HONOR_AMOUNT, _nodePoints[i]->GetLastControlledTeam() == TEAM_ALLIANCE ? ALLIANCE : HORDE); + UpdateWorldState((_nodePoints[i]->GetLastControlledTeam() == TEAM_ALLIANCE ? BG_IC_ALLIANCE_REINFORCEMENTS : BG_IC_HORDE_REINFORCEMENTS), _factionReinforcements[_nodePoints[i]->GetLastControlledTeam()]); } } - resourceTimer = IC_RESOURCE_TIME; - } else resourceTimer -= diff; -} - -void BattlegroundIC::StartingEventCloseDoors() -{ -} - -void BattlegroundIC::StartingEventOpenDoors() -{ - //after 20 seconds they should be despawned - DoorOpen(BG_IC_GO_DOODAD_ND_HUMAN_GATE_CLOSEDFX_DOOR01); - DoorOpen(BG_IC_GO_DOODAD_ND_WINTERORC_WALL_GATEFX_DOOR01); - DoorOpen(BG_IC_GO_DOODAD_ND_HUMAN_GATE_CLOSEDFX_DOOR02); - DoorOpen(BG_IC_GO_DOODAD_ND_WINTERORC_WALL_GATEFX_DOOR02); - DoorOpen(BG_IC_GO_DOODAD_ND_HUMAN_GATE_CLOSEDFX_DOOR03); - DoorOpen(BG_IC_GO_DOODAD_ND_WINTERORC_WALL_GATEFX_DOOR03); - - DoorOpen(BG_IC_GO_DOODAD_HU_PORTCULLIS01_1); - DoorOpen(BG_IC_GO_DOODAD_HU_PORTCULLIS01_2); - DoorOpen(BG_IC_GO_DOODAD_VR_PORTCULLIS01_1); - DoorOpen(BG_IC_GO_DOODAD_VR_PORTCULLIS01_2); - - for (uint8 i = 0; i < MAX_FORTRESS_TELEPORTERS_SPAWNS; ++i) - GetBGObject(BG_IC_Teleporters[i].type)->RemoveFlag(GO_FLAG_NOT_SELECTABLE); - - for (uint8 i = 0; i < MAX_FORTRESS_TELEPORTER_EFFECTS_SPAWNS; ++i) - GetBGObject(BG_IC_TeleporterEffects[i].type)->SetGoState(GO_STATE_ACTIVE); -} - -void BattlegroundIC::AddPlayer(Player* player, BattlegroundQueueTypeId queueId) -{ - Battleground::AddPlayer(player, queueId); - if (nodePoint[NODE_TYPE_QUARRY].nodeState == (GetPlayerTeam(player->GetGUID()) == ALLIANCE ? NODE_STATE_CONTROLLED_A : NODE_STATE_CONTROLLED_H)) - player->CastSpell(player, SPELL_QUARRY, true); - - if (nodePoint[NODE_TYPE_REFINERY].nodeState == (GetPlayerTeam(player->GetGUID()) == ALLIANCE ? NODE_STATE_CONTROLLED_A : NODE_STATE_CONTROLLED_H)) - player->CastSpell(player, SPELL_OIL_REFINERY, true); -} - -void BattlegroundIC::RemovePlayer(Player* player, ObjectGuid /*guid*/, uint32 /*team*/) -{ - if (player) - { - player->RemoveAura(SPELL_QUARRY); - player->RemoveAura(SPELL_OIL_REFINERY); + _resourceTimer.Reset(IOC_RESOURCE_TIMER); } } -void BattlegroundIC::HandleAreaTrigger(Player* player, uint32 trigger, bool entered) -{ - // this is wrong way to implement these things. On official it done by gameobject spell cast. - if (GetStatus() == STATUS_WAIT_JOIN && !entered) - if (trigger == 9176 || trigger == 9178) - TeleportPlayerToExploitLocation(player); - - /// @hack: this spell should be cast by npc 22515 (World Trigger) and not by the player - if (trigger == 5555 && GetPlayerTeam(player->GetGUID()) == HORDE) - { - if (GateStatus[BG_IC_A_FRONT] != BG_IC_GATE_DESTROYED - && GateStatus[BG_IC_A_WEST] != BG_IC_GATE_DESTROYED - && GateStatus[BG_IC_A_EAST] != BG_IC_GATE_DESTROYED) - player->CastSpell(player, SPELL_BACK_DOOR_JOB_ACHIEVEMENT, true); - } - else if (trigger == 5535 && GetPlayerTeam(player->GetGUID()) == ALLIANCE) - { - if (GateStatus[BG_IC_H_FRONT] != BG_IC_GATE_DESTROYED - && GateStatus[BG_IC_H_WEST] != BG_IC_GATE_DESTROYED - && GateStatus[BG_IC_H_EAST] != BG_IC_GATE_DESTROYED) - player->CastSpell(player, SPELL_BACK_DOOR_JOB_ACHIEVEMENT, true); - } -} - -bool BattlegroundIC::SetupBattleground() +void BattlegroundIC::StartingEventOpenDoors() { - for (uint8 i = 0; i < MAX_NORMAL_GAMEOBJECTS_SPAWNS; ++i) + auto gameobjectAction = [&](GuidVector const& guids, std::function<void(GameObject*)> const& action) -> void { - if (!AddObject(BG_IC_ObjSpawnlocs[i].type, BG_IC_ObjSpawnlocs[i].entry, BG_IC_ObjSpawnlocs[i].x, BG_IC_ObjSpawnlocs[i].y, BG_IC_ObjSpawnlocs[i].z, BG_IC_ObjSpawnlocs[i].o, 0, 0, 0, 0, RESPAWN_ONE_DAY)) - { - TC_LOG_ERROR("bg.battleground", "Isle of Conquest: There was an error spawning gameobject {}", BG_IC_ObjSpawnlocs[i].entry); - return false; - } - } + for (ObjectGuid const& guid : guids) + if (GameObject* gameObject = GetBgMap()->GetGameObject(guid)) + action(gameObject); + }; - for (uint8 i = 0; i < MAX_FORTRESS_TELEPORTERS_SPAWNS; ++i) + gameobjectAction(_mainGateDoorGUIDs, [&](GameObject* gameobject) -> void { - if (!AddObject(BG_IC_Teleporters[i].type, BG_IC_Teleporters[i].entry, BG_IC_Teleporters[i].x, BG_IC_Teleporters[i].y, BG_IC_Teleporters[i].z, BG_IC_Teleporters[i].o, 0, 0, 0, 0, RESPAWN_ONE_DAY)) - { - TC_LOG_ERROR("bg.battleground", "Isle of Conquest | Starting Event Open Doors: There was an error spawning gameobject {}", BG_IC_Teleporters[i].entry); - return false; - } - } + gameobject->UseDoorOrButton(); + gameobject->DespawnOrUnsummon(20s); + }); - for (uint8 i = 0; i < MAX_FORTRESS_TELEPORTER_EFFECTS_SPAWNS; ++i) + gameobjectAction(_portcullisGUIDs, [&](GameObject* gameobject) -> void { - if (!AddObject(BG_IC_TeleporterEffects[i].type, BG_IC_TeleporterEffects[i].entry, BG_IC_TeleporterEffects[i].x, BG_IC_TeleporterEffects[i].y, BG_IC_TeleporterEffects[i].z, BG_IC_TeleporterEffects[i].o, 0, 0, 0, 0, RESPAWN_ONE_DAY)) - { - TC_LOG_ERROR("bg.battleground", "Isle of Conquest | Starting Event Open Doors: There was an error spawning gameobject {}", BG_IC_Teleporters[i].entry); - return false; - } - } + gameobject->UseDoorOrButton(); + }); - for (uint8 i = 2; i < MAX_NORMAL_NPCS_SPAWNS; ++i) + gameobjectAction(_teleporterGUIDs, [&](GameObject* gameobject) -> void { - if (!AddCreature(BG_IC_NpcSpawnlocs[i].entry, BG_IC_NpcSpawnlocs[i].type, BG_IC_NpcSpawnlocs[i].x, BG_IC_NpcSpawnlocs[i].y, BG_IC_NpcSpawnlocs[i].z, BG_IC_NpcSpawnlocs[i].o, BG_IC_NpcSpawnlocs[i].team, RESPAWN_ONE_DAY)) - { - TC_LOG_ERROR("bg.battleground", "Isle of Conquest: There was an error spawning creature {}", BG_IC_NpcSpawnlocs[i].entry); - return false; - } - } + gameobject->RemoveFlag(GO_FLAG_NOT_SELECTABLE); + }); - if (!AddSpiritGuide(BG_IC_NPC_SPIRIT_GUIDE_1+3, BG_IC_SpiritGuidePos[5], TEAM_ALLIANCE) - || !AddSpiritGuide(BG_IC_NPC_SPIRIT_GUIDE_1+4, BG_IC_SpiritGuidePos[6], TEAM_HORDE) - || !AddSpiritGuide(BG_IC_NPC_SPIRIT_GUIDE_1+5, BG_IC_SpiritGuidePos[7], TEAM_ALLIANCE) - || !AddSpiritGuide(BG_IC_NPC_SPIRIT_GUIDE_1+6, BG_IC_SpiritGuidePos[8], TEAM_HORDE)) + gameobjectAction(_teleporterEffectGUIDs, [&](GameObject* gameobject) -> void { - TC_LOG_ERROR("bg.battleground", "Isle of Conquest: Failed to spawn initial spirit guide!"); - return false; - } - - gunshipHorde = sTransportMgr->CreateTransport(GO_HORDE_GUNSHIP, GetBgMap()); - gunshipAlliance = sTransportMgr->CreateTransport(GO_ALLIANCE_GUNSHIP, GetBgMap()); + gameobject->SetGoState(GO_STATE_ACTIVE); + }); - if (!gunshipAlliance || !gunshipHorde) + _scheduler.Schedule(20s, [&](TaskContext) { - TC_LOG_ERROR("bg.battleground", "Isle of Conquest: There was an error creating gunships!"); - return false; - } - - gunshipHorde->EnableMovement(false); - gunshipAlliance->EnableMovement(false); - - // setting correct factions for Keep Cannons - for (uint8 i = BG_IC_NPC_KEEP_CANNON_1; i <= BG_IC_NPC_KEEP_CANNON_12; ++i) - GetBGCreature(i)->SetFaction(BG_IC_Factions[0]); - for (uint8 i = BG_IC_NPC_KEEP_CANNON_13; i <= BG_IC_NPC_KEEP_CANNON_24; ++i) - GetBGCreature(i)->SetFaction(BG_IC_Factions[1]); - - // correcting spawn time for keeps bombs - for (uint8 i = BG_IC_GO_HUGE_SEAFORIUM_BOMBS_A_1; i < BG_IC_GO_HUGE_SEAFORIUM_BOMBS_H_4; ++i) - GetBGObject(i)->SetRespawnTime(10); - - return true; + for (ObjectGuid const& guid : _wallGUIDs) + if (GameObject* gameobject = GetBgMap()->GetGameObject(guid)) + gameobject->SetDestructibleState(GO_DESTRUCTIBLE_DAMAGED); + }); } void BattlegroundIC::HandleKillUnit(Creature* unit, Unit* killer) @@ -397,520 +235,472 @@ void BattlegroundIC::HandleKillPlayer(Player* player, Player* killer) Battleground::HandleKillPlayer(player, killer); - TeamId victimTeamId = GetTeamIndexByTeamId(GetPlayerTeam(player->GetGUID())); - factionReinforcements[victimTeamId] -= 1; + TeamId const victimTeamId = GetTeamIndexByTeamId(GetPlayerTeam(player->GetGUID())); + _factionReinforcements[victimTeamId] -= 1; - UpdateWorldState((GetPlayerTeam(player->GetGUID()) == ALLIANCE ? BG_IC_ALLIANCE_REINFORCEMENTS : BG_IC_HORDE_REINFORCEMENTS), factionReinforcements[victimTeamId]); + UpdateWorldState((GetPlayerTeam(player->GetGUID()) == ALLIANCE ? BG_IC_ALLIANCE_REINFORCEMENTS : BG_IC_HORDE_REINFORCEMENTS), _factionReinforcements[victimTeamId]); // we must end the battleground - if (factionReinforcements[victimTeamId] < 1) + if (_factionReinforcements[victimTeamId] < 1) EndBattleground(GetPlayerTeam(killer->GetGUID())); } -void BattlegroundIC::EventPlayerClickedOnFlag(Player* player, GameObject* target_obj) +uint32 BattlegroundIC::GetGateIDFromEntry(uint32 id) { - if (GetStatus() != STATUS_IN_PROGRESS) - return; - - // All the node points are iterated to find the clicked one - for (uint8 i = 0; i < MAX_NODE_TYPES; ++i) + switch (id) { - if (nodePoint[i].gameobject_entry == target_obj->GetEntry()) - { - TeamId teamId = GetTeamIndexByTeamId(GetPlayerTeam(player->GetGUID())); - - // THIS SHOULD NEEVEER HAPPEN - if (nodePoint[i].faction == teamId) - return; + case GO_HORDE_GATE_1: + return BG_IC_H_FRONT; + case GO_HORDE_GATE_2: + return BG_IC_H_WEST; + case GO_HORDE_GATE_3: + return BG_IC_H_EAST; + case GO_ALLIANCE_GATE_3: + return BG_IC_A_FRONT; + case GO_ALLIANCE_GATE_1: + return BG_IC_A_WEST; + case GO_ALLIANCE_GATE_2: + return BG_IC_A_EAST; + default: + return 0; + } +} - uint32 nextBanner = GetNextBanner(&nodePoint[i], teamId, false); +int32 BattlegroundIC::GetWorldStateFromGateEntry(uint32 id, bool open) +{ + int32 uws = 0; - // we set the new settings of the nodePoint - nodePoint[i].faction = teamId; - nodePoint[i].last_entry = nodePoint[i].gameobject_entry; - nodePoint[i].gameobject_entry = nextBanner; + switch (id) + { + case GO_HORDE_GATE_1: + uws = (open ? BG_IC_GATE_FRONT_H_WS_OPEN : BG_IC_GATE_FRONT_H_WS_CLOSED); + break; + case GO_HORDE_GATE_2: + uws = (open ? BG_IC_GATE_WEST_H_WS_OPEN : BG_IC_GATE_WEST_H_WS_CLOSED); + break; + case GO_HORDE_GATE_3: + uws = (open ? BG_IC_GATE_EAST_H_WS_OPEN : BG_IC_GATE_EAST_H_WS_CLOSED); + break; + case GO_ALLIANCE_GATE_3: + uws = (open ? BG_IC_GATE_FRONT_A_WS_OPEN : BG_IC_GATE_FRONT_A_WS_CLOSED); + break; + case GO_ALLIANCE_GATE_1: + uws = (open ? BG_IC_GATE_WEST_A_WS_OPEN : BG_IC_GATE_WEST_A_WS_CLOSED); + break; + case GO_ALLIANCE_GATE_2: + uws = (open ? BG_IC_GATE_EAST_A_WS_OPEN : BG_IC_GATE_EAST_A_WS_CLOSED); + break; + default: + break; + } + return uws; +} - // this is just needed if the next banner is grey - if (nodePoint[i].banners[BANNER_A_CONTESTED] == nextBanner || nodePoint[i].banners[BANNER_H_CONTESTED] == nextBanner) - { - nodePoint[i].timer = BANNER_STATE_CHANGE_TIME; // 1 minute for last change (real faction banner) - nodePoint[i].needChange = true; +void BattlegroundIC::UpdateNodeWorldState(ICNodePoint const& node) +{ + UpdateWorldState(node.GetNodeInfo().WorldStateIds.ConflictA, node.GetState() == IsleOfConquestNodeState::ConflictA); + UpdateWorldState(node.GetNodeInfo().WorldStateIds.ConflictH, node.GetState() == IsleOfConquestNodeState::ConflictH); + UpdateWorldState(node.GetNodeInfo().WorldStateIds.ControlledA, node.GetState() == IsleOfConquestNodeState::ControlledA); + UpdateWorldState(node.GetNodeInfo().WorldStateIds.ControlledH, node.GetState() == IsleOfConquestNodeState::ControlledH); + UpdateWorldState(node.GetNodeInfo().WorldStateIds.Uncontrolled, node.GetState() == IsleOfConquestNodeState::Neutral); +} - // if we are here means that the point has been lost, or it is the first capture +ICNodePointType BattlegroundIC::BannerToNodeType(uint32 bannerId) +{ + switch (bannerId) + { + case GO_BANNER_ALLIANCE_KEEP_CONTESTED_A: + case GO_BANNER_ALLIANCE_KEEP_CONTESTED_H: + case GO_BANNER_ALLIANCE_KEEP_CONTROLLED_A: + case GO_BANNER_ALLIANCE_KEEP_CONTROLLED_H: + return NODE_TYPE_GRAVEYARD_A; + case GO_BANNER_HORDE_KEEP_CONTESTED_A: + case GO_BANNER_HORDE_KEEP_CONTESTED_H: + case GO_BANNER_HORDE_KEEP_CONTROLLED_A: + case GO_BANNER_HORDE_KEEP_CONTROLLED_H: + return NODE_TYPE_GRAVEYARD_H; + case GO_BANNER_DOCKS_CONTESTED_A: + case GO_BANNER_DOCKS_CONTESTED_H: + case GO_BANNER_DOCKS_CONTROLLED_A: + case GO_BANNER_DOCKS_CONTROLLED_H: + case GO_BANNER_DOCKS_CONTROLLED_N: + return NODE_TYPE_DOCKS; + case GO_BANNER_HANGAR_CONTESTED_A: + case GO_BANNER_HANGAR_CONTESTED_H: + case GO_BANNER_HANGAR_CONTROLLED_A: + case GO_BANNER_HANGAR_CONTROLLED_H: + case GO_BANNER_HANGAR_CONTROLLED_N: + return NODE_TYPE_HANGAR; + case GO_BANNER_WORKSHOP_CONTESTED_A: + case GO_BANNER_WORKSHOP_CONTESTED_H: + case GO_BANNER_WORKSHOP_CONTROLLED_A: + case GO_BANNER_WORKSHOP_CONTROLLED_H: + case GO_BANNER_WORKSHOP_CONTROLLED_N: + return NODE_TYPE_WORKSHOP; + case GO_BANNER_QUARRY_CONTESTED_A: + case GO_BANNER_QUARRY_CONTESTED_H: + case GO_BANNER_QUARRY_CONTROLLED_A: + case GO_BANNER_QUARRY_CONTROLLED_H: + case GO_BANNER_QUARRY_CONTROLLED_N: + return NODE_TYPE_QUARRY; + case GO_BANNER_REFINERY_CONTESTED_A: + case GO_BANNER_REFINERY_CONTESTED_H: + case GO_BANNER_REFINERY_CONTROLLED_A: + case GO_BANNER_REFINERY_CONTROLLED_H: + case GO_BANNER_REFINERY_CONTROLLED_N: + return NODE_TYPE_REFINERY; + default: + break; + } - if (nodePoint[i].nodeType != NODE_TYPE_REFINERY && nodePoint[i].nodeType != NODE_TYPE_QUARRY) - if (!BgCreatures[BG_IC_NPC_SPIRIT_GUIDE_1 + uint32(nodePoint[i].nodeType) - 2].IsEmpty()) - DelCreature(BG_IC_NPC_SPIRIT_GUIDE_1 + uint32(nodePoint[i].nodeType) - 2); + return MAX_NODE_TYPES; +} - UpdatePvpStat(player, PVP_STAT_BASES_ASSAULTED, 1); +void BattlegroundIC::HandleCapturedNodes(ICNodePoint& node) +{ + if (node.GetLastControlledTeam() == TEAM_NEUTRAL) + return; - if (nodePoint[i].faction == TEAM_ALLIANCE) - SendBroadcastText(ICNodes[i].TextAssaulted, CHAT_MSG_BG_SYSTEM_ALLIANCE, player); - else - SendBroadcastText(ICNodes[i].TextAssaulted, CHAT_MSG_BG_SYSTEM_HORDE, player); + switch (node.GetNodeInfo().NodeType) + { + case NODE_TYPE_QUARRY: + case NODE_TYPE_REFINERY: + GetBgMap()->UpdateAreaDependentAuras(); + break; + case NODE_TYPE_HANGAR: + if (Transport* transport = GetBgMap()->GetTransport(_gunshipGUIDs[node.GetLastControlledTeam()])) + { + // Can't have this in spawngroup, creature is on a transport + if (TempSummon* trigger = transport->SummonPassenger(NPC_WORLD_TRIGGER_NOT_FLOATING, GunshipTeleportTriggerPosition[node.GetLastControlledTeam()], TEMPSUMMON_MANUAL_DESPAWN)) + _gunshipTeleportTarget = trigger->GetGUID(); - HandleContestedNodes(&nodePoint[i]); + transport->EnableMovement(true); } - else if (nextBanner == nodePoint[i].banners[BANNER_A_CONTROLLED] || nextBanner == nodePoint[i].banners[BANNER_H_CONTROLLED]) // if we are going to spawn the definitve faction banner, we dont need the timer anymore - { - nodePoint[i].timer = BANNER_STATE_CHANGE_TIME; - nodePoint[i].needChange = false; - if (nodePoint[i].faction == TEAM_ALLIANCE) - SendBroadcastText(ICNodes[i].TextDefended, CHAT_MSG_BG_SYSTEM_ALLIANCE, player); - else - SendBroadcastText(ICNodes[i].TextDefended, CHAT_MSG_BG_SYSTEM_HORDE, player); + for (ObjectGuid const& guid : _cannonGUIDs[node.GetLastControlledTeam()]) + if (Creature* cannon = GetBgMap()->GetCreature(guid)) + cannon->SetUninteractible(false); + break; + default: + break; + } +} - HandleCapturedNodes(&nodePoint[i], true); - UpdatePvpStat(player, PVP_STAT_BASES_DEFENDED, 1); - } +WorldSafeLocsEntry const* BattlegroundIC::GetExploitTeleportLocation(Team team) +{ + return sObjectMgr->GetWorldSafeLoc(team == ALLIANCE ? IC_EXPLOIT_TELEPORT_LOCATION_ALLIANCE : IC_EXPLOIT_TELEPORT_LOCATION_HORDE); +} - GameObject* banner = GetBGObject(nodePoint[i].gameobject_type); +void BattlegroundIC::OnCreatureCreate(Creature* creature) +{ + Battleground::OnCreatureCreate(creature); + if (creature->HasStringId("bg_ioc_faction_1735")) + creature->SetFaction(FACTION_HORDE_GENERIC_WG); + else if (creature->HasStringId("bg_ioc_faction_1732")) + creature->SetFaction(FACTION_ALLIANCE_GENERIC_WG); - if (!banner) // this should never happen - return; + switch (creature->GetEntry()) + { + case NPC_ALLIANCE_GUNSHIP_CANNON: + _cannonGUIDs[TEAM_ALLIANCE].emplace_back(creature->GetGUID()); + creature->SetUninteractible(true); + creature->SetControlled(true, UNIT_STATE_ROOT); + break; + case NPC_HORDE_GUNSHIP_CANNON: + _cannonGUIDs[TEAM_HORDE].emplace_back(creature->GetGUID()); + creature->SetUninteractible(true); + creature->SetControlled(true, UNIT_STATE_ROOT); + break; + default: + break; + } +} - float cords[4] = {banner->GetPositionX(), banner->GetPositionY(), banner->GetPositionZ(), banner->GetOrientation() }; +void BattlegroundIC::OnGameObjectCreate(GameObject* gameobject) +{ + Battleground::OnGameObjectCreate(gameobject); - DelObject(nodePoint[i].gameobject_type); - if (!AddObject(nodePoint[i].gameobject_type, nodePoint[i].gameobject_entry, cords[0], cords[1], cords[2], cords[3], 0, 0, 0, 0, RESPAWN_ONE_DAY)) - { - TC_LOG_ERROR("bg.battleground", "Isle of Conquest: There was an error spawning a banner (type: {}, entry: {}). Isle of Conquest BG cancelled.", nodePoint[i].gameobject_type, nodePoint[i].gameobject_entry); - EndBattleground(TEAM_OTHER); - } + if (gameobject->IsDestructibleBuilding()) + _wallGUIDs.emplace_back(gameobject->GetGUID()); - GetBGObject(nodePoint[i].gameobject_type)->SetFaction(nodePoint[i].faction == TEAM_ALLIANCE ? BG_IC_Factions[1] : BG_IC_Factions[0]); + if (gameobject->HasStringId("bg_ioc_faction_1735")) + gameobject->SetFaction(FACTION_HORDE_GENERIC_WG); + else if (gameobject->HasStringId("bg_ioc_faction_1732")) + gameobject->SetFaction(FACTION_ALLIANCE_GENERIC_WG); - UpdateNodeWorldState(&nodePoint[i]); - // we dont need iterating if we are here - // If the needChange bool was set true, we will handle the rest in the Update Map function. - return; - } + switch (gameobject->GetEntry()) + { + case GO_TELEPORTER_1: + case GO_TELEPORTER_2: + case GO_TELEPORTER_3: + case GO_TELEPORTER_4: + _teleporterGUIDs.emplace_back(gameobject->GetGUID()); + break; + case GO_TELEPORTER_EFFECTS_A: + case GO_TELEPORTER_EFFECTS_H: + _teleporterEffectGUIDs.emplace_back(gameobject->GetGUID()); + break; + case GO_DOODAD_ND_HUMAN_GATE_CLOSEDFX_DOOR01: + case GO_DOODAD_ND_WINTERORC_WALL_GATEFX_DOOR01: + _mainGateDoorGUIDs.emplace_back(gameobject->GetGUID()); + break; + case GO_DOODAD_HU_PORTCULLIS01: + case GO_DOODAD_VR_PORTCULLIS01: + _portcullisGUIDs.emplace_back(gameobject->GetGUID()); + break; + case GO_KEEP_GATE_H: + _keepGateGUIDs[TEAM_HORDE].emplace_back(gameobject->GetGUID()); + break; + case GO_KEEP_GATE_A: + case GO_KEEP_GATE_2_A: + _keepGateGUIDs[TEAM_ALLIANCE].emplace_back(gameobject->GetGUID()); + break; + case GO_BANNER_ALLIANCE_KEEP_CONTROLLED_A: + _keepBannerGUIDs[TEAM_ALLIANCE] = gameobject->GetGUID(); + break; + case GO_BANNER_HORDE_KEEP_CONTROLLED_H: + _keepBannerGUIDs[TEAM_HORDE] = gameobject->GetGUID(); + break; + default: + break; } } -void BattlegroundIC::UpdateNodeWorldState(ICNodePoint* node) +void BattlegroundIC::OnMapSet(BattlegroundMap* map) { - //updating worldstate - if (node->gameobject_entry == node->banners[BANNER_A_CONTROLLED]) - node->nodeState = NODE_STATE_CONTROLLED_A; - else if (node->gameobject_entry == node->banners[BANNER_A_CONTESTED]) - node->nodeState = NODE_STATE_CONFLICT_A; - else if (node->gameobject_entry == node->banners[BANNER_H_CONTROLLED]) - node->nodeState = NODE_STATE_CONTROLLED_H; - else if (node->gameobject_entry == node->banners[BANNER_H_CONTESTED]) - node->nodeState = NODE_STATE_CONFLICT_H; - - int32 worldstate = node->worldStates[node->nodeState]; - - // with this we are sure we dont bug the client - for (uint8 i = 0; i < 5; ++i) + Battleground::OnMapSet(map); + + if (Transport* transport = sTransportMgr->CreateTransport(GO_HORDE_GUNSHIP, map)) { - if (node->worldStates[i] == worldstate) - continue; - UpdateWorldState(node->worldStates[i], 0); + _gunshipGUIDs[TEAM_HORDE] = transport->GetGUID(); + transport->EnableMovement(false); } - UpdateWorldState(worldstate, 1); - UpdateWorldState(node->worldStates[5], node->nodeState == NODE_STATE_CONTROLLED_H ? 2 : node->nodeState == NODE_STATE_CONTROLLED_A ? 1 : 0); + if (Transport* transport = sTransportMgr->CreateTransport(GO_ALLIANCE_GUNSHIP, map)) + { + _gunshipGUIDs[TEAM_ALLIANCE] = transport->GetGUID(); + transport->EnableMovement(false); + } } -uint32 BattlegroundIC::GetNextBanner(ICNodePoint* node, uint32 team, bool returnDefinitve) +void BattlegroundIC::DoAction(uint32 actionId, WorldObject* source, WorldObject* target) { - // this is only used in the update map function - if (returnDefinitve) - // here is a special case, here we must return the definitve faction banner after the grey banner was spawned 1 minute - return node->banners[(team == TEAM_ALLIANCE ? BANNER_A_CONTROLLED : BANNER_H_CONTROLLED)]; - - // there were no changes, this point has never been captured by any faction or at least clicked - if (node->last_entry == 0) - // 1 returns the CONTESTED ALLIANCE BANNER, 3 returns the HORDE one - return node->banners[(team == TEAM_ALLIANCE ? BANNER_A_CONTESTED : BANNER_H_CONTESTED)]; - - // If the actual banner is the definitive faction banner, we must return the grey banner of the player's faction - if (node->gameobject_entry == node->banners[BANNER_A_CONTROLLED] || node->gameobject_entry == node->banners[BANNER_H_CONTROLLED]) - return node->banners[(team == TEAM_ALLIANCE ? BANNER_A_CONTESTED : BANNER_H_CONTESTED)]; - - // If the actual banner is the grey faction banner, we must return the previous banner - if (node->gameobject_entry == node->banners[BANNER_A_CONTESTED] || node->banners[BANNER_H_CONTESTED]) - return node->last_entry; - - // we should never be here... - TC_LOG_ERROR("bg.battleground", "Isle Of Conquest: Unexpected return in GetNextBanner function"); - return 0; -} -void BattlegroundIC::HandleContestedNodes(ICNodePoint* node) -{ - if (node->nodeType == NODE_TYPE_HANGAR) + switch (actionId) { - if (gunshipAlliance && gunshipHorde) - (node->faction == TEAM_ALLIANCE ? gunshipHorde : gunshipAlliance)->EnableMovement(false); - - for (uint8 u = BG_IC_GO_HANGAR_TELEPORTER_1; u <= BG_IC_GO_HANGAR_TELEPORTER_3; ++u) - DelObject(u); + case ACTION_IOC_INTERACT_CAPTURABLE_OBJECT: + OnPlayerInteractWithBanner(WorldObject::ToPlayer(source), WorldObject::ToGameObject(target)); + break; + case ACTION_IOC_CAPTURE_CAPTURABLE_OBJECT: + HandleCaptureNodeAction(WorldObject::ToGameObject(target)); + break; + default: + break; + } +} - for (uint8 u = BG_IC_GO_HANGAR_TELEPORTER_EFFECT_1; u <= BG_IC_GO_HANGAR_TELEPORTER_EFFECT_3; ++u) - DelObject(u); +void BattlegroundIC::OnPlayerInteractWithBanner(Player* player, GameObject* banner) +{ + if (!player || !banner) + return; - DelCreature(BG_IC_NPC_WORLD_TRIGGER_NOT_FLOATING); + Team const playerTeam = GetPlayerTeam(player->GetGUID()); + TeamId const playerTeamId = GetTeamIndexByTeamId(playerTeam); + ICNodePointType const nodeType = BannerToNodeType(banner->GetEntry()); + if (nodeType == MAX_NODE_TYPES) + return; - for (uint8 u = 0; u < MAX_CAPTAIN_SPAWNS_PER_FACTION; ++u) - { - uint8 type = BG_IC_NPC_GUNSHIP_CAPTAIN_1 + u; - DelCreature(type); - } + ICNodePoint& node = *_nodePoints[nodeType]; - std::list<Creature*> cannons; - if (node->faction == TEAM_HORDE) - gunshipAlliance->GetCreatureListWithEntryInGrid(cannons, NPC_ALLIANCE_GUNSHIP_CANNON, 150.0f); - else - gunshipHorde->GetCreatureListWithEntryInGrid(cannons, NPC_HORDE_GUNSHIP_CANNON, 150.0f); + bool assault = false; + bool defend = false; - for (Creature* cannon : cannons) - { - cannon->GetVehicleKit()->RemoveAllPassengers(); - cannon->SetUninteractible(true); - } - } - else if (node->nodeType == NODE_TYPE_WORKSHOP) + switch (node.GetState()) { - DelObject(BG_IC_GO_SEAFORIUM_BOMBS_1); - DelObject(BG_IC_GO_SEAFORIUM_BOMBS_2); + case IsleOfConquestNodeState::Neutral: + assault = true; + break; + case IsleOfConquestNodeState::ControlledH: + assault = playerTeamId != TEAM_HORDE; + break; + case IsleOfConquestNodeState::ControlledA: + assault = playerTeamId != TEAM_ALLIANCE; + break; + case IsleOfConquestNodeState::ConflictA: + defend = playerTeamId == node.GetLastControlledTeam(); + assault = !defend && playerTeamId == TEAM_HORDE; + break; + case IsleOfConquestNodeState::ConflictH: + defend = playerTeamId == node.GetLastControlledTeam(); + assault = !defend && playerTeamId == TEAM_ALLIANCE; + break; } + + if (assault) + OnPlayerAssaultNode(player, node); + else if (defend) + OnPlayerDefendNode(player, node); + + GetBgMap()->UpdateSpawnGroupConditions(); } -void BattlegroundIC::HandleCapturedNodes(ICNodePoint* node, bool recapture) +void BattlegroundIC::OnPlayerAssaultNode(Player* player, ICNodePoint& node) { - if (node->nodeType != NODE_TYPE_REFINERY && node->nodeType != NODE_TYPE_QUARRY) - { - if (!AddSpiritGuide(BG_IC_NPC_SPIRIT_GUIDE_1 + uint32(node->nodeType) - 2, BG_IC_SpiritGuidePos[node->nodeType], node->faction)) - TC_LOG_ERROR("bg.battleground", "Isle of Conquest: Failed to spawn spirit guide! point: {}, team: {}, ", node->nodeType, node->faction); - } + if (!player) + return; - switch (node->gameobject_type) - { - case BG_IC_GO_HANGAR_BANNER: - { - if (!gunshipAlliance || !gunshipHorde) - break; + Team const playerTeam = GetPlayerTeam(player->GetGUID()); + TeamId const playerTeamId = GetTeamIndexByTeamId(playerTeam); - std::list<Creature*> cannons; - if (node->faction == TEAM_ALLIANCE) - gunshipAlliance->GetCreatureListWithEntryInGrid(cannons, NPC_ALLIANCE_GUNSHIP_CANNON, 150.0f); - else - gunshipHorde->GetCreatureListWithEntryInGrid(cannons, NPC_HORDE_GUNSHIP_CANNON, 150.0f); + IsleOfConquestNodeState const newState = playerTeamId == TEAM_HORDE ? IsleOfConquestNodeState::ConflictH : IsleOfConquestNodeState::ConflictA; + node.UpdateState(newState); - for (Creature* cannon : cannons) - cannon->SetUninteractible(false); + UpdatePvpStat(player, PVP_STAT_BASES_ASSAULTED, 1); - for (uint8 u = 0; u < MAX_HANGAR_TELEPORTERS_SPAWNS; ++u) - { - uint8 type = BG_IC_GO_HANGAR_TELEPORTER_1 + u; - if (!AddObject(type, (node->faction == TEAM_ALLIANCE ? GO_ALLIANCE_GUNSHIP_PORTAL : GO_HORDE_GUNSHIP_PORTAL), BG_IC_HangarTeleporters[u], 0, 0, 0, 0, RESPAWN_ONE_DAY)) - TC_LOG_ERROR("bg.battleground", "Isle of Conquest: There was an error spawning a gunship portal. Type: {}", BG_IC_GO_HANGAR_TELEPORTER_1 + u); - } + ChatMsg const messageType = playerTeamId == TEAM_ALLIANCE ? CHAT_MSG_BG_SYSTEM_ALLIANCE : CHAT_MSG_BG_SYSTEM_HORDE; + SendBroadcastText(node.GetNodeInfo().TextIds.Assaulted, messageType, player); + UpdateNodeWorldState(node); - for (uint8 u = 0; u < MAX_HANGAR_TELEPORTER_EFFECTS_SPAWNS; ++u) - { - uint8 type = BG_IC_GO_HANGAR_TELEPORTER_EFFECT_1 + u; - if (!AddObject(type, (node->faction == TEAM_ALLIANCE ? GO_ALLIANCE_GUNSHIP_PORTAL_EFFECTS : GO_HORDE_GUNSHIP_PORTAL_EFFECTS), BG_IC_HangarTeleporterEffects[u], 0, 0, 0, 0, RESPAWN_ONE_DAY, GO_STATE_ACTIVE)) - TC_LOG_ERROR("bg.battleground", "Isle of Conquest: There was an error spawning a gunship portal effects. Type: {}", BG_IC_GO_HANGAR_TELEPORTER_1 + u); - } + // apply side effects of each node, only if it wasn't neutral before + if (node.GetLastControlledTeam() == TEAM_NEUTRAL) + return; - for (uint8 u = 0; u < MAX_TRIGGER_SPAWNS_PER_FACTION; ++u) - { - if (!AddCreature(NPC_WORLD_TRIGGER_NOT_FLOATING, BG_IC_NPC_WORLD_TRIGGER_NOT_FLOATING, BG_IC_HangarTrigger[node->faction], node->faction, RESPAWN_ONE_DAY, node->faction == TEAM_ALLIANCE ? gunshipAlliance : gunshipHorde)) - TC_LOG_ERROR("bg.battleground", "Isle of Conquest: There was an error spawning a world trigger. Type: {}", BG_IC_NPC_WORLD_TRIGGER_NOT_FLOATING); - } + switch (node.GetNodeInfo().NodeType) + { + case NODE_TYPE_HANGAR: + if (Transport* transport = GetBgMap()->GetTransport(_gunshipGUIDs[node.GetLastControlledTeam()])) + transport->EnableMovement(false); - for (uint8 u = 0; u < MAX_CAPTAIN_SPAWNS_PER_FACTION; ++u) + for (ObjectGuid const& guid : _cannonGUIDs[node.GetLastControlledTeam()]) + { + if (Creature* cannon = GetBgMap()->GetCreature(guid)) { - uint8 type = BG_IC_NPC_GUNSHIP_CAPTAIN_1 + u; - - if (type == BG_IC_NPC_GUNSHIP_CAPTAIN_1) - if (AddCreature(node->faction == TEAM_ALLIANCE ? NPC_ALLIANCE_GUNSHIP_CAPTAIN : NPC_HORDE_GUNSHIP_CAPTAIN, type, BG_IC_HangarCaptains[node->faction == TEAM_ALLIANCE ? 2 : 0], node->faction, RESPAWN_ONE_DAY)) - GetBGCreature(BG_IC_NPC_GUNSHIP_CAPTAIN_1)->GetAI()->DoAction(ACTION_GUNSHIP_READY); - - if (type == BG_IC_NPC_GUNSHIP_CAPTAIN_2) - if (!AddCreature(node->faction == TEAM_ALLIANCE ? NPC_ALLIANCE_GUNSHIP_CAPTAIN : NPC_HORDE_GUNSHIP_CAPTAIN, type, BG_IC_HangarCaptains[node->faction == TEAM_ALLIANCE ? 3 : 1], node->faction, RESPAWN_ONE_DAY, node->faction == TEAM_ALLIANCE ? gunshipAlliance : gunshipHorde)) - TC_LOG_ERROR("bg.battleground", "Isle of Conquest: There was an error spawning a world trigger. Type: {}", BG_IC_NPC_GUNSHIP_CAPTAIN_2); + cannon->GetVehicleKit()->RemoveAllPassengers(); + cannon->SetUninteractible(true); } - - (node->faction == TEAM_ALLIANCE ? gunshipAlliance : gunshipHorde)->EnableMovement(true); - break; } - case BG_IC_GO_QUARRY_BANNER: - RemoveAuraOnTeam(SPELL_QUARRY, (node->faction == TEAM_ALLIANCE ? HORDE : ALLIANCE)); - CastSpellOnTeam(SPELL_QUARRY, (node->faction == TEAM_ALLIANCE ? ALLIANCE : HORDE)); + + // Despawn teleport trigger target + if (Creature* creature = FindBgMap()->GetCreature(_gunshipTeleportTarget)) + creature->DespawnOrUnsummon(); break; - case BG_IC_GO_REFINERY_BANNER: - RemoveAuraOnTeam(SPELL_OIL_REFINERY, (node->faction == TEAM_ALLIANCE ? HORDE : ALLIANCE)); - CastSpellOnTeam(SPELL_OIL_REFINERY, (node->faction == TEAM_ALLIANCE ? ALLIANCE : HORDE)); + default: break; - case BG_IC_GO_DOCKS_BANNER: - if (recapture) - break; + } +} - if (docksTimer < DOCKS_UPDATE_TIME) - docksTimer = DOCKS_UPDATE_TIME; +void BattlegroundIC::OnPlayerDefendNode(Player* player, ICNodePoint& node) +{ + if (!player) + return; - // we must del opposing faction vehicles when the node is captured (unused ones) - for (uint8 i = (node->faction == TEAM_ALLIANCE ? BG_IC_NPC_GLAIVE_THROWER_1_H : BG_IC_NPC_GLAIVE_THROWER_1_A); i < (node->faction == TEAM_ALLIANCE ? BG_IC_NPC_GLAIVE_THROWER_2_H : BG_IC_NPC_GLAIVE_THROWER_2_A); ++i) - { - if (Creature* glaiveThrower = GetBGCreature(i, false)) - { - if (Vehicle* vehicleGlaive = glaiveThrower->GetVehicleKit()) - { - if (!vehicleGlaive->GetPassenger(0)) - DelCreature(i); - } - } - } + Team const playerTeam = GetPlayerTeam(player->GetGUID()); + TeamId const playerTeamId = GetTeamIndexByTeamId(playerTeam); - for (uint8 i = (node->faction == TEAM_ALLIANCE ? BG_IC_NPC_CATAPULT_1_H : BG_IC_NPC_CATAPULT_1_A); i < (node->faction == TEAM_ALLIANCE ? BG_IC_NPC_CATAPULT_4_H : BG_IC_NPC_CATAPULT_4_A); ++i) - { - if (Creature* catapult = GetBGCreature(i, false)) - { - if (Vehicle* vehicleGlaive = catapult->GetVehicleKit()) - { - if (!vehicleGlaive->GetPassenger(0)) - DelCreature(i); - } - } - } + node.UpdateState(playerTeamId == TEAM_HORDE ? IsleOfConquestNodeState::ControlledH : IsleOfConquestNodeState::ControlledA); + HandleCapturedNodes(node); + UpdatePvpStat(player, PVP_STAT_BASES_DEFENDED, 1); - // spawning glaive throwers - for (uint8 i = 0; i < MAX_GLAIVE_THROWERS_SPAWNS_PER_FACTION; ++i) - { - uint8 type = (node->faction == TEAM_ALLIANCE ? BG_IC_NPC_GLAIVE_THROWER_1_A : BG_IC_NPC_GLAIVE_THROWER_1_H)+i; + ChatMsg const messageType = playerTeamId == TEAM_ALLIANCE ? CHAT_MSG_BG_SYSTEM_ALLIANCE : CHAT_MSG_BG_SYSTEM_HORDE; + SendBroadcastText(node.GetNodeInfo().TextIds.Defended, messageType, player); + UpdateNodeWorldState(node); +} - if (GetBGCreature(type, false) && GetBGCreature(type)->IsAlive()) - continue; +void BattlegroundIC::ProcessEvent(WorldObject* target, uint32 eventId, WorldObject* invoker) +{ + Battleground::ProcessEvent(target, eventId, invoker); - if (AddCreature(node->faction == TEAM_ALLIANCE ? NPC_GLAIVE_THROWER_A : NPC_GLAIVE_THROWER_H, type, BG_IC_DocksVehiclesGlaives[i], node->faction, RESPAWN_ONE_DAY)) - GetBGCreature(type)->SetFaction(BG_IC_Factions[(node->faction == TEAM_ALLIANCE ? 0 : 1)]); - } + if (GameObject* obj = Object::ToGameObject(target)) + if (obj->GetGoType() == GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING) + if (obj->GetGOInfo()->destructibleBuilding.DestroyedEvent == eventId) + OnGateDestroyed(obj, invoker); +} - // spawning catapults - for (uint8 i = 0; i < MAX_CATAPULTS_SPAWNS_PER_FACTION; ++i) - { - uint8 type = (node->faction == TEAM_ALLIANCE ? BG_IC_NPC_CATAPULT_1_A : BG_IC_NPC_CATAPULT_1_H)+i; +void BattlegroundIC::HandleCaptureNodeAction(GameObject* banner) +{ + if (!banner) + return; - if (GetBGCreature(type, false) && GetBGCreature(type)->IsAlive()) - continue; + ICNodePointType const nodeType = BannerToNodeType(banner->GetEntry()); + if (nodeType == MAX_NODE_TYPES) + return; - if (AddCreature(NPC_CATAPULT, type, BG_IC_DocksVehiclesCatapults[i], node->faction, RESPAWN_ONE_DAY)) - GetBGCreature(type)->SetFaction(BG_IC_Factions[(node->faction == TEAM_ALLIANCE ? 0 : 1)]); - } - break; - case BG_IC_GO_WORKSHOP_BANNER: - { - if (siegeEngineWorkshopTimer < WORKSHOP_UPDATE_TIME) - siegeEngineWorkshopTimer = WORKSHOP_UPDATE_TIME; + ICNodePoint& node = *_nodePoints[nodeType]; + if (node.GetState() == IsleOfConquestNodeState::ConflictH) + node.UpdateState(IsleOfConquestNodeState::ControlledH); + else if (node.GetState() == IsleOfConquestNodeState::ConflictA) + node.UpdateState(IsleOfConquestNodeState::ControlledA); - if (!recapture) - { - // we must del opposing faction vehicles when the node is captured (unused ones) - for (uint8 i = (node->faction == TEAM_ALLIANCE ? BG_IC_NPC_DEMOLISHER_1_H : BG_IC_NPC_DEMOLISHER_1_A); i < (node->faction == TEAM_ALLIANCE ? BG_IC_NPC_DEMOLISHER_4_H : BG_IC_NPC_DEMOLISHER_4_A); ++i) - { - if (Creature* demolisher = GetBGCreature(i, false)) - { - if (Vehicle* vehicleDemolisher = demolisher->GetVehicleKit()) - { - // is IsVehicleInUse working as expected? - if (!vehicleDemolisher->IsVehicleInUse()) - DelCreature(i); - } - } - } - - for (uint8 i = 0; i < MAX_DEMOLISHERS_SPAWNS_PER_FACTION; ++i) - { - uint8 type = (node->faction == TEAM_ALLIANCE ? BG_IC_NPC_DEMOLISHER_1_A : BG_IC_NPC_DEMOLISHER_1_H)+i; - - if (GetBGCreature(type, false) && GetBGCreature(type)->IsAlive()) - continue; - - if (AddCreature(NPC_DEMOLISHER, type, BG_IC_WorkshopVehicles[i], node->faction, RESPAWN_ONE_DAY)) - GetBGCreature(type)->SetFaction(BG_IC_Factions[(node->faction == TEAM_ALLIANCE ? 0 : 1)]); - } - - // we check if the opossing siege engine is in use - int8 enemySiege = (node->faction == TEAM_ALLIANCE ? BG_IC_NPC_SIEGE_ENGINE_H : BG_IC_NPC_SIEGE_ENGINE_A); - - if (Creature* siegeEngine = GetBGCreature(enemySiege, false)) - { - if (Vehicle* vehicleSiege = siegeEngine->GetVehicleKit()) - { - // is VehicleInUse working as expected ? - if (!vehicleSiege->IsVehicleInUse()) - DelCreature(enemySiege); - } - } - - uint8 siegeType = (node->faction == TEAM_ALLIANCE ? BG_IC_NPC_SIEGE_ENGINE_A : BG_IC_NPC_SIEGE_ENGINE_H); - if (!GetBGCreature(siegeType, false) || !GetBGCreature(siegeType)->IsAlive()) - { - AddCreature((node->faction == TEAM_ALLIANCE ? NPC_SIEGE_ENGINE_A : NPC_SIEGE_ENGINE_H), siegeType, - BG_IC_WorkshopVehicles[4], node->faction, RESPAWN_ONE_DAY); - - if (Creature* siegeEngine = GetBGCreature(siegeType)) - { - siegeEngine->SetUnitFlag(UNIT_FLAG_CANT_SWIM); - siegeEngine->SetUninteractible(true); - siegeEngine->SetImmuneToPC(true); - siegeEngine->SetFaction(BG_IC_Factions[(node->faction == TEAM_ALLIANCE ? 0 : 1)]); - } - } - } + HandleCapturedNodes(node); - for (uint8 i = 0; i < MAX_WORKSHOP_BOMBS_SPAWNS_PER_FACTION; ++i) - { - AddObject(BG_IC_GO_SEAFORIUM_BOMBS_1+i, GO_SEAFORIUM_BOMBS, - workshopBombs[i].GetPositionX(), workshopBombs[i].GetPositionY(), - workshopBombs[i].GetPositionZ(), workshopBombs[i].GetOrientation(), - 0, 0, 0, 0, 10); - - if (GameObject* seaforiumBombs = GetBGObject(BG_IC_GO_SEAFORIUM_BOMBS_1+i)) - { - seaforiumBombs->SetRespawnTime(10); - seaforiumBombs->SetFaction(BG_IC_Factions[(node->faction == TEAM_ALLIANCE ? 0 : 1)]); - } - } - break; - } - default: - break; - } + ChatMsg const messageType = node.GetLastControlledTeam() == TEAM_ALLIANCE ? CHAT_MSG_BG_SYSTEM_ALLIANCE : CHAT_MSG_BG_SYSTEM_HORDE; + uint32 const textId = node.GetLastControlledTeam() == TEAM_ALLIANCE ? node.GetNodeInfo().TextIds.AllianceTaken : node.GetNodeInfo().TextIds.HordeTaken; + SendBroadcastText(textId, messageType); + UpdateNodeWorldState(node); } -void BattlegroundIC::DestroyGate(Player* player, GameObject* go) +void BattlegroundIC::OnGateDestroyed(GameObject* gate, WorldObject* destroyer) { - GateStatus[GetGateIDFromEntry(go->GetEntry())] = BG_IC_GATE_DESTROYED; - int32 uws_open = GetWorldStateFromGateEntry(go->GetEntry(), true); - int32 uws_close = GetWorldStateFromGateEntry(go->GetEntry(), false); - if (uws_open) + _gateStatus[GetGateIDFromEntry(gate->GetEntry())] = BG_IC_GATE_DESTROYED; + int32 const wsGateOpen = GetWorldStateFromGateEntry(gate->GetEntry(), true); + int32 const wsGateClosed = GetWorldStateFromGateEntry(gate->GetEntry(), false); + if (wsGateOpen) { - UpdateWorldState(uws_close, 0); - UpdateWorldState(uws_open, 1); - } - if (GetPlayerTeam(player->GetGUID()) == ALLIANCE) - { - DoorOpen(BG_IC_GO_HORDE_KEEP_PORTCULLIS); - GetBGObject(BG_IC_GO_HORDE_BANNER)->RemoveFlag(GO_FLAG_NOT_SELECTABLE); - } - else - { - DoorOpen(BG_IC_GO_DOODAD_PORTCULLISACTIVE02); - GetBGObject(BG_IC_GO_ALLIANCE_BANNER)->RemoveFlag(GO_FLAG_NOT_SELECTABLE); + UpdateWorldState(wsGateClosed, 0); + UpdateWorldState(wsGateOpen, 1); } + TeamId teamId = TEAM_NEUTRAL; uint32 textId; ChatMsg msgType; - switch (go->GetEntry()) + switch (gate->GetEntry()) { case GO_HORDE_GATE_1: textId = BG_IC_TEXT_FRONT_GATE_HORDE_DESTROYED; msgType = CHAT_MSG_BG_SYSTEM_ALLIANCE; + teamId = TEAM_HORDE; break; case GO_HORDE_GATE_2: textId = BG_IC_TEXT_WEST_GATE_HORDE_DESTROYED; msgType = CHAT_MSG_BG_SYSTEM_ALLIANCE; + teamId = TEAM_HORDE; break; case GO_HORDE_GATE_3: textId = BG_IC_TEXT_EAST_GATE_HORDE_DESTROYED; msgType = CHAT_MSG_BG_SYSTEM_ALLIANCE; + teamId = TEAM_HORDE; break; case GO_ALLIANCE_GATE_1: textId = BG_IC_TEXT_WEST_GATE_ALLIANCE_DESTROYED; msgType = CHAT_MSG_BG_SYSTEM_HORDE; + teamId = TEAM_ALLIANCE; break; case GO_ALLIANCE_GATE_2: textId = BG_IC_TEXT_EAST_GATE_ALLIANCE_DESTROYED; msgType = CHAT_MSG_BG_SYSTEM_HORDE; + teamId = TEAM_ALLIANCE; break; case GO_ALLIANCE_GATE_3: textId = BG_IC_TEXT_FRONT_GATE_ALLIANCE_DESTROYED; msgType = CHAT_MSG_BG_SYSTEM_HORDE; + teamId = TEAM_ALLIANCE; break; default: return; } - if (go->GetEntry() == GO_HORDE_GATE_1 || go->GetEntry() == GO_HORDE_GATE_2 || go->GetEntry() == GO_HORDE_GATE_3) - { - if (!GetBgMap()->GetCreature(BgCreatures[BG_IC_NpcSpawnlocs[BG_IC_NPC_OVERLORD_AGMAR].type]) && !AddCreature(BG_IC_NpcSpawnlocs[BG_IC_NPC_OVERLORD_AGMAR].entry, BG_IC_NpcSpawnlocs[BG_IC_NPC_OVERLORD_AGMAR].type, BG_IC_NpcSpawnlocs[BG_IC_NPC_OVERLORD_AGMAR].x, BG_IC_NpcSpawnlocs[BG_IC_NPC_OVERLORD_AGMAR].y, BG_IC_NpcSpawnlocs[BG_IC_NPC_OVERLORD_AGMAR].z, BG_IC_NpcSpawnlocs[BG_IC_NPC_OVERLORD_AGMAR].o, BG_IC_NpcSpawnlocs[BG_IC_NPC_OVERLORD_AGMAR].team, RESPAWN_ONE_DAY)) - TC_LOG_ERROR("bg.battleground", "Isle of Conquest: There was an error spawning creature {}", BG_IC_NpcSpawnlocs[BG_IC_NPC_OVERLORD_AGMAR].entry); - } - else if (go->GetEntry() == GO_ALLIANCE_GATE_1 || go->GetEntry() == GO_ALLIANCE_GATE_2 || go->GetEntry() == GO_ALLIANCE_GATE_3) - { - if (!GetBgMap()->GetCreature(BgCreatures[BG_IC_NpcSpawnlocs[BG_IC_NPC_HIGH_COMMANDER_HALFORD_WYRMBANE].type]) && !AddCreature(BG_IC_NpcSpawnlocs[BG_IC_NPC_HIGH_COMMANDER_HALFORD_WYRMBANE].entry, BG_IC_NpcSpawnlocs[BG_IC_NPC_HIGH_COMMANDER_HALFORD_WYRMBANE].type, BG_IC_NpcSpawnlocs[BG_IC_NPC_HIGH_COMMANDER_HALFORD_WYRMBANE].x, BG_IC_NpcSpawnlocs[BG_IC_NPC_HIGH_COMMANDER_HALFORD_WYRMBANE].y, BG_IC_NpcSpawnlocs[BG_IC_NPC_HIGH_COMMANDER_HALFORD_WYRMBANE].z, BG_IC_NpcSpawnlocs[BG_IC_NPC_HIGH_COMMANDER_HALFORD_WYRMBANE].o, BG_IC_NpcSpawnlocs[BG_IC_NPC_HIGH_COMMANDER_HALFORD_WYRMBANE].team, RESPAWN_ONE_DAY)) - TC_LOG_ERROR("bg.battleground", "Isle of Conquest: There was an error spawning creature {}", BG_IC_NpcSpawnlocs[BG_IC_NPC_HIGH_COMMANDER_HALFORD_WYRMBANE].entry); - } - - SendBroadcastText(textId, msgType); -} - -WorldSafeLocsEntry const* BattlegroundIC::GetClosestGraveyard(Player* player) -{ - TeamId teamIndex = GetTeamIndexByTeamId(GetPlayerTeam(player->GetGUID())); - - // Is there any occupied node for this team? - std::vector<uint8> nodes; - for (uint8 i = 0; i < MAX_NODE_TYPES; ++i) - if (nodePoint[i].faction == GetTeamIndexByTeamId(GetPlayerTeam(player->GetGUID()))) - nodes.push_back(i); - - WorldSafeLocsEntry const* good_entry = nullptr; - // If so, select the closest node to place ghost on - if (!nodes.empty()) + if (teamId != TEAM_NEUTRAL) { - float player_x = player->GetPositionX(); - float player_y = player->GetPositionY(); + GuidVector const keepGates = _keepGateGUIDs[teamId]; + ObjectGuid const bannerGuid = _keepBannerGUIDs[teamId]; - float mindist = 999999.0f; - for (uint8 i = 0; i < nodes.size(); ++i) - { - WorldSafeLocsEntry const*entry = sObjectMgr->GetWorldSafeLoc(BG_IC_GraveyardIds[nodes[i]]); - if (!entry) - continue; - float dist = (entry->Loc.GetPositionX() - player_x) * (entry->Loc.GetPositionX() - player_x) + (entry->Loc.GetPositionY() - player_y) * (entry->Loc.GetPositionY() - player_y); - if (mindist > dist) - { - mindist = dist; - good_entry = entry; - } - } - nodes.clear(); - } - // If not, place ghost on starting location - if (!good_entry) - good_entry = sObjectMgr->GetWorldSafeLoc(BG_IC_GraveyardIds[uint32(teamIndex) + MAX_NODE_TYPES]); - - return good_entry; -} + for (ObjectGuid const& guid : keepGates) + if (GameObject* keepGate = GetBgMap()->GetGameObject(guid)) + keepGate->UseDoorOrButton(); -WorldSafeLocsEntry const * BattlegroundIC::GetExploitTeleportLocation(Team team) -{ - return sObjectMgr->GetWorldSafeLoc(team == ALLIANCE ? IC_EXPLOIT_TELEPORT_LOCATION_ALLIANCE : IC_EXPLOIT_TELEPORT_LOCATION_HORDE); -} - -bool BattlegroundIC::IsSpellAllowed(uint32 spellId, Player const* player) const -{ - switch (spellId) - { - case SPELL_OIL_REFINERY: - case SPELL_QUARRY: - { - uint32 team = GetPlayerTeam(player->GetGUID()); - uint8 nodeType = spellId == SPELL_OIL_REFINERY ? NODE_TYPE_REFINERY : NODE_TYPE_QUARRY; - uint8 nodeState = team == ALLIANCE ? NODE_STATE_CONTROLLED_A : NODE_STATE_CONTROLLED_H; - return GetNodeState(nodeType) == nodeState; - } - default: - break; + if (GameObject* banner = GetBgMap()->GetGameObject(bannerGuid)) + banner->RemoveFlag(GO_FLAG_NOT_SELECTABLE); } - return true; + SendBroadcastText(textId, msgType, destroyer); } diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.h b/src/server/game/Battlegrounds/Zones/BattlegroundIC.h index a72a2b39d2c..c7d47d90d1f 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.h @@ -20,6 +20,8 @@ #include "Battleground.h" #include "Object.h" +#include "TaskScheduler.h" +#include "Timer.h" const uint32 BG_IC_Factions[2] = { @@ -49,384 +51,13 @@ enum creaturesIC NPC_WORLD_TRIGGER_HORDE_FRIENDLY = 20212 }; -enum gameobjectsIC -{ - GO_ALLIANCE_BANNER = 195396, - - GO_ALLIANCE_GATE_1 = 195699, - GO_ALLIANCE_GATE_2 = 195698, - GO_ALLIANCE_GATE_3 = 195700, - - GO_ALLIANCE_GUNSHIP_PORTAL = 195320, - - GO_ALLIANCE_GUNSHIP_PORTAL_EFFECTS = 195705, - - GO_BENCH_1 = 186896, - GO_BENCH_2 = 186922, - GO_BENCH_3 = 186899, - GO_BENCH_4 = 186904, - GO_BENCH_5 = 186897, - - GO_BONFIRE_1 = 195376, - GO_BONFIRE_2 = 195208, - GO_BONFIRE_3 = 195210, - GO_BONFIRE_4 = 195207, - GO_BONFIRE_5 = 195209, - GO_BONFIRE_6 = 195377, - - GO_DOCKS_BANNER = 195157, - - GO_DOODAD_HU_PORTCULLIS01 = 195436, - - GO_DOODAD_ND_HUMAN_GATE_CLOSEDFX_DOOR01 = 195703, - - GO_DOODAD_PORTCULLISACTIVE01 = 195451, - - GO_DOODAD_PORTCULLISACTIVE02 = 195452, - - GO_DOODAD_VR_PORTCULLIS01 = 195437, - - GO_CHAIR_1 = 195410, - GO_CHAIR_2 = 195414, - GO_CHAIR_3 = 160415, - GO_CHAIR_4 = 195418, - GO_CHAIR_5 = 195416, - GO_CHAIR_6 = 160410, - GO_CHAIR_7 = 160418, - GO_CHAIR_8 = 160416, - GO_CHAIR_9 = 160419, - - GO_FLAGPOLE_1 = 195131, - GO_FLAGPOLE_2 = 195439, - - GO_GUNSHIP_PORTAL_1 = 195371, - GO_GUNSHIP_PORTAL_2 = 196413, - - GO_HANGAR_BANNER = 195158, - - GO_HORDE_BANNER = 195393, - - GO_HORDE_GATE_1 = 195494, - GO_HORDE_GATE_2 = 195496, - GO_HORDE_GATE_3 = 195495, - - GO_HORDE_GUNSHIP_PORTAL = 195326, - - GO_HORDE_GUNSHIP_PORTAL_EFFECTS = 195706, - - GO_HORDE_KEEP_PORTCULLIS = 195223, - - GO_HUGE_SEAFORIUM_BOMB_A = 195332, - GO_HUGE_SEAFORIUM_BOMB_H = 195333, - - GO_QUARRY_BANNER = 195338, - GO_REFRESHMENT_PORTAL = 186811, - GO_SEAFORIUM_BOMBS = 195237, - - GO_STOVE_1 = 174863, - GO_STOVE_2 = 160411, - - GO_TELEPORTER_1 = 195314, // 195314 H-OUT 66549 - GO_TELEPORTER_2 = 195313, // 195313 H-IN 66548 - - GO_TELEPORTER_3 = 195315, // 195315 A-OUT 66549 - GO_TELEPORTER_4 = 195316, // 195316 A-IN 66548 - - GO_TELEPORTER_EFFECTS_A = 195701, - GO_TELEPORTER_EFFECTS_H = 195702, - - GO_WORKSHOP_BANNER = 195133, - - GO_BRAZIER_1 = 195402, - GO_BRAZIER_2 = 195403, - GO_BRAZIER_3 = 195425, - GO_BRAZIER_4 = 195424, - - GO_REFINERY_BANNER = 195343, - - GO_DOODAD_ND_WINTERORC_WALL_GATEFX_DOOR01 = 195491, - - GO_ALLIANCE_BANNER_DOCK = 195153, - GO_ALLIANCE_BANNER_DOCK_CONT = 195154, - GO_HORDE_BANNER_DOCK = 195155, - GO_HORDE_BANNER_DOCK_CONT = 195156, - - GO_HORDE_BANNER_HANGAR = 195130, - GO_HORDE_BANNER_HANGAR_CONT = 195145, - GO_ALLIANCE_BANNER_HANGAR = 195132, - GO_ALLIANCE_BANNER_HANGAR_CONT = 195144, - - GO_ALLIANCE_BANNER_QUARRY = 195334, - GO_ALLIANCE_BANNER_QUARRY_CONT = 195335, - GO_HORDE_BANNER_QUARRY = 195336, - GO_HORDE_BANNER_QUARRY_CONT = 195337, - - GO_ALLIANCE_BANNER_REFINERY = 195339, - GO_ALLIANCE_BANNER_REFINERY_CONT = 195340, - GO_HORDE_BANNER_REFINERY = 195341, - GO_HORDE_BANNER_REFINERY_CONT = 195342, - - GO_ALLIANCE_BANNER_WORKSHOP = 195149, - GO_ALLIANCE_BANNER_WORKSHOP_CONT = 195150, - GO_HORDE_BANNER_WORKSHOP = 195151, - GO_HORDE_BANNER_WORKSHOP_CONT = 195152, - - GO_ALLIANCE_BANNER_GRAVEYARD_A = 195396, - GO_ALLIANCE_BANNER_GRAVEYARD_A_CONT = 195397, - GO_HORDE_BANNER_GRAVEYARD_A = 195398, - GO_HORDE_BANNER_GRAVEYARD_A_CONT = 195399, - - GO_ALLIANCE_BANNER_GRAVEYARD_H = 195391, - GO_ALLIANCE_BANNER_GRAVEYARD_H_CONT = 195392, - GO_HORDE_BANNER_GRAVEYARD_H = 195393, - GO_HORDE_BANNER_GRAVEYARD_H_CONT = 195394, - - GO_HORDE_GUNSHIP = 195276, - GO_ALLIANCE_GUNSHIP = 195121 -}; - #define MAX_REINFORCEMENTS 400 -enum Times -{ - WORKSHOP_UPDATE_TIME = 180000, // 3 minutes - DOCKS_UPDATE_TIME = 180000, // not sure if it is 3 minutes - IC_RESOURCE_TIME = 45000, // not sure, need more research - CLOSE_DOORS_TIME = 20000, - BANNER_STATE_CHANGE_TIME = 60000, - TRANSPORT_PERIOD_TIME = 120000 -}; - enum Actions { - ACTION_GUNSHIP_READY = 1 -}; - -struct ICNpc -{ - uint32 type; - uint32 entry; - TeamId team; - float x; - float y; - float z; - float o; -}; - -enum BG_IC_GOs -{ - BG_IC_GO_ALLIANCE_BANNER = 0, - - BG_IC_GO_ALLIANCE_GATE_1, - BG_IC_GO_ALLIANCE_GATE_2, - BG_IC_GO_ALLIANCE_GATE_3, - - BG_IC_GO_BENCH_1, - BG_IC_GO_BENCH_2, - BG_IC_GO_BENCH_3, - BG_IC_GO_BENCH_4, - BG_IC_GO_BENCH_5, - - BG_IC_GO_BONFIRE_1, - BG_IC_GO_BONFIRE_2, - BG_IC_GO_BONFIRE_3, - BG_IC_GO_BONFIRE_4, - BG_IC_GO_BONFIRE_5, - BG_IC_GO_BONFIRE_6, - - BG_IC_GO_BRAZIER_1, - BG_IC_GO_BRAZIER_2, - BG_IC_GO_BRAZIER_3, - BG_IC_GO_BRAZIER_4, - - BG_IC_GO_CHAIR_1, - BG_IC_GO_CHAIR_2, - BG_IC_GO_CHAIR_3_1, - BG_IC_GO_CHAIR_4, - BG_IC_GO_CHAIR_5, - BG_IC_GO_CHAIR_6_1, - BG_IC_GO_CHAIR_7, - BG_IC_GO_CHAIR_3_2, - BG_IC_GO_CHAIR_6_2, - BG_IC_GO_CHAIR_8_1, - BG_IC_GO_CHAIR_8_2, - BG_IC_GO_CHAIR_9, - - BG_IC_GO_DOCKS_BANNER, - - BG_IC_GO_DOODAD_HU_PORTCULLIS01_1, - BG_IC_GO_DOODAD_HU_PORTCULLIS01_2, - - BG_IC_GO_DOODAD_ND_HUMAN_GATE_CLOSEDFX_DOOR01, - BG_IC_GO_DOODAD_ND_HUMAN_GATE_CLOSEDFX_DOOR02, - BG_IC_GO_DOODAD_ND_HUMAN_GATE_CLOSEDFX_DOOR03, - - BG_IC_GO_DOODAD_PORTCULLISACTIVE01, - - BG_IC_GO_DOODAD_PORTCULLISACTIVE02, - - BG_IC_GO_DOODAD_VR_PORTCULLIS01_1, - BG_IC_GO_DOODAD_VR_PORTCULLIS01_2, - - BG_IC_GO_FLAGPOLE_1_1, - BG_IC_GO_FLAGPOLE_2_1, - BG_IC_GO_FLAGPOLE_2_2, - BG_IC_GO_FLAGPOLE_1_2, - BG_IC_GO_FLAGPOLE_1_3, - BG_IC_GO_FLAGPOLE_1_4, - BG_IC_GO_FLAGPOLE_1_5, - BG_IC_GO_FLAGPOLE_1_6, - - BG_IC_GO_HANGAR_BANNER, - - BG_IC_GO_HORDE_BANNER, - - BG_IC_GO_HORDE_GATE_1, - BG_IC_GO_HORDE_GATE_2, - BG_IC_GO_HORDE_GATE_3, - - BG_IC_GO_HORDE_KEEP_PORTCULLIS, - - BG_IC_GO_QUARRY_BANNER, - - BG_IC_GO_STOVE_1_1, - BG_IC_GO_STOVE_2_1, - BG_IC_GO_STOVE_1_2, - BG_IC_GO_STOVE_2_2, - - BG_IC_GO_WORKSHOP_BANNER, - - BG_IC_GO_REFINERY_BANNER, - - BG_IC_GO_HUGE_SEAFORIUM_BOMBS_A_1, - BG_IC_GO_HUGE_SEAFORIUM_BOMBS_A_2, - BG_IC_GO_HUGE_SEAFORIUM_BOMBS_A_3, - BG_IC_GO_HUGE_SEAFORIUM_BOMBS_A_4, - - BG_IC_GO_HUGE_SEAFORIUM_BOMBS_H_1, - BG_IC_GO_HUGE_SEAFORIUM_BOMBS_H_2, - BG_IC_GO_HUGE_SEAFORIUM_BOMBS_H_3, - BG_IC_GO_HUGE_SEAFORIUM_BOMBS_H_4, - - BG_IC_GO_DOODAD_ND_WINTERORC_WALL_GATEFX_DOOR01, - BG_IC_GO_DOODAD_ND_WINTERORC_WALL_GATEFX_DOOR02, - BG_IC_GO_DOODAD_ND_WINTERORC_WALL_GATEFX_DOOR03, - - BG_IC_GO_SEAFORIUM_BOMBS_1, - BG_IC_GO_SEAFORIUM_BOMBS_2, - - BG_IC_GO_HANGAR_TELEPORTER_1, - BG_IC_GO_HANGAR_TELEPORTER_2, - BG_IC_GO_HANGAR_TELEPORTER_3, - - BG_IC_GO_HANGAR_TELEPORTER_EFFECT_1, - BG_IC_GO_HANGAR_TELEPORTER_EFFECT_2, - BG_IC_GO_HANGAR_TELEPORTER_EFFECT_3, - - BG_IC_GO_TELEPORTER_1_1, - BG_IC_GO_TELEPORTER_1_2, - BG_IC_GO_TELEPORTER_2_1, - BG_IC_GO_TELEPORTER_3_1, - BG_IC_GO_TELEPORTER_2_2, - BG_IC_GO_TELEPORTER_4_1, - BG_IC_GO_TELEPORTER_3_2, - BG_IC_GO_TELEPORTER_3_3, - BG_IC_GO_TELEPORTER_4_2, - BG_IC_GO_TELEPORTER_4_3, - BG_IC_GO_TELEPORTER_1_3, - BG_IC_GO_TELEPORTER_2_3, - - BG_IC_GO_TELEPORTER_EFFECTS_A_1, - BG_IC_GO_TELEPORTER_EFFECTS_A_2, - BG_IC_GO_TELEPORTER_EFFECTS_A_3, - BG_IC_GO_TELEPORTER_EFFECTS_A_4, - BG_IC_GO_TELEPORTER_EFFECTS_A_5, - BG_IC_GO_TELEPORTER_EFFECTS_A_6, - - BG_IC_GO_TELEPORTER_EFFECTS_H_1, - BG_IC_GO_TELEPORTER_EFFECTS_H_2, - BG_IC_GO_TELEPORTER_EFFECTS_H_3, - BG_IC_GO_TELEPORTER_EFFECTS_H_4, - BG_IC_GO_TELEPORTER_EFFECTS_H_5, - BG_IC_GO_TELEPORTER_EFFECTS_H_6 -}; - -enum BG_IC_NPCs -{ - BG_IC_NPC_OVERLORD_AGMAR = 0, - BG_IC_NPC_HIGH_COMMANDER_HALFORD_WYRMBANE, - BG_IC_NPC_KOR_KRON_GUARD_1, - BG_IC_NPC_KOR_KRON_GUARD_2, - BG_IC_NPC_KOR_KRON_GUARD_3, - BG_IC_NPC_KOR_KRON_GUARD_4, - BG_IC_NPC_SEVEN_TH_LEGION_INFANTRY_1, - BG_IC_NPC_SEVEN_TH_LEGION_INFANTRY_2, - BG_IC_NPC_SEVEN_TH_LEGION_INFANTRY_3, - BG_IC_NPC_SEVEN_TH_LEGION_INFANTRY_4, - BG_IC_NPC_KEEP_CANNON_1, - BG_IC_NPC_KEEP_CANNON_2, - BG_IC_NPC_KEEP_CANNON_3, - BG_IC_NPC_KEEP_CANNON_4, - BG_IC_NPC_KEEP_CANNON_5, - BG_IC_NPC_KEEP_CANNON_6, - BG_IC_NPC_KEEP_CANNON_7, - BG_IC_NPC_KEEP_CANNON_8, - BG_IC_NPC_KEEP_CANNON_9, - BG_IC_NPC_KEEP_CANNON_10, - BG_IC_NPC_KEEP_CANNON_11, - BG_IC_NPC_KEEP_CANNON_12, - BG_IC_NPC_KEEP_CANNON_13, - BG_IC_NPC_KEEP_CANNON_14, - BG_IC_NPC_KEEP_CANNON_15, - BG_IC_NPC_KEEP_CANNON_16, - BG_IC_NPC_KEEP_CANNON_17, - BG_IC_NPC_KEEP_CANNON_18, - BG_IC_NPC_KEEP_CANNON_19, - BG_IC_NPC_KEEP_CANNON_20, - BG_IC_NPC_KEEP_CANNON_21, - BG_IC_NPC_KEEP_CANNON_22, - BG_IC_NPC_KEEP_CANNON_23, - BG_IC_NPC_KEEP_CANNON_24, - - BG_IC_NPC_SIEGE_ENGINE_A, - BG_IC_NPC_SIEGE_ENGINE_H, - - BG_IC_NPC_DEMOLISHER_1_A, - BG_IC_NPC_DEMOLISHER_2_A, - BG_IC_NPC_DEMOLISHER_3_A, - BG_IC_NPC_DEMOLISHER_4_A, - - BG_IC_NPC_DEMOLISHER_1_H, - BG_IC_NPC_DEMOLISHER_2_H, - BG_IC_NPC_DEMOLISHER_3_H, - BG_IC_NPC_DEMOLISHER_4_H, - - BG_IC_NPC_GLAIVE_THROWER_1_A, - BG_IC_NPC_GLAIVE_THROWER_2_A, - BG_IC_NPC_GLAIVE_THROWER_1_H, - BG_IC_NPC_GLAIVE_THROWER_2_H, - - BG_IC_NPC_CATAPULT_1_A, - BG_IC_NPC_CATAPULT_2_A, - BG_IC_NPC_CATAPULT_3_A, - BG_IC_NPC_CATAPULT_4_A, - - BG_IC_NPC_CATAPULT_1_H, - BG_IC_NPC_CATAPULT_2_H, - BG_IC_NPC_CATAPULT_3_H, - BG_IC_NPC_CATAPULT_4_H, - - BG_IC_NPC_WORLD_TRIGGER_NOT_FLOATING, - BG_IC_NPC_GUNSHIP_CAPTAIN_1, - BG_IC_NPC_GUNSHIP_CAPTAIN_2, - - BG_IC_NPC_SPIRIT_GUIDE_1, - BG_IC_NPC_SPIRIT_GUIDE_2, - BG_IC_NPC_SPIRIT_GUIDE_3, - BG_IC_NPC_SPIRIT_GUIDE_4, - BG_IC_NPC_SPIRIT_GUIDE_5, - BG_IC_NPC_SPIRIT_GUIDE_6, - BG_IC_NPC_SPIRIT_GUIDE_7 + ACTION_GUNSHIP_READY = 1, + ACTION_IOC_INTERACT_CAPTURABLE_OBJECT = 2, + ACTION_IOC_CAPTURE_CAPTURABLE_OBJECT = 3 }; enum BannersTypes @@ -437,276 +68,12 @@ enum BannersTypes BANNER_H_CONTESTED }; -enum BG_IC_MaxSpawns -{ - MAX_NORMAL_GAMEOBJECTS_SPAWNS = BG_IC_GO_DOODAD_ND_WINTERORC_WALL_GATEFX_DOOR03+1, - MAX_NORMAL_NPCS_SPAWNS = BG_IC_NPC_KEEP_CANNON_24+1, - MAX_WORKSHOP_SPAWNS = 10, - MAX_DOCKS_SPAWNS = 12, - MAX_SPIRIT_GUIDES_SPAWNS = 7, - MAX_HANGAR_TELEPORTERS_SPAWNS = 3, - MAX_HANGAR_TELEPORTER_EFFECTS_SPAWNS = 3, - MAX_AIRSHIPS_SPAWNS = 2, - MAX_FORTRESS_GATES_SPAWNS = 6, - MAX_FORTRESS_TELEPORTERS_SPAWNS = 12, - MAX_FORTRESS_TELEPORTER_EFFECTS_SPAWNS = 12, - MAX_HANGAR_NPCS_SPAWNS = 3, - - // docks - MAX_GLAIVE_THROWERS_SPAWNS_PER_FACTION = 2, - MAX_CATAPULTS_SPAWNS_PER_FACTION = 4, - - // workshop - MAX_DEMOLISHERS_SPAWNS_PER_FACTION = 4, - MAX_WORKSHOP_BOMBS_SPAWNS_PER_FACTION = 2, - - // Hangar - MAX_TRIGGER_SPAWNS_PER_FACTION = 1, - MAX_CAPTAIN_SPAWNS_PER_FACTION = 2, -}; - enum BG_IC_ExploitTeleportLocations { IC_EXPLOIT_TELEPORT_LOCATION_ALLIANCE = 3986, IC_EXPLOIT_TELEPORT_LOCATION_HORDE = 3983 }; -const ICNpc BG_IC_NpcSpawnlocs[MAX_NORMAL_NPCS_SPAWNS] = -{ - {BG_IC_NPC_OVERLORD_AGMAR, NPC_OVERLORD_AGMAR, TEAM_HORDE, 1295.44f, -765.733f, 70.0541f, 0.0f}, //Overlord Agmar 1 - {BG_IC_NPC_HIGH_COMMANDER_HALFORD_WYRMBANE, NPC_HIGH_COMMANDER_HALFORD_WYRMBANE, TEAM_ALLIANCE, 224.983f, -831.573f, 60.9034f, 0.0f}, //High Commander Halford Wyrmbane 2 - {BG_IC_NPC_KOR_KRON_GUARD_1, NPC_KOR_KRON_GUARD, TEAM_HORDE, 1296.01f, -773.256f, 69.958f, 0.292168f}, // 3 - {BG_IC_NPC_KOR_KRON_GUARD_2, NPC_KOR_KRON_GUARD, TEAM_HORDE, 1295.94f, -757.756f, 69.9587f, 6.02165f}, // 4 - {BG_IC_NPC_KOR_KRON_GUARD_3, NPC_KOR_KRON_GUARD, TEAM_HORDE, 1295.09f, -760.927f, 69.9587f, 5.94311f}, // 5 - {BG_IC_NPC_KOR_KRON_GUARD_4, NPC_KOR_KRON_GUARD, TEAM_HORDE, 1295.13f, -769.7f, 69.95f, 0.34f}, // 6 - - {BG_IC_NPC_SEVEN_TH_LEGION_INFANTRY_1, NPC_SEVEN_TH_LEGION_INFANTRY, TEAM_ALLIANCE, 223.969f, -822.958f, 60.8151f, 0.46337f}, // 7 - {BG_IC_NPC_SEVEN_TH_LEGION_INFANTRY_2, NPC_SEVEN_TH_LEGION_INFANTRY, TEAM_ALLIANCE, 224.211f, -826.952f, 60.8188f, 6.25961f}, // 8 - {BG_IC_NPC_SEVEN_TH_LEGION_INFANTRY_3, NPC_SEVEN_TH_LEGION_INFANTRY, TEAM_ALLIANCE, 223.119f, -838.386f, 60.8145f, 5.64857f}, // 9 - {BG_IC_NPC_SEVEN_TH_LEGION_INFANTRY_4, NPC_SEVEN_TH_LEGION_INFANTRY, TEAM_ALLIANCE, 223.889f, -835.102f, 60.8201f, 6.21642f}, // 10 - - {BG_IC_NPC_KEEP_CANNON_1, NPC_KEEP_CANNON, TEAM_ALLIANCE, 415.825f, -754.634f, 87.799f, 1.78024f}, // 11 - {BG_IC_NPC_KEEP_CANNON_2, NPC_KEEP_CANNON, TEAM_ALLIANCE, 410.142f, -755.332f, 87.7991f, 1.78024f}, // 12 - {BG_IC_NPC_KEEP_CANNON_3, NPC_KEEP_CANNON, TEAM_ALLIANCE, 424.33f, -879.352f, 88.0446f, 0.436332f}, // 13 - {BG_IC_NPC_KEEP_CANNON_4, NPC_KEEP_CANNON, TEAM_ALLIANCE, 425.602f, -786.646f, 87.7991f, 5.74213f}, // 14 - {BG_IC_NPC_KEEP_CANNON_5, NPC_KEEP_CANNON, TEAM_ALLIANCE, 426.743f, -884.939f, 87.9613f, 0.436332f}, // 15 - {BG_IC_NPC_KEEP_CANNON_6, NPC_KEEP_CANNON, TEAM_ALLIANCE, 404.736f, -755.495f, 87.7989f, 1.78024f}, // 16 - {BG_IC_NPC_KEEP_CANNON_7, NPC_KEEP_CANNON, TEAM_ALLIANCE, 428.375f, -780.797f, 87.7991f, 5.79449f}, // 17 - {BG_IC_NPC_KEEP_CANNON_8, NPC_KEEP_CANNON, TEAM_ALLIANCE, 429.175f, -890.436f, 88.0446f, 0.436332f}, // 18 - {BG_IC_NPC_KEEP_CANNON_9, NPC_KEEP_CANNON, TEAM_ALLIANCE, 430.872f, -775.278f, 87.7991f, 5.88176f}, // 19 - {BG_IC_NPC_KEEP_CANNON_10, NPC_KEEP_CANNON, TEAM_ALLIANCE, 408.056f, -911.283f, 88.0445f, 4.64258f}, // 20 - {BG_IC_NPC_KEEP_CANNON_11, NPC_KEEP_CANNON, TEAM_ALLIANCE, 413.609f, -911.566f, 88.0447f, 4.66003f}, // 21 - {BG_IC_NPC_KEEP_CANNON_12, NPC_KEEP_CANNON, TEAM_ALLIANCE, 402.554f, -910.557f, 88.0446f, 4.57276f}, // 22 - - {BG_IC_NPC_KEEP_CANNON_13, NPC_KEEP_CANNON, TEAM_HORDE, 1158.91f, -660.144f, 87.9332f, 0.750492f}, // 23 - {BG_IC_NPC_KEEP_CANNON_14, NPC_KEEP_CANNON, TEAM_HORDE, 1156.22f, -866.809f, 87.8754f, 5.27089f}, // 24 - {BG_IC_NPC_KEEP_CANNON_15, NPC_KEEP_CANNON, TEAM_HORDE, 1163.74f, -663.67f, 88.3571f, 0.558505f}, // 25 - {BG_IC_NPC_KEEP_CANNON_16, NPC_KEEP_CANNON, TEAM_HORDE, 1135.18f, -683.896f, 88.0409f, 3.9619f}, // 26 - {BG_IC_NPC_KEEP_CANNON_17, NPC_KEEP_CANNON, TEAM_HORDE, 1138.91f, -836.359f, 88.3728f, 2.18166f}, // 27 - {BG_IC_NPC_KEEP_CANNON_18, NPC_KEEP_CANNON, TEAM_HORDE, 1162.08f, -863.717f, 88.358f, 5.48033f}, // 28 - {BG_IC_NPC_KEEP_CANNON_19, NPC_KEEP_CANNON, TEAM_HORDE, 1167.13f, -669.212f, 87.9682f, 0.383972f}, // 29 - {BG_IC_NPC_KEEP_CANNON_20, NPC_KEEP_CANNON, TEAM_HORDE, 1137.72f, -688.517f, 88.4023f, 3.9619f}, // 30 - {BG_IC_NPC_KEEP_CANNON_21, NPC_KEEP_CANNON, TEAM_HORDE, 1135.29f, -840.878f, 88.0252f, 2.30383f}, // 31 - {BG_IC_NPC_KEEP_CANNON_22, NPC_KEEP_CANNON, TEAM_HORDE, 1144.33f, -833.309f, 87.9268f, 2.14675f}, // 32 - {BG_IC_NPC_KEEP_CANNON_23, NPC_KEEP_CANNON, TEAM_HORDE, 1142.59f, -691.946f, 87.9756f, 3.9619f}, // 33 - {BG_IC_NPC_KEEP_CANNON_24, NPC_KEEP_CANNON, TEAM_HORDE, 1166.13f, -858.391f, 87.9653f, 5.63741f} // 34 -}; - -const Position BG_IC_WorkshopVehicles[5] = -{ - {751.8281f, -852.732666f, 12.5250978f, 1.46607661f}, // Demolisher - {761.809f, -854.2274f, 12.5263243f, 1.46607661f}, // Demolisher - {783.4722f, -853.9601f, 12.54775f, 1.71042264f}, // Demolisher - {793.055542f, -852.71875f, 12.5671329f, 1.71042264f}, // Demolisher - {773.680542f, -884.092041f, 16.8090363f, 1.58824956f} // Siege Engine -}; - -const Position BG_IC_DocksVehiclesGlaives[2] = -{ - {779.3125f, -342.972229f, 12.2104874f, 4.712389f}, // Glaive Throwers - {790.029541f, -342.899323f, 12.2128582f, 4.71238f} // Glaive Throwers -}; - -const Position BG_IC_DocksVehiclesCatapults[4] = -{ - {757.283f, -341.7795f, 12.2113762f, 4.729842f}, // Catapults - {766.947937f, -342.053833f, 12.2009945f, 4.694f}, // Catapults - {800.3785f, -342.607635f, 12.1669979f, 4.6774f}, // Catapults - {810.7257f, -342.083344f, 12.1675768f, 4.6600f} // Catapults -}; - -const Position BG_IC_HangarTeleporters[3] = -{ - {827.9219f, -993.3249f, 134.1972f, 3.141593f}, // Gunship Portal - {739.0226f, -1106.661f, 134.7551f, 2.426008f}, // Gunship Portal - {672.0799f, -1156.776f, 133.7057f, 1.832595f} // Gunship Portal -}; - -const Position BG_IC_HangarTeleporterEffects[3] = -{ - {827.9236f, -993.2986f, 134.2002f, 3.141593f}, // Gunship Portal Effect - {739.0139f, -1106.661f, 134.7548f, 3.141593f}, // Gunship Portal Effect - {672.0868f, -1156.786f, 133.7057f, 3.141593f} // Gunship Portal Effect -}; - -const Position BG_IC_HangarTrigger[2] = -{ - {11.69965f, 0.034146f, 20.62076f, 3.211406f}, - {7.305609f, -0.095246f, 34.51022f, 3.159046f} -}; - -const Position BG_IC_HangarCaptains[4] = -{ - {825.6667f, -994.00520f, 134.3569f, 3.403392f}, - {53.65112f, -0.1139221f, 30.09546f, 3.106686f}, - {826.2205f, -994.40280f, 134.2812f, 3.351032f}, - {10.89952f, 4.88029700f, 20.49038f, 4.840575f} -}; - -struct ICGo -{ - uint32 type; - uint32 entry; - float x; - float y; - float z; - float o; -}; - -const ICGo BG_IC_Teleporters[MAX_FORTRESS_TELEPORTERS_SPAWNS] = -{ - {BG_IC_GO_TELEPORTER_1_1, GO_TELEPORTER_1, 1143.25f, -779.599f, 48.629f, 1.64061f}, // Teleporter - {BG_IC_GO_TELEPORTER_1_2, GO_TELEPORTER_1, 1236.53f, -669.415f, 48.2729f, 0.104719f}, // Teleporter - {BG_IC_GO_TELEPORTER_2_1, GO_TELEPORTER_2, 1233.27f, -844.526f, 48.8824f, -0.0174525f}, // Teleporter - {BG_IC_GO_TELEPORTER_3_1, GO_TELEPORTER_3, 311.92f, -913.972f, 48.8159f, 3.08918f}, // Teleporter - {BG_IC_GO_TELEPORTER_2_2, GO_TELEPORTER_2, 1235.53f, -683.872f, 49.304f, -3.08918f}, // Teleporter - {BG_IC_GO_TELEPORTER_4_1, GO_TELEPORTER_4, 397.089f, -859.382f, 48.8993f, 1.64061f}, // Teleporter - {BG_IC_GO_TELEPORTER_3_2, GO_TELEPORTER_3, 324.635f, -749.128f, 49.3602f, 0.0174525f}, // Teleporter - {BG_IC_GO_TELEPORTER_3_3, GO_TELEPORTER_3, 425.675f, -857.09f, 48.5104f, -1.6057f}, // Teleporter - {BG_IC_GO_TELEPORTER_4_2, GO_TELEPORTER_4, 323.54f, -888.361f, 48.9197f, 0.0349063f}, // Teleporter - {BG_IC_GO_TELEPORTER_4_3, GO_TELEPORTER_4, 326.285f, -777.366f, 49.0208f, 3.12412f}, // Teleporter - {BG_IC_GO_TELEPORTER_1_3, GO_TELEPORTER_1, 1235.09f, -857.898f, 48.9163f, 3.07177f}, // Teleporter - {BG_IC_GO_TELEPORTER_2_3, GO_TELEPORTER_2, 1158.76f, -746.182f, 48.6277f, -1.51844f} // Teleporter -}; - -const ICGo BG_IC_TeleporterEffects[MAX_FORTRESS_TELEPORTER_EFFECTS_SPAWNS] = -{ - {BG_IC_GO_TELEPORTER_EFFECTS_A_1, GO_TELEPORTER_EFFECTS_A, 425.686f, -857.092f, 48.51f, -1.62316f}, // Teleporter Effects (Alliance) - {BG_IC_GO_TELEPORTER_EFFECTS_A_2, GO_TELEPORTER_EFFECTS_A, 324.634f, -749.148f, 49.359f, 0.0174525f}, // Teleporter Effects (Alliance) - {BG_IC_GO_TELEPORTER_EFFECTS_A_3, GO_TELEPORTER_EFFECTS_A, 311.911f, -913.986f, 48.8157f, 3.08918f}, // Teleporter Effects (Alliance) - {BG_IC_GO_TELEPORTER_EFFECTS_A_4, GO_TELEPORTER_EFFECTS_A, 326.266f, -777.347f, 49.0215f, 3.12412f}, // Teleporter Effects (Alliance) - {BG_IC_GO_TELEPORTER_EFFECTS_A_5, GO_TELEPORTER_EFFECTS_A, 323.55f, -888.347f, 48.9198f, 0.0174525f}, // Teleporter Effects (Alliance) - {BG_IC_GO_TELEPORTER_EFFECTS_A_6, GO_TELEPORTER_EFFECTS_A, 397.116f, -859.378f, 48.8989f, 1.64061f}, // Teleporter Effects (Alliance) - - {BG_IC_GO_TELEPORTER_EFFECTS_H_1, GO_TELEPORTER_EFFECTS_H, 1143.25f, -779.623f, 48.6291f, 1.62316f}, // Teleporter Effects (Horde) - {BG_IC_GO_TELEPORTER_EFFECTS_H_2, GO_TELEPORTER_EFFECTS_H, 1158.64f, -746.148f, 48.6277f, -1.50098f}, // Teleporter Effects (Horde) - {BG_IC_GO_TELEPORTER_EFFECTS_H_3, GO_TELEPORTER_EFFECTS_H, 1233.25f, -844.573f, 48.8836f, 0.0174525f}, // Teleporter Effects (Horde) - {BG_IC_GO_TELEPORTER_EFFECTS_H_4, GO_TELEPORTER_EFFECTS_H, 1235.07f, -857.957f, 48.9163f, 3.05433f}, // Teleporter Effects (Horde) - {BG_IC_GO_TELEPORTER_EFFECTS_H_5, GO_TELEPORTER_EFFECTS_H, 1236.46f, -669.344f, 48.2684f, 0.087266f}, // Teleporter Effects (Horde) - {BG_IC_GO_TELEPORTER_EFFECTS_H_6, GO_TELEPORTER_EFFECTS_H, 1235.6f, -683.806f, 49.3028f, -3.07177f} // Teleporter Effects (Horde) -}; - -const ICGo BG_IC_ObjSpawnlocs[MAX_NORMAL_GAMEOBJECTS_SPAWNS] = -{ - {BG_IC_GO_ALLIANCE_GATE_1, GO_ALLIANCE_GATE_1, 351.615f, -762.75f, 48.9162f, -1.5708f}, // Alliance Gate || Left - {BG_IC_GO_ALLIANCE_GATE_2, GO_ALLIANCE_GATE_2, 351.024f, -903.326f, 48.9247f, 1.5708f}, // Alliance Gate || Right - {BG_IC_GO_ALLIANCE_GATE_3, GO_ALLIANCE_GATE_3, 413.479f, -833.95f, 48.5238f, 3.14159f}, // Alliance Gate || Front - - {BG_IC_GO_HORDE_GATE_1, GO_HORDE_GATE_1, 1150.9f, -762.606f, 47.5077f, 3.14159f}, // Horde Gate || Front - {BG_IC_GO_HORDE_GATE_2, GO_HORDE_GATE_2, 1218.74f, -851.155f, 48.2533f, -1.5708f}, // Horde Gate || Left - {BG_IC_GO_HORDE_GATE_3, GO_HORDE_GATE_3, 1217.9f, -676.948f, 47.6341f, 1.5708f}, // Horde Gate || Right - - {BG_IC_GO_HORDE_BANNER, GO_HORDE_BANNER, 1284.76f, -705.668f, 48.9163f, -3.08918f}, // Horde Banner - {BG_IC_GO_ALLIANCE_BANNER, GO_ALLIANCE_BANNER, 299.153f, -784.589f, 48.9162f, -0.157079f}, // Alliance Banner - - {BG_IC_GO_WORKSHOP_BANNER, GO_WORKSHOP_BANNER, 776.229f, -804.283f, 6.45052f, 1.6057f}, // Workshop Banner - {BG_IC_GO_DOCKS_BANNER, GO_DOCKS_BANNER, 726.385f, -360.205f, 17.8153f, -1.62316f}, // Docks Banner - {BG_IC_GO_HANGAR_BANNER, GO_HANGAR_BANNER, 807.78f, -1000.07f, 132.381f, -1.93732f}, // Hangar Banner - {BG_IC_GO_QUARRY_BANNER, GO_QUARRY_BANNER, 251.016f, -1159.32f, 17.2376f, -2.25147f}, // Quarry Banner - {BG_IC_GO_REFINERY_BANNER, GO_REFINERY_BANNER, 1269.5f, -400.809f, 37.6253f, -1.76278f}, // Refinery Banner - - {BG_IC_GO_BENCH_1, GO_BENCH_1, 834.208f, -461.826f, 22.3067f, 1.5708f}, // Bench - {BG_IC_GO_BENCH_2, GO_BENCH_2, 826.153f, -461.985f, 22.5149f, 1.5708f}, // Bench - {BG_IC_GO_BENCH_3, GO_BENCH_3, 817.446f, -470.47f, 25.372f, -1.56207f}, // Bench - {BG_IC_GO_BENCH_4, GO_BENCH_4, 827.001f, -474.415f, 25.372f, 1.57952f}, // Bench - {BG_IC_GO_BENCH_5, GO_BENCH_5, 819.264f, -461.961f, 22.7614f, 1.57952f}, // Bench - - {BG_IC_GO_BONFIRE_1, GO_BONFIRE_1, 1162.91f, -734.578f, 48.8948f, -2.9845f}, // Bonfire - {BG_IC_GO_BONFIRE_2, GO_BONFIRE_2, 1282.34f, -799.762f, 87.1357f, -3.13286f}, // Bonfire - {BG_IC_GO_BONFIRE_3, GO_BONFIRE_3, 1358.06f, -732.178f, 87.1606f, -3.13284f}, // Bonfire - {BG_IC_GO_BONFIRE_4, GO_BONFIRE_4, 1281.76f, -732.844f, 87.1574f, -3.13246f}, // Bonfire - {BG_IC_GO_BONFIRE_5, GO_BONFIRE_5, 1358.81f, -797.899f, 87.2953f, 3.13312f}, // Bonfire - {BG_IC_GO_BONFIRE_6, GO_BONFIRE_6, 1162.21f, -790.543f, 48.9162f, 2.27765f}, // Bonfire - - {BG_IC_GO_BRAZIER_1, GO_BRAZIER_1, 1262.21f, -751.358f, 48.8133f, 2.26893f}, // Brazier - {BG_IC_GO_BRAZIER_2, GO_BRAZIER_2, 1262.58f, -781.861f, 48.8132f, 2.04203f}, // Brazier - {BG_IC_GO_BRAZIER_3, GO_BRAZIER_3, 223.818f, -839.352f, 60.7917f, 1.09083f}, // Brazier - {BG_IC_GO_BRAZIER_4, GO_BRAZIER_4, 224.277f, -822.77f, 60.7917f, 2.06822f}, // Brazier - - {BG_IC_GO_CHAIR_1, GO_CHAIR_1, 632.876f, -282.461f, 5.45364f, -0.851094f}, // Chair - {BG_IC_GO_CHAIR_2, GO_CHAIR_2, 635.796f, -276.295f, 5.48659f, -3.03273f}, // Chair - {BG_IC_GO_CHAIR_3_1, GO_CHAIR_3, 762.245f, -444.795f, 22.8526f, -1.98095f}, // Chair - {BG_IC_GO_CHAIR_4, GO_CHAIR_4, 632.156f, -304.503f, 5.4879f, 1.15603f}, // Chair - {BG_IC_GO_CHAIR_5, GO_CHAIR_5, 643.86f, -270.204f, 5.48898f, 2.36903f}, // Chair - {BG_IC_GO_CHAIR_6_1, GO_CHAIR_6, 902.234f, -455.508f, 18.3935f, -1.00356f}, // Chair - {BG_IC_GO_CHAIR_7, GO_CHAIR_7, 810.237f, -461.2f, 25.4627f, 1.5708f}, // Chair - {BG_IC_GO_CHAIR_3_2, GO_CHAIR_3, 1117.19f, -365.674f, 18.8456f, 0.968657f}, // Chair - {BG_IC_GO_CHAIR_6_2, GO_CHAIR_6, 1066.19f, -337.214f, 18.8225f, 0.453785f}, // Chair - {BG_IC_GO_CHAIR_8_1, GO_CHAIR_8, 798.324f, -444.951f, 22.5601f, -1.02102f}, // Chair - {BG_IC_GO_CHAIR_8_2, GO_CHAIR_8, 1081.81f, -358.637f, 18.5531f, 1.92859f}, // Chair - {BG_IC_GO_CHAIR_9, GO_CHAIR_9, 814.931f, -470.816f, 33.6373f, -3.12412f}, // Chair - - {BG_IC_GO_DOODAD_HU_PORTCULLIS01_1, GO_DOODAD_HU_PORTCULLIS01, 401.024f, -780.724f, 49.9482f, -2.52896f}, // Doodad_HU_Portcullis01 - {BG_IC_GO_DOODAD_HU_PORTCULLIS01_2, GO_DOODAD_HU_PORTCULLIS01, 399.802f, -885.208f, 50.1939f, 2.516f}, // Doodad_HU_Portcullis01 - - {BG_IC_GO_DOODAD_ND_HUMAN_GATE_CLOSEDFX_DOOR01, GO_DOODAD_ND_HUMAN_GATE_CLOSEDFX_DOOR01, 413.479f, -833.95f, 48.5238f, 3.14159f}, // Doodad_ND_Human_Gate_ClosedFX_Door01 - {BG_IC_GO_DOODAD_ND_HUMAN_GATE_CLOSEDFX_DOOR02, GO_DOODAD_ND_HUMAN_GATE_CLOSEDFX_DOOR01, 351.615f, -762.75f, 48.91625f, 4.71292f}, // Doodad_ND_Human_Gate_ClosedFX_Door01 - {BG_IC_GO_DOODAD_ND_HUMAN_GATE_CLOSEDFX_DOOR03, GO_DOODAD_ND_HUMAN_GATE_CLOSEDFX_DOOR01, 351.024f, -903.33f, 48.92472f, 1.570796f}, // Doodad_ND_Human_Gate_ClosedFX_Door01 - - {BG_IC_GO_DOODAD_PORTCULLISACTIVE01, GO_DOODAD_PORTCULLISACTIVE01, -832.595f, 51.4109f, -0.0261791f, 0.0f}, // Doodad_PortcullisActive01 - - {BG_IC_GO_DOODAD_PORTCULLISACTIVE02, GO_DOODAD_PORTCULLISACTIVE02, 273.033f, -832.199f, 51.4109f, -0.0261791f}, // Doodad_PortcullisActive02 - - {BG_IC_GO_DOODAD_VR_PORTCULLIS01_1, GO_DOODAD_VR_PORTCULLIS01, 1156.89f, -843.998f, 48.6322f, 0.732934f}, // Doodad_VR_Portcullis01 - {BG_IC_GO_DOODAD_VR_PORTCULLIS01_2, GO_DOODAD_VR_PORTCULLIS01, 1157.05f, -682.36f, 48.6322f, -0.829132f}, // Doodad_VR_Portcullis01 - - {BG_IC_GO_FLAGPOLE_1_1, GO_FLAGPOLE_1, -400.809f, 37.6253f, -1.76278f, 0.0f}, // Flagpole - {BG_IC_GO_FLAGPOLE_2_1, GO_FLAGPOLE_2, 1284.76f, -705.668f, 48.9163f, -3.08918f}, // Flagpole - {BG_IC_GO_FLAGPOLE_2_2, GO_FLAGPOLE_2, 299.153f, -784.589f, 48.9162f, -0.157079f}, // Flagpole - {BG_IC_GO_FLAGPOLE_1_2, GO_FLAGPOLE_1, 726.385f, -360.205f, 17.8153f, -1.6057f}, // Flagpole - {BG_IC_GO_FLAGPOLE_1_3, GO_FLAGPOLE_1, 807.78f, -1000.07f, 132.381f, -1.91986f}, // Flagpole - {BG_IC_GO_FLAGPOLE_1_4, GO_FLAGPOLE_1, 776.229f, -804.283f, 6.45052f, 1.6057f}, // Flagpole - {BG_IC_GO_FLAGPOLE_1_5, GO_FLAGPOLE_1, 251.016f, -1159.32f, 17.2376f, -2.25147f}, // Flagpole - {BG_IC_GO_FLAGPOLE_1_6, GO_FLAGPOLE_1, 1269.502f, -400.809f, 37.62525f, -1.762782f}, // Flagpole - - {BG_IC_GO_HORDE_KEEP_PORTCULLIS, GO_HORDE_KEEP_PORTCULLIS, 1283.05f, -765.878f, 50.8297f, -3.13286f}, // Horde Keep Portcullis - - {BG_IC_GO_STOVE_1_1, GO_STOVE_1, 903.291f, -457.345f, 18.1356f, 2.23402f}, // Stove - {BG_IC_GO_STOVE_2_1, GO_STOVE_2, 761.462f, -446.684f, 22.5602f, 0.244344f}, // Stove - {BG_IC_GO_STOVE_1_2, GO_STOVE_1, 11068.13f, -336.373f, 18.5647f, -2.59181f}, // Stove - {BG_IC_GO_STOVE_2_2, GO_STOVE_2, 1118.32f, -363.969f, 18.5532f, -3.08918f}, // Stove - - {BG_IC_GO_HUGE_SEAFORIUM_BOMBS_A_1, GO_HUGE_SEAFORIUM_BOMB_A, 297.3212f, -851.321167f, 48.91627f, -0.94247663f}, - {BG_IC_GO_HUGE_SEAFORIUM_BOMBS_A_2, GO_HUGE_SEAFORIUM_BOMB_A, 298.104156f, -861.026062f, 48.916275f, -2.75761318f}, - {BG_IC_GO_HUGE_SEAFORIUM_BOMBS_A_3, GO_HUGE_SEAFORIUM_BOMB_A, 300.371521f, -818.732666f, 48.91625f, 0.785396755f}, - {BG_IC_GO_HUGE_SEAFORIUM_BOMBS_A_4, GO_HUGE_SEAFORIUM_BOMB_A, 302.1354f, -810.7083f, 48.91625f, -1.04719758f}, - - {BG_IC_GO_HUGE_SEAFORIUM_BOMBS_H_1, GO_HUGE_SEAFORIUM_BOMB_H, 1268.30908f, -745.783f, 48.9187775f, 0.785396755f}, - {BG_IC_GO_HUGE_SEAFORIUM_BOMBS_H_2, GO_HUGE_SEAFORIUM_BOMB_H, 1268.50867f, -738.1215f, 48.9175f, -1.04719758f}, - {BG_IC_GO_HUGE_SEAFORIUM_BOMBS_H_3, GO_HUGE_SEAFORIUM_BOMB_H, 1273.066f, -786.572937f, 48.9419174f, -0.94247663f}, - {BG_IC_GO_HUGE_SEAFORIUM_BOMBS_H_4, GO_HUGE_SEAFORIUM_BOMB_H, 1273.849f, -796.2778f, 48.9364281f, -2.75761318f}, - - {BG_IC_GO_DOODAD_ND_WINTERORC_WALL_GATEFX_DOOR01, GO_DOODAD_ND_WINTERORC_WALL_GATEFX_DOOR01, 1150.903f, -762.6059f, 47.50768f, 3.141593f}, - {BG_IC_GO_DOODAD_ND_WINTERORC_WALL_GATEFX_DOOR02, GO_DOODAD_ND_WINTERORC_WALL_GATEFX_DOOR01, 1217.899f, -676.9479f, 47.63408f, 1.570796f}, - {BG_IC_GO_DOODAD_ND_WINTERORC_WALL_GATEFX_DOOR03, GO_DOODAD_ND_WINTERORC_WALL_GATEFX_DOOR01, 1218.743f, -851.1545f, 48.25328f, 4.712392f} -}; - -const Position workshopBombs[2] = -{ - {750.601f, -864.597f, 13.4754f, 1.93731f}, - {785.509f, -864.715f, 13.3993f, 2.47837f} -}; - enum Spells { SPELL_OIL_REFINERY = 68719, @@ -746,35 +113,30 @@ enum ICWorldStates BG_IC_GATE_WEST_A_WS_OPEN = 4324, BG_IC_GATE_EAST_A_WS_OPEN = 4325, - BG_IC_DOCKS_OWNER = 4235, BG_IC_DOCKS_UNCONTROLLED = 4301, BG_IC_DOCKS_CONFLICT_A = 4305, BG_IC_DOCKS_CONFLICT_H = 4302, BG_IC_DOCKS_CONTROLLED_A = 4304, BG_IC_DOCKS_CONTROLLED_H = 4303, - BG_IC_HANGAR_OWNER = 4234, BG_IC_HANGAR_UNCONTROLLED = 4296, BG_IC_HANGAR_CONFLICT_A = 4300, BG_IC_HANGAR_CONFLICT_H = 4297, BG_IC_HANGAR_CONTROLLED_A = 4299, BG_IC_HANGAR_CONTROLLED_H = 4298, - BG_IC_QUARRY_OWNER = 4289, BG_IC_QUARRY_UNCONTROLLED = 4306, BG_IC_QUARRY_CONFLICT_A = 4310, BG_IC_QUARRY_CONFLICT_H = 4307, BG_IC_QUARRY_CONTROLLED_A = 4309, BG_IC_QUARRY_CONTROLLED_H = 4308, - BG_IC_REFINERY_OWNER = 4287, BG_IC_REFINERY_UNCONTROLLED = 4311, BG_IC_REFINERY_CONFLICT_A = 4315, BG_IC_REFINERY_CONFLICT_H = 4312, BG_IC_REFINERY_CONTROLLED_A = 4314, BG_IC_REFINERY_CONTROLLED_H = 4313, - BG_IC_WORKSHOP_OWNER = 4232, BG_IC_WORKSHOP_UNCONTROLLED = 4294, BG_IC_WORKSHOP_CONFLICT_A = 4228, BG_IC_WORKSHOP_CONFLICT_H = 4293, @@ -827,17 +189,15 @@ enum ICNodePointType MAX_NODE_TYPES }; -enum ICNodeState +enum class IsleOfConquestNodeState { - NODE_STATE_UNCONTROLLED = 0, - NODE_STATE_CONFLICT_A, - NODE_STATE_CONFLICT_H, - NODE_STATE_CONTROLLED_A, - NODE_STATE_CONTROLLED_H + Neutral, + ConflictA, + ConflictH, + ControlledA, + ControlledH }; -const uint32 BG_IC_GraveyardIds[MAX_NODE_TYPES+2] = {0, 0, 1480, 1481, 1482, 1485, 1486, 1483, 1484}; - Position const BG_IC_SpiritGuidePos[MAX_NODE_TYPES+2] = { {0.0f, 0.0f, 0.0f, 0.0f}, // no grave @@ -861,50 +221,96 @@ enum ICBroadcastTexts BG_IC_TEXT_EAST_GATE_ALLIANCE_DESTROYED = 35414 }; -struct ICNodeInfo -{ - uint32 NodeId; - uint32 TextAssaulted; - uint32 TextDefended; - uint32 TextAllianceTaken; - uint32 TextHordeTaken; -}; +// I.E: Hangar, Quarry, Graveyards .. etc +struct IoCStaticNodeInfo +{ + ICNodePointType NodeType; + + struct + { + uint32 Assaulted; + uint32 Defended; + uint32 AllianceTaken; + uint32 HordeTaken; + } TextIds; + + struct + { + int32 Uncontrolled; + int32 ConflictA; + int32 ConflictH; + int32 ControlledA; + int32 ControlledH; + } WorldStateIds; +}; + +class ICNodePoint +{ +public: + explicit ICNodePoint(IsleOfConquestNodeState state, IoCStaticNodeInfo const& nodeInfo) : _state(state), _nodeInfo(nodeInfo) + { + switch (state) + { + case IsleOfConquestNodeState::ControlledH: + _lastControlled = TEAM_HORDE; + break; + case IsleOfConquestNodeState::ControlledA: + _lastControlled = TEAM_ALLIANCE; + break; + case IsleOfConquestNodeState::ConflictA: + case IsleOfConquestNodeState::ConflictH: + case IsleOfConquestNodeState::Neutral: + _lastControlled = TEAM_NEUTRAL; + break; + } + } -ICNodeInfo const ICNodes[MAX_NODE_TYPES] = -{ - { NODE_TYPE_REFINERY, 35377, 35378, 35379, 35380 }, - { NODE_TYPE_QUARRY, 35373, 35374, 35375, 35376 }, - { NODE_TYPE_DOCKS, 35365, 35366, 35367, 35368 }, - { NODE_TYPE_HANGAR, 35369, 35370, 35371, 35372 }, - { NODE_TYPE_WORKSHOP, 35278, 35286, 35279, 35280 }, - { NODE_TYPE_GRAVEYARD_A, 35461, 35459, 35463, 35466 }, - { NODE_TYPE_GRAVEYARD_H, 35462, 35460, 35464, 35465 } -}; + IsleOfConquestNodeState GetState() const { return _state; } -// I.E: Hangar, Quarry, Graveyards .. etc -struct ICNodePoint -{ - uint32 gameobject_type; // with this we will get the GameObject of that point - uint32 gameobject_entry; // what gameobject entry is active here. - TeamId faction; // who has this node - ICNodePointType nodeType; // here we can specify if it is graveyards, hangar etc... - uint32 banners[4]; // the banners that have this point - bool needChange; // this is used for the 1 minute time period after the point is captured - uint32 timer; // the same use for needChange - uint32 last_entry; // the last gameobject_entry - int32 worldStates[6]; // the worldstates that represent the node in the map - ICNodeState nodeState; + bool IsContested() const + { + return _state == IsleOfConquestNodeState::ConflictA || _state == IsleOfConquestNodeState::ConflictH; + } + + TeamId GetLastControlledTeam() const { return _lastControlled; } + + IoCStaticNodeInfo const& GetNodeInfo() const { return _nodeInfo; } + + void UpdateState(IsleOfConquestNodeState state) + { + switch (state) + { + case IsleOfConquestNodeState::ControlledA: + _lastControlled = TEAM_ALLIANCE; + break; + case IsleOfConquestNodeState::ControlledH: + _lastControlled = TEAM_HORDE; + break; + case IsleOfConquestNodeState::Neutral: + _lastControlled = TEAM_NEUTRAL; + break; + case IsleOfConquestNodeState::ConflictA: + case IsleOfConquestNodeState::ConflictH: + break; + } + + _state = state; + } +private: + IsleOfConquestNodeState _state; + TeamId _lastControlled; + IoCStaticNodeInfo _nodeInfo; }; -const ICNodePoint nodePointInitial[MAX_NODE_TYPES] = +const IoCStaticNodeInfo nodePointInitial[MAX_NODE_TYPES] = { - {BG_IC_GO_REFINERY_BANNER, GO_REFINERY_BANNER, TEAM_NEUTRAL, NODE_TYPE_REFINERY, {GO_ALLIANCE_BANNER_REFINERY, GO_ALLIANCE_BANNER_REFINERY_CONT, GO_HORDE_BANNER_REFINERY, GO_HORDE_BANNER_REFINERY_CONT}, false, 0, 0, {BG_IC_REFINERY_UNCONTROLLED, BG_IC_REFINERY_CONFLICT_A, BG_IC_REFINERY_CONFLICT_H, BG_IC_REFINERY_CONTROLLED_A, BG_IC_REFINERY_CONTROLLED_H, BG_IC_REFINERY_OWNER}, NODE_STATE_UNCONTROLLED}, - {BG_IC_GO_QUARRY_BANNER, GO_QUARRY_BANNER, TEAM_NEUTRAL, NODE_TYPE_QUARRY, {GO_ALLIANCE_BANNER_QUARRY, GO_ALLIANCE_BANNER_QUARRY_CONT, GO_HORDE_BANNER_QUARRY, GO_HORDE_BANNER_QUARRY_CONT}, false, 0, 0, {BG_IC_QUARRY_UNCONTROLLED, BG_IC_QUARRY_CONFLICT_A, BG_IC_QUARRY_CONFLICT_H, BG_IC_QUARRY_CONTROLLED_A, BG_IC_QUARRY_CONTROLLED_H, BG_IC_QUARRY_OWNER}, NODE_STATE_UNCONTROLLED}, - {BG_IC_GO_DOCKS_BANNER, GO_DOCKS_BANNER, TEAM_NEUTRAL, NODE_TYPE_DOCKS, {GO_ALLIANCE_BANNER_DOCK, GO_ALLIANCE_BANNER_DOCK_CONT, GO_HORDE_BANNER_DOCK, GO_HORDE_BANNER_DOCK_CONT}, false, 0, 0, {BG_IC_DOCKS_UNCONTROLLED, BG_IC_DOCKS_CONFLICT_A, BG_IC_DOCKS_CONFLICT_H, BG_IC_DOCKS_CONTROLLED_A, BG_IC_DOCKS_CONTROLLED_H, BG_IC_DOCKS_OWNER}, NODE_STATE_UNCONTROLLED}, - {BG_IC_GO_HANGAR_BANNER, GO_HANGAR_BANNER, TEAM_NEUTRAL, NODE_TYPE_HANGAR, {GO_ALLIANCE_BANNER_HANGAR, GO_ALLIANCE_BANNER_HANGAR_CONT, GO_HORDE_BANNER_HANGAR, GO_HORDE_BANNER_HANGAR_CONT}, false, 0, 0, {BG_IC_HANGAR_UNCONTROLLED, BG_IC_HANGAR_CONFLICT_A, BG_IC_HANGAR_CONFLICT_H, BG_IC_HANGAR_CONTROLLED_A, BG_IC_HANGAR_CONTROLLED_H, BG_IC_HANGAR_OWNER}, NODE_STATE_UNCONTROLLED}, - {BG_IC_GO_WORKSHOP_BANNER, GO_WORKSHOP_BANNER, TEAM_NEUTRAL, NODE_TYPE_WORKSHOP, {GO_ALLIANCE_BANNER_WORKSHOP, GO_ALLIANCE_BANNER_WORKSHOP_CONT, GO_HORDE_BANNER_WORKSHOP, GO_HORDE_BANNER_WORKSHOP_CONT}, false, 0, 0, {BG_IC_WORKSHOP_UNCONTROLLED, BG_IC_WORKSHOP_CONFLICT_A, BG_IC_WORKSHOP_CONFLICT_H, BG_IC_WORKSHOP_CONTROLLED_A, BG_IC_WORKSHOP_CONTROLLED_H, BG_IC_WORKSHOP_OWNER}, NODE_STATE_UNCONTROLLED}, - {BG_IC_GO_ALLIANCE_BANNER, GO_ALLIANCE_BANNER, TEAM_ALLIANCE, NODE_TYPE_GRAVEYARD_A, {GO_ALLIANCE_BANNER_GRAVEYARD_A, GO_ALLIANCE_BANNER_GRAVEYARD_A_CONT, GO_HORDE_BANNER_GRAVEYARD_A, GO_HORDE_BANNER_GRAVEYARD_A_CONT}, false, 0, 0, {BG_IC_ALLIANCE_KEEP_UNCONTROLLED, BG_IC_ALLIANCE_KEEP_CONFLICT_A, BG_IC_ALLIANCE_KEEP_CONFLICT_H, BG_IC_ALLIANCE_KEEP_CONTROLLED_A, BG_IC_ALLIANCE_KEEP_CONTROLLED_H, 0}, NODE_STATE_CONTROLLED_A}, - {BG_IC_GO_HORDE_BANNER, GO_HORDE_BANNER, TEAM_HORDE, NODE_TYPE_GRAVEYARD_H, {GO_ALLIANCE_BANNER_GRAVEYARD_H, GO_ALLIANCE_BANNER_GRAVEYARD_H_CONT, GO_HORDE_BANNER_GRAVEYARD_H, GO_HORDE_BANNER_GRAVEYARD_H_CONT}, false, 0, 0, {BG_IC_HORDE_KEEP_UNCONTROLLED, BG_IC_HORDE_KEEP_CONFLICT_A, BG_IC_HORDE_KEEP_CONFLICT_H, BG_IC_HORDE_KEEP_CONTROLLED_A, BG_IC_HORDE_KEEP_CONTROLLED_H, 0}, NODE_STATE_CONTROLLED_H} + { NODE_TYPE_REFINERY, { 35377, 35378, 35379, 35380 }, { BG_IC_REFINERY_UNCONTROLLED, BG_IC_REFINERY_CONFLICT_A, BG_IC_REFINERY_CONFLICT_H, BG_IC_REFINERY_CONTROLLED_A, BG_IC_REFINERY_CONTROLLED_H } }, + { NODE_TYPE_QUARRY, { 35373, 35374, 35375, 35376 }, { BG_IC_QUARRY_UNCONTROLLED, BG_IC_QUARRY_CONFLICT_A, BG_IC_QUARRY_CONFLICT_H, BG_IC_QUARRY_CONTROLLED_A, BG_IC_QUARRY_CONTROLLED_H } }, + { NODE_TYPE_DOCKS, { 35365, 35366, 35367, 35368 }, { BG_IC_DOCKS_UNCONTROLLED, BG_IC_DOCKS_CONFLICT_A, BG_IC_DOCKS_CONFLICT_H, BG_IC_DOCKS_CONTROLLED_A, BG_IC_DOCKS_CONTROLLED_H } }, + { NODE_TYPE_HANGAR, { 35369, 35370, 35371, 35372 }, { BG_IC_HANGAR_UNCONTROLLED, BG_IC_HANGAR_CONFLICT_A, BG_IC_HANGAR_CONFLICT_H, BG_IC_HANGAR_CONTROLLED_A, BG_IC_HANGAR_CONTROLLED_H } }, + { NODE_TYPE_WORKSHOP, { 35278, 35286, 35279, 35280 }, { BG_IC_WORKSHOP_UNCONTROLLED, BG_IC_WORKSHOP_CONFLICT_A, BG_IC_WORKSHOP_CONFLICT_H, BG_IC_WORKSHOP_CONTROLLED_A, BG_IC_WORKSHOP_CONTROLLED_H } }, + { NODE_TYPE_GRAVEYARD_A, { 35461, 35459, 35463, 35466 }, { BG_IC_ALLIANCE_KEEP_UNCONTROLLED, BG_IC_ALLIANCE_KEEP_CONFLICT_A, BG_IC_ALLIANCE_KEEP_CONFLICT_H, BG_IC_ALLIANCE_KEEP_CONTROLLED_A, BG_IC_ALLIANCE_KEEP_CONTROLLED_H } }, + { NODE_TYPE_GRAVEYARD_H, { 35462, 35460, 35464, 35465 }, { BG_IC_HORDE_KEEP_UNCONTROLLED, BG_IC_HORDE_KEEP_CONFLICT_A, BG_IC_HORDE_KEEP_CONFLICT_H, BG_IC_HORDE_KEEP_CONTROLLED_A, BG_IC_HORDE_KEEP_CONTROLLED_H } } }; enum HonorRewards @@ -917,95 +323,54 @@ class BattlegroundIC : public Battleground { public: BattlegroundIC(BattlegroundTemplate const* battlegroundTemplate); - ~BattlegroundIC(); + ~BattlegroundIC() override; /* inherited from BattlegroundClass */ - void AddPlayer(Player* player, BattlegroundQueueTypeId queueId) override; - void StartingEventCloseDoors() override; void StartingEventOpenDoors() override; void PostUpdateImpl(uint32 diff) override; - void RemovePlayer(Player* player, ObjectGuid guid, uint32 team) override; - void HandleAreaTrigger(Player* player, uint32 trigger, bool entered) override; - bool SetupBattleground() override; - void SpawnLeader(uint32 teamid); void HandleKillUnit(Creature* unit, Unit* killer) override; void HandleKillPlayer(Player* player, Player* killer) override; - void EventPlayerClickedOnFlag(Player* source, GameObject* /*target_obj*/) override; - void DestroyGate(Player* player, GameObject* go) override; - - WorldSafeLocsEntry const* GetClosestGraveyard(Player* player) override; WorldSafeLocsEntry const* GetExploitTeleportLocation(Team team) override; - /* Scorekeeping */ - void HandlePlayerResurrect(Player* player) override; - - uint32 GetNodeState(uint8 nodeType) const { return (uint8)nodePoint[nodeType].nodeState; } + void OnCreatureCreate(Creature* creature) override; + void OnGameObjectCreate(GameObject* gameobject) override; + void OnMapSet(BattlegroundMap* map) override; - bool IsSpellAllowed(uint32 spellId, Player const* player) const override; + void DoAction(uint32 actionId, WorldObject* source, WorldObject* target) override; + void OnPlayerInteractWithBanner(Player* player, GameObject* banner); + void OnPlayerAssaultNode(Player* player, ICNodePoint& node); + void OnPlayerDefendNode(Player* player, ICNodePoint& node); + void ProcessEvent(WorldObject* target, uint32 eventId, WorldObject* invoker) override; private: - uint32 closeFortressDoorsTimer; - bool doorsClosed; - uint32 docksTimer; - uint32 resourceTimer; - uint32 siegeEngineWorkshopTimer; - uint16 factionReinforcements[2]; - BG_IC_GateState GateStatus[6]; - ICNodePoint nodePoint[7]; - - Transport* gunshipAlliance; - Transport* gunshipHorde; - - uint32 GetNextBanner(ICNodePoint* node, uint32 team, bool returnDefinitve); - - uint32 GetGateIDFromEntry(uint32 id) - { - uint32 i = 0; - switch (id) - { - case GO_HORDE_GATE_1: i = BG_IC_H_FRONT ;break; - case GO_HORDE_GATE_2: i = BG_IC_H_WEST ;break; - case GO_HORDE_GATE_3: i = BG_IC_H_EAST ;break; - case GO_ALLIANCE_GATE_3: i = BG_IC_A_FRONT ;break; - case GO_ALLIANCE_GATE_1: i = BG_IC_A_WEST ;break; - case GO_ALLIANCE_GATE_2: i = BG_IC_A_EAST ;break; - } - return i; - } - - int32 GetWorldStateFromGateEntry(uint32 id, bool open) - { - int32 uws = 0; - - switch (id) - { - case GO_HORDE_GATE_1: - uws = (open ? BG_IC_GATE_FRONT_H_WS_OPEN : BG_IC_GATE_FRONT_H_WS_CLOSED); - break; - case GO_HORDE_GATE_2: - uws = (open ? BG_IC_GATE_WEST_H_WS_OPEN : BG_IC_GATE_WEST_H_WS_CLOSED); - break; - case GO_HORDE_GATE_3: - uws = (open ? BG_IC_GATE_EAST_H_WS_OPEN : BG_IC_GATE_EAST_H_WS_CLOSED); - break; - case GO_ALLIANCE_GATE_3: - uws = (open ? BG_IC_GATE_FRONT_A_WS_OPEN : BG_IC_GATE_FRONT_A_WS_CLOSED); - break; - case GO_ALLIANCE_GATE_1: - uws = (open ? BG_IC_GATE_WEST_A_WS_OPEN : BG_IC_GATE_WEST_A_WS_CLOSED); - break; - case GO_ALLIANCE_GATE_2: - uws = (open ? BG_IC_GATE_EAST_A_WS_OPEN : BG_IC_GATE_EAST_A_WS_CLOSED); - break; - } - return uws; - } - - void UpdateNodeWorldState(ICNodePoint* node); - void HandleCapturedNodes(ICNodePoint* node, bool recapture); - void HandleContestedNodes(ICNodePoint* node); + std::array<uint16, PVP_TEAMS_COUNT> _factionReinforcements; + std::array<BG_IC_GateState, 6> _gateStatus; + std::array<std::unique_ptr<ICNodePoint>, 7> _nodePoints; + std::array<ObjectGuid, PVP_TEAMS_COUNT> _gunshipGUIDs; + GuidVector _teleporterGUIDs; + GuidVector _teleporterEffectGUIDs; + GuidVector _mainGateDoorGUIDs; + GuidVector _portcullisGUIDs; + GuidVector _wallGUIDs; + std::array<GuidVector, PVP_TEAMS_COUNT> _cannonGUIDs; + std::array<GuidVector, PVP_TEAMS_COUNT> _keepGateGUIDs; + std::array<ObjectGuid, PVP_TEAMS_COUNT> _keepBannerGUIDs; + ObjectGuid _gunshipTeleportTarget; + + TaskScheduler _scheduler; + TimeTracker _resourceTimer; + + static uint32 GetGateIDFromEntry(uint32 id); + static int32 GetWorldStateFromGateEntry(uint32 id, bool open); + + void UpdateNodeWorldState(ICNodePoint const& node); + void HandleCapturedNodes(ICNodePoint& node); + void HandleCaptureNodeAction(GameObject* banner); + void OnGateDestroyed(GameObject* gate, WorldObject* destroyer); + + static ICNodePointType BannerToNodeType(uint32 bannerId); }; #endif diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index ecbba144f33..9425c36e836 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -1580,19 +1580,7 @@ void Spell::EffectOpenLock() if (goInfo->GetNoDamageImmune() && player->HasUnitFlag(UNIT_FLAG_IMMUNE)) return; - // Arathi Basin banner opening. /// @todo Verify correctness of this check - if (gameObjTarget->GetMapId() != 30 && gameObjTarget->GetMapId() != 607 && ((goInfo->type == GAMEOBJECT_TYPE_BUTTON && goInfo->button.noDamageImmune) || - (goInfo->type == GAMEOBJECT_TYPE_GOOBER && goInfo->goober.requireLOS))) - { - //CanUseBattlegroundObject() already called in CheckCast() - // in battleground check - if (Battleground* bg = player->GetBattleground()) - { - bg->EventPlayerClickedOnFlag(player, gameObjTarget); - return; - } - } - else if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND) + if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND) { //CanUseBattlegroundObject() already called in CheckCast() // in battleground check diff --git a/src/server/scripts/Northrend/IsleOfConquest/isle_of_conquest.cpp b/src/server/scripts/Northrend/IsleOfConquest/isle_of_conquest.cpp index 86942296681..1492335ce15 100644 --- a/src/server/scripts/Northrend/IsleOfConquest/isle_of_conquest.cpp +++ b/src/server/scripts/Northrend/IsleOfConquest/isle_of_conquest.cpp @@ -18,6 +18,7 @@ #include "ScriptMgr.h" #include "BattlegroundIC.h" #include "GameObject.h" +#include "GameObjectAI.h" #include "Map.h" #include "MotionMaster.h" #include "ObjectAccessor.h" @@ -27,6 +28,7 @@ #include "SpellInfo.h" #include "SpellScript.h" #include "Vehicle.h" +#include "WorldStateMgr.h" // TO-DO: This should be done with SmartAI, but yet it does not correctly support vehicles's AIs. // Even adding ReactState Passive we still have issues using SmartAI. @@ -81,13 +83,10 @@ struct npc_ioc_gunship_captain : public ScriptedAI { npc_ioc_gunship_captain(Creature* creature) : ScriptedAI(creature) { } - void DoAction(int32 action) override + void JustAppeared() override { - if (action == ACTION_GUNSHIP_READY) - { - DoCast(me, SPELL_SIMPLE_TELEPORT); - _events.ScheduleEvent(EVENT_TALK, 3s); - } + DoCast(me, SPELL_SIMPLE_TELEPORT); + _events.ScheduleEvent(EVENT_TALK, 3s); } void UpdateAI(uint32 diff) override @@ -103,9 +102,7 @@ struct npc_ioc_gunship_captain : public ScriptedAI DoCast(me, SPELL_TELEPORT_VISUAL_ONLY); break; case EVENT_DESPAWN: - if (BattlegroundMap* iocMap = me->GetMap()->ToBattlegroundMap()) - if (Battleground* bgIoC = iocMap->GetBG()) - bgIoC->DelCreature(BG_IC_NPC_GUNSHIP_CAPTAIN_1); + me->DespawnOrUnsummon(); break; default: break; @@ -117,6 +114,89 @@ private: EventMap _events; }; +struct npc_ioc_siege_engine : public ScriptedAI +{ + npc_ioc_siege_engine(Creature* creature) : ScriptedAI(creature) { } + + static constexpr uint32 SPELL_DAMAGED = 67323; + static constexpr uint32 VEHICLE_REC_ID = 514; + static constexpr int32 ACTION_REPAIRED = 1; + + void JustAppeared() override + { + me->RemoveVehicleKit(false); + DoCastSelf(SPELL_DAMAGED); + } + + void DoAction(int32 actionId) override + { + // there should be some moving involved first + if (actionId == ACTION_REPAIRED) + { + me->CreateVehicleKit(VEHICLE_REC_ID, me->GetEntry(), false); + me->GetVehicleKit()->InstallAllAccessories(false); + } + } +}; + +struct go_ioc_capturable_object : public GameObjectAI +{ + go_ioc_capturable_object(GameObject* go) : GameObjectAI(go) { } + + bool OnGossipHello(Player* player) override + { + if (me->GetGoState() != GO_STATE_READY || me->HasFlag(GO_FLAG_NOT_SELECTABLE)) + return true; + + if (ZoneScript* zonescript = me->GetZoneScript()) + { + zonescript->DoAction(ACTION_IOC_INTERACT_CAPTURABLE_OBJECT, player, me); + return false; + } + + return true; + } +}; + +struct go_ioc_contested_object : public go_ioc_capturable_object +{ + go_ioc_contested_object(GameObject* go) : go_ioc_capturable_object(go) { } + + void Reset() override + { + go_ioc_capturable_object::Reset(); + _scheduler.Schedule(1min, [&](TaskContext) + { + if (ZoneScript* zonescript = me->GetZoneScript()) + zonescript->DoAction(ACTION_IOC_CAPTURE_CAPTURABLE_OBJECT, me, me); + }); + } + + void UpdateAI(uint32 diff) override + { + _scheduler.Update(diff); + } + +private: + TaskScheduler _scheduler; +}; + +// 67323 - Damaged +class spell_ioc_damaged : public AuraScript +{ + void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) const + { + if (Creature const* creatureTarget = GetTarget()->ToCreature()) + if (UnitAI* ai = creatureTarget->GetAI()) + ai->DoAction(npc_ioc_siege_engine::ACTION_REPAIRED); + } + + void Register() override + { + OnEffectRemove += AuraEffectRemoveFn(spell_ioc_damaged::HandleRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } +}; + // 66630 - Alliance Gunship Portal // 66637 - Horde Gunship Portal class spell_ioc_gunship_portal : public SpellScript @@ -246,12 +326,67 @@ class spell_ioc_seaforium_blast_credit : public SpellScript } }; +class at_ioc_exploit : public AreaTriggerScript +{ +public: + at_ioc_exploit() : AreaTriggerScript("at_ioc_exploit") { } + + bool OnExit(Player* player, AreaTriggerEntry const* /*trigger*/) override + { + if (Battleground* battleground = player->GetBattleground()) + if (battleground->GetStatus() == STATUS_WAIT_JOIN) + battleground->TeleportPlayerToExploitLocation(player); + + return true; + } +}; + +class at_ioc_backdoor_job : public AreaTriggerScript +{ +public: + static constexpr uint32 AT_HORDE_KEEP = 5535; + static constexpr uint32 AT_ALLIANCE_KEEP = 5536; + + at_ioc_backdoor_job() : AreaTriggerScript("at_ioc_backdoor_job") { } + + bool OnTrigger(Player* player, AreaTriggerEntry const* trigger) override + { + /// @hack: this spell should be cast by npc 22515 (World Trigger) and not by the player + if (player->GetBGTeam() == HORDE && trigger->ID == AT_ALLIANCE_KEEP) + { + bool keepClosed = sWorldStateMgr->GetValue(BG_IC_GATE_EAST_A_WS_CLOSED, player->GetMap()) == 1 + && sWorldStateMgr->GetValue(BG_IC_GATE_WEST_A_WS_CLOSED, player->GetMap()) == 1 + && sWorldStateMgr->GetValue(BG_IC_GATE_FRONT_A_WS_CLOSED, player->GetMap()) == 1; + + if (keepClosed) + player->CastSpell(player, SPELL_BACK_DOOR_JOB_ACHIEVEMENT, true); + } + else if (player->GetBGTeam() == ALLIANCE && trigger->ID == AT_HORDE_KEEP) + { + bool keepClosed = sWorldStateMgr->GetValue(BG_IC_GATE_EAST_H_WS_CLOSED, player->GetMap()) == 1 + && sWorldStateMgr->GetValue(BG_IC_GATE_WEST_H_WS_CLOSED, player->GetMap()) == 1 + && sWorldStateMgr->GetValue(BG_IC_GATE_FRONT_H_WS_CLOSED, player->GetMap()) == 1; + + if (keepClosed) + player->CastSpell(player, SPELL_BACK_DOOR_JOB_ACHIEVEMENT, true); + } + + return true; + } +}; + void AddSC_isle_of_conquest() { RegisterCreatureAI(npc_four_car_garage); RegisterCreatureAI(npc_ioc_gunship_captain); + RegisterCreatureAI(npc_ioc_siege_engine); + RegisterGameObjectAI(go_ioc_capturable_object); + RegisterGameObjectAI(go_ioc_contested_object); + RegisterSpellScript(spell_ioc_damaged); RegisterSpellScript(spell_ioc_gunship_portal); RegisterSpellScript(spell_ioc_parachute_ic); RegisterSpellScript(spell_ioc_launch); RegisterSpellScript(spell_ioc_seaforium_blast_credit); + new at_ioc_exploit(); + new at_ioc_backdoor_job(); } |