diff --git a/src/game/OutdoorPvP/OutdoorPvPHP.cpp b/src/game/OutdoorPvP/OutdoorPvPHP.cpp index b166faf81..63f9d5cec 100644 --- a/src/game/OutdoorPvP/OutdoorPvPHP.cpp +++ b/src/game/OutdoorPvP/OutdoorPvPHP.cpp @@ -15,3 +15,243 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "OutdoorPvPHP.h" +#include "WorldPacket.h" +#include "../World.h" +#include "../Object.h" +#include "../Creature.h" +#include "../GameObject.h" +#include "../Player.h" + +OutdoorPvPHP::OutdoorPvPHP() : OutdoorPvP(), + m_towersAlliance(0), + m_towersHorde(0) +{ + m_towerWorldState[0] = WORLD_STATE_HP_OVERLOOK_NEUTRAL; + m_towerWorldState[1] = WORLD_STATE_HP_STADIUM_NEUTRAL; + m_towerWorldState[2] = WORLD_STATE_HP_BROKEN_HILL_NEUTRAL; + + for (uint8 i = 0; i < MAX_HP_TOWERS; ++i) + m_towerOwner[i] = TEAM_NONE; +} + +void OutdoorPvPHP::FillInitialWorldStates(WorldPacket& data, uint32& count) +{ + FillInitialWorldState(data, count, WORLD_STATE_HP_TOWER_COUNT_ALLIANCE, m_towersAlliance); + FillInitialWorldState(data, count, WORLD_STATE_HP_TOWER_COUNT_HORDE, m_towersHorde); + FillInitialWorldState(data, count, WORLD_STATE_HP_TOWER_DISPLAY_A, WORLD_STATE_ADD); + FillInitialWorldState(data, count, WORLD_STATE_HP_TOWER_DISPLAY_H, WORLD_STATE_ADD); + + for (uint8 i = 0; i < MAX_HP_TOWERS; ++i) + FillInitialWorldState(data, count, m_towerWorldState[i], WORLD_STATE_ADD); +} + +void OutdoorPvPHP::SendRemoveWorldStates(Player* player) +{ + player->SendUpdateWorldState(WORLD_STATE_HP_TOWER_DISPLAY_A, WORLD_STATE_REMOVE); + player->SendUpdateWorldState(WORLD_STATE_HP_TOWER_DISPLAY_H, WORLD_STATE_REMOVE); + + for (uint8 i = 0; i < MAX_HP_TOWERS; ++i) + player->SendUpdateWorldState(m_towerWorldState[i], WORLD_STATE_REMOVE); +} + +void OutdoorPvPHP::HandlePlayerEnterZone(Player* player, bool isMainZone) +{ + OutdoorPvP::HandlePlayerEnterZone(player, isMainZone); + + // remove the buff from the player first; Sometimes on relog players still have the aura + player->RemoveAurasDueToSpell(player->GetTeam() == ALLIANCE ? SPELL_HELLFIRE_SUPERIORITY_ALLIANCE : SPELL_HELLFIRE_SUPERIORITY_HORDE); + + // buff the player if same team is controlling all capture points + if (m_towersAlliance == MAX_HP_TOWERS && player->GetTeam() == ALLIANCE) + player->CastSpell(player, SPELL_HELLFIRE_SUPERIORITY_ALLIANCE, true); + else if (m_towersHorde == MAX_HP_TOWERS && player->GetTeam() == HORDE) + player->CastSpell(player, SPELL_HELLFIRE_SUPERIORITY_HORDE, true); +} + +void OutdoorPvPHP::HandlePlayerLeaveZone(Player* player, bool isMainZone) +{ + // remove the buff from the player + player->RemoveAurasDueToSpell(player->GetTeam() == ALLIANCE ? SPELL_HELLFIRE_SUPERIORITY_ALLIANCE : SPELL_HELLFIRE_SUPERIORITY_HORDE); + + OutdoorPvP::HandlePlayerLeaveZone(player, isMainZone); +} + +void OutdoorPvPHP::HandleGameObjectCreate(GameObject* go) +{ + switch (go->GetEntry()) + { + case GO_TOWER_BANNER_OVERLOOK: + m_banners[0] = go->GetObjectGuid(); + go->SetGoArtKit(GetBannerArtKit(m_towerOwner[0], GO_ARTKIT_OVERLOOK_ALLIANCE, GO_ARTKIT_OVERLOOK_HORDE, GO_ARTKIT_OVERLOOK_NEUTRAL)); + break; + case GO_TOWER_BANNER_STADIUM: + m_banners[1] = go->GetObjectGuid(); + go->SetGoArtKit(GetBannerArtKit(m_towerOwner[1], GO_ARTKIT_STADIUM_ALLIANCE, GO_ARTKIT_STADIUM_HORDE, GO_ARTKIT_STADIUM_NEUTRAL)); + break; + case GO_TOWER_BANNER_BROKEN_HILL: + m_banners[2] = go->GetObjectGuid(); + go->SetGoArtKit(GetBannerArtKit(m_towerOwner[2], GO_ARTKIT_BROKEN_HILL_ALLIANCE, GO_ARTKIT_BROKEN_HILL_HORDE, GO_ARTKIT_BROKEN_HILL_NEUTRAL)); + break; + case GO_HELLFIRE_BANNER_OVERLOOK: + m_towers[0] = go->GetObjectGuid(); + go->SetGoArtKit(GetBannerArtKit(m_towerOwner[0])); + break; + case GO_HELLFIRE_BANNER_STADIUM: + m_towers[1] = go->GetObjectGuid(); + go->SetGoArtKit(GetBannerArtKit(m_towerOwner[1])); + break; + case GO_HELLFIRE_BANNER_BROKEN_HILL: + m_towers[2] = go->GetObjectGuid(); + go->SetGoArtKit(GetBannerArtKit(m_towerOwner[2])); + break; + } +} + +void OutdoorPvPHP::HandleObjectiveComplete(uint32 eventId, std::list players, Team team) +{ + uint32 credit = 0; + + switch (eventId) + { + case EVENT_OVERLOOK_PROGRESS_ALLIANCE: + case EVENT_OVERLOOK_PROGRESS_HORDE: + credit = NPC_CAPTURE_CREDIT_OVERLOOK; + break; + case EVENT_STADIUM_PROGRESS_ALLIANCE: + case EVENT_STADIUM_PROGRESS_HORDE: + credit = NPC_CAPTURE_CREDIT_STADIUM; + break; + case EVENT_BROKEN_HILL_PROGRESS_ALLIANCE: + case EVENT_BROKEN_HILL_PROGRESS_HORDE: + credit = NPC_CAPTURE_CREDIT_BROKEN_HILL; + break; + default: + return; + } + + for (std::list::iterator itr = players.begin(); itr != players.end(); ++itr) + { + if ((*itr) && (*itr)->GetTeam() == team) + { + (*itr)->KilledMonsterCredit(credit); + (*itr)->RewardHonor(NULL, 1, HONOR_REWARD_HELLFIRE); + } + } +} + +// Cast player spell on opponent kill +void OutdoorPvPHP::HandlePlayerKillInsideArea(Player* player, Unit* /*victim*/) +{ + for (uint8 i = 0; i < MAX_HP_TOWERS; ++i) + { + if (GameObject* capturePoint = player->GetMap()->GetGameObject(m_towers[i])) + { + // 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_towerOwner[i]) + player->CastSpell(player, player->GetTeam() == ALLIANCE ? SPELL_HELLFIRE_TOWER_TOKEN_ALLIANCE : SPELL_HELLFIRE_TOWER_TOKEN_HORDE, true); + + return; + } + } + } +} + +// process the capture events +bool OutdoorPvPHP::HandleEvent(uint32 eventId, GameObject* go) +{ + for (uint8 i = 0; i < MAX_HP_TOWERS; ++i) + { + if (hellfireBanners[i] == go->GetEntry()) + { + for (uint8 j = 0; j < 4; ++j) + { + if (hellfireTowerEvents[i][j].eventEntry == eventId) + { + // prevent processing if the owner did not change (happens if progress event is called after contest event) + if (hellfireTowerEvents[i][j].team != m_towerOwner[i]) + { + if (hellfireTowerEvents[i][j].defenseMessage) + sWorld.SendDefenseMessage(ZONE_ID_HELLFIRE_PENINSULA, hellfireTowerEvents[i][j].defenseMessage); + + return ProcessCaptureEvent(go, i, hellfireTowerEvents[i][j].team, hellfireTowerEvents[i][j].worldState, hellfireTowerEvents[i][j].towerArtKit, hellfireTowerEvents[i][j].towerAnim); + } + // no need to iterate other events or towers + return false; + } + } + // no need to iterate other towers + return false; + } + } + + return false; +} + +bool OutdoorPvPHP::ProcessCaptureEvent(GameObject* go, uint32 towerId, Team team, uint32 newWorldState, uint32 towerArtKit, uint32 towerAnim) +{ + // set artkits and process buffs + if (team == ALLIANCE) + { + SetBannerVisual(go, CAPTURE_ARTKIT_ALLIANCE, CAPTURE_ANIM_ALLIANCE); + + // update counter state + ++m_towersAlliance; + SendUpdateWorldState(WORLD_STATE_HP_TOWER_COUNT_ALLIANCE, m_towersAlliance); + + if (m_towersAlliance == MAX_HP_TOWERS) + BuffTeam(ALLIANCE, SPELL_HELLFIRE_SUPERIORITY_ALLIANCE); + } + else if (team == HORDE) + { + SetBannerVisual(go, CAPTURE_ARTKIT_HORDE, CAPTURE_ANIM_HORDE); + + // update counter + ++m_towersHorde; + SendUpdateWorldState(WORLD_STATE_HP_TOWER_COUNT_HORDE, m_towersHorde); + + if (m_towersHorde == MAX_HP_TOWERS) + BuffTeam(HORDE, SPELL_HELLFIRE_SUPERIORITY_HORDE); + } + else + { + SetBannerVisual(go, CAPTURE_ARTKIT_NEUTRAL, CAPTURE_ANIM_NEUTRAL); + + if (m_towerOwner[towerId] == ALLIANCE) + { + if (m_towersAlliance == MAX_HP_TOWERS) + BuffTeam(ALLIANCE, SPELL_HELLFIRE_SUPERIORITY_ALLIANCE, true); + + // update counter + --m_towersAlliance; + SendUpdateWorldState(WORLD_STATE_HP_TOWER_COUNT_ALLIANCE, m_towersAlliance); + } + else + { + if (m_towersHorde == MAX_HP_TOWERS) + BuffTeam(HORDE, SPELL_HELLFIRE_SUPERIORITY_HORDE, true); + + // update counter + --m_towersHorde; + SendUpdateWorldState(WORLD_STATE_HP_TOWER_COUNT_HORDE, m_towersHorde); + } + } + + SetBannerVisual(go, m_banners[towerId], towerArtKit, towerAnim); + + // update tower state + SendUpdateWorldState(m_towerWorldState[towerId], WORLD_STATE_REMOVE); + m_towerWorldState[towerId] = newWorldState; + SendUpdateWorldState(m_towerWorldState[towerId], WORLD_STATE_ADD); + + // update capture point owner + m_towerOwner[towerId] = team; + + // the are no DB exceptions in this case + return true; +} diff --git a/src/game/OutdoorPvP/OutdoorPvPHP.h b/src/game/OutdoorPvP/OutdoorPvPHP.h index 44a91c853..2a8cd481e 100644 --- a/src/game/OutdoorPvP/OutdoorPvPHP.h +++ b/src/game/OutdoorPvP/OutdoorPvPHP.h @@ -19,4 +19,159 @@ #ifndef WORLD_PVP_HP #define WORLD_PVP_HP +#include "Common.h" +#include "OutdoorPvP.h" +#include "../Language.h" + +enum +{ + MAX_HP_TOWERS = 3, + + // spells + SPELL_HELLFIRE_TOWER_TOKEN_ALLIANCE = 32155, + SPELL_HELLFIRE_TOWER_TOKEN_HORDE = 32158, + SPELL_HELLFIRE_SUPERIORITY_ALLIANCE = 32071, + SPELL_HELLFIRE_SUPERIORITY_HORDE = 32049, + + // npcs + NPC_CAPTURE_CREDIT_OVERLOOK = 19028, + NPC_CAPTURE_CREDIT_STADIUM = 19029, + NPC_CAPTURE_CREDIT_BROKEN_HILL = 19032, + + // misc + HONOR_REWARD_HELLFIRE = 18, + + // gameobjects + GO_TOWER_BANNER_OVERLOOK = 182525, + GO_TOWER_BANNER_STADIUM = 183515, + GO_TOWER_BANNER_BROKEN_HILL = 183514, + + // capture points + GO_HELLFIRE_BANNER_OVERLOOK = 182174, + GO_HELLFIRE_BANNER_STADIUM = 182173, + GO_HELLFIRE_BANNER_BROKEN_HILL = 182175, + + // events + //EVENT_OVERLOOK_WIN_ALLIANCE = 11398, + //EVENT_OVERLOOK_WIN_HORDE = 11397, + //EVENT_OVERLOOK_CONTEST_ALLIANCE = 11392, + //EVENT_OVERLOOK_CONTEST_HORDE = 11391, + EVENT_OVERLOOK_PROGRESS_ALLIANCE = 11396, + EVENT_OVERLOOK_PROGRESS_HORDE = 11395, + EVENT_OVERLOOK_NEUTRAL_ALLIANCE = 11394, + EVENT_OVERLOOK_NEUTRAL_HORDE = 11393, + + //EVENT_STADIUM_WIN_ALLIANCE = 11390, + //EVENT_STADIUM_WIN_HORDE = 11389, + //EVENT_STADIUM_CONTEST_ALLIANCE = 11384, + //EVENT_STADIUM_CONTEST_HORDE = 11383, + EVENT_STADIUM_PROGRESS_ALLIANCE = 11388, + EVENT_STADIUM_PROGRESS_HORDE = 11387, + EVENT_STADIUM_NEUTRAL_ALLIANCE = 11386, + EVENT_STADIUM_NEUTRAL_HORDE = 11385, + + //EVENT_BROKEN_HILL_WIN_ALLIANCE = 11406, + //EVENT_BROKEN_HILL_WIN_HORDE = 11405, + //EVENT_BROKEN_HILL_CONTEST_ALLIANCE = 11400, + //EVENT_BROKEN_HILL_CONTEST_HORDE = 11399, + EVENT_BROKEN_HILL_PROGRESS_ALLIANCE = 11404, + EVENT_BROKEN_HILL_PROGRESS_HORDE = 11403, + EVENT_BROKEN_HILL_NEUTRAL_ALLIANCE = 11402, + EVENT_BROKEN_HILL_NEUTRAL_HORDE = 11401, + + // tower artkits + GO_ARTKIT_BROKEN_HILL_ALLIANCE = 65, + GO_ARTKIT_BROKEN_HILL_HORDE = 64, + GO_ARTKIT_BROKEN_HILL_NEUTRAL = 66, + + GO_ARTKIT_OVERLOOK_ALLIANCE = 62, + GO_ARTKIT_OVERLOOK_HORDE = 61, + GO_ARTKIT_OVERLOOK_NEUTRAL = 63, + + GO_ARTKIT_STADIUM_ALLIANCE = 67, + GO_ARTKIT_STADIUM_HORDE = 68, + GO_ARTKIT_STADIUM_NEUTRAL = 69, + + // world states + WORLD_STATE_HP_TOWER_DISPLAY_A = 2490, + WORLD_STATE_HP_TOWER_DISPLAY_H = 2489, + WORLD_STATE_HP_TOWER_COUNT_ALLIANCE = 2476, + WORLD_STATE_HP_TOWER_COUNT_HORDE = 2478, + + WORLD_STATE_HP_BROKEN_HILL_ALLIANCE = 2483, + WORLD_STATE_HP_BROKEN_HILL_HORDE = 2484, + WORLD_STATE_HP_BROKEN_HILL_NEUTRAL = 2485, + + WORLD_STATE_HP_OVERLOOK_ALLIANCE = 2480, + WORLD_STATE_HP_OVERLOOK_HORDE = 2481, + WORLD_STATE_HP_OVERLOOK_NEUTRAL = 2482, + + WORLD_STATE_HP_STADIUM_ALLIANCE = 2471, + WORLD_STATE_HP_STADIUM_HORDE = 2470, + WORLD_STATE_HP_STADIUM_NEUTRAL = 2472 +}; + +struct HellfireTowerEvent +{ + uint32 eventEntry; + Team team; + uint32 defenseMessage; + uint32 worldState; + uint32 towerArtKit; + uint32 towerAnim; +}; + +static const HellfireTowerEvent hellfireTowerEvents[MAX_HP_TOWERS][4] = +{ + { + {EVENT_OVERLOOK_PROGRESS_ALLIANCE, ALLIANCE, LANG_OPVP_HP_CAPTURE_OVERLOOK_A, WORLD_STATE_HP_OVERLOOK_ALLIANCE, GO_ARTKIT_OVERLOOK_ALLIANCE, CAPTURE_ANIM_ALLIANCE}, + {EVENT_OVERLOOK_PROGRESS_HORDE, HORDE, LANG_OPVP_HP_CAPTURE_OVERLOOK_H, WORLD_STATE_HP_OVERLOOK_HORDE, GO_ARTKIT_OVERLOOK_HORDE, CAPTURE_ANIM_HORDE}, + {EVENT_OVERLOOK_NEUTRAL_HORDE, TEAM_NONE, 0, WORLD_STATE_HP_OVERLOOK_NEUTRAL, GO_ARTKIT_OVERLOOK_NEUTRAL, CAPTURE_ANIM_NEUTRAL}, + {EVENT_OVERLOOK_NEUTRAL_ALLIANCE, TEAM_NONE, 0, WORLD_STATE_HP_OVERLOOK_NEUTRAL, GO_ARTKIT_OVERLOOK_NEUTRAL, CAPTURE_ANIM_NEUTRAL}, + }, + { + {EVENT_STADIUM_PROGRESS_ALLIANCE, ALLIANCE, LANG_OPVP_HP_CAPTURE_STADIUM_A, WORLD_STATE_HP_STADIUM_ALLIANCE, GO_ARTKIT_STADIUM_ALLIANCE, CAPTURE_ANIM_ALLIANCE}, + {EVENT_STADIUM_PROGRESS_HORDE, HORDE, LANG_OPVP_HP_CAPTURE_STADIUM_H, WORLD_STATE_HP_STADIUM_HORDE, GO_ARTKIT_STADIUM_HORDE, CAPTURE_ANIM_HORDE}, + {EVENT_STADIUM_NEUTRAL_HORDE, TEAM_NONE, 0, WORLD_STATE_HP_STADIUM_NEUTRAL, GO_ARTKIT_STADIUM_NEUTRAL, CAPTURE_ANIM_NEUTRAL}, + {EVENT_STADIUM_NEUTRAL_ALLIANCE, TEAM_NONE, 0, WORLD_STATE_HP_STADIUM_NEUTRAL, GO_ARTKIT_STADIUM_NEUTRAL, CAPTURE_ANIM_NEUTRAL}, + }, + { + {EVENT_BROKEN_HILL_PROGRESS_ALLIANCE, ALLIANCE, LANG_OPVP_HP_CAPTURE_BROKENHILL_A, WORLD_STATE_HP_BROKEN_HILL_ALLIANCE, GO_ARTKIT_BROKEN_HILL_ALLIANCE, CAPTURE_ANIM_ALLIANCE}, + {EVENT_BROKEN_HILL_PROGRESS_HORDE, HORDE, LANG_OPVP_HP_CAPTURE_BROKENHILL_H, WORLD_STATE_HP_BROKEN_HILL_HORDE, GO_ARTKIT_BROKEN_HILL_HORDE, CAPTURE_ANIM_HORDE}, + {EVENT_BROKEN_HILL_NEUTRAL_HORDE, TEAM_NONE, 0, WORLD_STATE_HP_BROKEN_HILL_NEUTRAL, GO_ARTKIT_BROKEN_HILL_NEUTRAL, CAPTURE_ANIM_NEUTRAL}, + {EVENT_BROKEN_HILL_NEUTRAL_ALLIANCE, TEAM_NONE, 0, WORLD_STATE_HP_BROKEN_HILL_NEUTRAL, GO_ARTKIT_BROKEN_HILL_NEUTRAL, CAPTURE_ANIM_NEUTRAL}, + }, +}; + +static const uint32 hellfireBanners[MAX_HP_TOWERS] = {GO_HELLFIRE_BANNER_OVERLOOK, GO_HELLFIRE_BANNER_STADIUM, GO_HELLFIRE_BANNER_BROKEN_HILL}; + +class OutdoorPvPHP : public OutdoorPvP +{ + public: + OutdoorPvPHP(); + + 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 HandleGameObjectCreate(GameObject* go) override; + void HandlePlayerKillInsideArea(Player* player, Unit* victim) override; + + private: + // process capture events + bool ProcessCaptureEvent(GameObject* go, uint32 towerId, Team team, uint32 newWorldState, uint32 towerArtKit, uint32 towerAnim); + + Team m_towerOwner[MAX_HP_TOWERS]; + uint32 m_towerWorldState[MAX_HP_TOWERS]; + uint8 m_towersAlliance; + uint8 m_towersHorde; + + ObjectGuid m_towers[MAX_HP_TOWERS]; + ObjectGuid m_banners[MAX_HP_TOWERS]; +}; + #endif diff --git a/src/game/OutdoorPvP/OutdoorPvPMgr.cpp b/src/game/OutdoorPvP/OutdoorPvPMgr.cpp index d2479df9c..6c640cbb6 100644 --- a/src/game/OutdoorPvP/OutdoorPvPMgr.cpp +++ b/src/game/OutdoorPvP/OutdoorPvPMgr.cpp @@ -51,6 +51,7 @@ void OutdoorPvPMgr::InitOutdoorPvP() { m_scripts[OPVP_ID_SI] = new OutdoorPvPSI(); m_scripts[OPVP_ID_EP] = new OutdoorPvPEP(); + m_scripts[OPVP_ID_HP] = new OutdoorPvPHP(); sLog.outString(); sLog.outString(">> Loaded %u Outdoor PvP zones", MAX_OPVP_ID);