/* * Copyright (C) 2008-2011 TrinityCore * Copyright (C) 2005-2009 MaNGOS * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include "Player.h" #include "Battleground.h" #include "BattlegroundIC.h" #include "Language.h" #include "WorldPacket.h" #include "GameObject.h" #include "ObjectMgr.h" #include "Vehicle.h" #include "Transport.h" BattlegroundIC::BattlegroundIC() { m_BgObjects.resize(MAX_NORMAL_GAMEOBJECTS_SPAWNS + MAX_AIRSHIPS_SPAWNS + MAX_HANGAR_TELEPORTERS_SPAWNS + MAX_FORTRESS_TELEPORTERS_SPAWNS); m_BgCreatures.resize(MAX_NORMAL_NPCS_SPAWNS + MAX_WORKSHOP_SPAWNS + MAX_DOCKS_SPAWNS + MAX_SPIRIT_GUIDES_SPAWNS); m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_IC_START_TWO_MINUTES; m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_IC_START_ONE_MINUTE; m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_IC_START_HALF_MINUTE; m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_IC_HAS_BEGUN; 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; closeFortressDoorsTimer = CLOSE_DOORS_TIME; // the doors are closed again... in a special way doorsClosed = false; resourceTimer = IC_RESOURCE_TIME; for (uint8 i = NODE_TYPE_REFINERY; i < MAX_NODE_TYPES; i++) nodePoint[i] = nodePointInitial[i]; siegeEngineWorkshopTimer = WORKSHOP_UPDATE_TIME; gunshipHorde = NULL; gunshipAlliance = NULL; } BattlegroundIC::~BattlegroundIC() { } void BattlegroundIC::HandlePlayerResurrect(Player* player) { if (nodePoint[NODE_TYPE_QUARRY].nodeState == (player->GetTeamId() == TEAM_ALLIANCE ? NODE_STATE_CONTROLLED_A : NODE_STATE_CONTROLLED_H)) player->CastSpell(player,SPELL_QUARRY,true); if (nodePoint[NODE_TYPE_REFINERY].nodeState == (player->GetTeamId() == TEAM_ALLIANCE ? NODE_STATE_CONTROLLED_A : NODE_STATE_CONTROLLED_H)) player->CastSpell(player,SPELL_OIL_REFINERY,true); } void BattlegroundIC::SendTransportInit(Player* player) { if (!gunshipAlliance || !gunshipHorde) return; UpdateData transData; gunshipAlliance->BuildCreateUpdateBlockForPlayer(&transData, player); gunshipHorde->BuildCreateUpdateBlockForPlayer(&transData, player); WorldPacket packet; transData.BuildPacket(&packet); player->GetSession()->SendPacket(&packet); } void BattlegroundIC::DoAction(uint32 action, uint64 var) { if (action != ACTION_TELEPORT_PLAYER_TO_TRANSPORT) return; Player* plr = sObjectMgr->GetPlayer(var); if (!plr || !gunshipAlliance || !gunshipHorde) return; plr->CastSpell(plr,SPELL_PARACHUTE,true); // this must be changed, there is a trigger in each transport that casts the spell. plr->CastSpell(plr,SPELL_SLOW_FALL,true); plr->SetTransport(plr->GetTeamId() == TEAM_ALLIANCE ? gunshipAlliance : gunshipHorde); plr->m_movementInfo.t_pos.m_positionX = TransportMovementInfo.GetPositionX(); plr->m_movementInfo.t_pos.m_positionY = TransportMovementInfo.GetPositionY(); plr->m_movementInfo.t_pos.m_positionZ = TransportMovementInfo.GetPositionZ(); plr->m_movementInfo.t_guid = (plr->GetTeamId() == TEAM_ALLIANCE ? gunshipAlliance : gunshipHorde)->GetGUID(); plr->TeleportTo(GetMapId(),TeleportToTransportPosition.GetPositionX(),TeleportToTransportPosition.GetPositionY(),TeleportToTransportPosition.GetPositionZ(),TeleportToTransportPosition.GetOrientation(),TELE_TO_NOT_LEAVE_TRANSPORT); } void BattlegroundIC::Update(uint32 diff) { Battleground::Update(diff); if (GetStatus() != STATUS_IN_PROGRESS) return; if (!doorsClosed) { if (closeFortressDoorsTimer <= diff) { GetBGObject(BG_IC_GO_DOODAD_ND_HUMAN_GATE_CLOSEDFX_DOOR01)->RemoveFromWorld(); GetBGObject(BG_IC_GO_DOODAD_ND_WINTERORC_WALL_GATEFX_DOOR01)->RemoveFromWorld(); GetBGObject(BG_IC_GO_ALLIANCE_GATE_3)->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED); // Alliance door GetBGObject(BG_IC_GO_HORDE_GATE_1)->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED); // Horde door 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 (nodePoint[i].timer <= 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 nodePoint[i].timer -= 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->HasFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_UNK_14|UNIT_FLAG_OOC_NOT_ATTACKABLE)) // following sniffs the vehicle always has UNIT_FLAG_UNK_14 siege->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_OOC_NOT_ATTACKABLE); else siege->SetHealth(siege->GetMaxHealth()); } else siege->Respawn(true); } // 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_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 his 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)->SetUInt32Value(GAMEOBJECT_FACTION, nodePoint[i].faction == TEAM_ALLIANCE ? BG_IC_Factions[1] : BG_IC_Factions[0]); UpdateNodeWorldState(&nodePoint[i]); HandleCapturedNodes(&nodePoint[i],false); SendMessage2ToAll(LANG_BG_IC_TEAM_HAS_TAKEN_NODE,CHAT_MSG_BG_SYSTEM_NEUTRAL,NULL,(nodePoint[i].faction == TEAM_ALLIANCE ? LANG_BG_IC_ALLIANCE : LANG_BG_IC_HORDE),nodePoint[i].string); nodePoint[i].needChange = false; nodePoint[i].timer = BANNER_STATE_CHANGE_TIME; } else nodePoint[i].timer -= diff; } } if (resourceTimer <= diff) { for (uint8 i = 0; i < NODE_TYPE_DOCKS; i++) { if (nodePoint[i].nodeState == NODE_STATE_CONTROLLED_A || nodePoint[i].nodeState == NODE_STATE_CONTROLLED_H) { 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_RENFORT : BG_IC_HORDE_RENFORT), factionReinforcements[nodePoint[i].faction]); } } resourceTimer = IC_RESOURCE_TIME; } else resourceTimer -= diff; } void BattlegroundIC::StartingEventCloseDoors() { // Show Full Gate Displays GetBGObject(BG_IC_GO_ALLIANCE_GATE_1)->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED); // Alliance door GetBGObject(BG_IC_GO_ALLIANCE_GATE_2)->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED); // Alliance door GetBGObject(BG_IC_GO_HORDE_GATE_2)->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED); // Horde door GetBGObject(BG_IC_GO_HORDE_GATE_3)->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED); // Horde door } 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_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++) { 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)) sLog->outError("Isle of Conquest | Starting Event Open Doors: There was an error spawning gameobject %u",BG_IC_Teleporters[i].entry); } } bool BattlegroundIC::IsAllNodesConrolledByTeam(uint32 team) const { uint32 count = 0; ICNodeState controlledState = team == ALLIANCE ? NODE_STATE_CONTROLLED_A : NODE_STATE_CONTROLLED_H; for (int i = 0; i < NODE_TYPE_WORKSHOP; ++i) { if (nodePoint[i].nodeState == controlledState) count++; } return count == NODE_TYPE_WORKSHOP; } void BattlegroundIC::AddPlayer(Player *plr) { Battleground::AddPlayer(plr); //create score and add it to map, default values are set in constructor BattlegroundICScore* sc = new BattlegroundICScore; m_PlayerScores[plr->GetGUID()] = sc; if (nodePoint[NODE_TYPE_QUARRY].nodeState == (plr->GetTeamId() == TEAM_ALLIANCE ? NODE_STATE_CONTROLLED_A : NODE_STATE_CONTROLLED_H)) plr->CastSpell(plr,SPELL_QUARRY,true); if (nodePoint[NODE_TYPE_REFINERY].nodeState == (plr->GetTeamId() == TEAM_ALLIANCE ? NODE_STATE_CONTROLLED_A : NODE_STATE_CONTROLLED_H)) plr->CastSpell(plr,SPELL_OIL_REFINERY,true); SendTransportInit(plr); } void BattlegroundIC::RemovePlayer(Player* plr, uint64 /*guid*/) { plr->RemoveAura(SPELL_QUARRY); plr->RemoveAura(SPELL_OIL_REFINERY); } void BattlegroundIC::HandleAreaTrigger(Player * /*Source*/, uint32 /*Trigger*/) { // this is wrong way to implement these things. On official it done by gameobject spell cast. if (GetStatus() != STATUS_IN_PROGRESS) return; } void BattlegroundIC::UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor) { std::map::iterator itr = m_PlayerScores.find(Source->GetGUID()); if (itr == m_PlayerScores.end()) // player not found... return; switch(type) { case SCORE_BASE_ASSAULTED: ((BattlegroundICScore*)itr->second)->BasesAssaulted += value; break; case SCORE_BASE_DEFENDED: ((BattlegroundICScore*)itr->second)->BasesDefended += value; break; default: Battleground::UpdatePlayerScore(Source,type,value, doAddHonor); break; } } void BattlegroundIC::FillInitialWorldStates(WorldPacket& data) { data << uint32(BG_IC_ALLIANCE_RENFORT_SET) << uint32(1); data << uint32(BG_IC_HORDE_RENFORT_SET) << uint32(1); data << uint32(BG_IC_ALLIANCE_RENFORT) << uint32(factionReinforcements[TEAM_ALLIANCE]); data << uint32(BG_IC_HORDE_RENFORT) << uint32(factionReinforcements[TEAM_HORDE]); for (uint8 i = 0; i < MAX_FORTRESS_GATES_SPAWNS; i++) { uint32 uws = GetWorldStateFromGateEntry(BG_IC_ObjSpawnlocs[i].entry,(GateStatus[GetGateIDFromEntry(BG_IC_ObjSpawnlocs[i].entry)] == BG_IC_GATE_DESTROYED ? true : false)); data << uint32(uws) << uint32(1); } for (uint8 i = 0 ; i < MAX_NODE_TYPES ; i++) data << uint32(nodePoint[i].worldStates[nodePoint[i].nodeState]) << uint32(1); } bool BattlegroundIC::SetupBattleground() { for (uint8 i = 0; i < MAX_NORMAL_GAMEOBJECTS_SPAWNS; i++) { 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)) { sLog->outError("Isle of Conquest: There was an error spawning gameobject %u",BG_IC_ObjSpawnlocs[i].entry); return false; } } for (uint8 i = 0; i < MAX_NORMAL_NPCS_SPAWNS; i++) { if (!AddCreature(BG_IC_NpcSpawnlocs[i].entry,BG_IC_NpcSpawnlocs[i].type,BG_IC_NpcSpawnlocs[i].team, BG_IC_NpcSpawnlocs[i].x,BG_IC_NpcSpawnlocs[i].y, BG_IC_NpcSpawnlocs[i].z,BG_IC_NpcSpawnlocs[i].o, RESPAWN_ONE_DAY)) { sLog->outError("Isle of Conquest: There was an error spawning creature %u",BG_IC_NpcSpawnlocs[i].entry); return false; } } if (!AddSpiritGuide(BG_IC_NPC_SPIRIT_GUIDE_1+5,BG_IC_SpiritGuidePos[5][0], BG_IC_SpiritGuidePos[5][1],BG_IC_SpiritGuidePos[5][2], BG_IC_SpiritGuidePos[5][3],ALLIANCE) || !AddSpiritGuide(BG_IC_NPC_SPIRIT_GUIDE_1+6,BG_IC_SpiritGuidePos[6][0], BG_IC_SpiritGuidePos[6][1],BG_IC_SpiritGuidePos[6][2], BG_IC_SpiritGuidePos[6][3],HORDE) || !AddSpiritGuide(BG_IC_NPC_SPIRIT_GUIDE_1+3,BG_IC_SpiritGuidePos[7][0], BG_IC_SpiritGuidePos[7][1],BG_IC_SpiritGuidePos[7][2], BG_IC_SpiritGuidePos[7][3],ALLIANCE) || !AddSpiritGuide(BG_IC_NPC_SPIRIT_GUIDE_1+4,BG_IC_SpiritGuidePos[8][0], BG_IC_SpiritGuidePos[8][1],BG_IC_SpiritGuidePos[8][2], BG_IC_SpiritGuidePos[8][3],HORDE)) { sLog->outError("Isle of Conquest: Failed to spawn initial spirit guide!"); return false; } gunshipHorde = CreateTransport(GO_HORDE_GUNSHIP,TRANSPORT_PERIOD_TIME); gunshipAlliance = CreateTransport(GO_ALLIANCE_GUNSHIP,TRANSPORT_PERIOD_TIME); if (!gunshipAlliance || !gunshipHorde) { sLog->outError("Isle of Conquest: There was an error creating gunships!"); return false; } //Send transport init packet to all player in map for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end();itr++) { if (Player* player = sObjectMgr->GetPlayer(itr->first)) SendTransportInit(player); } // 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_25; 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; } void BattlegroundIC::HandleKillUnit(Creature *unit, Player* killer) { if (GetStatus() != STATUS_IN_PROGRESS) return; uint32 entry = unit->GetEntry(); if (entry == NPC_HIGH_COMMANDER_HALFORD_WYRMBANE) { RewardHonorToTeam(WINNER_HONOR_AMOUNT,HORDE); EndBattleground(HORDE); } else if (entry == NPC_OVERLORD_AGMAR) { RewardHonorToTeam(WINNER_HONOR_AMOUNT,ALLIANCE); EndBattleground(ALLIANCE); } //Achievement Mowed Down // TO-DO: This should be done on the script of each vehicle of the BG. if (unit->IsVehicle()) killer->CastSpell(killer,SPELL_DESTROYED_VEHICLE_ACHIEVEMENT,true); } void BattlegroundIC::HandleKillPlayer(Player* player, Player* killer) { if (GetStatus() != STATUS_IN_PROGRESS) return; Battleground::HandleKillPlayer(player, killer); factionReinforcements[player->GetTeamId()] -= 1; UpdateWorldState((player->GetTeamId() == TEAM_ALLIANCE ? BG_IC_ALLIANCE_RENFORT : BG_IC_HORDE_RENFORT), factionReinforcements[player->GetTeamId()]); // we must end the battleground if (factionReinforcements[player->GetTeamId()] < 1) EndBattleground(killer->GetTeam()); } void BattlegroundIC::EndBattleground(uint32 winner) { SendMessage2ToAll(LANG_BG_IC_TEAM_WINS,CHAT_MSG_BG_SYSTEM_NEUTRAL,NULL, (winner == ALLIANCE ? LANG_BG_IC_ALLIANCE : LANG_BG_IC_HORDE)); Battleground::EndBattleground(winner); } void BattlegroundIC::RealocatePlayers(ICNodePointType nodeType) { // Those who are waiting to resurrect at this node are taken to the closest own node's graveyard std::vector ghost_list = m_ReviveQueue[m_BgCreatures[BG_IC_NPC_SPIRIT_GUIDE_1+nodeType-2]]; if (!ghost_list.empty()) { WorldSafeLocsEntry const *ClosestGrave = NULL; for (std::vector::const_iterator itr = ghost_list.begin(); itr != ghost_list.end(); ++itr) { Player* plr = sObjectMgr->GetPlayer(*itr); if (!plr) continue; if (!ClosestGrave) // cache ClosestGrave = GetClosestGraveYard(plr); if (ClosestGrave) plr->TeleportTo(GetMapId(), ClosestGrave->x, ClosestGrave->y, ClosestGrave->z, plr->GetOrientation()); } } } void BattlegroundIC::EventPlayerClickedOnFlag(Player* player, GameObject* target_obj) { 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++) { if (nodePoint[i].gameobject_entry == target_obj->GetEntry()) { // THIS SHOULD NEEVEER HAPPEN if (nodePoint[i].faction == player->GetTeamId()) return; uint32 nextBanner = GetNextBanner(&nodePoint[i],player->GetTeamId(),false); // we set the new settings of the nodePoint nodePoint[i].faction = player->GetTeamId(); nodePoint[i].last_entry = nodePoint[i].gameobject_entry; nodePoint[i].gameobject_entry = nextBanner; // 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; RealocatePlayers(nodePoint[i].nodeType); // if we are here means that the point has been lost, or it is the first capture if (nodePoint[i].nodeType != NODE_TYPE_REFINERY && nodePoint[i].nodeType != NODE_TYPE_QUARRY) if (m_BgCreatures[BG_IC_NPC_SPIRIT_GUIDE_1+(nodePoint[i].nodeType)-2]) DelCreature(BG_IC_NPC_SPIRIT_GUIDE_1+(nodePoint[i].nodeType)-2); UpdatePlayerScore(player, SCORE_BASE_ASSAULTED, 1); SendMessage2ToAll(LANG_BG_IC_TEAM_ASSAULTED_NODE_1,CHAT_MSG_BG_SYSTEM_NEUTRAL,player,nodePoint[i].string); SendMessage2ToAll(LANG_BG_IC_TEAM_ASSAULTED_NODE_2,CHAT_MSG_BG_SYSTEM_NEUTRAL,player,nodePoint[i].string, (player->GetTeamId() == TEAM_ALLIANCE ? LANG_BG_IC_ALLIANCE : LANG_BG_IC_HORDE)); HandleContestedNodes(&nodePoint[i]); } 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; SendMessage2ToAll(LANG_BG_IC_TEAM_DEFENDED_NODE,CHAT_MSG_BG_SYSTEM_NEUTRAL,player,nodePoint[i].string); HandleCapturedNodes(&nodePoint[i],true); UpdatePlayerScore(player, SCORE_BASE_DEFENDED, 1); } 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)->SetUInt32Value(GAMEOBJECT_FACTION, nodePoint[i].faction == TEAM_ALLIANCE ? BG_IC_Factions[1] : BG_IC_Factions[0]); if (nodePoint[i].nodeType == NODE_TYPE_WORKSHOP) { DelObject(BG_IC_GO_SEAFORIUM_BOMBS_1); DelObject(BG_IC_GO_SEAFORIUM_BOMBS_2); } 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; } } } void BattlegroundIC::UpdateNodeWorldState(ICNodePoint* nodePoint) { //updating worldstate if (nodePoint->gameobject_entry == nodePoint->banners[BANNER_A_CONTROLLED]) nodePoint->nodeState = NODE_STATE_CONTROLLED_A; else if (nodePoint->gameobject_entry == nodePoint->banners[BANNER_A_CONTESTED]) nodePoint->nodeState = NODE_STATE_CONFLICT_A; else if (nodePoint->gameobject_entry == nodePoint->banners[BANNER_H_CONTROLLED]) nodePoint->nodeState = NODE_STATE_CONTROLLED_H; else if (nodePoint->gameobject_entry == nodePoint->banners[BANNER_H_CONTESTED]) nodePoint->nodeState = NODE_STATE_CONFLICT_H; uint32 worldstate = nodePoint->worldStates[nodePoint->nodeState]; // with this we are sure we dont bug the client for (uint8 i = 0; i < 4; i++) UpdateWorldState(nodePoint->worldStates[i],0); UpdateWorldState(worldstate,1); } uint32 BattlegroundIC::GetNextBanner(ICNodePoint* nodePoint, uint32 team, bool returnDefinitve) { // 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 nodePoint->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 (nodePoint->last_entry == 0) // 1 returns the CONTESTED ALLIANCE BANNER, 3 returns the HORDE one return nodePoint->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 (nodePoint->gameobject_entry == nodePoint->banners[BANNER_A_CONTROLLED] || nodePoint->gameobject_entry == nodePoint->banners[BANNER_H_CONTROLLED]) return nodePoint->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 (nodePoint->gameobject_entry == nodePoint->banners[BANNER_A_CONTESTED] || nodePoint->banners[BANNER_H_CONTESTED]) return nodePoint->last_entry; // we should never be here... sLog->outError("Isle Of Conquest: Unexpected return in GetNextBanner function"); return 0; } void BattlegroundIC::HandleContestedNodes(ICNodePoint* nodePoint) { if (nodePoint->nodeType == NODE_TYPE_HANGAR) { if (gunshipAlliance && gunshipHorde) (nodePoint->faction == TEAM_ALLIANCE ? gunshipHorde : gunshipAlliance)->BuildStopMovePacket(GetBgMap()); for (uint8 u = BG_IC_GO_HANGAR_TELEPORTER_1; u < BG_IC_GO_HANGAR_TELEPORTER_3; u++) DelObject(u); } } void BattlegroundIC::HandleCapturedNodes(ICNodePoint* nodePoint, bool recapture) { if(nodePoint->nodeType != NODE_TYPE_REFINERY && nodePoint->nodeType != NODE_TYPE_QUARRY) { if (!AddSpiritGuide(BG_IC_NPC_SPIRIT_GUIDE_1+nodePoint->nodeType-2, BG_IC_SpiritGuidePos[nodePoint->nodeType][0], BG_IC_SpiritGuidePos[nodePoint->nodeType][1], BG_IC_SpiritGuidePos[nodePoint->nodeType][2], BG_IC_SpiritGuidePos[nodePoint->nodeType][3], (nodePoint->faction == TEAM_ALLIANCE ? ALLIANCE : HORDE))) sLog->outError("Isle of Conquest: Failed to spawn spirit guide! point: %u, team: %u,", nodePoint->nodeType, nodePoint->faction); } switch(nodePoint->gameobject_type) { case BG_IC_GO_HANGAR_BANNER: // all the players on the stopped transport should be teleported out if (!gunshipAlliance || !gunshipHorde) break; for (uint8 u = 0; u < MAX_HANGAR_TELEPORTERS_SPAWNS; u++) { uint8 type = BG_IC_GO_HANGAR_TELEPORTER_1+u; AddObject(type, (nodePoint->faction == TEAM_ALLIANCE ? GO_ALLIANCE_GUNSHIP_PORTAL : GO_HORDE_GUNSHIP_PORTAL), BG_IC_HangarTeleporters[u].GetPositionX(),BG_IC_HangarTeleporters[u].GetPositionY(), BG_IC_HangarTeleporters[u].GetPositionZ(),BG_IC_HangarTeleporters[u].GetOrientation(), 0,0,0,0,RESPAWN_ONE_DAY); } //sLog->outError("BG_IC_GO_HANGAR_BANNER CAPTURED Faction: %u", nodePoint->faction); (nodePoint->faction == TEAM_ALLIANCE ? gunshipAlliance : gunshipHorde)->BuildStartMovePacket(GetBgMap()); (nodePoint->faction == TEAM_ALLIANCE ? gunshipHorde : gunshipAlliance)->BuildStopMovePacket(GetBgMap()); // we should spawn teleporters break; case BG_IC_GO_QUARRY_BANNER: RemoveAuraOnTeam(SPELL_QUARRY,(nodePoint->faction == TEAM_ALLIANCE ? HORDE : ALLIANCE)); CastSpellOnTeam(SPELL_QUARRY,(nodePoint->faction == TEAM_ALLIANCE ? ALLIANCE : HORDE)); break; case BG_IC_GO_REFINERY_BANNER: RemoveAuraOnTeam(SPELL_OIL_REFINERY,(nodePoint->faction == TEAM_ALLIANCE ? HORDE : ALLIANCE)); CastSpellOnTeam(SPELL_OIL_REFINERY,(nodePoint->faction == TEAM_ALLIANCE ? ALLIANCE : HORDE)); break; case BG_IC_GO_DOCKS_BANNER: if (recapture) break; if (docksTimer < DOCKS_UPDATE_TIME) docksTimer = DOCKS_UPDATE_TIME; // we must del opposing faction vehicles when the node is captured (unused ones) for (uint8 i = (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_GLAIVE_THROWER_1_H : BG_IC_NPC_GLAIVE_THROWER_1_A); i < (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_GLAIVE_THROWER_2_H : BG_IC_NPC_GLAIVE_THROWER_2_A); i++) { if (Creature* glaiveThrower = GetBGCreature(i)) { if (Vehicle* vehicleGlaive = glaiveThrower->GetVehicleKit()) { if (!vehicleGlaive->GetPassenger(0)) DelCreature(i); } } } for (uint8 i = (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_CATAPULT_1_H : BG_IC_NPC_CATAPULT_1_A); i < (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_CATAPULT_4_H : BG_IC_NPC_CATAPULT_4_A); i++) { if (Creature* catapult = GetBGCreature(i)) { if (Vehicle* vehicleGlaive = catapult->GetVehicleKit()) { if (!vehicleGlaive->GetPassenger(0)) DelCreature(i); } } } // spawning glaive throwers for (uint8 i = 0; i < MAX_GLAIVE_THROWERS_SPAWNS_PER_FACTION; i++) { uint8 type = (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_GLAIVE_THROWER_1_A : BG_IC_NPC_GLAIVE_THROWER_1_H)+i; if (GetBGCreature(type) && GetBGCreature(type)->isAlive()) continue; if (AddCreature(nodePoint->faction == TEAM_ALLIANCE ? NPC_GLAIVE_THROWER_A : NPC_GLAIVE_THROWER_H,type,nodePoint->faction, BG_IC_DocksVehiclesGlaives[i].GetPositionX(),BG_IC_DocksVehiclesGlaives[i].GetPositionY(), BG_IC_DocksVehiclesGlaives[i].GetPositionZ(),BG_IC_DocksVehiclesGlaives[i].GetOrientation(), RESPAWN_ONE_DAY)) GetBGCreature(type)->setFaction(BG_IC_Factions[(nodePoint->faction == TEAM_ALLIANCE ? 0 : 1)]); } // spawning catapults for (uint8 i = 0; i < MAX_CATAPULTS_SPAWNS_PER_FACTION; i++) { uint8 type = (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_CATAPULT_1_A : BG_IC_NPC_CATAPULT_1_H)+i; if (GetBGCreature(type) && GetBGCreature(type)->isAlive()) continue; if (AddCreature(NPC_CATAPULT,type,nodePoint->faction, BG_IC_DocksVehiclesCatapults[i].GetPositionX(),BG_IC_DocksVehiclesCatapults[i].GetPositionY(), BG_IC_DocksVehiclesCatapults[i].GetPositionZ(),BG_IC_DocksVehiclesCatapults[i].GetOrientation(), RESPAWN_ONE_DAY)) GetBGCreature(type)->setFaction(BG_IC_Factions[(nodePoint->faction == TEAM_ALLIANCE ? 0 : 1)]); } break; case BG_IC_GO_WORKSHOP_BANNER: { if (siegeEngineWorkshopTimer < WORKSHOP_UPDATE_TIME) siegeEngineWorkshopTimer = WORKSHOP_UPDATE_TIME; if (!recapture) { // we must del opposing faction vehicles when the node is captured (unused ones) for (uint8 i = (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_DEMOLISHER_1_H : BG_IC_NPC_DEMOLISHER_1_A); i < (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_DEMOLISHER_4_H : BG_IC_NPC_DEMOLISHER_4_A); i++) { if (Creature* demolisher = GetBGCreature(i)) { 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 = (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_DEMOLISHER_1_A : BG_IC_NPC_DEMOLISHER_1_H)+i; if (GetBGCreature(type) && GetBGCreature(type)->isAlive()) continue; if (AddCreature(NPC_DEMOLISHER,type,nodePoint->faction, BG_IC_WorkshopVehicles[i].GetPositionX(),BG_IC_WorkshopVehicles[i].GetPositionY(), BG_IC_WorkshopVehicles[i].GetPositionZ(),BG_IC_WorkshopVehicles[i].GetOrientation(), RESPAWN_ONE_DAY)) GetBGCreature(type)->setFaction(BG_IC_Factions[(nodePoint->faction == TEAM_ALLIANCE ? 0 : 1)]); } // we check if the opossing siege engine is in use int8 enemySiege = (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_SIEGE_ENGINE_H : BG_IC_NPC_SIEGE_ENGINE_A); if (Creature* siegeEngine = GetBGCreature(enemySiege)) { if (Vehicle* vehicleSiege = siegeEngine->GetVehicleKit()) { // is VehicleInUse working as expected ? if (!vehicleSiege->IsVehicleInUse()) DelCreature(enemySiege); } } uint8 siegeType = (nodePoint->faction == TEAM_ALLIANCE ? BG_IC_NPC_SIEGE_ENGINE_A : BG_IC_NPC_SIEGE_ENGINE_H); if (!GetBGCreature(siegeType) || !GetBGCreature(siegeType)->isAlive()) { AddCreature((nodePoint->faction == TEAM_ALLIANCE ? NPC_SIEGE_ENGINE_A : NPC_SIEGE_ENGINE_H),siegeType,nodePoint->faction, BG_IC_WorkshopVehicles[4].GetPositionX(),BG_IC_WorkshopVehicles[4].GetPositionY(), BG_IC_WorkshopVehicles[4].GetPositionZ(),BG_IC_WorkshopVehicles[4].GetOrientation(), RESPAWN_ONE_DAY); if (Creature* siegeEngine = GetBGCreature(siegeType)) { siegeEngine->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_UNK_14|UNIT_FLAG_OOC_NOT_ATTACKABLE); siegeEngine->setFaction(BG_IC_Factions[(nodePoint->faction == TEAM_ALLIANCE ? 0 : 1)]); } } } 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->SetUInt32Value(GAMEOBJECT_FACTION,BG_IC_Factions[(nodePoint->faction == TEAM_ALLIANCE ? 0 : 1)]); } } break; } default: break; } } void BattlegroundIC::DestroyGate(Player* pl, GameObject* go, uint32 /*destroyedEvent*/) { GateStatus[GetGateIDFromEntry(go->GetEntry())] = BG_IC_GATE_DESTROYED; uint32 uws_open = GetWorldStateFromGateEntry(go->GetEntry(), true); uint32 uws_close = GetWorldStateFromGateEntry(go->GetEntry(), false); if (uws_open) { UpdateWorldState(uws_close,0); UpdateWorldState(uws_open, 1); } DoorOpen((pl->GetTeamId() == TEAM_ALLIANCE ? BG_IC_GO_HORDE_KEEP_PORTCULLIS : BG_IC_GO_DOODAD_PORTCULLISACTIVE02)); uint32 lang_entry = 0; switch(go->GetEntry()) { case GO_HORDE_GATE_1: lang_entry = LANG_BG_IC_NORTH_GATE_DESTROYED; case GO_HORDE_GATE_2: case GO_ALLIANCE_GATE_1: lang_entry = LANG_BG_IC_WEST_GATE_DESTROYED; break; case GO_HORDE_GATE_3: case GO_ALLIANCE_GATE_2: lang_entry = LANG_BG_IC_EAST_GATE_DESTROYED; break; case GO_ALLIANCE_GATE_3: lang_entry = LANG_BG_IC_SOUTH_GATE_DESTROYED; break; default: break; } SendMessage2ToAll(lang_entry,CHAT_MSG_BG_SYSTEM_NEUTRAL,NULL,(pl->GetTeamId() == TEAM_ALLIANCE ? LANG_BG_IC_HORDE_KEEP : LANG_BG_IC_ALLIANCE_KEEP)); } void BattlegroundIC::EventPlayerDamagedGO(Player* /*plr*/, GameObject* /*go*/, uint8 /*hitType*/, uint32 /*destroyedEvent*/) { } WorldSafeLocsEntry const* BattlegroundIC::GetClosestGraveYard(Player* player) { BattlegroundTeamId teamIndex = GetTeamIndexByTeamId(player->GetTeam()); // Is there any occupied node for this team? std::vector nodes; for (uint8 i = 0; i < MAX_NODE_TYPES; ++i) if (nodePoint[i].faction == player->GetTeamId()) nodes.push_back(i); WorldSafeLocsEntry const* good_entry = NULL; // If so, select the closest node to place ghost on if (!nodes.empty()) { float plr_x = player->GetPositionX(); float plr_y = player->GetPositionY(); float mindist = 999999.0f; for (uint8 i = 0; i < nodes.size(); ++i) { WorldSafeLocsEntry const*entry = sWorldSafeLocsStore.LookupEntry(BG_IC_GraveyardIds[nodes[i]]); if (!entry) continue; float dist = (entry->x - plr_x)*(entry->x - plr_x)+(entry->y - plr_y)*(entry->y - plr_y); if (mindist > dist) { mindist = dist; good_entry = entry; } } nodes.clear(); } // If not, place ghost on starting location if (!good_entry) good_entry = sWorldSafeLocsStore.LookupEntry(BG_IC_GraveyardIds[teamIndex+MAX_NODE_TYPES]); return good_entry; } Transport* BattlegroundIC::CreateTransport(uint32 goEntry,uint32 period) { Transport* t = new Transport(period,0); const GameObjectInfo* goinfo = sObjectMgr->GetGameObjectInfo(goEntry); if (!goinfo) { sLog->outErrorDb("Transport ID: %u will not be loaded, gameobject_template missing", goEntry); delete t; return NULL; } std::set mapsUsed; if (!t->GenerateWaypoints(goinfo->moTransport.taxiPathId, mapsUsed)) // skip transports with empty waypoints list { sLog->outErrorDb("Transport (path id %u) path size = 0. Transport ignored, check DBC files or transport GO data0 field.",goinfo->moTransport.taxiPathId); delete t; return NULL; } uint32 mapid = t->m_WayPoints[0].mapid; float x = t->m_WayPoints[0].x; float y = t->m_WayPoints[0].y; float z = t->m_WayPoints[0].z; float o = 1; // creates the Gameobject if (!t->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_MO_TRANSPORT),goEntry, mapid, x, y, z, o, 100, 0)) { delete t; return NULL; } //If we someday decide to use the grid to track transports, here: t->SetMap(GetBgMap()); for (uint8 i = 0; i < 5; i++) t->AddNPCPassenger(0,(goEntry == GO_HORDE_GUNSHIP ? NPC_HORDE_GUNSHIP_CANNON : NPC_ALLIANCE_GUNSHIP_CANNON), (goEntry == GO_HORDE_GUNSHIP ? hordeGunshipPassengers[i].GetPositionX() : allianceGunshipPassengers[i].GetPositionX()) , (goEntry == GO_HORDE_GUNSHIP ? hordeGunshipPassengers[i].GetPositionY() : allianceGunshipPassengers[i].GetPositionY()),(goEntry == GO_HORDE_GUNSHIP ? hordeGunshipPassengers[i].GetPositionZ() : allianceGunshipPassengers[i].GetPositionZ()), (goEntry == GO_HORDE_GUNSHIP ? hordeGunshipPassengers[i].GetOrientation() : allianceGunshipPassengers[i].GetOrientation())); return t; }