diff --git a/src/game/OutdoorPvP/OutdoorPvPMgr.cpp b/src/game/OutdoorPvP/OutdoorPvPMgr.cpp index 1bfab9945..c4af78ae1 100644 --- a/src/game/OutdoorPvP/OutdoorPvPMgr.cpp +++ b/src/game/OutdoorPvP/OutdoorPvPMgr.cpp @@ -54,6 +54,7 @@ void OutdoorPvPMgr::InitOutdoorPvP() m_scripts[OPVP_ID_HP] = new OutdoorPvPHP(); m_scripts[OPVP_ID_ZM] = new OutdoorPvPZM(); m_scripts[OPVP_ID_TF] = new OutdoorPvPTF(); + m_scripts[OPVP_ID_NA] = new OutdoorPvPNA(); sLog.outString(); sLog.outString(">> Loaded %u Outdoor PvP zones", MAX_OPVP_ID); diff --git a/src/game/OutdoorPvP/OutdoorPvPNA.cpp b/src/game/OutdoorPvP/OutdoorPvPNA.cpp index b166faf81..7b743d2f6 100644 --- a/src/game/OutdoorPvP/OutdoorPvPNA.cpp +++ b/src/game/OutdoorPvP/OutdoorPvPNA.cpp @@ -15,3 +15,546 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "OutdoorPvPNA.h" +#include "WorldPacket.h" +#include "../World.h" +#include "../ObjectMgr.h" +#include "../Object.h" +#include "../Creature.h" +#include "../GameObject.h" +#include "../Player.h" + +OutdoorPvPNA::OutdoorPvPNA() : OutdoorPvP(), + m_zoneOwner(TEAM_NONE), + m_soldiersRespawnTimer(0), + m_zoneWorldState(0), + m_zoneMapState(WORLD_STATE_NA_HALAA_NEUTRAL), + m_guardsLeft(0), + m_isUnderSiege(false) +{ + // initially set graveyard owner to neither faction + sObjectMgr.SetGraveYardLinkTeam(GRAVEYARD_ID_HALAA, GRAVEYARD_ZONE_ID_HALAA, TEAM_INVALID); +} + +void OutdoorPvPNA::FillInitialWorldStates(WorldPacket& data, uint32& count) +{ + if (m_zoneOwner != TEAM_NONE) + { + FillInitialWorldState(data, count, m_zoneWorldState, WORLD_STATE_ADD); + + // map states + for (uint8 i = 0; i < MAX_NA_ROOSTS; ++i) + FillInitialWorldState(data, count, m_roostWorldState[i], WORLD_STATE_ADD); + } + + FillInitialWorldState(data, count, m_zoneMapState, WORLD_STATE_ADD); + FillInitialWorldState(data, count, WORLD_STATE_NA_GUARDS_MAX, MAX_NA_GUARDS); + FillInitialWorldState(data, count, WORLD_STATE_NA_GUARDS_LEFT, m_guardsLeft); +} + +void OutdoorPvPNA::SendRemoveWorldStates(Player* player) +{ + player->SendUpdateWorldState(m_zoneWorldState, WORLD_STATE_REMOVE); + player->SendUpdateWorldState(m_zoneMapState, WORLD_STATE_REMOVE); + + for (uint8 i = 0; i < MAX_NA_ROOSTS; ++i) + player->SendUpdateWorldState(m_roostWorldState[i], WORLD_STATE_REMOVE); +} + +void OutdoorPvPNA::HandlePlayerEnterZone(Player* player, bool isMainZone) +{ + OutdoorPvP::HandlePlayerEnterZone(player, isMainZone); + + // remove the buff from the player first because there are some issues at relog + player->RemoveAurasDueToSpell(SPELL_STRENGTH_HALAANI); + + // buff the player if same team is controlling the zone + if (player->GetTeam() == m_zoneOwner) + player->CastSpell(player, SPELL_STRENGTH_HALAANI, true); +} + +void OutdoorPvPNA::HandlePlayerLeaveZone(Player* player, bool isMainZone) +{ + // remove the buff from the player + player->RemoveAurasDueToSpell(SPELL_STRENGTH_HALAANI); + + OutdoorPvP::HandlePlayerLeaveZone(player, isMainZone); +} + +void OutdoorPvPNA::HandleObjectiveComplete(uint32 eventId, std::list players, Team team) +{ + if (eventId == EVENT_HALAA_BANNER_WIN_ALLIANCE || eventId == EVENT_HALAA_BANNER_WIN_HORDE) + { + for (std::list::iterator itr = players.begin(); itr != players.end(); ++itr) + { + if ((*itr) && (*itr)->GetTeam() == team) + (*itr)->KilledMonsterCredit(NPC_HALAA_COMBATANT); + } + } +} + +// Cast player spell on opponent kill +void OutdoorPvPNA::HandlePlayerKillInsideArea(Player* player, Unit* /*victim*/) +{ + if (GameObject* capturePoint = player->GetMap()->GetGameObject(m_capturePoint)) + { + // check capture point range + GameObjectInfo const* info = capturePoint->GetGOInfo(); + if (info && player->IsWithinDistInMap(capturePoint, info->capturePoint.radius)) + { + // check capture point team + if (player->GetTeam() == m_zoneOwner) + player->CastSpell(player, player->GetTeam() == ALLIANCE ? SPELL_NAGRAND_TOKEN_ALLIANCE : SPELL_NAGRAND_TOKEN_HORDE, true); + + return; + } + } +} + +void OutdoorPvPNA::HandleCreatureCreate(Creature* creature) +{ + switch (creature->GetEntry()) + { + case NPC_RESEARCHER_KARTOS: + case NPC_QUARTERMASTER_DAVIAN: + case NPC_MERCHANT_ALDRAAN: + case NPC_VENDOR_CENDRII: + case NPC_AMMUNITIONER_BANRO: + case NPC_RESEARCHER_AMERELDINE: + case NPC_QUARTERMASTER_NORELIQE: + case NPC_MERCHANT_COREIEL: + case NPC_VENDOR_EMBELAR: + case NPC_AMMUNITIONER_TASALDAN: + m_teamVendors.push_back(creature->GetObjectGuid()); + break; + case NPC_HORDE_HALAANI_GUARD: + case NPC_ALLIANCE_HANAANI_GUARD: + // prevent updating guard counter on owner take over + if (m_guardsLeft == MAX_NA_GUARDS) + return; + + if (m_guardsLeft == 0) + { + LockHalaa(creature); + + // update world state + SendUpdateWorldState(m_zoneMapState, WORLD_STATE_REMOVE); + m_zoneMapState = m_zoneOwner == ALLIANCE ? WORLD_STATE_NA_HALAA_ALLIANCE : WORLD_STATE_NA_HALAA_HORDE; + SendUpdateWorldState(m_zoneMapState, WORLD_STATE_ADD); + } + + ++m_guardsLeft; + SendUpdateWorldState(WORLD_STATE_NA_GUARDS_LEFT, m_guardsLeft); + break; + } +} + +void OutdoorPvPNA::HandleCreatureDeath(Creature* creature) +{ + if (creature->GetEntry() != NPC_HORDE_HALAANI_GUARD && creature->GetEntry() != NPC_ALLIANCE_HANAANI_GUARD) + return; + + // get the location of the dead guard for future respawn + float x, y, z, o; + creature->GetRespawnCoord(x, y, z, &o); + HalaaSoldiersSpawns location = {x, y, z, o}; + m_deadSoldiers.push(location); + + // set the respawn timer after the last guard died - 5 min for the first time, or 1 hour if the city is under siege + if (!m_soldiersRespawnTimer) + m_soldiersRespawnTimer = m_isUnderSiege ? HOUR * IN_MILLISECONDS : 5 * MINUTE * IN_MILLISECONDS; + + // decrease the counter + --m_guardsLeft; + SendUpdateWorldState(WORLD_STATE_NA_GUARDS_LEFT, m_guardsLeft); + + if (m_guardsLeft == 0) + { + // set the zone under siege and increase the respawn timer + m_isUnderSiege = true; + m_soldiersRespawnTimer = HOUR * IN_MILLISECONDS; + + // make capturable + UnlockHalaa(creature); + + // update world state + SendUpdateWorldState(m_zoneMapState, WORLD_STATE_REMOVE); + m_zoneMapState = m_zoneOwner == ALLIANCE ? WORLD_STATE_NA_HALAA_NEUTRAL_A : WORLD_STATE_NA_HALAA_NEUTRAL_H; + SendUpdateWorldState(m_zoneMapState, WORLD_STATE_ADD); + + sWorld.SendDefenseMessage(ZONE_ID_NAGRAND, LANG_OPVP_NA_DEFENSELESS); + } +} + +void OutdoorPvPNA::HandleGameObjectCreate(GameObject* go) +{ + switch (go->GetEntry()) + { + case GO_HALAA_BANNER: + m_capturePoint = go->GetObjectGuid(); + go->SetGoArtKit(GetBannerArtKit(m_zoneOwner)); + break; + + case GO_WYVERN_ROOST_ALLIANCE_SOUTH: + m_roostsAlliance[0] = go->GetObjectGuid(); + break; + case GO_WYVERN_ROOST_ALLIANCE_NORTH: + m_roostsAlliance[1] = go->GetObjectGuid(); + break; + case GO_WYVERN_ROOST_ALLIANCE_EAST: + m_roostsAlliance[2] = go->GetObjectGuid(); + break; + case GO_WYVERN_ROOST_ALLIANCE_WEST: + m_roostsAlliance[3] = go->GetObjectGuid(); + break; + + case GO_BOMB_WAGON_HORDE_SOUTH: + m_wagonsHorde[0] = go->GetObjectGuid(); + break; + case GO_BOMB_WAGON_HORDE_NORTH: + m_wagonsHorde[1] = go->GetObjectGuid(); + break; + case GO_BOMB_WAGON_HORDE_EAST: + m_wagonsHorde[2] = go->GetObjectGuid(); + break; + case GO_BOMB_WAGON_HORDE_WEST: + m_wagonsHorde[3] = go->GetObjectGuid(); + break; + + case GO_DESTROYED_ROOST_ALLIANCE_SOUTH: + m_roostsBrokenAlliance[0] = go->GetObjectGuid(); + break; + case GO_DESTROYED_ROOST_ALLIANCE_NORTH: + m_roostsBrokenAlliance[1] = go->GetObjectGuid(); + break; + case GO_DESTROYED_ROOST_ALLIANCE_EAST: + m_roostsBrokenAlliance[2] = go->GetObjectGuid(); + break; + case GO_DESTROYED_ROOST_ALLIANCE_WEST: + m_roostsBrokenAlliance[3] = go->GetObjectGuid(); + break; + + case GO_WYVERN_ROOST_HORDE_SOUTH: + m_roostsHorde[0] = go->GetObjectGuid(); + break; + case GO_WYVERN_ROOST_HORDE_NORTH: + m_roostsHorde[1] = go->GetObjectGuid(); + break; + case GO_WYVERN_ROOST_HORDE_EAST: + m_roostsHorde[2] = go->GetObjectGuid(); + break; + case GO_WYVERN_ROOST_HORDE_WEST: + m_roostsHorde[3] = go->GetObjectGuid(); + break; + + case GO_BOMB_WAGON_ALLIANCE_SOUTH: + m_wagonsAlliance[0] = go->GetObjectGuid(); + break; + case GO_BOMB_WAGON_ALLIANCE_NORTH: + m_wagonsAlliance[1] = go->GetObjectGuid(); + break; + case GO_BOMB_WAGON_ALLIANCE_EAST: + m_wagonsAlliance[2] = go->GetObjectGuid(); + break; + case GO_BOMB_WAGON_ALLIANCE_WEST: + m_wagonsAlliance[3] = go->GetObjectGuid(); + break; + + case GO_DESTROYED_ROOST_HORDE_SOUTH: + m_roostsBrokenHorde[0] = go->GetObjectGuid(); + break; + case GO_DESTROYED_ROOST_HORDE_NORTH: + m_roostsBrokenHorde[1] = go->GetObjectGuid(); + break; + case GO_DESTROYED_ROOST_HORDE_EAST: + m_roostsBrokenHorde[2] = go->GetObjectGuid(); + break; + case GO_DESTROYED_ROOST_HORDE_WEST: + m_roostsBrokenHorde[3] = go->GetObjectGuid(); + break; + } +} + +void OutdoorPvPNA::UpdateWorldState(uint32 value) +{ + SendUpdateWorldState(m_zoneWorldState, value); + SendUpdateWorldState(m_zoneMapState, value); + + UpdateWyvernsWorldState(value); +} + +void OutdoorPvPNA::UpdateWyvernsWorldState(uint32 value) +{ + for (uint8 i = 0; i < MAX_NA_ROOSTS; ++i) + SendUpdateWorldState(m_roostWorldState[i], value); +} + +// process the capture events +bool OutdoorPvPNA::HandleEvent(uint32 eventId, GameObject* go) +{ + // If we are not using the Halaa banner return + if (go->GetEntry() != GO_HALAA_BANNER) + return false; + + bool eventHandled = true; + + switch (eventId) + { + case EVENT_HALAA_BANNER_WIN_ALLIANCE: + ProcessCaptureEvent(go, ALLIANCE); + eventHandled = false; + break; + case EVENT_HALAA_BANNER_WIN_HORDE: + ProcessCaptureEvent(go, HORDE); + eventHandled = false; + break; + case EVENT_HALAA_BANNER_PROGRESS_ALLIANCE: + SetBannerVisual(go, CAPTURE_ARTKIT_ALLIANCE, CAPTURE_ANIM_ALLIANCE); + sWorld.SendDefenseMessage(ZONE_ID_NAGRAND, LANG_OPVP_NA_PROGRESS_A); + break; + case EVENT_HALAA_BANNER_PROGRESS_HORDE: + SetBannerVisual(go, CAPTURE_ARTKIT_HORDE, CAPTURE_ANIM_HORDE); + sWorld.SendDefenseMessage(ZONE_ID_NAGRAND, LANG_OPVP_NA_PROGRESS_H); + break; + } + + // there are some events which required further DB script + return eventHandled; +} + +void OutdoorPvPNA::ProcessCaptureEvent(GameObject* go, Team team) +{ + BuffTeam(m_zoneOwner, SPELL_STRENGTH_HALAANI, true); + + // update capture point owner + m_zoneOwner = team; + + LockHalaa(go); + m_guardsLeft = MAX_NA_GUARDS; + + m_isUnderSiege = false; + m_soldiersRespawnTimer = 0; + + UpdateWorldState(WORLD_STATE_REMOVE); + DespawnVendors(go); + sObjectMgr.SetGraveYardLinkTeam(GRAVEYARD_ID_HALAA, GRAVEYARD_ZONE_ID_HALAA, m_zoneOwner); + + if (m_zoneOwner == ALLIANCE) + { + m_zoneWorldState = WORLD_STATE_NA_GUARDS_ALLIANCE; + m_zoneMapState = WORLD_STATE_NA_HALAA_ALLIANCE; + } + else + { + m_zoneWorldState = WORLD_STATE_NA_GUARDS_HORDE; + m_zoneMapState = WORLD_STATE_NA_HALAA_HORDE; + } + + HandleFactionObjects(go); + UpdateWorldState(WORLD_STATE_ADD); + + SendUpdateWorldState(WORLD_STATE_NA_GUARDS_LEFT, m_guardsLeft); + + BuffTeam(m_zoneOwner, SPELL_STRENGTH_HALAANI); + sWorld.SendDefenseMessage(ZONE_ID_NAGRAND, m_zoneOwner == ALLIANCE ? LANG_OPVP_NA_CAPTURE_A: LANG_OPVP_NA_CAPTURE_H); +} + +// Handle the gameobjects spawn/despawn depending on the controller faction +void OutdoorPvPNA::HandleFactionObjects(const WorldObject* objRef) +{ + if (m_zoneOwner == ALLIANCE) + { + for (uint8 i = 0; i < MAX_NA_ROOSTS; ++i) + { + RespawnGO(objRef, m_wagonsHorde[i], false); + RespawnGO(objRef, m_roostsBrokenAlliance[i], false); + RespawnGO(objRef, m_roostsAlliance[i], false); + RespawnGO(objRef, m_wagonsAlliance[i], false); + RespawnGO(objRef, m_roostsBrokenHorde[i], true); + + m_roostWorldState[i] = nagrandRoostStatesHordeNeutral[i]; + } + } + else + { + for (uint8 i = 0; i < MAX_NA_ROOSTS; ++i) + { + RespawnGO(objRef, m_wagonsAlliance[i], false); + RespawnGO(objRef, m_roostsBrokenHorde[i], false); + RespawnGO(objRef, m_roostsHorde[i], false); + RespawnGO(objRef, m_wagonsHorde[i], false); + RespawnGO(objRef, m_roostsBrokenAlliance[i], true); + + m_roostWorldState[i] = nagrandRoostStatesAllianceNeutral[i]; + } + } +} + +// Handle vendors despawn when the city is captured by the other faction +void OutdoorPvPNA::DespawnVendors(const WorldObject* objRef) +{ + // despawn all team vendors + for (GuidList::const_iterator itr = m_teamVendors.begin(); itr != m_teamVendors.end(); ++itr) + { + if (Creature* soldier = objRef->GetMap()->GetCreature(*itr)) + soldier->ForcedDespawn(); + } + m_teamVendors.clear(); +} + +bool OutdoorPvPNA::HandleGameObjectUse(Player* player, GameObject* go) +{ + if (player->GetTeam() == ALLIANCE) + { + for (uint8 i = 0; i < MAX_NA_ROOSTS; ++i) + { + if (go->GetEntry() == nagrandWagonsAlliance[i]) + { + // update roost states + UpdateWyvernsWorldState(WORLD_STATE_REMOVE); + m_roostWorldState[i] = nagrandRoostStatesHordeNeutral[i]; + UpdateWyvernsWorldState(WORLD_STATE_ADD); + + // spawn the broken roost and despawn the other one + RespawnGO(go, m_roostsHorde[i], false); + RespawnGO(go, m_roostsBrokenHorde[i], true); + + // no need to iterate the other roosts + return false; + } + else if (go->GetEntry() == nagrandRoostsBrokenAlliance[i]) + { + // update roost states + UpdateWyvernsWorldState(WORLD_STATE_REMOVE); + m_roostWorldState[i] = nagrandRoostStatesAlliance[i]; + UpdateWyvernsWorldState(WORLD_STATE_ADD); + + // spawn the repaired one along with the explosive wagon - the broken one despawns by self + RespawnGO(go, m_wagonsHorde[i], true); + RespawnGO(go, m_roostsAlliance[i], true); + + // no need to iterate the other roosts + return false; + } + else if (go->GetEntry() == nagrandRoostsAlliance[i]) + { + // mark player as pvp + player->UpdatePvP(true, true); + player->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP); + + // prevent despawning after go use + go->SetRespawnTime(0); + + // no need to iterate the other roosts + return false; + } + } + } + else if (player->GetTeam() == HORDE) + { + for (uint8 i = 0; i < MAX_NA_ROOSTS; ++i) + { + if (go->GetEntry() == nagrandWagonsHorde[i]) + { + // update roost states + UpdateWyvernsWorldState(WORLD_STATE_REMOVE); + m_roostWorldState[i] = nagrandRoostStatesAllianceNeutral[i]; + UpdateWyvernsWorldState(WORLD_STATE_ADD); + + // spawn the broken roost and despawn the other one + RespawnGO(go, m_roostsAlliance[i], false); + RespawnGO(go, m_roostsBrokenAlliance[i], true); + + // no need to iterate the other roosts + return false; + } + else if (go->GetEntry() == nagrandRoostsBrokenHorde[i]) + { + // update roost states + UpdateWyvernsWorldState(WORLD_STATE_REMOVE); + m_roostWorldState[i] = nagrandRoostStatesHorde[i]; + UpdateWyvernsWorldState(WORLD_STATE_ADD); + + // spawn the repaired one along with the explosive wagon - the broken one despawns by self + RespawnGO(go, m_wagonsAlliance[i], true); + RespawnGO(go, m_roostsHorde[i], true); + + // no need to iterate the other roosts + return false; + } + else if (go->GetEntry() == nagrandRoostsHorde[i]) + { + // mark player as pvp + player->UpdatePvP(true, true); + player->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP); + + // prevent despawning after go use + go->SetRespawnTime(0); + + // no need to iterate the other roosts + return false; + } + } + } + + return false; +} + +void OutdoorPvPNA::Update(uint32 diff) +{ + if (m_soldiersRespawnTimer) + { + if (m_soldiersRespawnTimer < diff) + { + RespawnSoldier(); + + // if all the guards are respawned, stop the timer, else resume the timer depending on the siege state + if (m_guardsLeft == MAX_NA_GUARDS) + m_soldiersRespawnTimer = 0; + else + m_soldiersRespawnTimer = m_isUnderSiege ? HOUR * IN_MILLISECONDS : 5 * MINUTE * IN_MILLISECONDS; + } + else + m_soldiersRespawnTimer -= diff; + } +} + +// Handle soldiers respawn on timer - this will summon a replacement for the dead soldier +void OutdoorPvPNA::RespawnSoldier() +{ + for (GuidZoneMap::iterator itr = m_zonePlayers.begin(); itr != m_zonePlayers.end(); ++itr) + { + // Find player who is in main zone (Nagrand) to get correct map reference + if (!itr->second) + continue; + + if (Player* player = sObjectMgr.GetPlayer(itr->first)) + { + // summon a soldier replacement in the order they were set in the deque. delete the element after summon + player->SummonCreature(m_zoneOwner == ALLIANCE ? NPC_ALLIANCE_HANAANI_GUARD : NPC_HORDE_HALAANI_GUARD, m_deadSoldiers.front().x, m_deadSoldiers.front().y, m_deadSoldiers.front().z, m_deadSoldiers.front().o, TEMPSUMMON_DEAD_DESPAWN, 0, true); + m_deadSoldiers.pop(); + break; + } + } +} + +// Lock Halaa when captured +void OutdoorPvPNA::LockHalaa(const WorldObject* objRef) +{ + if (GameObject* go = objRef->GetMap()->GetGameObject(m_capturePoint)) + go->SetLootState(GO_JUST_DEACTIVATED); + + sOutdoorPvPMgr.SetCapturePointSlider(m_capturePoint, m_zoneOwner == ALLIANCE ? CAPTURE_SLIDER_ALLIANCE_LOCKED : CAPTURE_SLIDER_HORDE_LOCKED); +} + +// Unlock Halaa when all the soldiers are killed +void OutdoorPvPNA::UnlockHalaa(const WorldObject* objRef) +{ + if (GameObject* go = objRef->GetMap()->GetGameObject(m_capturePoint)) + go->SetCapturePointSlider(m_zoneOwner == ALLIANCE ? CAPTURE_SLIDER_ALLIANCE : CAPTURE_SLIDER_HORDE); + // no banner visual update needed because it already has the correct one + else + // if grid is unloaded, resetting the slider value is enough + sOutdoorPvPMgr.SetCapturePointSlider(m_capturePoint, m_zoneOwner == ALLIANCE ? CAPTURE_SLIDER_ALLIANCE : CAPTURE_SLIDER_HORDE); +} diff --git a/src/game/OutdoorPvP/OutdoorPvPNA.h b/src/game/OutdoorPvP/OutdoorPvPNA.h index 24440b621..bf7e83ce2 100644 --- a/src/game/OutdoorPvP/OutdoorPvPNA.h +++ b/src/game/OutdoorPvP/OutdoorPvPNA.h @@ -19,4 +19,201 @@ #ifndef WORLD_PVP_NA #define WORLD_PVP_NA +#include "Common.h" +#include "OutdoorPvP.h" +#include "../Language.h" + +enum +{ + MAX_NA_GUARDS = 15, + MAX_NA_ROOSTS = 4, // roosts for each type and team + MAX_FIRE_BOMBS = 10, + + // spells + SPELL_STRENGTH_HALAANI = 33795, + SPELL_NAGRAND_TOKEN_ALLIANCE = 33005, + SPELL_NAGRAND_TOKEN_HORDE = 33004, + + // npcs + // quest credit + NPC_HALAA_COMBATANT = 24867, + + GRAVEYARD_ID_HALAA = 993, + GRAVEYARD_ZONE_ID_HALAA = 3518, + + ITEM_ID_FIRE_BOMB = 24538, + + // gameobjects + GO_HALAA_BANNER = 182210, + + // spawned when horde is in control - alliance is attacking + GO_WYVERN_ROOST_ALLIANCE_SOUTH = 182267, + GO_WYVERN_ROOST_ALLIANCE_WEST = 182280, + GO_WYVERN_ROOST_ALLIANCE_NORTH = 182281, + GO_WYVERN_ROOST_ALLIANCE_EAST = 182282, + + GO_BOMB_WAGON_HORDE_SOUTH = 182222, + GO_BOMB_WAGON_HORDE_WEST = 182272, + GO_BOMB_WAGON_HORDE_NORTH = 182273, + GO_BOMB_WAGON_HORDE_EAST = 182274, + + GO_DESTROYED_ROOST_ALLIANCE_SOUTH = 182266, + GO_DESTROYED_ROOST_ALLIANCE_WEST = 182275, + GO_DESTROYED_ROOST_ALLIANCE_NORTH = 182276, + GO_DESTROYED_ROOST_ALLIANCE_EAST = 182277, + + // spawned when alliance is in control - horde is attacking + GO_WYVERN_ROOST_HORDE_SOUTH = 182301, + GO_WYVERN_ROOST_HORDE_WEST = 182302, + GO_WYVERN_ROOST_HORDE_NORTH = 182303, + GO_WYVERN_ROOST_HORDE_EAST = 182304, + + GO_BOMB_WAGON_ALLIANCE_SOUTH = 182305, + GO_BOMB_WAGON_ALLIANCE_WEST = 182306, + GO_BOMB_WAGON_ALLIANCE_NORTH = 182307, + GO_BOMB_WAGON_ALLIANCE_EAST = 182308, + + GO_DESTROYED_ROOST_HORDE_SOUTH = 182297, + GO_DESTROYED_ROOST_HORDE_WEST = 182298, + GO_DESTROYED_ROOST_HORDE_NORTH = 182299, + GO_DESTROYED_ROOST_HORDE_EAST = 182300, + + // npcs + // alliance + NPC_RESEARCHER_KARTOS = 18817, + NPC_QUARTERMASTER_DAVIAN = 18822, + NPC_MERCHANT_ALDRAAN = 21485, + NPC_VENDOR_CENDRII = 21487, + NPC_AMMUNITIONER_BANRO = 21488, + NPC_ALLIANCE_HANAANI_GUARD = 18256, + + // horde + NPC_RESEARCHER_AMERELDINE = 18816, + NPC_QUARTERMASTER_NORELIQE = 18821, + NPC_MERCHANT_COREIEL = 21474, + NPC_VENDOR_EMBELAR = 21484, + NPC_AMMUNITIONER_TASALDAN = 21483, + NPC_HORDE_HALAANI_GUARD = 18192, + + // events + EVENT_HALAA_BANNER_WIN_ALLIANCE = 11504, + EVENT_HALAA_BANNER_WIN_HORDE = 11503, + EVENT_HALAA_BANNER_CONTEST_ALLIANCE = 11559, + EVENT_HALAA_BANNER_CONTEST_HORDE = 11558, + EVENT_HALAA_BANNER_PROGRESS_ALLIANCE = 11821, + EVENT_HALAA_BANNER_PROGRESS_HORDE = 11822, + + // world states + WORLD_STATE_NA_GUARDS_HORDE = 2503, + WORLD_STATE_NA_GUARDS_ALLIANCE = 2502, + WORLD_STATE_NA_GUARDS_MAX = 2493, + WORLD_STATE_NA_GUARDS_LEFT = 2491, + + // map states + WORLD_STATE_NA_WYVERN_NORTH_NEUTRAL_H = 2762, + WORLD_STATE_NA_WYVERN_NORTH_NEUTRAL_A = 2662, + WORLD_STATE_NA_WYVERN_NORTH_H = 2663, + WORLD_STATE_NA_WYVERN_NORTH_A = 2664, + + WORLD_STATE_NA_WYVERN_SOUTH_NEUTRAL_H = 2760, + WORLD_STATE_NA_WYVERN_SOUTH_NEUTRAL_A = 2670, + WORLD_STATE_NA_WYVERN_SOUTH_H = 2668, + WORLD_STATE_NA_WYVERN_SOUTH_A = 2669, + + WORLD_STATE_NA_WYVERN_WEST_NEUTRAL_H = 2761, + WORLD_STATE_NA_WYVERN_WEST_NEUTRAL_A = 2667, + WORLD_STATE_NA_WYVERN_WEST_H = 2665, + WORLD_STATE_NA_WYVERN_WEST_A = 2666, + + WORLD_STATE_NA_WYVERN_EAST_NEUTRAL_H = 2763, + WORLD_STATE_NA_WYVERN_EAST_NEUTRAL_A = 2659, + WORLD_STATE_NA_WYVERN_EAST_H = 2660, + WORLD_STATE_NA_WYVERN_EAST_A = 2661, + + WORLD_STATE_NA_HALAA_NEUTRAL = 2671, + WORLD_STATE_NA_HALAA_NEUTRAL_A = 2676, + WORLD_STATE_NA_HALAA_NEUTRAL_H = 2677, + WORLD_STATE_NA_HALAA_HORDE = 2672, + WORLD_STATE_NA_HALAA_ALLIANCE = 2673, +}; + +struct HalaaSoldiersSpawns +{ + float x, y, z, o; +}; + +static const uint32 nagrandRoostsAlliance[MAX_NA_ROOSTS] = {GO_WYVERN_ROOST_ALLIANCE_SOUTH, GO_WYVERN_ROOST_ALLIANCE_NORTH, GO_WYVERN_ROOST_ALLIANCE_EAST, GO_WYVERN_ROOST_ALLIANCE_WEST}; +static const uint32 nagrandRoostsHorde[MAX_NA_ROOSTS] = {GO_WYVERN_ROOST_HORDE_SOUTH, GO_WYVERN_ROOST_HORDE_NORTH, GO_WYVERN_ROOST_HORDE_EAST, GO_WYVERN_ROOST_HORDE_WEST}; +static const uint32 nagrandRoostsBrokenAlliance[MAX_NA_ROOSTS] = {GO_DESTROYED_ROOST_ALLIANCE_SOUTH, GO_DESTROYED_ROOST_ALLIANCE_NORTH, GO_DESTROYED_ROOST_ALLIANCE_EAST, GO_DESTROYED_ROOST_ALLIANCE_WEST}; +static const uint32 nagrandRoostsBrokenHorde[MAX_NA_ROOSTS] = {GO_DESTROYED_ROOST_HORDE_SOUTH, GO_DESTROYED_ROOST_HORDE_NORTH, GO_DESTROYED_ROOST_HORDE_EAST, GO_DESTROYED_ROOST_HORDE_WEST}; +static const uint32 nagrandWagonsAlliance[MAX_NA_ROOSTS] = {GO_BOMB_WAGON_ALLIANCE_SOUTH, GO_BOMB_WAGON_ALLIANCE_NORTH, GO_BOMB_WAGON_ALLIANCE_EAST, GO_BOMB_WAGON_ALLIANCE_WEST}; +static const uint32 nagrandWagonsHorde[MAX_NA_ROOSTS] = {GO_BOMB_WAGON_HORDE_SOUTH, GO_BOMB_WAGON_HORDE_NORTH, GO_BOMB_WAGON_HORDE_EAST, GO_BOMB_WAGON_HORDE_WEST}; + +static const uint32 nagrandRoostStatesAlliance[MAX_NA_ROOSTS] = {WORLD_STATE_NA_WYVERN_SOUTH_A, WORLD_STATE_NA_WYVERN_NORTH_A, WORLD_STATE_NA_WYVERN_EAST_A, WORLD_STATE_NA_WYVERN_WEST_A}; +static const uint32 nagrandRoostStatesHorde[MAX_NA_ROOSTS] = {WORLD_STATE_NA_WYVERN_SOUTH_H, WORLD_STATE_NA_WYVERN_NORTH_H, WORLD_STATE_NA_WYVERN_EAST_H, WORLD_STATE_NA_WYVERN_WEST_H}; +static const uint32 nagrandRoostStatesAllianceNeutral[MAX_NA_ROOSTS] = {WORLD_STATE_NA_WYVERN_SOUTH_NEUTRAL_A, WORLD_STATE_NA_WYVERN_NORTH_NEUTRAL_A, WORLD_STATE_NA_WYVERN_EAST_NEUTRAL_A, WORLD_STATE_NA_WYVERN_WEST_NEUTRAL_A}; +static const uint32 nagrandRoostStatesHordeNeutral[MAX_NA_ROOSTS] = {WORLD_STATE_NA_WYVERN_SOUTH_NEUTRAL_H, WORLD_STATE_NA_WYVERN_NORTH_NEUTRAL_H, WORLD_STATE_NA_WYVERN_EAST_NEUTRAL_H, WORLD_STATE_NA_WYVERN_WEST_NEUTRAL_H}; + +class OutdoorPvPNA : public OutdoorPvP +{ + public: + OutdoorPvPNA(); + + void HandlePlayerEnterZone(Player* player, bool isMainZone) override; + void HandlePlayerLeaveZone(Player* player, bool isMainZone) override; + void FillInitialWorldStates(WorldPacket& data, uint32& count) override; + void SendRemoveWorldStates(Player* player) override; + + bool HandleEvent(uint32 eventId, GameObject* go) override; + void HandleObjectiveComplete(uint32 eventId, std::list players, Team team) override; + + void HandleCreatureCreate(Creature* creature) override; + void HandleGameObjectCreate(GameObject* go) override; + void HandleCreatureDeath(Creature* creature) override; + + void HandlePlayerKillInsideArea(Player* player, Unit* victim) override; + bool HandleGameObjectUse(Player* player, GameObject* go) override; + void Update(uint32 diff) override; + + private: + // world states handling + void UpdateWorldState(uint32 value); + void UpdateWyvernsWorldState(uint32 value); + + // process capture events + void ProcessCaptureEvent(GameObject* go, Team team); + + // set specific team vendors and objects after capture + void DespawnVendors(const WorldObject* objRef); + void HandleFactionObjects(const WorldObject* objRef); + + // handle a specific game objects + void LockHalaa(const WorldObject* objRef); + void UnlockHalaa(const WorldObject* objRef); + + // handle soldier respawn on timer + void RespawnSoldier(); + + Team m_zoneOwner; + uint32 m_soldiersRespawnTimer; + uint32 m_zoneWorldState; + uint32 m_zoneMapState; + uint32 m_roostWorldState[MAX_NA_ROOSTS]; + uint8 m_guardsLeft; + + bool m_isUnderSiege; + + ObjectGuid m_capturePoint; + ObjectGuid m_roostsAlliance[MAX_NA_ROOSTS]; + ObjectGuid m_roostsHorde[MAX_NA_ROOSTS]; + ObjectGuid m_roostsBrokenAlliance[MAX_NA_ROOSTS]; + ObjectGuid m_roostsBrokenHorde[MAX_NA_ROOSTS]; + ObjectGuid m_wagonsAlliance[MAX_NA_ROOSTS]; + ObjectGuid m_wagonsHorde[MAX_NA_ROOSTS]; + + GuidList m_teamVendors; + + std::queue m_deadSoldiers; +}; + #endif \ No newline at end of file