aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/AI/CoreAI/GameObjectAI.h6
-rwxr-xr-xsrc/server/game/AI/CreatureAISelector.cpp5
-rw-r--r--src/server/game/Battlefield/Battlefield.cpp1155
-rw-r--r--src/server/game/Battlefield/Battlefield.h401
-rw-r--r--src/server/game/Battlefield/BattlefieldHandler.cpp152
-rw-r--r--src/server/game/Battlefield/BattlefieldMgr.cpp143
-rw-r--r--src/server/game/Battlefield/BattlefieldMgr.h79
-rw-r--r--src/server/game/Battlefield/Zones/BattlefieldWG.cpp1141
-rw-r--r--src/server/game/Battlefield/Zones/BattlefieldWG.h1906
-rwxr-xr-xsrc/server/game/Battlegrounds/Battleground.cpp2
-rw-r--r--src/server/game/CMakeLists.txt5
-rwxr-xr-xsrc/server/game/Entities/GameObject/GameObject.cpp9
-rwxr-xr-xsrc/server/game/Entities/GameObject/GameObject.h1
-rwxr-xr-xsrc/server/game/Entities/Object/Object.cpp9
-rwxr-xr-xsrc/server/game/Entities/Player/Player.cpp17
-rwxr-xr-xsrc/server/game/Entities/Player/Player.h4
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.cpp7
-rwxr-xr-xsrc/server/game/Entities/Vehicle/Vehicle.cpp21
-rwxr-xr-xsrc/server/game/Entities/Vehicle/Vehicle.h3
-rwxr-xr-xsrc/server/game/Globals/ObjectAccessor.h1
-rwxr-xr-xsrc/server/game/Globals/ObjectMgr.h5
-rwxr-xr-xsrc/server/game/Groups/Group.cpp58
-rwxr-xr-xsrc/server/game/Groups/Group.h4
-rwxr-xr-xsrc/server/game/Quests/QuestDef.h2
-rwxr-xr-xsrc/server/game/Scripting/ScriptLoader.cpp2
-rwxr-xr-xsrc/server/game/Scripting/ScriptMgr.cpp8
-rwxr-xr-xsrc/server/game/Scripting/ScriptMgr.h5
-rwxr-xr-xsrc/server/game/Server/Protocol/Handlers/BattleGroundHandler.cpp40
-rwxr-xr-xsrc/server/game/Server/Protocol/Handlers/MiscHandler.cpp56
-rwxr-xr-xsrc/server/game/Server/Protocol/Opcodes.cpp6
-rwxr-xr-xsrc/server/game/Server/WorldSession.h10
-rwxr-xr-xsrc/server/game/Spells/Auras/SpellAuraEffects.cpp8
-rwxr-xr-xsrc/server/game/Spells/Spell.cpp4
-rwxr-xr-xsrc/server/game/Spells/SpellEffects.cpp1
-rwxr-xr-xsrc/server/game/Spells/SpellMgr.cpp21
-rwxr-xr-xsrc/server/game/World/World.cpp17
-rwxr-xr-xsrc/server/game/World/World.h7
-rw-r--r--src/server/scripts/CMakeLists.txt3
-rw-r--r--src/server/scripts/Commands/CMakeLists.txt1
-rw-r--r--src/server/scripts/Commands/cs_bf.cpp180
-rw-r--r--src/server/scripts/Northrend/CMakeLists.txt1
-rw-r--r--src/server/scripts/Northrend/wintergrasp.cpp418
-rw-r--r--src/server/scripts/PrecompiledHeaders/ScriptPCH.h1
-rwxr-xr-xsrc/server/shared/Logging/Log.h1
-rw-r--r--src/server/worldserver/worldserver.conf.dist51
45 files changed, 5894 insertions, 83 deletions
diff --git a/src/server/game/AI/CoreAI/GameObjectAI.h b/src/server/game/AI/CoreAI/GameObjectAI.h
index ed3a5b47e76..5c1c34d56b6 100644
--- a/src/server/game/AI/CoreAI/GameObjectAI.h
+++ b/src/server/game/AI/CoreAI/GameObjectAI.h
@@ -39,6 +39,12 @@ class GameObjectAI
virtual void Reset() {};
+ // Pass parameters between AI
+ virtual void DoAction(const int32 /*param = 0 */) {}
+ virtual uint32 GetData(uint32 /*id = 0*/) { return 0; }
+ virtual void SetGUID(const uint64 &/*guid*/, int32 /*id = 0 */) {}
+ virtual uint64 GetGUID(int32 /*id = 0 */) { return 0; }
+
static int Permissible(const GameObject* go);
virtual bool GossipHello(Player* /*player*/) {return false;}
diff --git a/src/server/game/AI/CreatureAISelector.cpp b/src/server/game/AI/CreatureAISelector.cpp
index 46cbd1abf5d..981a7fd3888 100755
--- a/src/server/game/AI/CreatureAISelector.cpp
+++ b/src/server/game/AI/CreatureAISelector.cpp
@@ -134,6 +134,11 @@ namespace FactorySelector
GameObjectAIRegistry& ai_registry(*GameObjectAIRepository::instance());
ai_factory = ai_registry.GetRegistryItem(go->GetAIName());
+
+ //scriptname in db
+ if (!ai_factory)
+ if (GameObjectAI* scriptedAI = sScriptMgr->GetGameObjectAI(go))
+ return scriptedAI;
//future goAI types go here
diff --git a/src/server/game/Battlefield/Battlefield.cpp b/src/server/game/Battlefield/Battlefield.cpp
new file mode 100644
index 00000000000..7a745e52d6a
--- /dev/null
+++ b/src/server/game/Battlefield/Battlefield.cpp
@@ -0,0 +1,1155 @@
+/*
+ * Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "Battlefield.h"
+#include "BattlefieldMgr.h"
+#include "ObjectAccessor.h"
+#include "ObjectMgr.h"
+#include "Map.h"
+#include "MapManager.h"
+#include "Group.h"
+#include "WorldPacket.h"
+#include "GridNotifiers.h"
+#include "GridNotifiersImpl.h"
+#include "GridNotifiers.h"
+#include "GridNotifiersImpl.h"
+#include "CellImpl.h"
+#include "CreatureTextMgr.h"
+
+#include "GroupMgr.h"
+
+Battlefield::Battlefield()
+{
+ m_Timer = 0;
+ m_enable = true;
+ m_WarTime = false;
+ m_DefenderTeam = TEAM_NEUTRAL;
+
+ m_TypeId = 0;
+ m_BattleId = 0;
+ m_ZoneId = 0;
+ m_MapId = 0;
+ m_MaxPlayer = 0;
+ m_MinPlayer = 0;
+ m_BattleTime = 0;
+ m_NoWarBattleTime = 0;
+ m_TimeForAcceptInvite = 20;
+ m_uiKickDontAcceptTimer = 1000;
+
+ m_uiKickAfkTimer = 1000;
+
+ m_LastResurectTimer = 30000;
+ m_StartGroupingTimer = 0;
+ m_StartGrouping = false;
+ StalkerGuid = 0;
+}
+
+Battlefield::~Battlefield()
+{
+}
+
+void Battlefield::HandlePlayerEnterZone(Player *plr, uint32 /*zone */ )
+{
+ //If battle is start,
+ // if it not fully > invite player to join the war
+ // if it fully > announce to player that BF is full and kick after few second if he dont leave
+ if (IsWarTime())
+ {
+ if (m_PlayersInWar[plr->GetTeamId()].size() + m_InvitedPlayers[plr->GetTeamId()].size() < m_MaxPlayer) //Not fully
+ {
+ InvitePlayerToWar(plr);
+ }
+ else //Full
+ {
+ //TODO:Send packet for announce it to player
+ m_PlayersWillBeKick[plr->GetTeamId()][plr->GetGUID()] = time(NULL) + 10;
+ InvitePlayerToQueue(plr);
+ }
+ }
+ else
+ {
+ //If time left is <15 minutes invite player to join queue
+ if (m_Timer <= m_StartGroupingTimer)
+ InvitePlayerToQueue(plr);
+ }
+
+ //Add player in list of player in zone
+ m_players[plr->GetTeamId()].insert(plr->GetGUID());
+ OnPlayerEnterZone(plr); //for scripting
+}
+
+//Called when a player leave the zone
+void Battlefield::HandlePlayerLeaveZone(Player *plr, uint32 /*zone */ )
+{
+ if (IsWarTime())
+ {
+ //if player is in war list
+ if (m_PlayersInWar[plr->GetTeamId()].find(plr->GetGUID()) != m_PlayersInWar[plr->GetTeamId()].end())
+ {
+ m_PlayersInWar[plr->GetTeamId()].erase(plr->GetGUID());
+ plr->GetSession()->SendBfLeaveMessage(m_BattleId);
+ if (Group* group = GetGroupPlayer(plr->GetGUID(), plr->GetTeamId())) // remove from raid group if player is member
+ {
+ // I think that now is not a hack
+ if (!group->RemoveMember(plr->GetGUID())) // group was disbanded
+ {
+ m_Groups[plr->GetTeamId()].erase(group->GetGUID());
+ group->SetBattlefieldGroup(NULL);
+ sGroupMgr->RemoveGroup(group);
+ delete group;
+ }
+ }
+ OnPlayerLeaveWar(plr); //For scripting
+ }
+ }
+
+ for (BfCapturePointMap::iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr)
+ itr->second->HandlePlayerLeave(plr);
+
+ m_InvitedPlayers[plr->GetTeamId()].erase(plr->GetGUID());
+ m_PlayersWillBeKick[plr->GetTeamId()].erase(plr->GetGUID());
+ m_players[plr->GetTeamId()].erase(plr->GetGUID());
+ SendRemoveWorldStates(plr);
+ RemovePlayerFromResurrectQueue(plr->GetGUID());
+ OnPlayerLeaveZone(plr); //For scripting
+}
+
+bool Battlefield::Update(uint32 diff)
+{
+ //When global timer is end
+ if (m_Timer <= diff)
+ {
+ //Here end of battle by timer
+ if (IsWarTime())
+ EndBattle(true);
+ //Start of battle
+ else
+ StartBattle();
+ }
+ else
+ m_Timer -= diff;
+
+ //Some times before battle start invite player to queue
+ if (!m_StartGrouping && m_Timer <= m_StartGroupingTimer)
+ {
+ m_StartGrouping = true;
+ InvitePlayerInZoneToQueue();
+ OnStartGrouping(); // for scripting
+ }
+
+ bool objective_changed = false;
+ if (IsWarTime())
+ {
+ if (m_uiKickAfkTimer <= diff)
+ {
+ m_uiKickAfkTimer = 1000;
+ KickAfk();
+ }
+ else
+ m_uiKickAfkTimer -= diff;
+
+ //Here kick player witch dont have accept invitation to join the war when time is end (time of windows)
+ if (m_uiKickDontAcceptTimer <= diff)
+ {
+ for (int team = 0; team < 2; team++)
+ for (PlayerTimerMap::iterator itr = m_InvitedPlayers[team].begin(); itr != m_InvitedPlayers[team].end(); itr++)
+ if ((*itr).second <= time(NULL))
+ KickPlayerFromBf((*itr).first);
+ InvitePlayerInZoneToWar();
+ for (int team = 0; team < 2; team++)
+ for (PlayerTimerMap::iterator itr = m_PlayersWillBeKick[team].begin(); itr != m_PlayersWillBeKick[team].end(); itr++)
+ if ((*itr).second <= time(NULL))
+ KickPlayerFromBf((*itr).first);
+
+ m_uiKickDontAcceptTimer = 1000;
+ }
+ else
+ m_uiKickDontAcceptTimer -= diff;
+
+ for (BfCapturePointMap::iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr)
+ if (itr->second->Update(diff))
+ objective_changed = true;
+ }
+
+
+ if (m_LastResurectTimer <= diff)
+ {
+ for (uint8 i = 0; i < m_GraveYardList.size(); i++)
+ if (GetGraveYardById(i))
+ m_GraveYardList[i]->Resurrect();
+ m_LastResurectTimer = RESURRECTION_INTERVAL;
+ }
+ else
+ m_LastResurectTimer -= diff;
+
+ return objective_changed;
+}
+
+void Battlefield::InvitePlayerInZoneToQueue()
+{
+ for (uint8 team = 0; team < 2; ++team)
+ for (GuidSet::const_iterator p_itr = m_players[team].begin(); p_itr != m_players[team].end(); ++p_itr)
+ if (Player* plr = sObjectMgr->GetPlayer((*p_itr)))
+ InvitePlayerToQueue(plr);
+}
+
+void Battlefield::InvitePlayerToQueue(Player *plr)
+{
+ if (m_PlayersInQueue[plr->GetTeamId()].count(plr->GetGUID()))
+ return;
+
+ if (m_PlayersInQueue[plr->GetTeam()].size() <= m_MinPlayer || m_PlayersInQueue[plr->GetTeam() == TEAM_ALLIANCE ? TEAM_HORDE : TEAM_ALLIANCE].size() >= m_MinPlayer)
+ plr->GetSession()->SendBfInvitePlayerToQueue(m_BattleId);
+}
+
+void Battlefield::InvitePlayerInQueueToWar()
+{
+ for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team)
+ {
+ for (GuidSet::const_iterator p_itr = m_PlayersInQueue[team].begin(); p_itr != m_PlayersInQueue[team].end(); ++p_itr)
+ {
+ if (Player* plr = sObjectAccessor->FindPlayer(*p_itr))
+ {
+ if (m_PlayersInWar[plr->GetTeamId()].size() + m_InvitedPlayers[plr->GetTeamId()].size() < m_MaxPlayer)
+ InvitePlayerToWar(plr);
+ else
+ {
+ //Full
+ }
+ }
+ }
+ m_PlayersInQueue[team].clear();
+ }
+}
+
+void Battlefield::InvitePlayerInZoneToWar()
+{
+ for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team)
+ for (GuidSet::const_iterator p_itr = m_players[team].begin(); p_itr != m_players[team].end(); ++p_itr)
+ {
+ if (Player* plr = sObjectMgr->GetPlayer((*p_itr)))
+ {
+ if (m_PlayersInWar[plr->GetTeamId()].count(plr->GetGUID()) || m_InvitedPlayers[plr->GetTeamId()].count(plr->GetGUID()))
+ continue;
+ if (m_PlayersInWar[plr->GetTeamId()].size() + m_InvitedPlayers[plr->GetTeamId()].size() < m_MaxPlayer)
+ InvitePlayerToWar(plr);
+ else
+ {
+ //full
+ m_PlayersWillBeKick[plr->GetTeamId()][plr->GetGUID()] = time(NULL) + 10;
+ }
+ }
+ }
+}
+
+void Battlefield::InvitePlayerToWar(Player *plr)
+{
+ if (!plr)
+ return;
+
+ //TODO : needed ?
+ if (plr->isInFlight())
+ return;
+
+ if (plr->InArena() || plr->GetBattleground())
+ {
+ m_PlayersInQueue[plr->GetTeamId()].erase(plr->GetGUID());
+ return;
+ }
+
+ if (plr->getLevel() < m_MinLevel)
+ {
+ if (m_PlayersWillBeKick[plr->GetTeamId()].count(plr->GetGUID()) == 0)
+ m_PlayersWillBeKick[plr->GetTeamId()][plr->GetGUID()] = time(NULL) + 10;
+ return;
+ }
+ //Check if player is not already in war
+ if (m_PlayersInWar[plr->GetTeamId()].count(plr->GetGUID()) || m_InvitedPlayers[plr->GetTeamId()].count(plr->GetGUID()))
+ return;
+
+ m_PlayersWillBeKick[plr->GetTeamId()].erase(plr->GetGUID());
+ m_InvitedPlayers[plr->GetTeamId()][plr->GetGUID()] = time(NULL) + m_TimeForAcceptInvite;
+ plr->GetSession()->SendBfInvitePlayerToWar(m_BattleId, m_ZoneId, m_TimeForAcceptInvite);
+}
+
+void Battlefield::InitStalker(uint32 entry, float x, float y, float z, float o)
+{
+ if (Creature * creature = SpawnCreature(entry, x, y, z, o, TEAM_NEUTRAL))
+ StalkerGuid = creature->GetGUID();
+ else
+ sLog->outError("Battlefield::InitStalker: could not spawn Stalker (Creature entry %u), zone messeges will be un-available", entry);
+}
+
+void Battlefield::KickAfk()
+{
+ for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team)
+ for (GuidSet::const_iterator p_itr = m_PlayersInWar[team].begin(); p_itr != m_PlayersInWar[team].end(); ++p_itr)
+ if (Player* plr = sObjectAccessor->FindPlayer((*p_itr)))
+ if (plr->isAFK())
+ KickPlayerFromBf((*p_itr));
+}
+
+void Battlefield::KickPlayerFromBf(uint64 guid)
+{
+ if (Player* plr = sObjectAccessor->FindPlayer(guid))
+ if (plr->GetZoneId() == GetZoneId())
+ plr->TeleportTo(KickPosition);
+}
+
+void Battlefield::StartBattle()
+{
+ if (m_WarTime)
+ return;
+
+ for (int team = 0; team < BG_TEAMS_COUNT; team++)
+ {
+ m_PlayersInWar[team].clear();
+ m_Groups[team].clear();
+ }
+
+ m_Timer = m_BattleTime;
+ m_WarTime = true;
+
+ InvitePlayerInZoneToWar();
+ InvitePlayerInQueueToWar();
+
+ PlaySoundToAll(BF_START);
+
+ OnBattleStart();
+}
+
+void Battlefield::EndBattle(bool endbytimer)
+{
+ m_WarTime = false;
+
+ m_StartGrouping = false;
+
+ if (!endbytimer)
+ SetDefenderTeam(GetAttackerTeam());
+
+ if (GetDefenderTeam() == TEAM_ALLIANCE)
+ PlaySoundToAll(BF_ALLIANCE_WINS); // alliance wins sound
+ else
+ PlaySoundToAll(BF_HORDE_WINS); // horde wins sound
+
+
+ OnBattleEnd(endbytimer);
+
+ //reset bf timer
+ m_Timer = m_NoWarBattleTime;
+ SendInitWorldStatesToAll();
+}
+
+void Battlefield::PlaySoundToAll(uint32 SoundID)
+{
+ WorldPacket data;
+ data.Initialize(SMSG_PLAY_SOUND, 4);
+ data << uint32(SoundID);
+
+ for (int team = 0; team < BG_TEAMS_COUNT; team++)
+ for (GuidSet::const_iterator itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr)
+ {
+ Player *plr = sObjectMgr->GetPlayer((*itr));
+ if (plr)
+ plr->GetSession()->SendPacket(&data);
+ }
+}
+
+bool Battlefield::HasPlayer(Player *plr) const
+{
+ return m_players[plr->GetTeamId()].find(plr->GetGUID()) != m_players[plr->GetTeamId()].end();
+}
+
+// Called in WorldSession::HandleBfQueueInviteResponse
+void Battlefield::PlayerAcceptInviteToQueue(Player *plr)
+{
+ // Add player in queueVenez
+ m_PlayersInQueue[plr->GetTeamId()].insert(plr->GetGUID());
+ // Send notification
+ plr->GetSession()->SendBfQueueInviteResponce(m_BattleId, m_ZoneId);
+}
+// Called in WorldSession::HandleBfExitRequest
+void Battlefield::AskToLeaveQueue(Player *plr)
+{
+ // Remove player from queue
+ m_PlayersInQueue[plr->GetTeamId()].erase(plr->GetGUID());
+}
+
+// Called in WorldSession::HandleBfEntryInviteResponse
+void Battlefield::PlayerAcceptInviteToWar(Player *plr)
+{
+ if (!IsWarTime())
+ return;
+
+ if (AddOrSetPlayerToCorrectBfGroup(plr))
+ {
+ plr->GetSession()->SendBfEntered(m_BattleId);
+ m_PlayersInWar[plr->GetTeamId()].insert(plr->GetGUID());
+ m_InvitedPlayers[plr->GetTeamId()].erase(plr->GetGUID());
+ //Remove player AFK
+ if (plr->isAFK())
+ plr->ToggleAFK();
+
+ OnPlayerJoinWar(plr); //for scripting
+ }
+}
+
+void Battlefield::TeamCastSpell(TeamId team, int32 spellId)
+{
+ if (spellId > 0)
+ for (GuidSet::const_iterator p_itr = m_PlayersInWar[team].begin(); p_itr != m_PlayersInWar[team].end(); ++p_itr)
+ if (Player* plr = sObjectMgr->GetPlayer((*p_itr)))
+ plr->CastSpell(plr, (uint32) spellId, true);
+ else
+ for (GuidSet::const_iterator p_itr = m_PlayersInWar[team].begin(); p_itr != m_PlayersInWar[team].end(); ++p_itr)
+ if (Player* plr = sObjectMgr->GetPlayer((*p_itr)))
+ plr->RemoveAuraFromStack((uint32) - spellId);
+}
+
+void Battlefield::BroadcastPacketZone(WorldPacket & data) const
+{
+ for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team)
+ for (GuidSet::const_iterator itr = m_players[team].begin(); itr != m_players[team].end(); ++itr)
+ if (Player* plr = sObjectMgr->GetPlayer((*itr)))
+ plr->GetSession()->SendPacket(&data);
+}
+
+void Battlefield::BroadcastPacketQueue(WorldPacket & data) const
+{
+ for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team)
+ for (GuidSet::const_iterator itr = m_PlayersInQueue[team].begin(); itr != m_PlayersInQueue[team].end(); ++itr)
+ if (Player* plr = sObjectMgr->GetPlayer((*itr)))
+ plr->GetSession()->SendPacket(&data);
+}
+
+void Battlefield::BroadcastPacketWar(WorldPacket & data) const
+{
+ for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team)
+ for (GuidSet::const_iterator itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr)
+ if (Player* plr = sObjectMgr->GetPlayer((*itr)))
+ plr->GetSession()->SendPacket(&data);
+}
+
+WorldPacket Battlefield::BuildWarningAnnPacket(std::string msg)
+{
+ WorldPacket data(SMSG_MESSAGECHAT, 200);
+
+ data << uint8(CHAT_MSG_RAID_BOSS_EMOTE);
+ data << uint32(LANG_UNIVERSAL);
+ data << uint64(0);
+ data << uint32(0); // 2.1.0
+ data << uint32(1);
+ data << uint8(0);
+ data << uint64(0);
+ data << uint32(strlen(msg.c_str()) + 1);
+ data << msg.c_str();
+ data << uint8(0);
+
+ return data;
+}
+
+void Battlefield::SendWarningToAllInZone(uint32 entry)
+{
+ if (Unit* unit = sObjectAccessor->FindUnit(StalkerGuid))
+ if (Creature* stalker = unit->ToCreature())
+ // FIXME: replaced CHAT_TYPE_END with CHAT_MSG_BG_SYSTEM_NEUTRAL to fix compile, it's a guessed change :/
+ sCreatureTextMgr->SendChat(stalker, (uint8) entry, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_ADDON, TEXT_RANGE_ZONE);
+}
+
+/*void Battlefield::SendWarningToAllInWar(int32 entry,...)
+{
+ const char *format = sObjectMgr->GetTrinityStringForDBCLocale(entry);
+ va_list ap;
+ char str [1024];
+ va_start(ap, entry);
+ vsnprintf(str,1024,format, ap);
+ va_end(ap);
+ std::string msg = (std::string)str;
+
+ WorldPacket data = BuildWarningAnnPacket(msg);
+ BroadcastPacketWar(data);
+}*/
+void Battlefield::SendWarningToPlayer(Player *plr, uint32 entry)
+{
+ if (!plr)
+ return;
+
+ if (Unit* unit = sObjectAccessor->FindUnit(StalkerGuid))
+ if (Creature* stalker = unit->ToCreature())
+ sCreatureTextMgr->SendChat(stalker, (uint8)entry, plr->GetGUID());
+}
+
+void Battlefield::SendUpdateWorldState(uint32 field, uint32 value)
+{
+ for (uint8 i = 0; i < BG_TEAMS_COUNT; ++i)
+ for (GuidSet::iterator itr = m_players[i].begin(); itr != m_players[i].end(); ++itr)
+ if (Player *plr = sObjectMgr->GetPlayer((*itr)))
+ plr->SendUpdateWorldState(field, value);
+}
+
+void Battlefield::RegisterZone(uint32 zoneId)
+{
+ sBattlefieldMgr.AddZone(zoneId, this);
+}
+
+void Battlefield::HideNpc(Creature * p_Creature)
+{
+ p_Creature->CombatStop();
+ p_Creature->SetReactState(REACT_PASSIVE);
+ p_Creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
+ p_Creature->SetPhaseMask(2, true);
+ p_Creature->DisappearAndDie();
+ p_Creature->SetVisible(false);
+}
+
+void Battlefield::ShowNpc(Creature * p_Creature, bool p_Aggressive)
+{
+ p_Creature->SetPhaseMask(1, true);
+ p_Creature->SetVisible(true);
+ p_Creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
+ if (!p_Creature->isAlive())
+ p_Creature->Respawn(true);
+ if (p_Aggressive)
+ p_Creature->SetReactState(REACT_AGGRESSIVE);
+ else
+ {
+ p_Creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ p_Creature->SetReactState(REACT_PASSIVE);
+ }
+}
+
+//*****************************************************
+//*******************Group System**********************
+//*****************************************************
+Group *Battlefield::GetFreeBfRaid(TeamId TeamId)
+{
+ //if found free group we return it
+ for (GuidSet::const_iterator itr = m_Groups[TeamId].begin(); itr != m_Groups[TeamId].end(); ++itr)
+ if (Group* group = sGroupMgr->GetGroupByGUID(*itr))
+ if (!group->IsFull())
+ return group;
+
+ return NULL;
+}
+
+Group *Battlefield::GetGroupPlayer(uint64 guid, TeamId TeamId)
+{
+ for (GuidSet::const_iterator itr = m_Groups[TeamId].begin(); itr != m_Groups[TeamId].end(); ++itr)
+ if (Group* group = sGroupMgr->GetGroupByGUID(*itr))
+ if (group->IsMember(guid))
+ return group;
+
+ return NULL;
+}
+
+bool Battlefield::AddOrSetPlayerToCorrectBfGroup(Player *plr)
+{
+ if (!plr->IsInWorld())
+ return false;
+
+ if (Group* group = plr->GetGroup())
+ group->RemoveMember(plr->GetGUID());
+
+ Group* group = GetFreeBfRaid(plr->GetTeamId());
+ if (!group)
+ {
+ group = new Group;
+ group->SetBattlefieldGroup(this);
+ group->Create(plr);
+ sGroupMgr->AddGroup(group);
+ m_Groups[plr->GetTeamId()].insert(group->GetGUID());
+ }
+ else if (group->IsMember(plr->GetGUID()))
+ {
+ uint8 subgroup = group->GetMemberGroup(plr->GetGUID());
+ plr->SetBattlegroundOrBattlefieldRaid(group, subgroup);
+ }
+ else
+ group->AddMember(plr);
+
+ return true;
+}
+
+//***************End of Group System*******************
+
+//*****************************************************
+//***************Spirit Guide System*******************
+//*****************************************************
+//--------------------
+//-Battlefield Method-
+//--------------------
+BfGraveYard *Battlefield::GetGraveYardById(uint32 id)
+{
+ if (id < m_GraveYardList.size())
+ {
+ if (m_GraveYardList[id])
+ return m_GraveYardList[id];
+ else
+ sLog->outError("Battlefield::GetGraveYardById Id:%u not existed", id);
+ }
+ else
+ sLog->outError("Battlefield::GetGraveYardById Id:%u cant be found", id);
+
+ return NULL;
+}
+
+WorldSafeLocsEntry const *Battlefield::GetClosestGraveYard(Player *plr)
+{
+ BfGraveYard* closestGY = NULL;
+ float maxdist = -1;
+ for (uint8 i = 0; i < m_GraveYardList.size(); i++)
+ {
+ if (m_GraveYardList[i])
+ {
+ if (m_GraveYardList[i]->GetControlTeamId() != plr->GetTeamId())
+ continue;
+
+ float dist = m_GraveYardList[i]->GetDistance(plr);
+ if (dist < maxdist || maxdist < 0)
+ {
+ closestGY = m_GraveYardList[i];
+ maxdist = dist;
+ }
+ }
+ }
+
+ if (closestGY)
+ return sWorldSafeLocsStore.LookupEntry(closestGY->GetGraveYardId());
+
+ return NULL;
+}
+
+void Battlefield::AddPlayerToResurrectQueue(uint64 npc_guid, uint64 player_guid)
+{
+ for (uint8 i = 0; i < m_GraveYardList.size(); i++)
+ {
+ if (!m_GraveYardList[i])
+ continue;
+
+ if (m_GraveYardList[i]->HasNpc(npc_guid))
+ {
+ m_GraveYardList[i]->AddPlayer(player_guid);
+ break;
+ }
+ }
+}
+
+void Battlefield::RemovePlayerFromResurrectQueue(uint64 player_guid)
+{
+ for (uint8 i = 0; i < m_GraveYardList.size(); i++)
+ {
+ if (!m_GraveYardList[i])
+ continue;
+
+ if (m_GraveYardList[i]->HasPlayer(player_guid))
+ {
+ m_GraveYardList[i]->RemovePlayer(player_guid);
+ break;
+ }
+ }
+}
+
+void Battlefield::SendAreaSpiritHealerQueryOpcode(Player *pl, const uint64 &guid)
+{
+ sLog->outError("SendAreaSpiritHealerQueryOpcode");
+ WorldPacket data(SMSG_AREA_SPIRIT_HEALER_TIME, 12);
+ uint32 time = m_LastResurectTimer; // resurrect every 30 seconds
+
+ data << guid << time;
+ ASSERT(pl && pl->GetSession());
+ pl->GetSession()->SendPacket(&data);
+}
+
+bool Battlefield::IncrementQuest(Player *player, uint32 quest, bool complete)
+{
+ if (!player)
+ return false;
+
+ Quest const* pQuest = sObjectMgr->GetQuestTemplate(quest);
+ if (!pQuest || player->GetQuestStatus(quest) == QUEST_STATUS_NONE)
+ return false;
+
+ if (complete)
+ {
+ player->CompleteQuest(quest);
+ return true;
+ }
+ else
+ {
+ for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
+ {
+ int32 creature = pQuest->ReqCreatureOrGOId[i];
+ if (uint32 spell_id = pQuest->ReqSpell[i])
+ {
+ player->CastedCreatureOrGO(creature, 0, spell_id);
+ return true;
+ }
+ else if (creature > 0)
+ {
+ player->KilledMonsterCredit(creature, 0);
+ return true;
+ }
+ else if (creature < 0)
+ {
+ player->CastedCreatureOrGO(creature, 0, 0);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+//--------------------
+//-BfGraveYard Method-
+//--------------------
+BfGraveYard::BfGraveYard(Battlefield *Bf)
+{
+ m_Bf = Bf;
+ m_GraveyardId = 0;
+ m_ControlTeam = TEAM_NEUTRAL;
+ m_SpiritGuide[0] = NULL;
+ m_SpiritGuide[1] = NULL;
+ m_ResurrectQueue.clear();
+}
+
+void BfGraveYard::Init(uint32 horde_entry, uint32 alliance_entry, float x, float y, float z, float o, TeamId startcontrol, uint32 gy)
+{
+ m_ControlTeam = startcontrol;
+ if (Creature * cre = m_Bf->SpawnCreature(horde_entry, x, y, z, o, TEAM_HORDE))
+ {
+ m_SpiritGuide[TEAM_HORDE] = cre;
+ m_SpiritGuide[TEAM_HORDE]->SetReactState(REACT_PASSIVE);
+ if (m_ControlTeam == TEAM_ALLIANCE)
+ m_SpiritGuide[TEAM_HORDE]->SetVisible(false);
+ }
+ else
+ sLog->outError("BfGraveYard::Init can't spawn horde spiritguide %u", horde_entry);
+
+ if (Creature * cre = m_Bf->SpawnCreature(alliance_entry, x, y, z, o, TEAM_ALLIANCE))
+ {
+ m_SpiritGuide[TEAM_ALLIANCE] = cre;
+ m_SpiritGuide[TEAM_ALLIANCE]->SetReactState(REACT_PASSIVE);
+ if (m_ControlTeam == TEAM_HORDE)
+ m_SpiritGuide[TEAM_ALLIANCE]->SetVisible(false);
+ }
+ else
+ sLog->outError("BfGraveYard::Init can't spawn alliance spiritguide %u", alliance_entry);
+
+ m_GraveyardId = gy;
+}
+
+float BfGraveYard::GetDistance(Player *plr)
+{
+ const WorldSafeLocsEntry* ws = sWorldSafeLocsStore.LookupEntry(m_GraveyardId);
+ return plr->GetDistance2d(ws->x, ws->y);
+}
+
+void BfGraveYard::AddPlayer(uint64 player_guid)
+{
+ if (!m_ResurrectQueue.count(player_guid))
+ {
+ m_ResurrectQueue.insert(player_guid);
+
+ Player* plr = sObjectMgr->GetPlayer(player_guid);
+ if (plr)
+ plr->CastSpell(plr, SPELL_WAITING_FOR_RESURRECT, true);
+ }
+}
+
+void BfGraveYard::RemovePlayer(uint64 player_guid)
+{
+ m_ResurrectQueue.erase(m_ResurrectQueue.find(player_guid));
+ Player* plr = sObjectMgr->GetPlayer(player_guid);
+
+ if (plr)
+ plr->RemoveAurasDueToSpell(SPELL_WAITING_FOR_RESURRECT);
+}
+
+void BfGraveYard::Resurrect()
+{
+ if (m_ResurrectQueue.empty())
+ return;
+
+ for (GuidSet::const_iterator itr = m_ResurrectQueue.begin(); itr != m_ResurrectQueue.end(); ++itr)
+ {
+ //Get player object from his guid
+ Player* plr = sObjectMgr->GetPlayer(*itr);
+ if (!plr)
+ continue;
+
+ //Cherck player isinworld and player is on good graveyard
+ if (plr->IsInWorld())
+ if (m_SpiritGuide[m_ControlTeam])
+ m_SpiritGuide[m_ControlTeam]->CastSpell(m_SpiritGuide[m_ControlTeam], SPELL_SPIRIT_HEAL, true);
+
+ //Resurect player
+ plr->CastSpell(plr, SPELL_RESURRECTION_VISUAL, true);
+ plr->ResurrectPlayer(1.0f);
+ plr->CastSpell(plr, 6962, true);
+ plr->CastSpell(plr, SPELL_SPIRIT_HEAL_MANA, true);
+
+ sObjectAccessor->ConvertCorpseForPlayer(plr->GetGUID());
+ }
+
+ m_ResurrectQueue.clear();
+}
+
+//For changing graveyard control
+void BfGraveYard::ChangeControl(TeamId team)
+{
+ //Guide switching
+ if (m_SpiritGuide[1 - team])
+ m_SpiritGuide[1 - team]->SetVisible(false);
+ if (m_SpiritGuide[team])
+ m_SpiritGuide[team]->SetVisible(true);
+
+ m_ControlTeam = team;
+ //Teleport to other graveyard, player witch were on this graveyard
+ RelocateDeadPlayers();
+}
+
+void BfGraveYard::RelocateDeadPlayers()
+{
+ WorldSafeLocsEntry const* ClosestGrave = NULL;
+ for (GuidSet::const_iterator itr = m_ResurrectQueue.begin(); itr != m_ResurrectQueue.end(); ++itr)
+ {
+ Player* plr = sObjectMgr->GetPlayer(*itr);
+ if (!plr)
+ continue;
+
+ if (ClosestGrave)
+ plr->TeleportTo(plr->GetMapId(), ClosestGrave->x, ClosestGrave->y, ClosestGrave->z, plr->GetOrientation());
+ else
+ {
+ ClosestGrave = m_Bf->GetClosestGraveYard(plr);
+ if (ClosestGrave)
+ plr->TeleportTo(plr->GetMapId(), ClosestGrave->x, ClosestGrave->y, ClosestGrave->z, plr->GetOrientation());
+ }
+ }
+}
+
+//***************End Spirit Guide system***************
+
+//*****************************************************
+//**********************Misc***************************
+//*****************************************************
+//Method for spawn creature on map
+Creature *Battlefield::SpawnCreature(uint32 entry, Position pos, TeamId team)
+{
+ return SpawnCreature(entry, pos.m_positionX, pos.m_positionY, pos.m_positionZ, pos.m_orientation, team);
+}
+
+Creature *Battlefield::SpawnCreature(uint32 entry, float x, float y, float z, float o, TeamId team)
+{
+ //Get map object
+ Map* map = const_cast < Map * >(sMapMgr->CreateBaseMap(m_MapId));
+ if (!map)
+ {
+ sLog->outError("Can't create creature entry: %u map not found", entry);
+ return 0;
+ }
+
+ //Create creature
+ Creature* pCreature = new Creature;
+ if (!pCreature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, PHASEMASK_NORMAL, entry, 0, team, x, y, z, o))
+ {
+ sLog->outError("Can't create creature entry: %u", entry);
+ delete pCreature;
+ return NULL;
+ }
+
+ pCreature->SetHomePosition(x, y, z, o);
+
+ CreatureTemplate const* cinfo = sObjectMgr->GetCreatureTemplate(entry);
+ if (!cinfo)
+ {
+ sLog->outErrorDb("Battleground::AddCreature: entry %u does not exist.", entry);
+ return NULL;
+ }
+ //force using DB speeds
+ pCreature->SetSpeed(MOVE_WALK, cinfo->speed_walk);
+ pCreature->SetSpeed(MOVE_RUN, cinfo->speed_run);
+
+ //Set creature in world
+ map->Add(pCreature);
+ pCreature->setActive(true);
+
+ return pCreature;
+}
+
+//Method for spawning gameobject on map
+GameObject *Battlefield::SpawnGameObject(uint32 entry, float x, float y, float z, float o)
+{
+ //Get map object
+ Map *map = const_cast < Map * >(sMapMgr->CreateBaseMap(571));
+ if (!map)
+ return 0;
+
+ //Create gameobject
+ GameObject *go = new GameObject;
+ if (!go->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), entry, map, PHASEMASK_NORMAL, x, y, z, o, 0, 0, 0, 0, 100, GO_STATE_READY))
+ {
+ sLog->outErrorDb("Gameobject template %u not found in database! Battleground not created!", entry);
+ sLog->outError("Cannot create gameobject template %u! Battleground not created!", entry);
+ delete go;
+ return NULL;
+ }
+
+ //Add in the world
+ map->Add(go);
+ go->setActive(true);
+ return go;
+}
+
+//*****************************************************
+//*******************CapturePoint**********************
+//*****************************************************
+
+BfCapturePoint::BfCapturePoint(Battlefield *Bf):m_Bf(Bf), m_capturePoint(NULL)
+{
+ m_team = TEAM_NEUTRAL;
+ m_value = 0;
+ m_maxValue = 0;
+ m_State = BF_CAPTUREPOINT_OBJECTIVESTATE_NEUTRAL;
+ m_OldState = BF_CAPTUREPOINT_OBJECTIVESTATE_NEUTRAL;
+ m_capturePointEntry = 0;
+ m_neutralValuePct = 0;
+ m_maxSpeed = 0;
+}
+
+bool BfCapturePoint::HandlePlayerEnter(Player *plr)
+{
+ if (m_capturePoint)
+ {
+ plr->SendUpdateWorldState(m_capturePoint->GetGOInfo()->capturePoint.worldState1, 1);
+ plr->SendUpdateWorldState(m_capturePoint->GetGOInfo()->capturePoint.worldstate2, (uint32) ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f));
+ plr->SendUpdateWorldState(m_capturePoint->GetGOInfo()->capturePoint.worldstate3, m_neutralValuePct);
+ }
+ return m_activePlayers[plr->GetTeamId()].insert(plr->GetGUID()).second;
+}
+
+void BfCapturePoint::HandlePlayerLeave(Player *plr)
+{
+ if (m_capturePoint)
+ plr->SendUpdateWorldState(m_capturePoint->GetGOInfo()->capturePoint.worldState1, 0);
+ m_activePlayers[plr->GetTeamId()].erase(plr->GetGUID());
+}
+
+void BfCapturePoint::SendChangePhase()
+{
+ if (!m_capturePoint)
+ return;
+
+ // send this too, sometimes the slider disappears, dunno why :(
+ SendUpdateWorldState(m_capturePoint->GetGOInfo()->capturePoint.worldState1, 1);
+ // send these updates to only the ones in this objective
+ SendUpdateWorldState(m_capturePoint->GetGOInfo()->capturePoint.worldstate2, (uint32) ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f));
+ // send this too, sometimes it resets :S
+ SendUpdateWorldState(m_capturePoint->GetGOInfo()->capturePoint.worldstate3, m_neutralValuePct);
+}
+
+bool BfCapturePoint::SetCapturePointData(uint32 entry, uint32 /*map */ , float x, float y, float z, float o)
+{
+ sLog->outDebug(LOG_FILTER_BATTLEFIELD, "Creating capture point %u", entry);
+
+ // check info existence
+ GameObjectTemplate const* goinfo = sObjectMgr->GetGameObjectTemplate(entry);
+ if (!goinfo || goinfo->type != GAMEOBJECT_TYPE_CAPTURE_POINT)
+ {
+ sLog->outError("OutdoorPvP: GO %u is not capture point!", entry);
+ return false;
+ }
+ m_capturePoint = m_Bf->SpawnGameObject(entry, x, y, z, o);
+ if (m_capturePoint)
+ {
+ // get the needed values from goinfo
+ m_maxValue = goinfo->capturePoint.maxTime;
+ m_maxSpeed = m_maxValue / (goinfo->capturePoint.minTime ? goinfo->capturePoint.minTime : 60);
+ m_neutralValuePct = goinfo->capturePoint.neutralPercent;
+ m_minValue = m_maxValue * goinfo->capturePoint.neutralPercent / 100;
+ m_capturePointEntry = entry;
+ if (m_team == TEAM_ALLIANCE)
+ {
+ m_value = m_maxValue;
+ m_State = BF_CAPTUREPOINT_OBJECTIVESTATE_ALLIANCE;
+ }
+ else
+ {
+ m_value = -m_maxValue;
+ m_State = BF_CAPTUREPOINT_OBJECTIVESTATE_HORDE;
+ }
+ return true;
+ }
+
+ return false;
+}
+
+bool BfCapturePoint::DelCapturePoint()
+{
+ if (m_capturePoint)
+ {
+ m_capturePoint->SetRespawnTime(0); // not save respawn time
+ m_capturePoint->Delete();
+ m_capturePoint = NULL;
+ }
+
+ return true;
+}
+
+bool BfCapturePoint::Update(uint32 diff)
+{
+ if (!m_capturePoint)
+ return false;
+
+ float radius = m_capturePoint->GetGOInfo()->capturePoint.radius;
+
+ for (uint8 team = 0; team < 2; ++team)
+ for (GuidSet::iterator itr = m_activePlayers[team].begin(); itr != m_activePlayers[team].end(); ++itr)
+ if (Player* plr = sObjectMgr->GetPlayer((*itr)))
+ if (!m_capturePoint->IsWithinDistInMap(plr, radius) || !plr->IsOutdoorPvPActive())
+ HandlePlayerLeave(plr);
+
+ std::list < Player * >players;
+ Trinity::AnyPlayerInObjectRangeCheck checker(m_capturePoint, radius);
+ Trinity::PlayerListSearcher < Trinity::AnyPlayerInObjectRangeCheck > searcher(m_capturePoint, players, checker);
+ m_capturePoint->VisitNearbyWorldObject(radius, searcher);
+
+ for (std::list < Player * >::iterator itr = players.begin(); itr != players.end(); ++itr)
+ if ((*itr)->IsOutdoorPvPActive())
+ if (m_activePlayers[(*itr)->GetTeamId()].insert((*itr)->GetGUID()).second)
+ HandlePlayerEnter(*itr);
+
+ // get the difference of numbers
+ float fact_diff = ((float) m_activePlayers[0].size() - (float) m_activePlayers[1].size()) * diff / BATTLEFIELD_OBJECTIVE_UPDATE_INTERVAL;
+ if (!fact_diff)
+ return false;
+
+ uint32 Challenger = 0;
+ float maxDiff = m_maxSpeed * diff;
+
+ if (fact_diff < 0)
+ {
+ // horde is in majority, but it's already horde-controlled -> no change
+ if (m_State == BF_CAPTUREPOINT_OBJECTIVESTATE_HORDE && m_value <= -m_maxValue)
+ return false;
+
+ if (fact_diff < -maxDiff)
+ fact_diff = -maxDiff;
+
+ Challenger = HORDE;
+ }
+ else
+ {
+ // ally is in majority, but it's already ally-controlled -> no change
+ if (m_State == BF_CAPTUREPOINT_OBJECTIVESTATE_ALLIANCE && m_value >= m_maxValue)
+ return false;
+
+ if (fact_diff > maxDiff)
+ fact_diff = maxDiff;
+
+ Challenger = ALLIANCE;
+ }
+
+ float oldValue = m_value;
+ TeamId oldTeam = m_team;
+
+ m_OldState = m_State;
+
+ m_value += fact_diff;
+
+ if (m_value < -m_minValue) // red
+ {
+ if (m_value < -m_maxValue)
+ m_value = -m_maxValue;
+ m_State = BF_CAPTUREPOINT_OBJECTIVESTATE_HORDE;
+ m_team = TEAM_HORDE;
+ }
+ else if (m_value > m_minValue) // blue
+ {
+ if (m_value > m_maxValue)
+ m_value = m_maxValue;
+ m_State = BF_CAPTUREPOINT_OBJECTIVESTATE_ALLIANCE;
+ m_team = TEAM_ALLIANCE;
+ }
+ else if (oldValue * m_value <= 0) // grey, go through mid point
+ {
+ // if challenger is ally, then n->a challenge
+ if (Challenger == ALLIANCE)
+ m_State = BF_CAPTUREPOINT_OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE;
+ // if challenger is horde, then n->h challenge
+ else if (Challenger == HORDE)
+ m_State = BF_CAPTUREPOINT_OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE;
+ m_team = TEAM_NEUTRAL;
+ }
+ else // grey, did not go through mid point
+ {
+ // old phase and current are on the same side, so one team challenges the other
+ if (Challenger == ALLIANCE && (m_OldState == BF_CAPTUREPOINT_OBJECTIVESTATE_HORDE || m_OldState == BF_CAPTUREPOINT_OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE))
+ m_State = BF_CAPTUREPOINT_OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE;
+ else if (Challenger == HORDE && (m_OldState == BF_CAPTUREPOINT_OBJECTIVESTATE_ALLIANCE || m_OldState == BF_CAPTUREPOINT_OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE))
+ m_State = BF_CAPTUREPOINT_OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE;
+ m_team = TEAM_NEUTRAL;
+ }
+
+ if (m_value != oldValue)
+ SendChangePhase();
+
+ if (m_OldState != m_State)
+ {
+ //sLog->outError("%u->%u", m_OldState, m_State);
+ if (oldTeam != m_team)
+ ChangeTeam(oldTeam);
+ return true;
+ }
+
+ return false;
+}
+
+void BfCapturePoint::SendUpdateWorldState(uint32 field, uint32 value)
+{
+ for (uint8 team = 0; team < 2; ++team)
+ for (GuidSet::iterator itr = m_activePlayers[team].begin(); itr != m_activePlayers[team].end(); ++itr) // send to all players present in the area
+ if (Player* plr = sObjectMgr->GetPlayer((*itr)))
+ plr->SendUpdateWorldState(field, value);
+}
+
+void BfCapturePoint::SendObjectiveComplete(uint32 id, uint64 guid)
+{
+ uint8 team;
+ switch (m_State)
+ {
+ case BF_CAPTUREPOINT_OBJECTIVESTATE_ALLIANCE:
+ team = 0;
+ break;
+ case BF_CAPTUREPOINT_OBJECTIVESTATE_HORDE:
+ team = 1;
+ break;
+ default:
+ return;
+ }
+
+ // send to all players present in the area
+ for (GuidSet::iterator itr = m_activePlayers[team].begin(); itr != m_activePlayers[team].end(); ++itr)
+ if (Player* plr = sObjectMgr->GetPlayer((*itr)))
+ plr->KilledMonsterCredit(id, guid);
+}
+
+bool BfCapturePoint::IsInsideObjective(Player *plr) const
+{
+ return m_activePlayers[plr->GetTeamId()].find(plr->GetGUID()) != m_activePlayers[plr->GetTeamId()].end();
+}
diff --git a/src/server/game/Battlefield/Battlefield.h b/src/server/game/Battlefield/Battlefield.h
new file mode 100644
index 00000000000..c083fbfb232
--- /dev/null
+++ b/src/server/game/Battlefield/Battlefield.h
@@ -0,0 +1,401 @@
+/*
+ * Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef BATTLEFIELD_H_
+#define BATTLEFIELD_H_
+
+#include "Utilities/Util.h"
+#include "SharedDefines.h"
+#include "ZoneScript.h"
+#include "WorldPacket.h"
+#include "GameObject.h"
+
+enum BattlefieldTypes
+{
+ BATTLEFIELD_WG, // Wintergrasp
+ BATTLEFIELD_TB, // Tol Barad (cataclysm)
+};
+
+enum BattlefieldIDs
+{
+ BATTLEFIELD_BATTLEID_WG = 1, // Wintergrasp battle
+};
+
+enum BattlefieldObjectiveStates
+{
+ BF_CAPTUREPOINT_OBJECTIVESTATE_NEUTRAL = 0,
+ BF_CAPTUREPOINT_OBJECTIVESTATE_ALLIANCE,
+ BF_CAPTUREPOINT_OBJECTIVESTATE_HORDE,
+ BF_CAPTUREPOINT_OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE,
+ BF_CAPTUREPOINT_OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE,
+ BF_CAPTUREPOINT_OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE,
+ BF_CAPTUREPOINT_OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE,
+};
+
+enum BattlefieldSounds
+{
+ BF_HORDE_WINS = 8454,
+ BF_ALLIANCE_WINS = 8455,
+ BF_START = 3439
+};
+
+enum BattlefieldTimers
+{
+ BATTLEFIELD_OBJECTIVE_UPDATE_INTERVAL = 1000
+};
+
+// some class predefs
+class Player;
+class GameObject;
+class WorldPacket;
+class Creature;
+class Unit;
+
+class Battlefield;
+class BfGraveYard;
+
+typedef std::set < uint64 > GuidSet;
+typedef std::vector < BfGraveYard * >GraveYardVect;
+typedef std::map < uint64, uint32 > PlayerTimerMap;
+
+class BfCapturePoint
+{
+public:
+ BfCapturePoint(Battlefield * bf);
+
+ virtual void FillInitialWorldStates(WorldPacket & /*data */ ) {}
+
+ // send world state update to all players present
+ void SendUpdateWorldState(uint32 field, uint32 value);
+
+ // send kill notify to players in the controlling faction
+ void SendObjectiveComplete(uint32 id, uint64 guid);
+
+ // used when player is activated/inactivated in the area
+ virtual bool HandlePlayerEnter(Player * plr);
+ virtual void HandlePlayerLeave(Player * plr);
+ //virtual void HandlePlayerActivityChanged(Player * plr);
+
+ // checks if player is in range of a capture credit marker
+ bool IsInsideObjective(Player * plr) const;
+
+ // returns true if the state of the objective has changed, in this case, the OutdoorPvP must send a world state ui update.
+ virtual bool Update(uint32 diff);
+ virtual void ChangeTeam(TeamId /*oldTeam */ ) {}
+ virtual void SendChangePhase();
+
+ bool SetCapturePointData(uint32 entry, uint32 map, float x, float y, float z, float o);
+ GameObject *GetCapturePointGo() { return m_capturePoint; }
+
+ TeamId GetTeamId() {return m_team;}
+protected:
+ bool DelCapturePoint();
+
+ // active players in the area of the objective, 0 - alliance, 1 - horde
+ GuidSet m_activePlayers[2];
+
+ // total shift needed to capture the objective
+ float m_maxValue;
+ float m_minValue;
+
+ // maximum speed of capture
+ float m_maxSpeed;
+
+ // the status of the objective
+ float m_value;
+ TeamId m_team;
+
+ // objective states
+ BattlefieldObjectiveStates m_OldState;
+ BattlefieldObjectiveStates m_State;
+
+ // neutral value on capture bar
+ uint32 m_neutralValuePct;
+
+ // pointer to the Battlefield this objective belongs to
+ Battlefield *m_Bf;
+ uint32 m_capturePointEntry;
+ GameObject *m_capturePoint;
+};
+
+class BfGraveYard
+{
+public:
+ BfGraveYard(Battlefield *Bf);
+
+ // method for change who control the graveyard
+ void ChangeControl(TeamId team);
+ TeamId GetControlTeamId() { return m_ControlTeam; }
+
+ // use for found the nearest graveyard
+ float GetDistance(Player * plr);
+ void Init(uint32 horde_entry, uint32 alliance_entry, float x, float y, float z, float o, TeamId startcontrol, uint32 gy);
+ void AddPlayer(uint64 player_guid);
+ void RemovePlayer(uint64 player_guid);
+
+ void Resurrect();
+ void RelocateDeadPlayers();
+
+ bool HasNpc(uint64 guid) { return (m_SpiritGuide[0]->GetGUID() == guid || m_SpiritGuide[1]->GetGUID() == guid); }
+ bool HasPlayer(uint64 guid) { return m_ResurrectQueue.find(guid) != m_ResurrectQueue.end(); }
+ uint32 GetGraveYardId() { return m_GraveyardId; }
+
+protected:
+
+ TeamId m_ControlTeam;
+ uint32 m_GraveyardId;
+ Creature *m_SpiritGuide[2];
+ GuidSet m_ResurrectQueue;
+ Battlefield *m_Bf;
+};
+
+class Battlefield:public ZoneScript
+{
+ friend class BattlefieldMgr;
+
+ public:
+ /// Constructor
+ Battlefield();
+ /// Destructor
+ virtual ~Battlefield();
+
+ /// typedef of map witch store capturepoint and the associate gameobject entry
+ typedef std::map < uint32 /*lowguid */ , BfCapturePoint * >BfCapturePointMap;
+
+ /// Call this to init the Battlefield
+ virtual bool SetupBattlefield() { return true; }
+
+ /// Generate packet which contain all worldstatedata of area
+ virtual void FillInitialWorldStates(WorldPacket & /*data */ ) {}
+
+ /// Call when a GameObject/Creature is created OR destroyed (view bool add)
+ void OnGameObjectCreate(GameObject * /*go */ , bool /*add */ ) {}
+ void OnCreatureCreate(Creature * /*cre */ , bool /*add */ ) {}
+
+ /// Update data of a worldstate to all players present in zone
+ void SendUpdateWorldState(uint32 field, uint32 value);
+
+ /**
+ * \brief Called every time for update bf data and time
+ * -Update timer for start/end battle
+ * -Invite player in zone to queue x minutes before start (x = m_StartGroupingTimer)
+ * -Kick Afk players
+ * \param diff : time ellapsed since last call (in ms)
+ */
+ virtual bool Update(uint32 diff);
+
+ /// Invite all player in zone, to join the queue, called x minutes before battle start in Update()
+ void InvitePlayerInZoneToQueue();
+ /// Invite all player in queue to join battle on battle start
+ void InvitePlayerInQueueToWar();
+ /// Invite all player in zone to join battle on battle start
+ void InvitePlayerInZoneToWar();
+
+ /// Called when a Unit is kill in battlefield zone
+ virtual void HandleKill(Player * /*killer */ , Unit * /*killed */ ) {};
+
+ uint32 GetTypeId() { return m_TypeId; }
+ uint32 GetZoneId() { return m_ZoneId; }
+
+ void TeamApplyBuff(TeamId team, uint32 spellId, uint32 spellId2 = 0);
+
+ /// Return true if battle is start, false if battle is not started
+ bool IsWarTime() { return m_WarTime; }
+
+ /// Enable or Disable battlefield
+ void SetEnable(bool enable) { m_enable = enable; }
+ /// Return if battlefield is enable
+ bool GetEnable() { return m_enable; }
+
+ /**
+ * \brief Kick player from battlefield and teleport him to kick-point location
+ * \param guid : guid of player who must be kick
+ */
+ void KickPlayerFromBf(uint64 guid);
+
+ /// Called when player (plr) enter in zone
+ void HandlePlayerEnterZone(Player * plr, uint32 zone);
+ /// Called when player (plr) leave the zone
+ void HandlePlayerLeaveZone(Player * plr, uint32 zone);
+
+ // All-purpose data storage 64 bit
+ virtual uint64 GetData64(uint32 DataId) { return m_Data64[DataId]; }
+ virtual void SetData64(uint32 DataId, uint64 Value) { m_Data64[DataId] = Value; }
+
+ // All-purpose data storage 32 bit
+ virtual uint32 GetData(uint32 DataId) { return m_Data32[DataId]; }
+ virtual void SetData(uint32 DataId, uint32 Value) { m_Data32[DataId] = Value; }
+
+ // Battlefield - generic methods
+ TeamId GetDefenderTeam() { return m_DefenderTeam; }
+ TeamId GetAttackerTeam() { return TeamId(1 - m_DefenderTeam); }
+ void SetDefenderTeam(TeamId team) { m_DefenderTeam = team; }
+
+ // Group methods
+ /**
+ * \brief Find a not full battlefield group, if there is no, create one
+ * \param TeamId : Id of player team for who we search a group (plr->GetTeamId())
+ */
+ Group *GetFreeBfRaid(TeamId TeamId);
+ /// Return battlefield group where player is.
+ Group *GetGroupPlayer(uint64 guid, TeamId TeamId);
+ /// Force player to join a battlefield group
+ bool AddOrSetPlayerToCorrectBfGroup(Player * plr);
+
+ // Graveyard methods
+ // Find which graveyard the player must be teleported to to be resurrected by spiritguide
+ WorldSafeLocsEntry const *GetClosestGraveYard(Player * plr);
+
+ virtual void AddPlayerToResurrectQueue(uint64 npc_guid, uint64 player_guid);
+ void RemovePlayerFromResurrectQueue(uint64 player_guid);
+ void SetGraveyardNumber(uint32 number) { m_GraveYardList.resize(number); }
+ BfGraveYard *GetGraveYardById(uint32 id);
+
+ // Misc methods
+ Creature *SpawnCreature(uint32 entry, float x, float y, float z, float o, TeamId team);
+ Creature *SpawnCreature(uint32 entry, Position pos, TeamId team);
+ GameObject *SpawnGameObject(uint32 entry, float x, float y, float z, float o);
+
+ // Script-methods
+
+ /// Called on start
+ virtual void OnBattleStart() {};
+ /// Called at the end of battle
+ virtual void OnBattleEnd(bool /*endbytimer */ ) {};
+ /// Called x minutes before battle start when player in zone are invite to join queue
+ virtual void OnStartGrouping() {};
+ /// Called when a player accept to join the battle
+ virtual void OnPlayerJoinWar(Player * /*plr */ ) {};
+ /// Called when a player leave the battle
+ virtual void OnPlayerLeaveWar(Player * /*plr */ ) {};
+ /// Called when a player leave battlefield zone
+ virtual void OnPlayerLeaveZone(Player * /*plr */ ) {};
+ /// Called when a player enter in battlefield zone
+ virtual void OnPlayerEnterZone(Player * /*plr */ ) {};
+
+ WorldPacket BuildWarningAnnPacket(std::string msg);
+ void SendWarningToAllInZone(uint32 entry);
+ //void SendWarningToAllInWar(int32 entry, ...); -- UNUSED
+ void SendWarningToPlayer(Player * plr, uint32 entry);
+
+ void PlayerAcceptInviteToQueue(Player * plr);
+ void PlayerAcceptInviteToWar(Player * plr);
+ uint32 GetBattleId() { return m_BattleId; }
+ void AskToLeaveQueue(Player * plr);
+
+ virtual void DoCompleteOrIncrementAchievement(uint32 /*achievement */ , Player * /*player */ , uint8 /*incrementNumber = 1 */ ) {};
+
+ /// Send all worldstate data to all player in zone.
+ virtual void SendInitWorldStatesToAll() {};
+
+ /// Return if we can use mount in battlefield
+ bool CanFlyIn() { return !m_WarTime; } // Used for check if we can use flying mount or not
+ bool IncrementQuest(Player * player, uint32 quest, bool complete = false);
+ void SendAreaSpiritHealerQueryOpcode(Player * pl, const uint64 & guid);
+
+ void StartBattle();
+ void EndBattle(bool endbytimer);
+
+ void HideNpc(Creature * p_Creature);
+ void ShowNpc(Creature * p_Creature, bool p_Aggressive);
+
+ GraveYardVect GetGraveYardVect() { return m_GraveYardList; }
+
+ uint32 GetTimer() { return m_Timer; }
+ void SetTimer(uint32 timer) { m_Timer = timer; }
+
+ void PlaySoundToAll(uint32 SoundID);
+
+ void InvitePlayerToQueue(Player * plr);
+ void InvitePlayerToWar(Player * plr);
+
+ void InitStalker(uint32 entry, float x, float y, float z, float o);
+
+protected:
+ uint64 StalkerGuid;
+ uint32 m_Timer; // Global timer for event
+ bool m_enable;
+ bool m_WarTime;
+ TeamId m_DefenderTeam;
+
+ // the map of the objectives belonging to this outdoorpvp
+ BfCapturePointMap m_capturePoints;
+
+ // the set of player
+ GuidSet m_players[BG_TEAMS_COUNT]; // Players in zone
+ GuidSet m_PlayersInQueue[BG_TEAMS_COUNT]; // Players in the queue
+ GuidSet m_PlayersInWar[BG_TEAMS_COUNT]; // Players in WG combat
+ PlayerTimerMap m_InvitedPlayers[BG_TEAMS_COUNT];
+ PlayerTimerMap m_PlayersWillBeKick[BG_TEAMS_COUNT];
+
+ //Variables that must exist for each battlefield
+ uint32 m_TypeId; // See enum BattlefieldTypes
+ uint32 m_BattleId; // BattleID (for packet)
+ uint32 m_ZoneId; // ZoneID of Wintergrasp = 4197
+ uint32 m_MapId; // MapId where is Battlefield
+ uint32 m_MaxPlayer; // Maximum number of player that participated to Battlefield
+ uint32 m_MinPlayer; // Minimum number of player for Battlefield start
+ uint32 m_MinLevel; // Required level to participate at Battlefield
+ uint32 m_BattleTime; // Length of a battle
+ uint32 m_NoWarBattleTime; // Time between two battles
+ uint32 m_RestartAfterCrash; // Delay to restart Wintergrasp if the server crashed during a running battle.
+ uint32 m_TimeForAcceptInvite;
+ uint32 m_uiKickDontAcceptTimer;
+ WorldLocation KickPosition; // Position where player is teleport if they switch to afk during battle or if they dont accept invitation
+
+ uint32 m_uiKickAfkTimer; // Timer for check Afk in war
+
+ //Graveyard variables
+ GraveYardVect m_GraveYardList; // Vector witch contain the different GY of the battle
+ uint32 m_LastResurectTimer; // Timer for resurect player every 30 sec
+
+ uint32 m_StartGroupingTimer; // Timer for invite players in area 15 minute before start battle
+ bool m_StartGrouping; // bool for know if all players in area has been invited
+
+ GuidSet m_Groups[BG_TEAMS_COUNT]; // Contain different raid group
+
+ std::vector < uint64 > m_Data64;
+ std::vector < uint32 > m_Data32;
+
+ void KickAfk();
+ // use for switch off all worldstate for client
+ virtual void SendRemoveWorldStates(Player * /*plr */ ) {}
+
+ // use for send a packet for all player list
+ void BroadcastPacketZone(WorldPacket & data) const;
+ void BroadcastPacketQueue(WorldPacket & data) const;
+ void BroadcastPacketWar(WorldPacket & data) const;
+
+ //CapturePoint system
+ void AddCapturePoint(BfCapturePoint * cp) { m_capturePoints[cp->GetCapturePointGo()->GetEntry()] = cp; }
+
+ BfCapturePoint *GetCapturePoint(uint32 lowguid) const
+ {
+ Battlefield::BfCapturePointMap::const_iterator itr = m_capturePoints.find(lowguid);
+ if (itr != m_capturePoints.end())
+ return itr->second;
+ return NULL;
+ }
+
+ void RegisterZone(uint32 zoneid);
+ bool HasPlayer(Player * plr) const;
+ void TeamCastSpell(TeamId team, int32 spellId);
+
+};
+
+#endif
diff --git a/src/server/game/Battlefield/BattlefieldHandler.cpp b/src/server/game/Battlefield/BattlefieldHandler.cpp
new file mode 100644
index 00000000000..b0d0a239d45
--- /dev/null
+++ b/src/server/game/Battlefield/BattlefieldHandler.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "Common.h"
+#include "ObjectAccessor.h"
+#include "ObjectMgr.h"
+#include "WorldPacket.h"
+#include "WorldSession.h"
+
+#include "Battlefield.h"
+#include "BattlefieldMgr.h"
+#include "Opcodes.h"
+
+//This send to player windows for invite player to join the war
+//Param1:(BattleId) the BattleId of Bf
+//Param2:(ZoneId) the zone where the battle is (4197 for wg)
+//Param3:(time) Time in second that the player have for accept
+void WorldSession::SendBfInvitePlayerToWar(uint32 BattleId, uint32 ZoneId, uint32 p_time)
+{
+ //Send packet
+ WorldPacket data(SMSG_BATTLEFIELD_MGR_ENTRY_INVITE, 12);
+ data << uint32(BattleId);
+ data << uint32(ZoneId);
+ data << uint32((time(NULL) + p_time));
+
+ //Sending the packet to player
+ SendPacket(&data);
+}
+
+//This send invitation to player to join the queue
+//Param1:(BattleId) the BattleId of Bf
+void WorldSession::SendBfInvitePlayerToQueue(uint32 BattleId)
+{
+ WorldPacket data(SMSG_BATTLEFIELD_MGR_QUEUE_INVITE, 5);
+
+ data << uint32(BattleId);
+ data << uint8(1); //warmup ? used ?
+
+ //Sending packet to player
+ SendPacket(&data);
+}
+
+//This send packet for inform player that he join queue
+//Param1:(BattleId) the BattleId of Bf
+//Param2:(ZoneId) the zone where the battle is (4197 for wg)
+void WorldSession::SendBfQueueInviteResponce(uint32 BattleId, uint32 ZoneId)
+{
+ WorldPacket data(SMSG_BATTLEFIELD_MGR_QUEUE_REQUEST_RESPONSE, 11);
+ data << uint32(BattleId);
+ data << uint32(ZoneId);
+ data << uint8(1); //Accepted
+ data << uint8(0); //Logging In
+ data << uint8(1); //Warmup
+
+ SendPacket(&data);
+}
+
+//This is call when player accept to join war
+//Param1:(BattleId) the BattleId of Bf
+void WorldSession::SendBfEntered(uint32 BattleId)
+{
+// m_PlayerInWar[plr->GetTeamId()].insert(plr->GetGUID());
+ WorldPacket data(SMSG_BATTLEFIELD_MGR_ENTERED, 7);
+ data << uint32(BattleId);
+ data << uint8(1); //unk
+ data << uint8(1); //unk
+ data << uint8(_player->isAFK() ? 1 : 0); //Clear AFK
+
+ SendPacket(&data);
+}
+
+//Send when player is kick from Battlefield
+void WorldSession::SendBfLeaveMessage(uint32 BattleId)
+{
+ WorldPacket data(SMSG_BATTLEFIELD_MGR_EJECTED, 7);
+ data << uint32(BattleId);
+ data << uint8(8); //byte Reason
+ data << uint8(2); //byte BattleStatus
+ data << uint8(0); //bool Relocated
+
+ SendPacket(&data);
+}
+
+//Send by client when he click on accept for queue
+void WorldSession::HandleBfQueueInviteResponse(WorldPacket & recv_data)
+{
+ uint32 BattleId;
+ uint8 Accepted;
+
+ recv_data >> BattleId >> Accepted;
+ sLog->outError("HandleQueueInviteResponse: BattleID:%u Accepted:%u", BattleId, Accepted);
+ Battlefield* Bf = sBattlefieldMgr.GetBattlefieldByBattleId(BattleId);
+ if (!Bf)
+ return;
+
+ if (Accepted)
+ {
+ Bf->PlayerAcceptInviteToQueue(_player);
+ }
+}
+
+//Send by client on clicking in accept or refuse of invitation windows for join game
+void WorldSession::HandleBfEntryInviteResponse(WorldPacket & recv_data)
+{
+ uint32 BattleId;
+ uint8 Accepted;
+
+ recv_data >> BattleId >> Accepted;
+ sLog->outError("HandleBattlefieldInviteResponse: BattleID:%u Accepted:%u", BattleId, Accepted);
+ Battlefield* Bf = sBattlefieldMgr.GetBattlefieldByBattleId(BattleId);
+ if (!Bf)
+ return;
+
+ //If player accept invitation
+ if (Accepted)
+ {
+ Bf->PlayerAcceptInviteToWar(_player);
+ }
+ else
+ {
+ if (_player->GetZoneId() == Bf->GetZoneId())
+ Bf->KickPlayerFromBf(_player->GetGUID());
+ }
+}
+
+void WorldSession::HandleBfExitRequest(WorldPacket & recv_data)
+{
+ uint32 BattleId;
+
+ recv_data >> BattleId;
+ sLog->outError("HandleBfExitRequest: BattleID:%u ", BattleId);
+ Battlefield* Bf = sBattlefieldMgr.GetBattlefieldByBattleId(BattleId);
+ if (!Bf)
+ return;
+
+ Bf->AskToLeaveQueue(_player);
+}
diff --git a/src/server/game/Battlefield/BattlefieldMgr.cpp b/src/server/game/Battlefield/BattlefieldMgr.cpp
new file mode 100644
index 00000000000..29640414f2b
--- /dev/null
+++ b/src/server/game/Battlefield/BattlefieldMgr.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "BattlefieldMgr.h"
+#include "Zones/BattlefieldWG.h"
+#include "ObjectMgr.h"
+#include "Player.h"
+
+BattlefieldMgr::BattlefieldMgr()
+{
+ m_UpdateTimer = 0;
+ //sLog->outDebug(LOG_FILTER_BATTLEFIELD, "Instantiating BattlefieldMgr");
+}
+
+BattlefieldMgr::~BattlefieldMgr()
+{
+ //sLog->outDebug(LOG_FILTER_BATTLEFIELD, "Deleting BattlefieldMgr");
+ for (BattlefieldSet::iterator itr = m_BattlefieldSet.begin(); itr != m_BattlefieldSet.end(); ++itr)
+ delete *itr;
+}
+
+void BattlefieldMgr::InitBattlefield()
+{
+ Battlefield* pBf = new BattlefieldWG;
+ // respawn, init variables
+ if (!pBf->SetupBattlefield())
+ {
+ sLog->outString();
+ sLog->outString("Battlefield : Wintergrasp init failed.");
+ delete pBf;
+ }
+ else
+ {
+ m_BattlefieldSet.push_back(pBf);
+ sLog->outString();
+ sLog->outString("Battlefield : Wintergrasp successfully initiated.");
+ }
+
+ /* For Cataclysm: Tol Barad
+ pBf = new BattlefieldTB;
+ // respawn, init variables
+ if(!pBf->SetupBattlefield())
+ {
+ sLog->outDebug(LOG_FILTER_BATTLEFIELD, "Battlefield : Tol Barad init failed.");
+ delete pBf;
+ }
+ else
+ {
+ m_BattlefieldSet.push_back(pBf);
+ sLog->outDebug(LOG_FILTER_BATTLEFIELD, "Battlefield : Tol Barad successfully initiated.");
+ } */
+}
+
+void BattlefieldMgr::AddZone(uint32 zoneid, Battlefield *handle)
+{
+ m_BattlefieldMap[zoneid] = handle;
+}
+
+void BattlefieldMgr::HandlePlayerEnterZone(Player * plr, uint32 zoneid)
+{
+ BattlefieldMap::iterator itr = m_BattlefieldMap.find(zoneid);
+ if (itr == m_BattlefieldMap.end())
+ return;
+
+ if (itr->second->HasPlayer(plr))
+ return;
+ if (itr->second->GetEnable() == false)
+ return;
+ itr->second->HandlePlayerEnterZone(plr, zoneid);
+ sLog->outDebug(LOG_FILTER_BATTLEFIELD, "Player %u entered outdoorpvp id %u", plr->GetGUIDLow(), itr->second->GetTypeId());
+}
+
+void BattlefieldMgr::HandlePlayerLeaveZone(Player * plr, uint32 zoneid)
+{
+ BattlefieldMap::iterator itr = m_BattlefieldMap.find(zoneid);
+ if (itr == m_BattlefieldMap.end())
+ return;
+
+ // teleport: remove once in removefromworld, once in updatezone
+ if (!itr->second->HasPlayer(plr))
+ return;
+ itr->second->HandlePlayerLeaveZone(plr, zoneid);
+ sLog->outDebug(LOG_FILTER_BATTLEFIELD, "Player %u left outdoorpvp id %u", plr->GetGUIDLow(), itr->second->GetTypeId());
+}
+
+Battlefield *BattlefieldMgr::GetBattlefieldToZoneId(uint32 zoneid)
+{
+ BattlefieldMap::iterator itr = m_BattlefieldMap.find(zoneid);
+ if (itr == m_BattlefieldMap.end())
+ {
+ // no handle for this zone, return
+ return NULL;
+ }
+ if (itr->second->GetEnable() == false)
+ return NULL;
+ return itr->second;
+}
+
+Battlefield *BattlefieldMgr::GetBattlefieldByBattleId(uint32 battleid)
+{
+ for (BattlefieldSet::iterator itr = m_BattlefieldSet.begin(); itr != m_BattlefieldSet.end(); ++itr)
+ {
+ if ((*itr)->GetBattleId() == battleid)
+ return (*itr);
+ }
+ return NULL;
+}
+
+void BattlefieldMgr::Update(uint32 diff)
+{
+ m_UpdateTimer += diff;
+ if (m_UpdateTimer > BATTLEFIELD_OBJECTIVE_UPDATE_INTERVAL)
+ {
+ for (BattlefieldSet::iterator itr = m_BattlefieldSet.begin(); itr != m_BattlefieldSet.end(); ++itr)
+ if ((*itr)->GetEnable())
+ (*itr)->Update(m_UpdateTimer);
+ m_UpdateTimer = 0;
+ }
+}
+
+ZoneScript *BattlefieldMgr::GetZoneScript(uint32 zoneId)
+{
+ BattlefieldMap::iterator itr = m_BattlefieldMap.find(zoneId);
+ if (itr != m_BattlefieldMap.end())
+ return itr->second;
+ else
+ return NULL;
+}
diff --git a/src/server/game/Battlefield/BattlefieldMgr.h b/src/server/game/Battlefield/BattlefieldMgr.h
new file mode 100644
index 00000000000..eec66483974
--- /dev/null
+++ b/src/server/game/Battlefield/BattlefieldMgr.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef BATTLEFIELD_MGR_H_
+#define BATTLEFIELD_MGR_H_
+
+#include "Battlefield.h"
+#include "ace/Singleton.h"
+
+class Player;
+class GameObject;
+class Creature;
+class ZoneScript;
+struct GossipMenuItems;
+
+// class to handle player enter / leave / areatrigger / GO use events
+class BattlefieldMgr
+{
+ public:
+ // ctor
+ BattlefieldMgr();
+ // dtor
+ ~BattlefieldMgr();
+
+ // create battlefield events
+ void InitBattlefield();
+ // called when a player enters an battlefield area
+ void HandlePlayerEnterZone(Player * plr, uint32 areaflag);
+ // called when player leaves an battlefield area
+ void HandlePlayerLeaveZone(Player * plr, uint32 areaflag);
+ // called when player resurrects
+ void HandlePlayerResurrects(Player * plr, uint32 areaflag);
+ // return assigned battlefield
+ Battlefield *GetBattlefieldToZoneId(uint32 zoneid);
+ Battlefield *GetBattlefieldByBattleId(uint32 battleid);
+
+ ZoneScript *GetZoneScript(uint32 zoneId);
+
+ void AddZone(uint32 zoneid, Battlefield * handle);
+
+ void Update(uint32 diff);
+
+ void HandleGossipOption(Player * player, uint64 guid, uint32 gossipid);
+
+ bool CanTalkTo(Player * player, Creature * creature, GossipMenuItems gso);
+
+ void HandleDropFlag(Player * plr, uint32 spellId);
+
+ typedef std::vector < Battlefield * >BattlefieldSet;
+ typedef std::map < uint32 /* zoneid */ , Battlefield * >BattlefieldMap;
+ private:
+ // contains all initiated battlefield events
+ // used when initing / cleaning up
+ BattlefieldSet m_BattlefieldSet;
+ // maps the zone ids to an battlefield event
+ // used in player event handling
+ BattlefieldMap m_BattlefieldMap;
+ // update interval
+ uint32 m_UpdateTimer;
+};
+
+#define sBattlefieldMgr (*ACE_Singleton<BattlefieldMgr, ACE_Null_Mutex>::instance())
+
+#endif
diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp
new file mode 100644
index 00000000000..bf6a0a04add
--- /dev/null
+++ b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp
@@ -0,0 +1,1141 @@
+/*
+ * Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+// TODO: Implement proper support for vehicle+player teleportation
+// TODO: Use spell victory/defeat in wg instead of RewardMarkOfHonor() && RewardHonor
+// TODO: Add proper implement of achievement
+
+#include "BattlefieldWG.h"
+#include "SpellAuras.h"
+
+enum eWGBfData
+{
+ BATTLEFIELD_WG_ZONEID = 4197, // Wintergrasp
+ BATTLEFIELD_WG_MAPID = 571, // Northrend
+};
+
+bool BattlefieldWG::SetupBattlefield()
+{
+ InitStalker(BATTLEFIELD_WG_NPC_STALKER, WintergraspStalkerPos[0], WintergraspStalkerPos[1], WintergraspStalkerPos[2], WintergraspStalkerPos[3]);
+
+ m_TypeId = BATTLEFIELD_WG; // See enum BattlefieldTypes
+ m_BattleId = BATTLEFIELD_BATTLEID_WG;
+ m_ZoneId = BATTLEFIELD_WG_ZONEID;
+ m_MapId = BATTLEFIELD_WG_MAPID;
+
+ m_MaxPlayer = sWorld->getIntConfig(CONFIG_WINTERGRASP_PLR_MAX);
+ m_enable = sWorld->getBoolConfig(CONFIG_WINTERGRASP_ENABLE);
+ m_MinPlayer = sWorld->getIntConfig(CONFIG_WINTERGRASP_PLR_MIN);
+ m_MinLevel = sWorld->getIntConfig(CONFIG_WINTERGRASP_PLR_MIN_LVL);
+ m_BattleTime = sWorld->getIntConfig(CONFIG_WINTERGRASP_BATTLETIME) * MINUTE;
+ m_NoWarBattleTime = sWorld->getIntConfig(CONFIG_WINTERGRASP_NOBATTLETIME) * MINUTE;
+ m_RestartAfterCrash = sWorld->getIntConfig(CONFIG_WINTERGRASP_RESTART_AFTER_CRASH) * MINUTE;
+
+ m_TimeForAcceptInvite = 20;
+ m_StartGroupingTimer = 15 * MINUTE;
+ m_StartGrouping = false;
+
+ m_tenacityStack = 0;
+
+ KickPosition.Relocate(5728.117f, 2714.346f, 697.733f, 0);
+ KickPosition.m_mapId = m_MapId;
+
+ RegisterZone(m_ZoneId);
+
+ m_Data32.resize(BATTLEFIELD_WG_DATA_MAX);
+
+ m_saveTimer = 60000;
+
+ // Init GraveYards
+ SetGraveyardNumber(BATTLEFIELD_WG_GY_MAX);
+
+ // Load from db
+ if ((sWorld->getWorldState(3801) == 0) && (sWorld->getWorldState(3802) == 0) && (sWorld->getWorldState(ClockWorldState[0]) == 0))
+ {
+ sWorld->setWorldState(3801, false);
+ sWorld->setWorldState(3802, urand(0, 1));
+ sWorld->setWorldState(ClockWorldState[0], m_NoWarBattleTime);
+ }
+
+ m_WarTime = sWorld->getWorldState(3801);
+ m_DefenderTeam = TeamId(sWorld->getWorldState(3802));
+
+ m_Timer = sWorld->getWorldState(ClockWorldState[0]);
+ if (m_WarTime)
+ {
+ m_WarTime = false;
+ m_Timer = m_RestartAfterCrash;
+ }
+
+ for (uint8 i = 0; i < BATTLEFIELD_WG_GY_MAX; i++)
+ {
+ BfGraveYardWG *gy = new BfGraveYardWG(this);
+ if (WGGraveYard[i].startcontrol == TEAM_NEUTRAL) // When between games, the graveyard is controlled by the defending team
+ gy->Init(31841, 31842, WGGraveYard[i].x, WGGraveYard[i].y, WGGraveYard[i].z, WGGraveYard[i].o, m_DefenderTeam, WGGraveYard[i].gyid);
+ else
+ gy->Init(31841, 31842, WGGraveYard[i].x, WGGraveYard[i].y, WGGraveYard[i].z, WGGraveYard[i].o, WGGraveYard[i].startcontrol, WGGraveYard[i].gyid);
+ gy->SetTextId(WGGraveYard[i].textid);
+ m_GraveYardList[i] = gy;
+ }
+
+ // Spawn workshop creatures and gameobjects
+ for (uint8 i = 0; i < WG_MAX_WORKSHOP; i++)
+ {
+ BfWGWorkShopData *ws = new BfWGWorkShopData(this); // Create new object
+ // Init:setup variable
+ ws->Init(WGWorkShopDataBase[i].worldstate, WGWorkShopDataBase[i].type, WGWorkShopDataBase[i].nameid);
+ // Spawn associate npc on this point (Guard/Engineer)
+ for (uint8 c = 0; c < WGWorkShopDataBase[i].nbcreature; c++)
+ ws->AddCreature(WGWorkShopDataBase[i].CreatureData[c]);
+
+ // Spawn associate gameobject on this point (Horde/Alliance flags)
+ for (uint8 g = 0; g < WGWorkShopDataBase[i].nbgob; g++)
+ ws->AddGameObject(WGWorkShopDataBase[i].GameObjectData[g]);
+
+ // Create PvPCapturePoint
+ if (WGWorkShopDataBase[i].type < BATTLEFIELD_WG_WORKSHOP_KEEP_WEST)
+ {
+ ws->ChangeControl(GetAttackerTeam(), true); // Update control of this point
+ // Create Object
+ BfCapturePointWG *workshop = new BfCapturePointWG(this, GetAttackerTeam());
+ // Spawn gameobject associate (see in OnGameObjectCreate, of OutdoorPvP for see association)
+ workshop->SetCapturePointData(WGWorkShopDataBase[i].CapturePoint.entryh, 571,
+ WGWorkShopDataBase[i].CapturePoint.x, WGWorkShopDataBase[i].CapturePoint.y, WGWorkShopDataBase[i].CapturePoint.z, 0);
+ workshop->LinkToWorkShop(ws); // Link our point to the capture point (for faction changement)
+ AddCapturePoint(workshop); // Add this capture point to list for update this (view in Update() of OutdoorPvP)
+ }
+ else
+ ws->ChangeControl(GetDefenderTeam(), true); // Update control of this point (Keep workshop= to deffender team)
+
+ WorkShopList.insert(ws);
+ }
+ // Spawning npc in keep
+ for (uint8 i = 0; i < WG_MAX_KEEP_NPC; i++)
+ {
+ // Horde npc
+ if (Creature * creature = SpawnCreature(WGKeepNPC[i].entryh, WGKeepNPC[i].x, WGKeepNPC[i].y, WGKeepNPC[i].z, WGKeepNPC[i].o, TEAM_HORDE))
+ KeepCreature[TEAM_HORDE].insert(creature->GetGUID());
+ // Alliance npc
+ if (Creature * creature = SpawnCreature(WGKeepNPC[i].entrya, WGKeepNPC[i].x, WGKeepNPC[i].y, WGKeepNPC[i].z, WGKeepNPC[i].o, TEAM_ALLIANCE))
+ KeepCreature[TEAM_ALLIANCE].insert(creature->GetGUID());
+ }
+ // Hide keep npc
+ for (GuidSet::const_iterator itr = KeepCreature[GetAttackerTeam()].begin(); itr != KeepCreature[GetAttackerTeam()].end(); ++itr)
+ if (Unit * unit = sObjectAccessor->FindUnit((*itr)))
+ if (Creature * creature = unit->ToCreature())
+ HideNpc(creature);
+ // Spawn out of keep npc
+ // Horde npc
+ for (uint8 i = 0; i < WG_OUTSIDE_ALLIANCE_NPC; i++)
+ if (Creature * creature = SpawnCreature(WGOutsideNPC[i].entryh, WGOutsideNPC[i].x, WGOutsideNPC[i].y, WGOutsideNPC[i].z, WGOutsideNPC[i].o, TEAM_HORDE))
+ OutsideCreature[TEAM_HORDE].insert(creature->GetGUID());
+ // Alliance npc
+ for (uint8 i = WG_OUTSIDE_ALLIANCE_NPC; i < WG_MAX_OUTSIDE_NPC; i++)
+ if (Creature * creature = SpawnCreature(WGOutsideNPC[i].entrya, WGOutsideNPC[i].x, WGOutsideNPC[i].y, WGOutsideNPC[i].z, WGOutsideNPC[i].o, TEAM_ALLIANCE))
+ OutsideCreature[TEAM_ALLIANCE].insert(creature->GetGUID());
+ // Hide outside npc
+ for (GuidSet::const_iterator itr = OutsideCreature[GetDefenderTeam()].begin(); itr != OutsideCreature[GetDefenderTeam()].end(); ++itr)
+ if (Unit * unit = sObjectAccessor->FindUnit((*itr)))
+ if (Creature * creature = unit->ToCreature())
+ HideNpc(creature);
+ for (uint8 i = 0; i < WG_MAX_TURRET; i++)
+ {
+ if (Creature * creature = SpawnCreature(28366, WGTurret[i].x, WGTurret[i].y, WGTurret[i].z, WGTurret[i].o, TeamId(0)))
+ {
+ CanonList.insert(creature->GetGUID());
+ HideNpc(creature);
+ }
+ }
+ // Spawning Buiding
+ for (uint8 i = 0; i < WG_MAX_OBJ; i++)
+ {
+ GameObject *go =
+ SpawnGameObject(WGGameObjectBuillding[i].entry, WGGameObjectBuillding[i].x, WGGameObjectBuillding[i].y, WGGameObjectBuillding[i].z, WGGameObjectBuillding[i].o);
+ BfWGGameObjectBuilding *b = new BfWGGameObjectBuilding(this);
+ b->Init(go, WGGameObjectBuillding[i].type, WGGameObjectBuillding[i].WorldState, WGGameObjectBuillding[i].nameid);
+ BuildingsInZone.insert(b);
+ }
+ // Spawning portal defender
+ for (uint8 i = 0; i < WG_MAX_TELEPORTER; i++)
+ {
+ GameObject *go = SpawnGameObject(WGPortalDefenderData[i].entry, WGPortalDefenderData[i].x, WGPortalDefenderData[i].y, WGPortalDefenderData[i].z, WGPortalDefenderData[i].o);
+ DefenderPortalList.insert(go);
+ go->SetUInt32Value(GAMEOBJECT_FACTION, WintergraspFaction[GetDefenderTeam()]);
+ }
+
+ // Spawn banner in keep
+ for (uint8 i = 0; i < WG_KEEPGAMEOBJECT_MAX; i++)
+ {
+ if (GameObject * go = SpawnGameObject(WGKeepGameObject[i].entryh, WGKeepGameObject[i].x, WGKeepGameObject[i].y, WGKeepGameObject[i].z, WGKeepGameObject[i].o))
+ {
+ go->SetRespawnTime(GetDefenderTeam()? RESPAWN_ONE_DAY : RESPAWN_IMMEDIATELY);
+ m_KeepGameObject[1].insert(go);
+ }
+ if (GameObject * go = SpawnGameObject(WGKeepGameObject[i].entrya, WGKeepGameObject[i].x, WGKeepGameObject[i].y, WGKeepGameObject[i].z, WGKeepGameObject[i].o))
+ {
+ go->SetRespawnTime(GetDefenderTeam()? RESPAWN_IMMEDIATELY : RESPAWN_ONE_DAY);
+ m_KeepGameObject[0].insert(go);
+ }
+ }
+
+ // Show defender banner in keep
+ for (GameObjectSet::const_iterator itr = m_KeepGameObject[GetDefenderTeam()].begin(); itr != m_KeepGameObject[GetDefenderTeam()].end(); ++itr)
+ (*itr)->SetRespawnTime(RESPAWN_IMMEDIATELY);
+
+ // Hide attackant banner in keep
+ for (GameObjectSet::const_iterator itr = m_KeepGameObject[GetAttackerTeam()].begin(); itr != m_KeepGameObject[GetAttackerTeam()].end(); ++itr)
+ (*itr)->SetRespawnTime(RESPAWN_ONE_DAY);
+
+ UpdateCounterVehicle(true);
+ return true;
+}
+
+bool BattlefieldWG::Update(uint32 diff)
+{
+ bool m_return = Battlefield::Update(diff);
+ if (m_saveTimer <= diff)
+ {
+ sWorld->setWorldState(3801, m_WarTime);
+ sWorld->setWorldState(3802, m_DefenderTeam);
+ sWorld->setWorldState(ClockWorldState[0], m_Timer);
+ m_saveTimer = 60 * IN_MILLISECONDS;
+ }
+ else
+ m_saveTimer -= diff;
+
+ for (GuidSet::const_iterator itr = m_PlayersIsSpellImu.begin(); itr != m_PlayersIsSpellImu.end(); ++itr)
+ if (Player* plr = sObjectMgr->GetPlayer((*itr)))
+ {
+ if (plr->HasAura(SPELL_SPIRITUAL_IMMUNITY))
+ {
+ const WorldSafeLocsEntry *graveyard = GetClosestGraveYard(plr);
+ if (graveyard)
+ {
+ if (plr->GetDistance2d(graveyard->x, graveyard->y) > 10.0f)
+ {
+ plr->RemoveAurasDueToSpell(SPELL_SPIRITUAL_IMMUNITY);
+ m_PlayersIsSpellImu.erase(plr->GetGUID());
+ }
+ }
+ }
+ }
+
+ if (m_WarTime)
+ {
+ for (uint8 team = 0; team < 2; ++team)
+ for (GuidSet::const_iterator itr = m_vehicles[team].begin(); itr != m_vehicles[team].end(); ++itr)
+ if (Unit* unit = sObjectAccessor->FindUnit((*itr)))
+ {
+ if (unit->IsInWater() && !unit->HasAura(SPELL_WINTERGRASP_WATER))
+ unit->AddAura(SPELL_WINTERGRASP_WATER, unit);
+ if (!unit->IsInWater() && unit->HasAura(SPELL_WINTERGRASP_WATER))
+ unit->RemoveAurasDueToSpell(SPELL_WINTERGRASP_WATER);
+ }
+
+ }
+
+ for (uint8 team = 0; team < 2; ++team)
+ for (GuidSet::const_iterator itr = m_players[team].begin(); itr != m_players[team].end(); ++itr)
+ if (Player* plr = sObjectMgr->GetPlayer((*itr)))
+ for (BfCapturePointMap::iterator cp_itr = m_capturePoints.begin(); cp_itr != m_capturePoints.end(); ++cp_itr)
+ {
+ if ((*cp_itr).second->GetCapturePointGo()->GetExactDist2dSq(plr) < 22500.0f) // 150*150
+ {
+ plr->AddAura((*cp_itr).second->GetTeamId() == TEAM_HORDE ? SPELL_HORDE_CONTROLS_FACTORY_PHASE_SHIFT : SPELL_ALLIANCE_CONTROLS_FACTORY_PHASE_SHIFT, plr);
+ plr->RemoveAurasDueToSpell((*cp_itr).second->GetTeamId() == TEAM_ALLIANCE ? SPELL_HORDE_CONTROLS_FACTORY_PHASE_SHIFT : SPELL_ALLIANCE_CONTROLS_FACTORY_PHASE_SHIFT);
+ break;
+ }
+ }
+
+ return m_return;
+}
+
+void BattlefieldWG::AddPlayerToResurrectQueue(uint64 npc_guid, uint64 player_guid)
+{
+ Battlefield::AddPlayerToResurrectQueue(npc_guid, player_guid);
+ if (IsWarTime())
+ {
+ if (Player* plr = sObjectMgr->GetPlayer(player_guid))
+ {
+ if (!plr->HasAura(SPELL_SPIRITUAL_IMMUNITY))
+ {
+ plr->CastSpell(plr, SPELL_SPIRITUAL_IMMUNITY, true);
+ m_PlayersIsSpellImu.insert(plr->GetGUID());
+ }
+ }
+ }
+}
+
+void BattlefieldWG::OnBattleStart()
+{
+ // Spawn titan relic
+ m_relic = SpawnGameObject(BATTLEFIELD_WG_GAMEOBJECT_TITAN_RELIC, 5440.0f, 2840.8f, 430.43f, 0);
+ if (m_relic)
+ {
+ // Update faction of relic, only attacker can click on
+ m_relic->SetUInt32Value(GAMEOBJECT_FACTION, WintergraspFaction[GetAttackerTeam()]);
+ // Set in use (not allow to click on before last door is broken)
+ m_relic->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE);
+ }
+ else
+ sLog->outError("WG: Failed to spawn titan relic.");
+
+
+ // Update tower visibility and update faction
+ for (GuidSet::const_iterator itr = CanonList.begin(); itr != CanonList.end(); ++itr)
+ {
+ if (Unit * unit = sObjectAccessor->FindUnit((*itr)))
+ {
+ if (Creature * creature = unit->ToCreature())
+ {
+ ShowNpc(creature, true);
+ creature->setFaction(WintergraspFaction[GetDefenderTeam()]);
+ }
+ }
+ }
+
+ // Rebuild all wall
+ for (GameObjectBuilding::const_iterator itr = BuildingsInZone.begin(); itr != BuildingsInZone.end(); ++itr)
+ {
+ if ((*itr))
+ {
+ (*itr)->Rebuild();
+ (*itr)->UpdateTurretAttack(false);
+ }
+ }
+
+ m_Data32[BATTLEFIELD_WG_DATA_BROKEN_TOWER_ATT] = 0;
+ m_Data32[BATTLEFIELD_WG_DATA_BROKEN_TOWER_DEF] = 0;
+ m_Data32[BATTLEFIELD_WG_DATA_DAMAGED_TOWER_ATT] = 0;
+ m_Data32[BATTLEFIELD_WG_DATA_DAMAGED_TOWER_DEF] = 0;
+
+ // Update graveyard (in no war time all graveyard is to deffender, in war time, depend of base)
+ for (WorkShop::const_iterator itr = WorkShopList.begin(); itr != WorkShopList.end(); ++itr)
+ {
+ if ((*itr))
+ (*itr)->UpdateGraveYardAndWorkshop();
+ }
+
+ for (uint8 team = 0; team < 2; ++team)
+ for (GuidSet::const_iterator p_itr = m_players[team].begin(); p_itr != m_players[team].end(); ++p_itr)
+ {
+ // Kick player in orb room, TODO: offline player ?
+ if (Player* plr = sObjectMgr->GetPlayer((*p_itr)))
+ {
+ float x, y, z;
+ plr->GetPosition(x, y, z);
+ if (5500 > x && x > 5392 && y < 2880 && y > 2800 && z < 480)
+ plr->TeleportTo(571, 5349.8686f, 2838.481f, 409.240f, 0.046328f);
+ SendInitWorldStatesTo(plr);
+ }
+ }
+ // Initialize vehicle counter
+ UpdateCounterVehicle(true);
+ // Send start warning to all players
+ SendWarningToAllInZone(BATTLEFIELD_WG_TEXT_START);
+}
+
+void BattlefieldWG::UpdateCounterVehicle(bool init)
+{
+ if (init)
+ {
+ m_Data32[BATTLEFIELD_WG_DATA_VEHICLE_H] = 0;
+ m_Data32[BATTLEFIELD_WG_DATA_VEHICLE_A] = 0;
+ }
+ m_Data32[BATTLEFIELD_WG_DATA_MAX_VEHICLE_H] = 0;
+ m_Data32[BATTLEFIELD_WG_DATA_MAX_VEHICLE_A] = 0;
+
+ for (WorkShop::const_iterator itr = WorkShopList.begin(); itr != WorkShopList.end(); ++itr)
+ {
+ if (BfWGWorkShopData * workshop = (*itr))
+ {
+ if (workshop->m_TeamControl == TEAM_ALLIANCE)
+ m_Data32[BATTLEFIELD_WG_DATA_MAX_VEHICLE_A] = m_Data32[BATTLEFIELD_WG_DATA_MAX_VEHICLE_A] + 4;
+ else if (workshop->m_TeamControl == TEAM_HORDE)
+ m_Data32[BATTLEFIELD_WG_DATA_MAX_VEHICLE_H] = m_Data32[BATTLEFIELD_WG_DATA_MAX_VEHICLE_H] + 4;
+ }
+ }
+
+ UpdateVehicleCountWG();
+}
+
+void BattlefieldWG::OnBattleEnd(bool endbytimer)
+{
+ // Remove relic
+ if (m_relic)
+ m_relic->RemoveFromWorld();
+ m_relic = NULL;
+
+ // Remove turret
+ for (GuidSet::const_iterator itr = CanonList.begin(); itr != CanonList.end(); ++itr)
+ {
+ if (Unit* unit = sObjectAccessor->FindUnit((*itr)))
+ {
+ if (Creature* creature = unit->ToCreature())
+ {
+ if (!endbytimer)
+ creature->setFaction(WintergraspFaction[GetDefenderTeam()]);
+ HideNpc(creature);
+ }
+ }
+ }
+
+ // If endbytimer is false, battle is end by clicking on relic
+ if (!endbytimer)
+ {
+ // Change all npc in keep
+ for (GuidSet::const_iterator itr = KeepCreature[GetAttackerTeam()].begin(); itr != KeepCreature[GetAttackerTeam()].end(); ++itr)
+ {
+ if (Unit* unit = sObjectAccessor->FindUnit((*itr)))
+ if (Creature * creature = unit->ToCreature())
+ HideNpc(creature);
+ }
+ for (GuidSet::const_iterator itr = KeepCreature[GetDefenderTeam()].begin(); itr != KeepCreature[GetDefenderTeam()].end(); ++itr)
+ {
+ if (Unit* unit = sObjectAccessor->FindUnit((*itr)))
+ if (Creature * creature = unit->ToCreature())
+ ShowNpc(creature, true);
+ }
+ // Change all npc out of keep
+ for (GuidSet::const_iterator itr = OutsideCreature[GetDefenderTeam()].begin(); itr != OutsideCreature[GetDefenderTeam()].end(); ++itr)
+ {
+ if (Unit* unit = sObjectAccessor->FindUnit((*itr)))
+ if (Creature * creature = unit->ToCreature())
+ HideNpc(creature);
+ }
+ for (GuidSet::const_iterator itr = OutsideCreature[GetAttackerTeam()].begin(); itr != OutsideCreature[GetAttackerTeam()].end(); ++itr)
+ {
+ if (Unit* unit = sObjectAccessor->FindUnit((*itr)))
+ if (Creature* creature = unit->ToCreature())
+ ShowNpc(creature, true);
+ }
+ }
+
+ // Update all graveyard, control is to defender when no wartime
+ for (uint8 i = 0; i < BATTLEFIELD_WG_GY_HORDE; i++)
+ {
+ if (GetGraveYardById(i))
+ {
+ GetGraveYardById(i)->ChangeControl(GetDefenderTeam());
+ }
+ }
+
+ for (GameObjectSet::const_iterator itr = m_KeepGameObject[GetDefenderTeam()].begin(); itr != m_KeepGameObject[GetDefenderTeam()].end(); ++itr)
+ (*itr)->SetRespawnTime(RESPAWN_IMMEDIATELY);
+
+ for (GameObjectSet::const_iterator itr = m_KeepGameObject[GetAttackerTeam()].begin(); itr != m_KeepGameObject[GetAttackerTeam()].end(); ++itr)
+ (*itr)->SetRespawnTime(RESPAWN_ONE_DAY);
+
+ // Update portal defender faction
+ for (GameObjectSet::const_iterator itr = DefenderPortalList.begin(); itr != DefenderPortalList.end(); ++itr)
+ (*itr)->SetUInt32Value(GAMEOBJECT_FACTION, WintergraspFaction[GetDefenderTeam()]);
+
+ // Saving data
+ for (GameObjectBuilding::const_iterator itr = BuildingsInZone.begin(); itr != BuildingsInZone.end(); ++itr)
+ (*itr)->Save();
+ for (WorkShop::const_iterator itr = WorkShopList.begin(); itr != WorkShopList.end(); ++itr)
+ (*itr)->Save();
+
+ uint32 WinerHonor = 0;
+ uint32 LooserHonor = 0;
+
+ if (!endbytimer)
+ {
+ WinerHonor = 3000 + 400 * m_Data32[BATTLEFIELD_WG_DATA_BROKEN_TOWER_DEF] + 100 * m_Data32[BATTLEFIELD_WG_DATA_DAMAGED_TOWER_DEF];
+ LooserHonor = 1000 + 400 * m_Data32[BATTLEFIELD_WG_DATA_BROKEN_TOWER_ATT] + 100 * m_Data32[BATTLEFIELD_WG_DATA_DAMAGED_TOWER_ATT];
+ }
+ else
+ {
+ WinerHonor = 3000 + 400 * m_Data32[BATTLEFIELD_WG_DATA_BROKEN_TOWER_ATT] + 100 * m_Data32[BATTLEFIELD_WG_DATA_DAMAGED_TOWER_ATT];
+ LooserHonor = 1000 + 400 * m_Data32[BATTLEFIELD_WG_DATA_BROKEN_TOWER_DEF] + 100 * m_Data32[BATTLEFIELD_WG_DATA_DAMAGED_TOWER_DEF];
+ }
+
+ for (GuidSet::const_iterator itr = m_PlayersInWar[GetDefenderTeam()].begin(); itr != m_PlayersInWar[GetDefenderTeam()].end(); ++itr)
+ {
+ if (Player* plr = sObjectMgr->GetPlayer((*itr)))
+ {
+ plr->AddAura(58045, plr);
+ if (plr->HasAura(SPELL_LIEUTENANT))
+ {
+ plr->RewardHonor(NULL, 1, WinerHonor);
+ RewardMarkOfHonor(plr, 3);
+ }
+ else if (plr->HasAura(SPELL_CORPORAL))
+ {
+ plr->RewardHonor(NULL, 1, WinerHonor);
+ RewardMarkOfHonor(plr, 2);
+ }
+ if (plr->GetTeamId() == TEAM_HORDE)
+ IncrementQuest(plr, 13183, true);
+ else
+ IncrementQuest(plr, 13181, true);
+ // Send Wintergrasp victory achievement
+ DoCompleteOrIncrementAchievement(ACHIEVEMENTS_WIN_WG, plr);
+ // Award achievement for succeeding in Wintergrasp in 10 minutes or less
+ if (!endbytimer && GetTimer() <= 10000)
+ DoCompleteOrIncrementAchievement(ACHIEVEMENTS_WIN_WG_TIMER_10, plr);
+ }
+ }
+ for (GuidSet::const_iterator itr = m_PlayersInWar[GetAttackerTeam()].begin(); itr != m_PlayersInWar[GetAttackerTeam()].end(); ++itr)
+ {
+ if (Player* plr = sObjectMgr->GetPlayer((*itr)))
+ {
+ if (plr->HasAura(SPELL_LIEUTENANT))
+ {
+ plr->RewardHonor(NULL, 1, LooserHonor);
+ RewardMarkOfHonor(plr, 1);
+ }
+ else if (plr->HasAura(SPELL_CORPORAL))
+ {
+ plr->RewardHonor(NULL, 1, LooserHonor);
+ RewardMarkOfHonor(plr, 1);
+ }
+ }
+ }
+
+ for (uint8 team = 0; team < 2; ++team)
+ {
+ for (GuidSet::const_iterator itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr)
+ {
+ if (Player* plr = sObjectMgr->GetPlayer((*itr)))
+ {
+ plr->RemoveAura(SPELL_TOWER_CONTROL);
+ plr->RemoveAurasDueToSpell(SPELL_RECRUIT);
+ plr->RemoveAurasDueToSpell(SPELL_CORPORAL);
+ plr->RemoveAurasDueToSpell(SPELL_LIEUTENANT);
+ plr->RemoveAurasDueToSpell(SPELL_TENACITY);
+ plr->RemoveAurasDueToSpell(SPELL_SPIRITUAL_IMMUNITY);
+ }
+ }
+ m_PlayersInWar[team].clear();
+
+ for (GuidSet::const_iterator itr = m_vehicles[team].begin(); itr != m_vehicles[team].end(); ++itr)
+ {
+ if (Unit* unit = sObjectAccessor->FindUnit((*itr)))
+ if (Creature* creature = unit->ToCreature())
+ if (creature->IsVehicle())
+ creature->GetVehicleKit()->Dismiss();
+ }
+ m_vehicles[team].clear();
+ }
+
+ if (!endbytimer)
+ {
+ for (uint8 team = 0; team < 2; ++team)
+ {
+ for (GuidSet::const_iterator itr = m_players[team].begin(); itr != m_players[team].end(); ++itr)
+ {
+ if (Player* plr = sObjectMgr->GetPlayer((*itr)))
+ {
+ plr->RemoveAurasDueToSpell(m_DefenderTeam == TEAM_ALLIANCE ? SPELL_HORDE_CONTROL_PHASE_SHIFT : SPELL_ALLIANCE_CONTROL_PHASE_SHIFT, plr->GetGUID());
+ plr->AddAura(m_DefenderTeam == TEAM_HORDE ? SPELL_HORDE_CONTROL_PHASE_SHIFT : SPELL_ALLIANCE_CONTROL_PHASE_SHIFT, plr);
+ }
+ }
+ }
+ }
+
+ if (!endbytimer)
+ { // win alli/horde
+ SendWarningToAllInZone((GetDefenderTeam() == TEAM_ALLIANCE) ? BATTLEFIELD_WG_TEXT_WIN_KEEP : BATTLEFIELD_WG_TEXT_WIN_KEEP + 1);
+ }
+ else
+ { // defend alli/horde
+ SendWarningToAllInZone((GetDefenderTeam() == TEAM_ALLIANCE) ? BATTLEFIELD_WG_TEXT_DEFEND_KEEP : BATTLEFIELD_WG_TEXT_DEFEND_KEEP + 1);
+ }
+}
+
+// *****************************************************
+// *******************Reward System*********************
+// *****************************************************
+void BattlefieldWG::DoCompleteOrIncrementAchievement(uint32 achievement, Player *player, uint8 /*incrementNumber */ )
+{
+ AchievementEntry const* AE = GetAchievementStore()->LookupEntry(achievement);
+
+ switch (achievement)
+ {
+ case ACHIEVEMENTS_WIN_WG_100:
+ {
+ // player->GetAchievementMgr().UpdateAchievementCriteria();
+ }
+ default:
+ {
+ if (player)
+ player->CompletedAchievement(AE);
+ }
+ break;
+ }
+
+}
+
+void BattlefieldWG::RewardMarkOfHonor(Player *plr, uint32 count)
+{
+ // 'Inactive' this aura prevents the player from gaining honor points and battleground tokens
+ if (count == 0)
+ return;
+
+ ItemPosCountVec dest;
+ uint32 no_space_count = 0;
+ uint8 msg = plr->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, WG_MARK_OF_HONOR, count, &no_space_count);
+
+ if (msg == EQUIP_ERR_ITEM_NOT_FOUND)
+ {
+ return;
+ }
+
+ if (msg != EQUIP_ERR_OK) // convert to possible store amount
+ count -= no_space_count;
+
+ if (count != 0 && !dest.empty()) // can add some
+ if (Item * item = plr->StoreNewItem(dest, WG_MARK_OF_HONOR, true, 0))
+ plr->SendNewItem(item, count, true, false);
+}
+
+void BattlefieldWG::OnStartGrouping()
+{
+ // Warn
+ SendWarningToAllInZone(BATTLEFIELD_WG_TEXT_WILL_START);
+}
+
+void BattlefieldWG::OnCreatureCreate(Creature * creature, bool add)
+{
+ if (IsWarTime())
+ {
+ switch (creature->GetEntry())
+ {
+ case 28312:
+ case 32627:
+ case 27881:
+ case 28094:
+ {
+ uint8 team;
+ if (creature->getFaction() == WintergraspFaction[TEAM_ALLIANCE])
+ team = TEAM_ALLIANCE;
+ else if (creature->getFaction() == WintergraspFaction[TEAM_HORDE])
+ team = TEAM_HORDE;
+ else
+ return;
+
+ if (add)
+ {
+ if (team == TEAM_HORDE)
+ {
+ m_Data32[BATTLEFIELD_WG_DATA_VEHICLE_H]++;
+ if (GetData(BATTLEFIELD_WG_DATA_VEHICLE_H) <= GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_H))
+ {
+ creature->AddAura(SPELL_HORDE_FLAG, creature);
+ m_vehicles[team].insert(creature->GetGUID());
+ UpdateVehicleCountWG();
+ }
+ else
+ {
+ creature->setDeathState(DEAD);
+ creature->SetRespawnTime(RESPAWN_ONE_DAY);
+ return;
+ }
+ }
+ else
+ {
+ m_Data32[BATTLEFIELD_WG_DATA_VEHICLE_A]++;
+ if (GetData(BATTLEFIELD_WG_DATA_VEHICLE_A) <= GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_A))
+ {
+ creature->AddAura(SPELL_ALLIANCE_FLAG, creature);
+ m_vehicles[team].insert(creature->GetGUID());
+ UpdateVehicleCountWG();
+ }
+ else
+ {
+ creature->setDeathState(DEAD);
+ creature->SetRespawnTime(RESPAWN_ONE_DAY);
+ return;
+ }
+ }
+ }
+ else
+ {
+ m_vehicles[team].erase(creature->GetGUID());
+ if (team == TEAM_HORDE)
+ m_Data32[BATTLEFIELD_WG_DATA_VEHICLE_H]--;
+ else
+ m_Data32[BATTLEFIELD_WG_DATA_VEHICLE_A]--;
+ UpdateVehicleCountWG();
+ }
+ break;
+ }
+ }
+ }
+}
+
+// Called when player kill a unit in wg zone
+void BattlefieldWG::HandleKill(Player *killer, Unit *victim)
+{
+ if (killer == victim)
+ return;
+
+ bool again = false;
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ {
+ IncrementQuest(killer, WGQuest[killer->GetTeamId()][4]);
+ IncrementQuest(killer, WGQuest[killer->GetTeamId()][5]);
+ for (GuidSet::const_iterator p_itr = m_PlayersInWar[killer->GetTeamId()].begin(); p_itr != m_PlayersInWar[killer->GetTeamId()].end(); ++p_itr)
+ {
+ if (Player* plr = sObjectAccessor->FindPlayer(*p_itr))
+ if (plr->GetDistance2d(killer) < 40)
+ PromotePlayer(plr);
+ }
+ return;
+ }
+ for (GuidSet::const_iterator itr = m_vehicles[killer->GetTeamId()? TEAM_ALLIANCE : TEAM_HORDE].begin();
+ itr != m_vehicles[killer->GetTeamId()? TEAM_ALLIANCE : TEAM_HORDE].end(); ++itr)
+ {
+ if (Unit * unit = sObjectAccessor->FindUnit((*itr)))
+ {
+ if (Creature * creature = unit->ToCreature())
+ {
+ if (victim->GetEntry() == creature->GetEntry() && !again)
+ {
+ again = true;
+ for (GuidSet::const_iterator p_itr = m_PlayersInWar[killer->GetTeamId()].begin(); p_itr != m_PlayersInWar[killer->GetTeamId()].end(); ++p_itr)
+ {
+ if (Player* plr = sObjectAccessor->FindPlayer(*p_itr))
+ if (plr->GetDistance2d(killer) < 40)
+ IncrementQuest(plr, IncrementQuest(killer, WGQuest[killer->GetTeamId()][0]));
+ }
+ }
+ }
+ }
+ }
+ for (GuidSet::const_iterator itr = KeepCreature[killer->GetTeamId()? TEAM_ALLIANCE : TEAM_HORDE].begin();
+ itr != KeepCreature[killer->GetTeamId()? TEAM_ALLIANCE : TEAM_HORDE].end(); ++itr)
+ {
+ if (Unit * unit = sObjectAccessor->FindUnit((*itr)))
+ {
+ if (Creature * creature = unit->ToCreature())
+ {
+ if (victim->GetEntry() == creature->GetEntry() && !again)
+ {
+ again = true;
+ IncrementQuest(killer, WGQuest[killer->GetTeamId()][4]);
+ IncrementQuest(killer, WGQuest[killer->GetTeamId()][5]);
+ for (GuidSet::const_iterator p_itr = m_PlayersInWar[killer->GetTeamId()].begin(); p_itr != m_PlayersInWar[killer->GetTeamId()].end(); ++p_itr)
+ {
+ if (Player* plr = sObjectAccessor->FindPlayer(*p_itr))
+ if (plr->GetDistance2d(killer) < 40)
+ PromotePlayer(plr);
+ }
+ }
+ }
+ }
+ }
+ // TODO:Recent PvP activity worldstate
+}
+
+// Update rank for player
+void BattlefieldWG::PromotePlayer(Player *killer)
+{
+ if (!m_WarTime)
+ return;
+ // Updating rank of player
+ if (Aura * aur = killer->GetAura(SPELL_RECRUIT))
+ {
+ if (aur->GetStackAmount() >= 5) // 7 or more TODO:
+ {
+ killer->RemoveAura(SPELL_RECRUIT);
+ killer->CastSpell(killer, SPELL_CORPORAL, true);
+ SendWarningToPlayer(killer, BATTLEFIELD_WG_TEXT_FIRSTRANK);
+ }
+ else
+ killer->CastSpell(killer, SPELL_RECRUIT, true);
+ }
+ else if (Aura * aur = killer->GetAura(SPELL_CORPORAL))
+ {
+ if (aur->GetStackAmount() >= 5) // 7 or more TODO:
+ {
+ killer->RemoveAura(SPELL_CORPORAL);
+ killer->CastSpell(killer, SPELL_LIEUTENANT, true);
+ SendWarningToPlayer(killer, BATTLEFIELD_WG_TEXT_SECONDRANK);
+ }
+ else
+ killer->CastSpell(killer, SPELL_CORPORAL, true);
+ }
+}
+
+void BattlefieldWG::OnPlayerJoinWar(Player *plr)
+{
+ plr->RemoveAurasDueToSpell(SPELL_RECRUIT);
+ plr->RemoveAurasDueToSpell(SPELL_CORPORAL);
+ plr->RemoveAurasDueToSpell(SPELL_LIEUTENANT);
+ plr->RemoveAurasDueToSpell(SPELL_TOWER_CONTROL);
+ plr->RemoveAurasDueToSpell(SPELL_SPIRITUAL_IMMUNITY);
+ plr->RemoveAurasDueToSpell(SPELL_TENACITY);
+ plr->RemoveAurasDueToSpell(58045);
+
+ plr->CastSpell(plr, SPELL_RECRUIT, true);
+
+ if (plr->GetZoneId() != m_ZoneId)
+ {
+ if (plr->GetTeamId() == GetDefenderTeam())
+ {
+ plr->TeleportTo(571, 5345, 2842, 410, 3.14f);
+ }
+ else
+ {
+ if (plr->GetTeamId() == TEAM_HORDE)
+ plr->TeleportTo(571, 5025.857422f, 3674.628906f, 362.737122f, 4.135169f);
+ else
+ plr->TeleportTo(571, 5101.284f, 2186.564f, 373.549f, 3.812f);
+ }
+ }
+
+ UpdateTenacity();
+
+ if (plr->GetTeamId() == GetAttackerTeam())
+ {
+ if (3 - m_Data32[BATTLEFIELD_WG_DATA_BROKEN_TOWER_ATT] > 0)
+ plr->SetAuraStack(SPELL_TOWER_CONTROL, plr, 3 - m_Data32[BATTLEFIELD_WG_DATA_BROKEN_TOWER_ATT]);
+ }
+ else
+ {
+ if (m_Data32[BATTLEFIELD_WG_DATA_BROKEN_TOWER_ATT] > 0)
+ plr->SetAuraStack(SPELL_TOWER_CONTROL, plr, m_Data32[BATTLEFIELD_WG_DATA_BROKEN_TOWER_ATT]);
+ }
+ SendInitWorldStatesTo(plr);
+}
+
+void BattlefieldWG::OnPlayerLeaveWar(Player *plr)
+{
+ // Remove all aura from WG // TODO: false we can go out of this zone on retail and keep Rank buff, remove on end of WG
+ if (!plr->GetSession()->PlayerLogout())
+ {
+ if (plr->GetVehicle()) // Remove vehicle of player if he go out.
+ plr->GetVehicle()->Dismiss();
+ plr->RemoveAurasDueToSpell(SPELL_RECRUIT);
+ plr->RemoveAurasDueToSpell(SPELL_CORPORAL);
+ plr->RemoveAurasDueToSpell(SPELL_LIEUTENANT);
+ plr->RemoveAurasDueToSpell(SPELL_TOWER_CONTROL);
+ plr->RemoveAurasDueToSpell(SPELL_SPIRITUAL_IMMUNITY);
+ plr->RemoveAurasDueToSpell(SPELL_TENACITY);
+ plr->RemoveAurasDueToSpell(58730);
+ plr->RemoveAurasDueToSpell(58045);
+ plr->RemoveAurasDueToSpell(SPELL_TOWER_CONTROL);
+ }
+ plr->RemoveAurasDueToSpell(SPELL_HORDE_CONTROLS_FACTORY_PHASE_SHIFT);
+ plr->RemoveAurasDueToSpell(SPELL_ALLIANCE_CONTROLS_FACTORY_PHASE_SHIFT);
+ plr->RemoveAurasDueToSpell(SPELL_HORDE_CONTROL_PHASE_SHIFT);
+ plr->RemoveAurasDueToSpell(SPELL_ALLIANCE_CONTROL_PHASE_SHIFT);
+}
+
+void BattlefieldWG::OnPlayerLeaveZone(Player *plr)
+{
+ plr->RemoveAurasDueToSpell(58045);
+ if (!m_WarTime)
+ {
+ plr->RemoveAurasDueToSpell(SPELL_RECRUIT);
+ plr->RemoveAurasDueToSpell(SPELL_CORPORAL);
+ plr->RemoveAurasDueToSpell(SPELL_LIEUTENANT);
+ plr->RemoveAurasDueToSpell(SPELL_TOWER_CONTROL);
+ plr->RemoveAurasDueToSpell(SPELL_SPIRITUAL_IMMUNITY);
+ plr->RemoveAurasDueToSpell(SPELL_TENACITY);
+ plr->RemoveAurasDueToSpell(58730);
+ plr->RemoveAurasDueToSpell(SPELL_TOWER_CONTROL);
+ }
+ plr->RemoveAurasDueToSpell(SPELL_HORDE_CONTROLS_FACTORY_PHASE_SHIFT);
+ plr->RemoveAurasDueToSpell(SPELL_ALLIANCE_CONTROLS_FACTORY_PHASE_SHIFT);
+ plr->RemoveAurasDueToSpell(SPELL_HORDE_CONTROL_PHASE_SHIFT);
+ plr->RemoveAurasDueToSpell(SPELL_ALLIANCE_CONTROL_PHASE_SHIFT);
+}
+
+void BattlefieldWG::OnPlayerEnterZone(Player *plr)
+{
+ plr->RemoveAurasDueToSpell(58045);
+ if (!m_WarTime)
+ {
+ plr->RemoveAurasDueToSpell(SPELL_RECRUIT);
+ plr->RemoveAurasDueToSpell(SPELL_CORPORAL);
+ plr->RemoveAurasDueToSpell(SPELL_LIEUTENANT);
+ plr->RemoveAurasDueToSpell(SPELL_TOWER_CONTROL);
+ plr->RemoveAurasDueToSpell(SPELL_SPIRITUAL_IMMUNITY);
+ plr->RemoveAurasDueToSpell(SPELL_TENACITY);
+ plr->RemoveAurasDueToSpell(58730);
+ plr->RemoveAurasDueToSpell(SPELL_TOWER_CONTROL);
+ if (plr->GetTeamId() == GetDefenderTeam())
+ plr->AddAura(58045, plr);
+ }
+
+ plr->AddAura(m_DefenderTeam == TEAM_HORDE ?
+ SPELL_HORDE_CONTROL_PHASE_SHIFT:
+ SPELL_ALLIANCE_CONTROL_PHASE_SHIFT,
+ plr);
+ // Send worldstate to player
+ SendInitWorldStatesTo(plr);
+}
+
+// Method sending worldsate to player
+WorldPacket BattlefieldWG::BuildInitWorldStates()
+{
+ WorldPacket data(SMSG_INIT_WORLD_STATES, (4 + 4 + 4 + 2 + (BuildingsInZone.size() * 8) + (WorkShopList.size() * 8)));
+
+ data << uint32(m_MapId);
+ data << uint32(m_ZoneId);
+ data << uint32(0);
+ data << uint16(4 + 2 + 4 + BuildingsInZone.size() + WorkShopList.size());
+
+ data << uint32(3803) << uint32(GetAttackerTeam());
+ data << uint32(3802) << uint32(GetDefenderTeam());
+ data << uint32(3801) << uint32(IsWarTime()? 0 : 1);
+ data << uint32(3710) << uint32(IsWarTime()? 1 : 0);
+
+ for (uint32 i = 0; i < 2; ++i)
+ data << ClockWorldState[i] << uint32(time(NULL) + (m_Timer / 1000));
+
+ data << uint32(3490) << uint32(GetData(BATTLEFIELD_WG_DATA_VEHICLE_H));
+ data << uint32(3491) << GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_H);
+ data << uint32(3680) << uint32(GetData(BATTLEFIELD_WG_DATA_VEHICLE_A));
+ data << uint32(3681) << GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_A);
+
+ for (GameObjectBuilding::const_iterator itr = BuildingsInZone.begin(); itr != BuildingsInZone.end(); ++itr)
+ {
+ data << (*itr)->m_WorldState << (*itr)->m_State;
+ }
+ for (WorkShop::const_iterator itr = WorkShopList.begin(); itr != WorkShopList.end(); ++itr)
+ {
+ data << (*itr)->m_WorldState << (*itr)->m_State;
+ }
+ return data;
+}
+
+void BattlefieldWG::SendInitWorldStatesTo(Player *player)
+{
+ WorldPacket data = BuildInitWorldStates();
+ player->GetSession()->SendPacket(&data);
+}
+
+void BattlefieldWG::SendInitWorldStatesToAll()
+{
+ WorldPacket data = BuildInitWorldStates();
+ for (uint8 team = 0; team < 2; team++)
+ for (GuidSet::iterator itr = m_players[team].begin(); itr != m_players[team].end(); ++itr)
+ if (Player* plr = sObjectMgr->GetPlayer((*itr)))
+ plr->GetSession()->SendPacket(&data);
+}
+
+void BattlefieldWG::BrokenWallOrTower(TeamId team)
+{
+ if (team == GetDefenderTeam())
+ {
+ for (GuidSet::const_iterator p_itr = m_PlayersInWar[GetAttackerTeam()].begin(); p_itr != m_PlayersInWar[GetAttackerTeam()].end(); ++p_itr)
+ {
+ if (Player* plr = sObjectMgr->GetPlayer((*p_itr)))
+ {
+ if (plr->GetTeamId() == TEAM_ALLIANCE)
+ IncrementQuest(plr, 13222);
+ else
+ IncrementQuest(plr, 13223);
+ }
+ }
+ }
+}
+// Called when a tower is broke
+void BattlefieldWG::AddBrokenTower(TeamId team)
+{
+ // Destroy an attack tower
+ if (team == GetAttackerTeam())
+ {
+ // Update counter
+ m_Data32[BATTLEFIELD_WG_DATA_DAMAGED_TOWER_ATT]--;
+ m_Data32[BATTLEFIELD_WG_DATA_BROKEN_TOWER_ATT]++;
+
+ // Remove buff stack
+ for (GuidSet::const_iterator itr = m_PlayersInWar[GetAttackerTeam()].begin(); itr != m_PlayersInWar[GetAttackerTeam()].end(); ++itr)
+ if (Player* plr = sObjectMgr->GetPlayer((*itr)))
+ plr->RemoveAuraFromStack(SPELL_TOWER_CONTROL);
+
+ // Add buff stack
+ for (GuidSet::const_iterator itr = m_PlayersInWar[GetDefenderTeam()].begin(); itr != m_PlayersInWar[GetDefenderTeam()].end(); ++itr)
+ if (Player* plr = sObjectMgr->GetPlayer((*itr)))
+ {
+ plr->CastSpell(plr, SPELL_TOWER_CONTROL, true);
+ if (plr->GetTeamId() == TEAM_HORDE)
+ IncrementQuest(plr, 13539, true);
+ else
+ IncrementQuest(plr, 13538, true);
+ DoCompleteOrIncrementAchievement(ACHIEVEMENTS_WG_TOWER_DESTROY, plr);
+ }
+ // If the threw south tower is destroy
+ if (m_Data32[BATTLEFIELD_WG_DATA_BROKEN_TOWER_ATT] == 3)
+ {
+ // Remove 10 minutes to battle time
+ if (int32(m_Timer - 600000) < 0)
+ {
+ m_Timer = 0;
+ }
+ else
+ {
+ m_Timer -= 600000;
+ }
+ SendInitWorldStatesToAll();
+ }
+ }
+ else
+ {
+ m_Data32[BATTLEFIELD_WG_DATA_DAMAGED_TOWER_DEF]--;
+ m_Data32[BATTLEFIELD_WG_DATA_BROKEN_TOWER_DEF]++;
+ }
+}
+
+void BattlefieldWG::ProcessEvent(GameObject * obj, uint32 eventId)
+{
+ if (!obj || !IsWarTime())
+ return;
+
+ // On click on titan relic
+ if (obj->GetEntry() == BATTLEFIELD_WG_GAMEOBJECT_TITAN_RELIC)
+ {
+ // Check that the door is break
+ if (m_bCanClickOnOrb)
+ EndBattle(false);
+ else // if door is not break, respawn relic.
+ m_relic->SetRespawnTime(RESPAWN_IMMEDIATELY);
+ }
+
+ // if destroy or damage event, search the wall/tower and update worldstate/send warning message
+ for (GameObjectBuilding::const_iterator itr = BuildingsInZone.begin(); itr != BuildingsInZone.end(); ++itr)
+ {
+ if (obj->GetEntry() == (*itr)->m_Build->GetEntry())
+ {
+ if ((*itr)->m_Build->GetGOInfo()->building.damagedEvent == eventId)
+ (*itr)->Damaged();
+
+ if ((*itr)->m_Build->GetGOInfo()->building.destroyedEvent == eventId)
+ (*itr)->Destroyed();
+
+ break;
+ }
+ }
+}
+
+// Called when a tower is damaged, used for honor reward calcul
+void BattlefieldWG::AddDamagedTower(TeamId team)
+{
+ if (team == GetAttackerTeam())
+ {
+ m_Data32[BATTLEFIELD_WG_DATA_DAMAGED_TOWER_ATT]++;
+ }
+ else
+ {
+ m_Data32[BATTLEFIELD_WG_DATA_DAMAGED_TOWER_DEF]++;
+ }
+}
+
+// Update vehicle count WorldState to player
+void BattlefieldWG::UpdateVehicleCountWG()
+{
+ SendUpdateWorldState(3490, GetData(BATTLEFIELD_WG_DATA_VEHICLE_H));
+ SendUpdateWorldState(3491, GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_H));
+ SendUpdateWorldState(3680, GetData(BATTLEFIELD_WG_DATA_VEHICLE_A));
+ SendUpdateWorldState(3681, GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_A));
+}
+
+void BattlefieldWG::UpdateTenacity()
+{
+ TeamId team = TEAM_NEUTRAL;
+ uint32 allianceNum = m_PlayersInWar[TEAM_ALLIANCE].size();
+ uint32 hordeNum = m_PlayersInWar[TEAM_HORDE].size();
+ int32 newStack = 0;
+
+ if (allianceNum && hordeNum)
+ {
+ if (allianceNum < hordeNum)
+ newStack = int32((float (hordeNum) / float (allianceNum) - 1) *4); // positive, should cast on alliance
+ else if (allianceNum > hordeNum)
+ newStack = int32((1 - float (allianceNum) / float (hordeNum)) *4); // negative, should cast on horde
+ }
+
+ if (newStack == int32(m_tenacityStack))
+ return;
+
+ if (m_tenacityStack > 0 && newStack <= 0) // old buff was on alliance
+ team = TEAM_ALLIANCE;
+ else if (newStack >= 0) // old buff was on horde
+ team = TEAM_HORDE;
+
+ m_tenacityStack = newStack;
+ // Remove old buff
+ if (team != TEAM_NEUTRAL)
+ {
+ for (GuidSet::const_iterator itr = m_players[team].begin(); itr != m_players[team].end(); ++itr)
+ if (Player* plr = sObjectMgr->GetPlayer((*itr)))
+ if (plr->getLevel() > 76)
+ plr->RemoveAurasDueToSpell(SPELL_TENACITY);
+
+ for (GuidSet::const_iterator itr = m_vehicles[team].begin(); itr != m_vehicles[team].end(); ++itr)
+ if (Unit* unit = sObjectAccessor->FindUnit((*itr)))
+ if (Creature* creature = unit->ToCreature())
+ creature->RemoveAurasDueToSpell(SPELL_TENACITY_VEHICLE);
+ }
+
+ // Apply new buff
+ if (newStack)
+ {
+ team = newStack > 0 ? TEAM_ALLIANCE : TEAM_HORDE;
+
+ if (newStack < 0)
+ newStack = -newStack;
+ if (newStack > 20)
+ newStack = 20;
+
+ uint32 buff_honnor = SPELL_GREATEST_HONOR;
+ buff_honnor = (newStack < 15) ? (uint32) SPELL_GREATER_HONOR : buff_honnor;
+ buff_honnor = (newStack < 10) ? (uint32) SPELL_GREAT_HONOR : buff_honnor;
+ buff_honnor = (newStack < 5) ? 0 : buff_honnor;
+
+ for (GuidSet::const_iterator itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr)
+ if (Player* plr = sObjectMgr->GetPlayer((*itr)))
+ plr->SetAuraStack(SPELL_TENACITY, plr, newStack);
+ for (GuidSet::const_iterator itr = m_vehicles[team].begin(); itr != m_vehicles[team].end(); ++itr)
+ if (Unit* unit = sObjectAccessor->FindUnit((*itr)))
+ if (Creature * creature = unit->ToCreature())
+ creature->SetAuraStack(SPELL_TENACITY_VEHICLE, creature, newStack);
+
+ if (buff_honnor != 0)
+ {
+ for (GuidSet::const_iterator itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr)
+ if (Player* plr = sObjectMgr->GetPlayer((*itr)))
+ plr->AddAura(buff_honnor, plr);
+ for (GuidSet::const_iterator itr = m_vehicles[team].begin(); itr != m_vehicles[team].end(); ++itr)
+ if (Unit* unit = sObjectAccessor->FindUnit((*itr)))
+ if (Creature* creature = unit->ToCreature())
+ creature->AddAura(buff_honnor, creature);
+ }
+ }
+}
+
+void BfCapturePointWG::ChangeTeam(TeamId /*oldTeam */ )
+{
+ m_WorkShop->ChangeControl(m_team, false);
+}
+
+BfCapturePointWG::BfCapturePointWG(BattlefieldWG * bf, TeamId control):BfCapturePoint(bf)
+{
+ m_Bf = bf;
+ m_team = control;
+}
+
+BfGraveYardWG::BfGraveYardWG(BattlefieldWG * bf):BfGraveYard(bf)
+{
+ m_Bf = bf;
+}
diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.h b/src/server/game/Battlefield/Zones/BattlefieldWG.h
new file mode 100644
index 00000000000..6a768c1e164
--- /dev/null
+++ b/src/server/game/Battlefield/Zones/BattlefieldWG.h
@@ -0,0 +1,1906 @@
+/*
+ * Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef BATTLEFIELD_WG_
+#define BATTLEFIELD_WG_
+
+#include "Battlefield.h"
+#include "Group.h"
+#include "WorldPacket.h"
+#include "World.h"
+
+const uint32 VehNumWorldState[2] = { 3680, 3490 };
+const uint32 MaxVehNumWorldState[2] = { 3681, 3491 };
+const uint32 ClockWorldState[2] = { 3781, 4354 };
+const uint32 WintergraspFaction[3] = { 1732, 1735, 35 };
+
+const float WintergraspStalkerPos[4] = { 0, 0, 0, 0 };
+
+class BattlefieldWG;
+class BfCapturePointWG;
+
+struct BfWGGameObjectBuilding;
+struct BfWGWorkShopData;
+
+typedef std::set<GameObject *>GameObjectSet;
+typedef std::set<BfWGGameObjectBuilding *> GameObjectBuilding;
+typedef std::set<BfWGWorkShopData *> WorkShop;
+//typedef std::set<BfCapturePointWG *> CapturePointSet; unused ?
+typedef std::set<Group *> GroupSet;
+
+enum eWGItem
+{
+// *INDENT-OFF*
+ WG_MARK_OF_HONOR = 43589,
+// *INDENT-ON*
+};
+
+enum eWGSpell
+{
+// *INDENT-OFF*
+ // Wartime auras
+ SPELL_RECRUIT = 37795,
+ SPELL_CORPORAL = 33280,
+ SPELL_LIEUTENANT = 55629,
+ SPELL_TENACITY = 58549,
+ SPELL_TENACITY_VEHICLE = 59911,
+ SPELL_TOWER_CONTROL = 62064,
+ SPELL_SPIRITUAL_IMMUNITY = 58729,
+ SPELL_GREAT_HONOR = 58555,
+ SPELL_GREATER_HONOR = 58556,
+ SPELL_GREATEST_HONOR = 58557,
+ SPELL_ALLIANCE_FLAG = 14268,
+ SPELL_HORDE_FLAG = 14267,
+
+ // Reward spells
+ SPELL_VICTORY_REWARD = 56902,
+ SPELL_DEFEAT_REWARD = 58494,
+ SPELL_DAMAGED_TOWER = 59135,
+ SPELL_DESTROYED_TOWER = 59136,
+ SPELL_DAMAGED_BUILDING = 59201,
+ SPELL_INTACT_BUILDING = 59203,
+
+ SPELL_TELEPORT_BRIDGE = 59096,
+ SPELL_TELEPORT_FORTRESS = 60035,
+
+ SPELL_TELEPORT_DALARAN = 53360,
+ SPELL_VICTORY_AURA = 60044,
+
+ // Other spells
+ SPELL_WINTERGRASP_WATER = 36444,
+
+ // Phasing spells
+ SPELL_ALLIANCE_CONTROLS_FACTORY_PHASE_SHIFT = 56617,// ADDS PHASE 32
+ SPELL_HORDE_CONTROLS_FACTORY_PHASE_SHIFT = 56618,// ADDS PHASE 16
+
+ SPELL_HORDE_CONTROL_PHASE_SHIFT = 55773,// ADDS PHASE 64
+ SPELL_ALLIANCE_CONTROL_PHASE_SHIFT = 55774,// ADDS PHASE 128
+
+// *INDENT-ON*
+};
+
+enum eWGData32
+{
+ BATTLEFIELD_WG_DATA_DAMAGED_TOWER_DEF,
+ BATTLEFIELD_WG_DATA_BROKEN_TOWER_DEF,
+ BATTLEFIELD_WG_DATA_DAMAGED_TOWER_ATT,
+ BATTLEFIELD_WG_DATA_BROKEN_TOWER_ATT,
+ BATTLEFIELD_WG_DATA_MAX_VEHICLE_A,
+ BATTLEFIELD_WG_DATA_MAX_VEHICLE_H,
+ BATTLEFIELD_WG_DATA_VEHICLE_A,
+ BATTLEFIELD_WG_DATA_VEHICLE_H,
+ BATTLEFIELD_WG_DATA_MAX,
+};
+
+enum WB_ACHIEVEMENTS
+{
+// *INDENT-OFF*
+ ACHIEVEMENTS_WIN_WG = 1717,
+ ACHIEVEMENTS_WIN_WG_100 = 1718, // todo
+ ACHIEVEMENTS_WG_GNOMESLAUGHTER = 1723, // todo
+ ACHIEVEMENTS_WG_TOWER_DESTROY = 1727,
+ ACHIEVEMENTS_DESTRUCTION_DERBY_A = 1737, // todo
+ ACHIEVEMENTS_WG_TOWER_CANNON_KILL = 1751, // todo
+ ACHIEVEMENTS_WG_MASTER_A = 1752, // todo
+ ACHIEVEMENTS_WIN_WG_TIMER_10 = 1755,
+ ACHIEVEMENTS_STONE_KEEPER_50 = 2085, // todo
+ ACHIEVEMENTS_STONE_KEEPER_100 = 2086, // todo
+ ACHIEVEMENTS_STONE_KEEPER_250 = 2087, // todo
+ ACHIEVEMENTS_STONE_KEEPER_500 = 2088, // todo
+ ACHIEVEMENTS_STONE_KEEPER_1000 = 2089, // todo
+ ACHIEVEMENTS_WG_RANGER = 2199, // todo
+ ACHIEVEMENTS_DESTRUCTION_DERBY_H = 2476, // todo
+ ACHIEVEMENTS_WG_MASTER_H = 2776, // todo
+// *INDENT-ON*
+};
+
+/*#########################
+*####### Graveyards ######*
+#########################*/
+
+class BfGraveYardWG : public BfGraveYard
+{
+ public:
+ BfGraveYardWG(BattlefieldWG *Bf);
+
+ void SetTextId(uint32 textid) { m_GossipTextId = textid; }
+ uint32 GetTextId() { return m_GossipTextId; }
+ protected:
+ uint32 m_GossipTextId;
+};
+
+enum eWGGraveyardId
+{
+ BATTLEFIELD_WG_GY_WORKSHOP_NE,
+ BATTLEFIELD_WG_GY_WORKSHOP_NW,
+ BATTLEFIELD_WG_GY_WORKSHOP_SE,
+ BATTLEFIELD_WG_GY_WORKSHOP_SW,
+ BATTLEFIELD_WG_GY_KEEP,
+ BATTLEFIELD_WG_GY_HORDE,
+ BATTLEFIELD_WG_GY_ALLIANCE,
+ BATTLEFIELD_WG_GY_MAX,
+};
+
+enum eWGGossipText
+{
+// *INDENT-OFF*
+ BATTLEFIELD_WG_GOSSIPTEXT_GY_NE = -1850501,
+ BATTLEFIELD_WG_GOSSIPTEXT_GY_NW = -1850502,
+ BATTLEFIELD_WG_GOSSIPTEXT_GY_SE = -1850504,
+ BATTLEFIELD_WG_GOSSIPTEXT_GY_SW = -1850503,
+ BATTLEFIELD_WG_GOSSIPTEXT_GY_KEEP = -1850500,
+ BATTLEFIELD_WG_GOSSIPTEXT_GY_HORDE = -1850505,
+ BATTLEFIELD_WG_GOSSIPTEXT_GY_ALLIANCE = -1850506,
+// *INDENT-ON*
+};
+
+enum eWGNpc
+{
+// *INDENT-OFF*
+ BATTLEFIELD_WG_NPC_GUARD_H = 30739,
+ BATTLEFIELD_WG_NPC_GUARD_A = 30740,
+ BATTLEFIELD_WG_NPC_STALKER = 00000,
+
+ BATTLEFIELD_WG_NPC_VIERON_BLAZEFEATHER = 31102,
+ BATTLEFIELD_WG_NPC_STONE_GUARD_MUKAR = 32296,// <WINTERGRASP QUARTERMASTER>
+ BATTLEFIELD_WG_NPC_HOODOO_MASTER_FU_JIN = 31101,// <MASTER HEXXER>
+ BATTLEFIELD_WG_NPC_CHAMPION_ROS_SLAI = 39173,// <WINTERGRASP QUARTERMASTER>
+ BATTLEFIELD_WG_NPC_COMMANDER_DARDOSH = 31091,
+ BATTLEFIELD_WG_NPC_TACTICAL_OFFICER_KILRATH = 31151,
+ BATTLEFIELD_WG_NPC_SIEGESMITH_STRONGHOOF = 31106,
+ BATTLEFIELD_WG_NPC_PRIMALIST_MULFORT = 31053,
+ BATTLEFIELD_WG_NPC_LIEUTENANT_MURP = 31107,
+
+ BATTLEFIELD_WG_NPC_BOWYER_RANDOLPH = 31052,
+ BATTLEFIELD_WG_NPC_KNIGHT_DAMERON = 32294,// <WINTERGRASP QUARTERMASTER>
+ BATTLEFIELD_WG_NPC_SORCERESS_KAYLANA = 31051,// <ENCHANTRESS>
+ BATTLEFIELD_WG_NPC_MARSHAL_MAGRUDER = 39172,// <WINTERGRASP QUARTERMASTER>
+ BATTLEFIELD_WG_NPC_COMMANDER_ZANNETH = 31036,
+ BATTLEFIELD_WG_NPC_TACTICAL_OFFICER_AHBRAMIS = 31153,
+ BATTLEFIELD_WG_NPC_SIEGE_MASTER_STOUTHANDLE = 31108,
+ BATTLEFIELD_WG_NPC_ANCHORITE_TESSA = 31054,
+ BATTLEFIELD_WG_NPC_SENIOR_DEMOLITIONIST_LEGOSO = 31109,
+// *INDENT-ON*
+};
+
+struct BfWGCoordGY
+{
+ float x;
+ float y;
+ float z;
+ float o;
+ uint32 gyid;
+ uint8 type;
+ uint32 textid; // for gossip menu
+ TeamId startcontrol;
+};
+
+const uint32 WGQuest[2][6] = {
+ { 13186, 13181, 13222, 13538, 13177, 13179 },
+ { 13185, 13183, 13223, 13539, 13178, 13180 },
+};
+// 7 in sql, 7 in header
+const BfWGCoordGY WGGraveYard[BATTLEFIELD_WG_GY_MAX] = {
+ { 5104.750f, 2300.940f, 368.579f, 0.733038f, 1329, BATTLEFIELD_WG_GY_WORKSHOP_NE, BATTLEFIELD_WG_GOSSIPTEXT_GY_NE, TEAM_NEUTRAL },
+ { 5099.120f, 3466.036f, 368.484f, 5.317802f, 1330, BATTLEFIELD_WG_GY_WORKSHOP_NW, BATTLEFIELD_WG_GOSSIPTEXT_GY_NW, TEAM_NEUTRAL },
+ { 4314.648f, 2408.522f, 392.642f, 6.268125f, 1333, BATTLEFIELD_WG_GY_WORKSHOP_SE, BATTLEFIELD_WG_GOSSIPTEXT_GY_SE, TEAM_NEUTRAL },
+ { 4331.716f, 3235.695f, 390.251f, 0.008500f, 1334, BATTLEFIELD_WG_GY_WORKSHOP_SW, BATTLEFIELD_WG_GOSSIPTEXT_GY_SW, TEAM_NEUTRAL },
+ { 5537.986f, 2897.493f, 517.057f, 4.819249f, 1285, BATTLEFIELD_WG_GY_KEEP, BATTLEFIELD_WG_GOSSIPTEXT_GY_KEEP, TEAM_NEUTRAL },
+ { 5032.454f, 3711.382f, 372.468f, 3.971623f, 1331, BATTLEFIELD_WG_GY_HORDE, BATTLEFIELD_WG_GOSSIPTEXT_GY_HORDE, TEAM_HORDE },
+ { 5140.790f, 2179.120f, 390.950f, 1.972220f, 1332, BATTLEFIELD_WG_GY_ALLIANCE, BATTLEFIELD_WG_GOSSIPTEXT_GY_ALLIANCE, TEAM_ALLIANCE },
+};
+
+/*#########################
+* BfCapturePointWG *
+#########################*/
+
+class BfCapturePointWG : public BfCapturePoint
+{
+ public:
+ BfCapturePointWG(BattlefieldWG *bf, TeamId control);
+
+ void LinkToWorkShop(BfWGWorkShopData *ws)
+ {
+ m_WorkShop = ws;
+ }
+
+ void ChangeTeam(TeamId oldteam);
+ TeamId GetTeam() const
+ {
+ return m_team;
+ }
+
+ protected:
+ BfWGWorkShopData *m_WorkShop;
+};
+
+/*#########################
+* WinterGrasp Battlefield *
+#########################*/
+
+class BattlefieldWG : public Battlefield
+{
+ public:
+ /**
+ * \brief Called when the battle start
+ * -Spawn relic and turret
+ * -Rebuild tower and wall
+ * -Invite player to war
+ */
+ void OnBattleStart();
+
+ /**
+ * \brief Called when battle end
+ * -Remove relic and turret
+ * -Change banner/npc in keep if it needed
+ * -Saving battlestate
+ * -Reward honor/mark to player
+ * -Remove vehicle
+ * \param endbytimer : true if battle end when timer is at 00:00, false if battle end by clicking on relic
+ */
+ void OnBattleEnd(bool endbytimer);
+
+ /**
+ * \brief Called when grouping start (15 minutes before battlestart)
+ * -Invite all player in zone to join queue
+ */
+ void OnStartGrouping();
+
+ /**
+ * \brief Called when player accept invite to join battle
+ * -Update aura
+ * -Teleport if it needed
+ * -Update worldstate
+ * -Update tenacity
+ * \param plr: Player who accept invite
+ */
+ void OnPlayerJoinWar(Player *plr);
+
+ /**
+ * \brief Called when player leave battle
+ * -Update player aura
+ * \param plr : Player who leave battle
+ */
+ void OnPlayerLeaveWar(Player *plr);
+
+ /**
+ * \brief Called when player leave WG zone
+ * \param plr : Player who leave zone
+ */
+ void OnPlayerLeaveZone(Player *plr);
+
+ /**
+ * \brief Called when player enter in WG zone
+ * -Update aura
+ * -Update worldstate
+ * \param plr : Player who leave zone
+ */
+ void OnPlayerEnterZone(Player *plr);
+
+ /**
+ * \brief Called for update battlefield data
+ * -Save battle timer in database every minutes
+ * -Update imunity aura from graveyard
+ * -Update water aura, if player is in water (HACK)
+ * \param diff : time ellapsed since the last call (in ms)
+ */
+ bool Update(uint32 diff);
+
+ /**
+ * \brief Called when a creature is spawn or remove from WG
+ * -Update vehicle count
+ * \param add : true > creature is spawn false > creature is remove
+ */
+ void OnCreatureCreate(Creature *creature, bool add);
+
+ /**
+ * \brief Called when a wall/tower is broken
+ * -Update quest
+ */
+ void BrokenWallOrTower(TeamId team);
+
+ /**
+ * \brief Called when a tower is damaged
+ * -Update tower count (for reward calcul)
+ */
+ void AddDamagedTower(TeamId team);
+
+ /**
+ * \brief Called when tower is broken
+ * -Update tower buff
+ * -check if three south tower is down for remove 10 minutes to wg
+ */
+ void AddBrokenTower(TeamId team);
+
+ void DoCompleteOrIncrementAchievement(uint32 achievement, Player *player, uint8 incrementNumber = 1);
+
+ /**
+ * \brief called when a player is die, for add him to resurrect queue
+ */
+ void AddPlayerToResurrectQueue(uint64 npc_guid, uint64 player_guid);
+
+ /**
+ * \brief Called when battlefield is setup, at server start
+ */
+ bool SetupBattlefield();
+
+ /// Return pointer to relic object
+ GameObject *GetRelic()
+ {
+ return m_relic;
+ }
+
+ /// Define relic object
+ void SetRelic(GameObject * relic)
+ {
+ m_relic = relic;
+ }
+
+ /// Say if player can click or not on orb (last door broken)
+ bool CanClickOnOrb()
+ {
+ return m_bCanClickOnOrb;
+ }
+
+ /// Define if player can click or not on orb (if last door broken)
+ void AllowToClickOnOrb(bool allow)
+ {
+ m_bCanClickOnOrb = allow;
+ }
+
+ void RewardMarkOfHonor(Player *plr, uint32 count);
+
+ void UpdateVehicleCountWG();
+ void UpdateCounterVehicle(bool init);
+
+ WorldPacket BuildInitWorldStates();
+ void SendInitWorldStatesTo(Player * plr);
+ void SendInitWorldStatesToAll();
+
+ void HandleKill(Player *killer, Unit *victim);
+ void PromotePlayer(Player *killer);
+
+ void UpdateTenacity();
+ void ProcessEvent(GameObject *obj, uint32 eventId);
+
+ protected:
+ bool m_bCanClickOnOrb;
+ GameObject *m_relic;
+ GameObjectBuilding BuildingsInZone;
+ GuidSet KeepCreature[2];
+ GuidSet OutsideCreature[2];
+ WorkShop WorkShopList;
+ GuidSet CanonList;
+ GameObjectSet DefenderPortalList;
+ GameObjectSet m_KeepGameObject[2];
+ GuidSet m_vehicles[2];
+ GuidSet m_PlayersIsSpellImu; // Player is dead
+ uint32 m_tenacityStack;
+ uint32 m_saveTimer;
+};
+
+#define NORTHREND_WINTERGRASP 4197
+
+enum eWGGameObjectBuildingType
+{
+ BATTLEFIELD_WG_OBJECTTYPE_DOOR,
+ BATTLEFIELD_WG_OBJECTTYPE_TITANRELIC,
+ BATTLEFIELD_WG_OBJECTTYPE_WALL,
+ BATTLEFIELD_WG_OBJECTTYPE_DOOR_LAST,
+ BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER,
+ BATTLEFIELD_WG_OBJECTTYPE_TOWER,
+};
+
+enum eWGGameObjectState
+{
+ BATTLEFIELD_WG_OBJECTSTATE_NONE,
+ BATTLEFIELD_WG_OBJECTSTATE_NEUTRAL_INTACT,
+ BATTLEFIELD_WG_OBJECTSTATE_NEUTRAL_DAMAGE,
+ BATTLEFIELD_WG_OBJECTSTATE_NEUTRAL_DESTROY,
+ BATTLEFIELD_WG_OBJECTSTATE_HORDE_INTACT,
+ BATTLEFIELD_WG_OBJECTSTATE_HORDE_DAMAGE,
+ BATTLEFIELD_WG_OBJECTSTATE_HORDE_DESTROY,
+ BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_INTACT,
+ BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_DAMAGE,
+ BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_DESTROY,
+};
+
+enum eWGWorkShopType
+{
+ BATTLEFIELD_WG_WORKSHOP_NE,
+ BATTLEFIELD_WG_WORKSHOP_NW,
+ BATTLEFIELD_WG_WORKSHOP_SE,
+ BATTLEFIELD_WG_WORKSHOP_SW,
+ BATTLEFIELD_WG_WORKSHOP_KEEP_WEST,
+ BATTLEFIELD_WG_WORKSHOP_KEEP_EAST,
+};
+
+enum eWGTeamControl
+{
+ BATTLEFIELD_WG_TEAM_ALLIANCE,
+ BATTLEFIELD_WG_TEAM_HORDE,
+ BATTLEFIELD_WG_TEAM_NEUTRAL,
+};
+
+// TODO: Handle this with creature_text ?
+enum eWGText
+{
+// *INDENT-OFF*
+ BATTLEFIELD_WG_TEXT_WORKSHOP_NAME_NE = 12055,
+ BATTLEFIELD_WG_TEXT_WORKSHOP_NAME_NW = 12052,
+ BATTLEFIELD_WG_TEXT_WORKSHOP_NAME_SE = 12053,
+ BATTLEFIELD_WG_TEXT_WORKSHOP_NAME_SW = 12054,
+ BATTLEFIELD_WG_TEXT_WORKSHOP_ATTACK = 12051,
+ BATTLEFIELD_WG_TEXT_WORKSHOP_TAKEN = 12050,
+ BATTLEFIELD_WG_TEXT_ALLIANCE = 12057,
+ BATTLEFIELD_WG_TEXT_HORDE = 12056,
+ BATTLEFIELD_WG_TEXT_WILL_START = 12058,
+ BATTLEFIELD_WG_TEXT_START = 12067,
+ BATTLEFIELD_WG_TEXT_FIRSTRANK = 12059,
+ BATTLEFIELD_WG_TEXT_SECONDRANK = 12060,
+ BATTLEFIELD_WG_TEXT_KEEPTOWER_NAME_NE = 12062,
+ BATTLEFIELD_WG_TEXT_KEEPTOWER_NAME_NW = 12064,
+ BATTLEFIELD_WG_TEXT_KEEPTOWER_NAME_SE = 12061,
+ BATTLEFIELD_WG_TEXT_KEEPTOWER_NAME_SW = 12063,
+ BATTLEFIELD_WG_TEXT_TOWER_DAMAGE = 12065,
+ BATTLEFIELD_WG_TEXT_TOWER_DESTROY = 12066,
+ BATTLEFIELD_WG_TEXT_TOWER_NAME_S = 12069,
+ BATTLEFIELD_WG_TEXT_TOWER_NAME_E = 12070,
+ BATTLEFIELD_WG_TEXT_TOWER_NAME_W = 12071,
+ BATTLEFIELD_WG_TEXT_DEFEND_KEEP = 12068,
+ BATTLEFIELD_WG_TEXT_WIN_KEEP = 12072,
+// *INDENT-ON*
+};
+
+enum eWGObject
+{
+// *INDENT-OFF*
+ BATTLEFIELD_WG_GAMEOBJECT_FACTORY_BANNER_NE = 190475,
+ BATTLEFIELD_WG_GAMEOBJECT_FACTORY_BANNER_NW = 190487,
+ BATTLEFIELD_WG_GAMEOBJECT_FACTORY_BANNER_SE = 194959,
+ BATTLEFIELD_WG_GAMEOBJECT_FACTORY_BANNER_SW = 194962,
+ BATTLEFIELD_WG_GAMEOBJECT_TITAN_RELIC = 192829,
+// *INDENT-ON*
+};
+struct BfWGObjectPosition
+{
+ float x;
+ float y;
+ float z;
+ float o;
+ uint32 entryh;
+ uint32 entrya;
+};
+
+// *********************************************************
+// ************Destructible (Wall,Tower..)******************
+// *********************************************************
+
+struct BfWGBuildingSpawnData
+{
+ uint32 entry;
+ uint32 WorldState;
+ float x;
+ float y;
+ float z;
+ float o;
+ uint32 type;
+ uint32 nameid;
+};
+
+#define WG_MAX_OBJ 32
+const BfWGBuildingSpawnData WGGameObjectBuillding[WG_MAX_OBJ] = {
+ // Wall (Not spawned in db)
+ // Entry WS X Y Z O type NameID
+ { 190219, 3749, 5371.46f, 3047.47f, 407.571f, 3.14159f, BATTLEFIELD_WG_OBJECTTYPE_WALL, 0 },
+ { 190220, 3750, 5331.26f, 3047.1f, 407.923f, 0.052359f, BATTLEFIELD_WG_OBJECTTYPE_WALL, 0 },
+ { 191795, 3764, 5385.84f, 2909.49f, 409.713f, 0.00872f, BATTLEFIELD_WG_OBJECTTYPE_WALL, 0 },
+ { 191796, 3772, 5384.45f, 2771.84f, 410.27f, 3.14159f, BATTLEFIELD_WG_OBJECTTYPE_WALL, 0 },
+ { 191799, 3762, 5371.44f, 2630.61f, 408.816f, 3.13286f, BATTLEFIELD_WG_OBJECTTYPE_WALL, 0 },
+ { 191800, 3766, 5301.84f, 2909.09f, 409.866f, 0.008724f, BATTLEFIELD_WG_OBJECTTYPE_WALL, 0 },
+ { 191801, 3770, 5301.06f, 2771.41f, 409.901f, 3.14159f, BATTLEFIELD_WG_OBJECTTYPE_WALL, 0 },
+ { 191802, 3751, 5280.2f, 2995.58f, 408.825f, 1.61443f, BATTLEFIELD_WG_OBJECTTYPE_WALL, 0 },
+ { 191803, 3752, 5279.14f, 2956.02f, 408.604f, 1.5708f, BATTLEFIELD_WG_OBJECTTYPE_WALL, 0 },
+ { 191804, 3767, 5278.69f, 2882.51f, 409.539f, 1.5708f, BATTLEFIELD_WG_OBJECTTYPE_WALL, 0 },
+ { 191806, 3769, 5279.5f, 2798.94f, 409.998f, 1.5708f, BATTLEFIELD_WG_OBJECTTYPE_WALL, 0 },
+ { 191807, 3759, 5279.94f, 2724.77f, 409.945f, 1.56207f, BATTLEFIELD_WG_OBJECTTYPE_WALL, 0 },
+ { 191808, 3760, 5279.6f, 2683.79f, 409.849f, 1.55334f, BATTLEFIELD_WG_OBJECTTYPE_WALL, 0 },
+ { 191809, 3761, 5330.96f, 2630.78f, 409.283f, 3.13286f, BATTLEFIELD_WG_OBJECTTYPE_WALL, 0 },
+ { 190369, 3753, 5256.08f, 2933.96f, 409.357f, 3.13286f, BATTLEFIELD_WG_OBJECTTYPE_WALL, 0 },
+ { 190370, 3758, 5257.46f, 2747.33f, 409.743f, -3.13286f, BATTLEFIELD_WG_OBJECTTYPE_WALL, 0 },
+ { 190371, 3754, 5214.96f, 2934.09f, 409.19f, -0.008724f, BATTLEFIELD_WG_OBJECTTYPE_WALL, 0 },
+ { 190372, 3757, 5215.82f, 2747.57f, 409.188f, -3.13286f, BATTLEFIELD_WG_OBJECTTYPE_WALL, 0 },
+ { 190374, 3755, 5162.27f, 2883.04f, 410.256f, 1.57952f, BATTLEFIELD_WG_OBJECTTYPE_WALL, 0 },
+ { 190376, 3756, 5163.72f, 2799.84f, 409.227f, 1.57952f, BATTLEFIELD_WG_OBJECTTYPE_WALL, 0 },
+
+ // Tower of keep (Not spawned in db)
+ { 190221, 3711, 5281.15f, 3044.59f, 407.843f, 3.11539f, BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER, BATTLEFIELD_WG_TEXT_KEEPTOWER_NAME_NW },
+ { 190373, 3713, 5163.76f, 2932.23f, 409.19f, 3.12412f, BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER, BATTLEFIELD_WG_TEXT_KEEPTOWER_NAME_SW },
+ { 190377, 3714, 5166.4f, 2748.37f, 409.188f, -1.5708f, BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER, BATTLEFIELD_WG_TEXT_KEEPTOWER_NAME_SE },
+ { 190378, 3712, 5281.19f, 2632.48f, 409.099f, -1.58825f, BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER, BATTLEFIELD_WG_TEXT_KEEPTOWER_NAME_NE },
+
+ // Wall (with passage) (Not spawned in db)
+ { 191797, 3765, 5343.29f, 2908.86f, 409.576f, 0.008724f, BATTLEFIELD_WG_OBJECTTYPE_WALL, 0 },
+ { 191798, 3771, 5342.72f, 2771.39f, 409.625f, 3.14159f, BATTLEFIELD_WG_OBJECTTYPE_WALL, 0 },
+ { 191805, 3768, 5279.13f, 2840.8f, 409.783f, 1.57952f, BATTLEFIELD_WG_OBJECTTYPE_WALL, 0 },
+
+ // South tower (Not spawned in db)
+ { 190356, 3704, 4557.17f, 3623.94f, 395.883f, 1.67552f, BATTLEFIELD_WG_OBJECTTYPE_TOWER, BATTLEFIELD_WG_TEXT_TOWER_NAME_W },
+ { 190357, 3705, 4398.17f, 2822.5f, 405.627f, -3.12412f, BATTLEFIELD_WG_OBJECTTYPE_TOWER, BATTLEFIELD_WG_TEXT_TOWER_NAME_S },
+ { 190358, 3706, 4459.1f, 1944.33f, 434.991f, -2.00276f, BATTLEFIELD_WG_OBJECTTYPE_TOWER, BATTLEFIELD_WG_TEXT_TOWER_NAME_E },
+
+ // Door of forteress (Not spawned in db)
+ { 190375, 3763, 5162.99f, 2841.23f, 410.162f, -3.13286f, BATTLEFIELD_WG_OBJECTTYPE_DOOR, 0 },
+
+ // Last door (Not spawned in db)
+ { 191810, 3773, 5397.11f, 2841.54f, 425.899f, 3.14159f, BATTLEFIELD_WG_OBJECTTYPE_DOOR_LAST, 0 },
+};
+
+
+// *********************************************************
+// **********Keep Element(GameObject,Creature)**************
+// *********************************************************
+
+// Keep gameobject
+// 192488 : 10 in sql, 19 in header
+// 192501 : 12 in sql, 17 in header
+// 192416 : 1 in sql, 33 in header
+// 192374 : 1 in sql, 1 in header
+// 192375 : 1 in sql, 1 in header
+// 192336 : 1 in sql, 1 in header
+// 192255 : 1 in sql, 1 in header
+// 192269 : 1 in sql, 7 in header
+// 192254 : 1 in sql, 1 in header
+// 192349 : 1 in sql, 1 in header
+// 192366 : 1 in sql, 3 in header
+// 192367 : 1 in sql, 1 in header
+// 192364 : 1 in sql, 1 in header
+// 192370 : 1 in sql, 1 in header
+// 192369 : 1 in sql, 1 in header
+// 192368 : 1 in sql, 1 in header
+// 192362 : 1 in sql, 1 in header
+// 192363 : 1 in sql, 1 in header
+// 192379 : 1 in sql, 1 in header
+// 192378 : 1 in sql, 1 in header
+// 192355 : 1 in sql, 1 in header
+// 192354 : 1 in sql, 1 in header
+// 192358 : 1 in sql, 1 in header
+// 192359 : 1 in sql, 1 in header
+// 192338 : 1 in sql, 1 in header
+// 192339 : 1 in sql, 1 in header
+// 192284 : 1 in sql, 1 in header
+// 192285 : 1 in sql, 1 in header
+// 192371 : 1 in sql, 1 in header
+// 192372 : 1 in sql, 1 in header
+// 192373 : 1 in sql, 1 in header
+// 192360 : 1 in sql, 1 in header
+// 192361 : 1 in sql, 1 in header
+// 192356 : 1 in sql, 1 in header
+// 192352 : 1 in sql, 1 in header
+// 192353 : 1 in sql, 1 in header
+// 192357 : 1 in sql, 1 in header
+// 192350 : 1 in sql, 1 in header
+// 192351 : 1 in sql, 1 in header
+#define WG_KEEPGAMEOBJECT_MAX 44
+const BfWGObjectPosition WGKeepGameObject[WG_KEEPGAMEOBJECT_MAX] = {
+ { 5262.540039f, 3047.949951f, 432.054993f, 3.106650f, 192488, 192501 }, // Flag on tower
+ { 5272.939941f, 2976.550049f, 444.492004f, 3.124120f, 192374, 192416 }, // Flag on Wall Intersect
+ { 5235.189941f, 2941.899902f, 444.278015f, 1.588250f, 192375, 192416 }, // Flag on Wall Intersect
+ { 5163.129883f, 2952.590088f, 433.502991f, 1.535890f, 192488, 192501 }, // Flag on tower
+ { 5145.109863f, 2935.000000f, 433.385986f, 3.141590f, 192488, 192501 }, // Flag on tower
+ { 5158.810059f, 2883.129883f, 431.618011f, 3.141590f, 192488, 192416 }, // Flag on wall
+ { 5154.490234f, 2862.149902f, 445.011993f, 3.141590f, 192336, 192416 }, // Flag on Wall Intersect
+ { 5154.520020f, 2853.310059f, 409.183014f, 3.141590f, 192255, 192269 }, // Flag on the floor
+ { 5154.459961f, 2828.939941f, 409.188995f, 3.141590f, 192254, 192269 }, // Flag on the floor
+ { 5155.310059f, 2820.739990f, 444.979004f, -3.13286f, 192349, 192416 }, // Flag on wall intersect
+ { 5160.339844f, 2798.610107f, 430.769012f, 3.141590f, 192488, 192416 }, // Flag on wall
+ { 5146.040039f, 2747.209961f, 433.584015f, 3.071770f, 192488, 192501 }, // Flag on tower
+ { 5163.779785f, 2729.679932f, 433.394012f, -1.58825f, 192488, 192501 }, // Flag on tower
+ { 5236.270020f, 2739.459961f, 444.992004f, -1.59698f, 192366, 192416 }, // Flag on wall intersect
+ { 5271.799805f, 2704.870117f, 445.183014f, -3.13286f, 192367, 192416 }, // Flag on wall intersect
+ { 5260.819824f, 2631.800049f, 433.324005f, 3.054330f, 192488, 192501 }, // Flag on tower
+ { 5278.379883f, 2613.830078f, 433.408997f, -1.58825f, 192488, 192501 }, // Flag on tower
+ { 5350.879883f, 2622.719971f, 444.686005f, -1.57080f, 192364, 192416 }, // Flag on wall intersect
+ { 5392.270020f, 2639.739990f, 435.330994f, 1.509710f, 192370, 192416 }, // Flag on wall intersect
+ { 5350.950195f, 2640.360107f, 435.407990f, 1.570800f, 192369, 192416 }, // Flag on wall intersect
+ { 5289.459961f, 2704.679932f, 435.875000f, -0.01745f, 192368, 192416 }, // Flag on wall intersect
+ { 5322.120117f, 2763.610107f, 444.973999f, -1.55334f, 192362, 192416 }, // Flag on wall intersect
+ { 5363.609863f, 2763.389893f, 445.023987f, -1.54462f, 192363, 192416 }, // Flag on wall intersect
+ { 5363.419922f, 2781.030029f, 435.763000f, 1.570800f, 192379, 192416 }, // Flag on wall intersect
+ { 5322.020020f, 2781.129883f, 435.811005f, 1.570800f, 192378, 192416 }, // Flag on wall intersect
+ { 5288.919922f, 2820.219971f, 435.721008f, 0.017452f, 192355, 192416 }, // Flag on wall intersect
+ { 5288.410156f, 2861.790039f, 435.721008f, 0.017452f, 192354, 192416 }, // Flag on wall intersect
+ { 5322.229980f, 2899.429932f, 435.808014f, -1.58825f, 192358, 192416 }, // Flag on wall intersect
+ { 5364.350098f, 2899.399902f, 435.838989f, -1.57080f, 192359, 192416 }, // Flag on wall intersect
+ { 5397.759766f, 2873.080078f, 455.460999f, 3.106650f, 192338, 192416 }, // Flag on keep
+ { 5397.390137f, 2809.330078f, 455.343994f, 3.106650f, 192339, 192416 }, // Flag on keep
+ { 5372.479980f, 2862.500000f, 409.049011f, 3.141590f, 192284, 192269 }, // Flag on floor
+ { 5371.490234f, 2820.800049f, 409.177002f, 3.141590f, 192285, 192269 }, // Flag on floor
+ { 5364.290039f, 2916.939941f, 445.330994f, 1.579520f, 192371, 192416 }, // Flag on wall intersect
+ { 5322.859863f, 2916.949951f, 445.153992f, 1.562070f, 192372, 192416 }, // Flag on wall intersect
+ { 5290.350098f, 2976.560059f, 435.221008f, 0.017452f, 192373, 192416 }, // Flag on wall intersect
+ { 5352.370117f, 3037.090088f, 435.252014f, -1.57080f, 192360, 192416 }, // Flag on wall intersect
+ { 5392.649902f, 3037.110107f, 433.713013f, -1.52716f, 192361, 192416 }, // Flag on wall intersect
+ { 5237.069824f, 2757.030029f, 435.795990f, 1.518440f, 192356, 192416 }, // Flag on wall intersect
+ { 5173.020020f, 2820.929932f, 435.720001f, 0.017452f, 192352, 192416 }, // Flag on wall intersect
+ { 5172.109863f, 2862.570068f, 435.721008f, 0.017452f, 192353, 192416 }, // Flag on wall intersect
+ { 5235.339844f, 2924.340088f, 435.040009f, -1.57080f, 192357, 192416 }, // Flag on wall intersect
+ { 5270.689941f, 2861.780029f, 445.058014f, -3.11539f, 192350, 192416 }, // Flag on wall intersect
+ { 5271.279785f, 2820.159912f, 445.200989f, -3.13286f, 192351, 192416 } // Flag on wall intersect
+};
+
+// Keep turret
+struct BfWGTurretPos
+{
+ float x;
+ float y;
+ float z;
+ float o;
+};
+
+#define WG_MAX_TURRET 15
+const BfWGTurretPos WGTurret[WG_MAX_TURRET] = {
+ { 5391.19f, 3060.8f, 419.616f, 1.69557f },
+ { 5266.75f, 2976.5f, 421.067f, 3.20354f },
+ { 5234.86f, 2948.8f, 420.88f, 1.61311f },
+ { 5323.05f, 2923.7f, 421.645f, 1.5817f },
+ { 5363.82f, 2923.87f, 421.709f, 1.60527f },
+ { 5264.04f, 2861.34f, 421.587f, 3.21142f },
+ { 5264.68f, 2819.78f, 421.656f, 3.15645f },
+ { 5322.16f, 2756.69f, 421.646f, 4.69978f },
+ { 5363.78f, 2756.77f, 421.629f, 4.78226f },
+ { 5236.2f, 2732.68f, 421.649f, 4.72336f },
+ { 5265.02f, 2704.63f, 421.7f, 3.12507f },
+ { 5350.87f, 2616.03f, 421.243f, 4.72729f },
+ { 5390.95f, 2615.5f, 421.126f, 4.6409f },
+ { 5148.8f, 2820.24f, 421.621f, 3.16043f },
+ { 5147.98f, 2861.93f, 421.63f, 3.18792f },
+};
+
+
+// Here there is all npc keeper spawn point
+#define WG_MAX_KEEP_NPC 39
+const BfWGObjectPosition WGKeepNPC[WG_MAX_KEEP_NPC] = {
+ // X Y Z O horde alliance
+ // North East
+ { 5326.203125f, 2660.026367f, 409.100891f, 2.543383f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Roaming Guard
+ { 5298.430176f, 2738.760010f, 409.316010f, 3.971740f, BATTLEFIELD_WG_NPC_VIERON_BLAZEFEATHER, BATTLEFIELD_WG_NPC_BOWYER_RANDOLPH }, // Vieron Plumembrase
+ { 5335.310059f, 2764.110107f, 409.274994f, 4.834560f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 5349.810059f, 2763.629883f, 409.333008f, 4.660030f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ // North
+ { 5373.470215f, 2789.060059f, 409.322998f, 2.600540f, BATTLEFIELD_WG_NPC_STONE_GUARD_MUKAR, BATTLEFIELD_WG_NPC_KNIGHT_DAMERON }, // Stone Guard Mukar
+ { 5296.560059f, 2789.870117f, 409.274994f, 0.733038f, BATTLEFIELD_WG_NPC_HOODOO_MASTER_FU_JIN, BATTLEFIELD_WG_NPC_SORCERESS_KAYLANA }, // Voodoo Master Fu'jin
+ { 5372.670000f, 2786.740000f, 409.442000f, 2.809980f, BATTLEFIELD_WG_NPC_CHAMPION_ROS_SLAI, BATTLEFIELD_WG_NPC_MARSHAL_MAGRUDER }, // Wintergrasp Quartermaster
+ { 5368.709961f, 2856.360107f, 409.322998f, 2.949610f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 5367.910156f, 2826.520020f, 409.322998f, 3.333580f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 5389.270020f, 2847.370117f, 418.759003f, 3.106690f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 5388.560059f, 2834.770020f, 418.759003f, 3.071780f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 5359.129883f, 2837.989990f, 409.364014f, 4.698930f, BATTLEFIELD_WG_NPC_COMMANDER_DARDOSH, BATTLEFIELD_WG_NPC_COMMANDER_ZANNETH }, // Commander Dardosh
+ { 5366.129883f, 2833.399902f, 409.322998f, 3.141590f, BATTLEFIELD_WG_NPC_TACTICAL_OFFICER_KILRATH, BATTLEFIELD_WG_NPC_TACTICAL_OFFICER_AHBRAMIS }, // Tactical Officer Kilrath
+ // X Y Z O horde alliance
+ // North West
+ { 5350.680176f, 2917.010010f, 409.274994f, 1.466080f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 5335.120117f, 2916.800049f, 409.444000f, 1.500980f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 5295.560059f, 2926.669922f, 409.274994f, 0.872665f, BATTLEFIELD_WG_NPC_SIEGESMITH_STRONGHOOF, BATTLEFIELD_WG_NPC_SIEGE_MASTER_STOUTHANDLE }, // Stronghoof
+ { 5371.399902f, 3026.510010f, 409.205994f, 3.250030f, BATTLEFIELD_WG_NPC_PRIMALIST_MULFORT, BATTLEFIELD_WG_NPC_ANCHORITE_TESSA }, // Primalist Mulfort
+ { 5392.123535f, 3031.110352f, 409.187683f, 3.677212f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Roaming Guard
+ // South
+ { 5270.060059f, 2847.550049f, 409.274994f, 3.071780f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 5270.160156f, 2833.479980f, 409.274994f, 3.124140f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 5179.109863f, 2837.129883f, 409.274994f, 3.211410f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 5179.669922f, 2846.600098f, 409.274994f, 3.089230f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 5234.970215f, 2883.399902f, 409.274994f, 4.293510f, BATTLEFIELD_WG_NPC_LIEUTENANT_MURP, BATTLEFIELD_WG_NPC_SENIOR_DEMOLITIONIST_LEGOSO }, // Lieutenant Murp
+ // X Y Z O horde alliance
+ // Portal guards (from around the fortress)
+ { 5319.209473f, 3055.947754f, 409.176636f, 1.020201f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 5311.612305f, 3061.207275f, 408.734161f, 0.965223f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 5264.713379f, 3017.283447f, 408.479706f, 3.482424f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 5269.096191f, 3008.315918f, 408.826294f, 3.843706f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 5201.414551f, 2945.096924f, 409.190735f, 0.945592f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 5193.386230f, 2949.617188f, 409.190735f, 1.145859f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 5148.116211f, 2904.761963f, 409.193756f, 3.368532f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 5153.355957f, 2895.501465f, 409.199310f, 3.549174f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 5154.353027f, 2787.349365f, 409.250183f, 2.555644f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 5150.066406f, 2777.876953f, 409.343903f, 2.708797f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 5193.706543f, 2732.882812f, 409.189514f, 4.845073f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 5202.126953f, 2737.570557f, 409.189514f, 5.375215f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 5269.181152f, 2671.174072f, 409.098999f, 2.457459f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 5264.960938f, 2662.332520f, 409.098999f, 2.598828f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 5307.111816f, 2616.006836f, 409.095734f, 5.355575f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 5316.770996f, 2619.430176f, 409.027740f, 5.363431f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A } // Standing Guard
+};
+
+#define WG_MAX_OUTSIDE_NPC 14
+#define WG_OUTSIDE_ALLIANCE_NPC 7
+const BfWGObjectPosition WGOutsideNPC[WG_MAX_OUTSIDE_NPC] =
+{
+ { 5032.04f, 3681.79f, 362.980f, 4.210f, BATTLEFIELD_WG_NPC_VIERON_BLAZEFEATHER, 0 },
+ { 5020.71f, 3626.19f, 360.150f, 4.640f, BATTLEFIELD_WG_NPC_HOODOO_MASTER_FU_JIN, 0 },
+ { 4994.85f, 3660.51f, 359.150f, 2.260f, BATTLEFIELD_WG_NPC_COMMANDER_DARDOSH, 0 },
+ { 5015.46f, 3677.11f, 362.970f, 6.009f, BATTLEFIELD_WG_NPC_TACTICAL_OFFICER_KILRATH, 0 },
+ { 5031.12f, 3663.77f, 363.500f, 3.110f, BATTLEFIELD_WG_NPC_SIEGESMITH_STRONGHOOF, 0 },
+ { 5042.74f, 3675.82f, 363.060f, 3.358f, BATTLEFIELD_WG_NPC_PRIMALIST_MULFORT, 0 },
+ { 5014.45f, 3640.87f, 361.390f, 3.280f, BATTLEFIELD_WG_NPC_LIEUTENANT_MURP, 0 },
+ { 5100.07f, 2168.89f, 365.779f, 1.972f, 0, BATTLEFIELD_WG_NPC_BOWYER_RANDOLPH },
+ { 5081.70f, 2173.73f, 365.878f, 0.855f, 0, BATTLEFIELD_WG_NPC_SORCERESS_KAYLANA },
+ { 5078.28f, 2183.70f, 365.029f, 1.466f, 0, BATTLEFIELD_WG_NPC_COMMANDER_ZANNETH },
+ { 5088.49f, 2188.18f, 365.647f, 5.253f, 0, BATTLEFIELD_WG_NPC_TACTICAL_OFFICER_AHBRAMIS },
+ { 5095.67f, 2193.28f, 365.924f, 4.939f, 0, BATTLEFIELD_WG_NPC_SIEGE_MASTER_STOUTHANDLE },
+ { 5088.61f, 2167.66f, 365.689f, 0.680f, 0, BATTLEFIELD_WG_NPC_ANCHORITE_TESSA },
+ { 5080.40f, 2199.00f, 359.489f, 2.967f, 0, BATTLEFIELD_WG_NPC_SENIOR_DEMOLITIONIST_LEGOSO },
+};
+
+struct BfWGWGTeleporterData
+{
+ uint32 entry; // gameobject entry
+ float x;
+ float y;
+ float z;
+ float o;
+};
+
+#define WG_MAX_TELEPORTER 12
+const BfWGWGTeleporterData WGPortalDefenderData[WG_MAX_TELEPORTER] =
+{
+ // Player teleporter
+ { 190763, 5153.41f, 2901.35f, 409.191f, -0.069f },
+ { 190763, 5268.70f, 2666.42f, 409.099f, -0.715f },
+ { 190763, 5197.05f, 2944.81f, 409.191f, 2.3387f },
+ { 190763, 5196.67f, 2737.34f, 409.189f, -2.932f },
+ { 190763, 5314.58f, 3055.85f, 408.862f, 0.5410f },
+ { 190763, 5391.28f, 2828.09f, 418.675f, -2.164f },
+ { 190763, 5153.93f, 2781.67f, 409.246f, 1.6580f },
+ { 190763, 5311.44f, 2618.93f, 409.092f, -2.373f },
+ { 190763, 5269.21f, 3013.84f, 408.828f, -1.762f },
+ { 190763, 5401.62f, 2853.66f, 418.674f, 2.6354f },
+ // Vehicle teleporter
+ { 192951, 5314.51f, 2703.69f, 408.550f, -0.890f },
+ { 192951, 5316.25f, 2977.04f, 408.539f, -0.820f },
+};
+
+// *********************************************************
+// **********Tower Element(GameObject,Creature)*************
+// *********************************************************
+
+struct BfWGTowerData
+{
+ uint32 towerentry; // Gameobject id of tower
+ uint8 nbObject; // Number of gameobjects spawned on this point
+ BfWGObjectPosition GameObject[6]; // Gameobject position and entry (Horde/Alliance)
+
+ // Creature : Turrets and Guard, TODO: check if killed on tower destruction? tower damage?
+ uint8 nbCreatureBottom;
+ BfWGObjectPosition CreatureBottom[9];
+ uint8 nbCreatureTop;
+ BfWGObjectPosition CreatureTop[5];
+};
+
+#define WG_MAX_ATTACKTOWERS 3
+// 192414 : 0 in sql, 1 in header
+// 192278 : 0 in sql, 3 in header
+const BfWGTowerData AttackTowers[WG_MAX_ATTACKTOWERS] = {
+ // West tower
+ {
+ 190356,
+ 6,
+ {
+ { 4559.109863f, 3606.219971f, 419.998993f, -1.483530f, 192488, 192501 }, // Flag on tower
+ { 4539.419922f, 3622.489990f, 420.033997f, -3.071770f, 192488, 192501 }, // Flag on tower
+ { 4555.259766f, 3641.649902f, 419.973999f, 1.675510f, 192488, 192501 }, // Flag on tower
+ { 4574.870117f, 3625.909912f, 420.079010f, 0.080117f, 192488, 192501 }, // Flag on tower
+ { 4433.899902f, 3534.139893f, 360.274994f, -1.850050f, 192269, 192278 }, // Flag near workshop
+ { 4572.930176f, 3475.520020f, 363.009003f, 1.42240f, 192269, 192278 } // Flag near bridge
+ },
+ 1,
+ {
+ { 4418.688477f, 3506.251709f, 358.975494f, 4.293305f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Roaming Guard
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ },
+ 0,
+ {
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ }
+ },
+
+ // South Tower
+ {
+ 190357,
+ 5,
+ {
+ { 4416.000000f, 2822.669922f, 429.851013f, -0.017452f, 192488, 192501 }, // Flag on tower
+ { 4398.819824f, 2804.699951f, 429.791992f, -1.588250f, 192488, 192501 }, // Flag on tower
+ { 4387.620117f, 2719.570068f, 389.934998f, -1.544620f, 192366, 192414 }, // Flag near tower
+ { 4464.120117f, 2855.449951f, 406.110992f, 0.829032f, 192366, 192429 }, // Flag near tower
+ { 4526.459961f, 2810.179932f, 391.200012f, -2.993220f, 192269, 192278 }, // Flag near bridge
+ { 0, 0, 0, 0, 0, 0 },
+ },
+ 6,
+ {
+ { 4452.859863f, 2808.870117f, 402.604004f, 6.056290f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 4455.899902f, 2835.958008f, 401.122559f, 0.034907f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 4412.649414f, 2953.792236f, 374.799957f, 0.980838f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Roaming Guard
+ { 4362.089844f, 2811.510010f, 407.337006f, 3.193950f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 4412.290039f, 2753.790039f, 401.015015f, 5.829400f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 4421.939941f, 2773.189941f, 400.894989f, 5.707230f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 0, 0, 0, 0, 0, 0},
+ { 0, 0, 0, 0, 0, 0},
+ { 0, 0, 0, 0, 0, 0},
+ },
+ 0,
+ {
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ },
+ },
+
+ // East Tower
+ {
+ 190358,
+ 4,
+ {
+ { 4466.790039f, 1960.420044f, 459.144012f, 1.151920f, 192488, 192501 }, // Flag on tower
+ { 4475.350098f, 1937.030029f, 459.070007f, -0.43633f, 192488, 192501 }, // Flag on tower
+ { 4451.759766f, 1928.099976f, 459.075989f, -2.00713f, 192488, 192501 }, // Flag on tower
+ { 4442.990234f, 1951.900024f, 459.092987f, 2.740160f, 192488, 192501 }, // Flag on tower
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ },
+ 5,
+ {
+ { 4501.060059f, 1990.280029f, 431.157013f, 1.029740f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 4463.830078f, 2015.180054f, 430.299988f, 1.431170f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 4494.580078f, 1943.760010f, 435.627014f, 6.195920f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 4450.149902f, 1897.579956f, 435.045013f, 4.398230f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 4428.870117f, 1906.869995f, 432.648010f, 3.996800f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A }, // Standing Guard
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ },
+ 0,
+ {
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ },
+ },
+};
+
+struct BfWGTurretData
+{
+ uint32 towerentry;
+ uint8 nbTurretBottom;
+ BfWGTurretPos TurretBottom[5];
+ uint8 nbTurretTop;
+ BfWGTurretPos TurretTop[5];
+};
+
+#define WG_MAX_TOWERTURRET 7
+
+const BfWGTurretData TowerTurret[WG_MAX_TOWERTURRET] =
+{
+ {
+ 190221,
+ 0,
+ {
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ },
+ 2,
+ {
+ { 5255.88f, 3047.63f, 438.499f, 3.13677f },
+ { 5280.9f, 3071.32f, 438.499f, 1.62879f },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ },
+ },
+ {
+ 190373,
+ 0,
+ {
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ },
+ 2,
+ {
+ { 5138.59f, 2935.16f, 439.845f, 3.11723f },
+ { 5163.06f, 2959.52f, 439.846f, 1.47258f },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ },
+ },
+ {
+ 190377,
+ 0,
+ {
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ },
+ 2,
+ {
+ { 5163.84f, 2723.74f, 439.844f, 1.3994f },
+ { 5139.69f, 2747.4f, 439.844f, 3.17221f },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ },
+ },
+ {
+ 190378,
+ 0,
+ {
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ },
+ 2,
+ {
+ { 5278.21f, 2607.23f, 439.755f, 4.71944f },
+ { 5255.01f, 2631.98f, 439.755f, 3.15257f },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ },
+ },
+ {
+ 190356,
+ 2,
+ {
+ {4537.380371f, 3599.531738f, 402.886993f, 3.998462f},
+ {4581.497559f, 3604.087158f, 402.886963f, 5.651723f},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ },
+ 2,
+ {
+ {4469.448242f, 1966.623779f, 465.647217f, 1.153573f},
+ {4581.895996f, 3626.438477f, 426.539062f, 0.117806f},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ },
+ },
+ {
+ 190357,
+ 2,
+ {
+ { 4421.640137f, 2799.935791f, 412.630920f, 5.459298f },
+ { 4420.263184f, 2845.340332f, 412.630951f, 0.742197f },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ },
+ 3,
+ {
+ { 4423.430664f, 2822.762939f, 436.283142f, 6.223487f },
+ { 4397.825684f, 2847.629639f, 436.283325f, 1.579430f },
+ { 4398.814941f, 2797.266357f, 436.283051f, 4.703747f },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ },
+ },
+ {
+ 190358,
+ 2,
+ {
+ { 4448.138184f, 1974.998779f, 441.995911f, 1.967238f },
+ { 4448.713379f, 1955.148682f, 441.995178f, 0.380733f },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ },
+ 2,
+ {
+ { 4469.448242f, 1966.623779f, 465.647217f, 1.153573f },
+ { 4481.996582f, 1933.658325f, 465.647186f, 5.873029f },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ },
+ },
+};
+
+// *********************************************************
+// *****************WorkShop Data & Element*****************
+// *********************************************************
+
+struct BfWGWorkShopDataBase
+{
+ uint32 entry;
+ uint32 worldstate;
+ uint32 type;
+ uint32 nameid;
+ BfWGObjectPosition CapturePoint;
+ uint8 nbcreature;
+ BfWGObjectPosition CreatureData[10];
+ uint8 nbgob;
+ BfWGObjectPosition GameObjectData[10];
+};
+// 6 engineer per faction in sql / 6 engineer per faction in header
+#define WG_MAX_WORKSHOP 6
+const BfWGWorkShopDataBase WGWorkShopDataBase[WG_MAX_WORKSHOP] = {
+ {
+ 192031,
+ 3701,
+ BATTLEFIELD_WG_WORKSHOP_NE,
+ BATTLEFIELD_WG_TEXT_WORKSHOP_NAME_NE,
+ { 4949.344238f, 2432.585693f, 320.176971f, 1.386214f, BATTLEFIELD_WG_GAMEOBJECT_FACTORY_BANNER_NE, BATTLEFIELD_WG_GAMEOBJECT_FACTORY_BANNER_NE },
+ 1,
+ {
+ { 4939.759766f, 2389.060059f, 326.153015f, 3.263770f, 30400, 30499 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 }
+ },
+ 6,
+ {
+ { 4778.189f, 2438.060f, 345.644f, -2.940f, 192280, 192274 },
+ { 5024.569f, 2532.750f, 344.023f, -1.937f, 192280, 192274 },
+ { 4811.399f, 2441.899f, 358.207f, -2.003f, 192435, 192406 },
+ { 4805.669f, 2407.479f, 358.191f, 1.780f, 192435, 192406 },
+ { 5004.350f, 2486.360f, 358.449f, 2.172f, 192435, 192406 },
+ { 4983.279f, 2503.090f, 358.177f, -0.427f, 192435, 192406 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 }
+ }
+ },
+ {
+ 192030,
+ 3700,
+ BATTLEFIELD_WG_WORKSHOP_NW,
+ BATTLEFIELD_WG_TEXT_WORKSHOP_NAME_NW,
+ { 4948.524414f, 3342.337891f, 376.875366f, 4.400566f, BATTLEFIELD_WG_GAMEOBJECT_FACTORY_BANNER_NW, BATTLEFIELD_WG_GAMEOBJECT_FACTORY_BANNER_NW },
+ 1,
+ {
+ { 4964.890137f, 3383.060059f, 382.911011f, 6.126110f, 30400, 30499 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 }
+ },
+ 4,
+ {
+ { 5006.339f, 3280.399f, 371.162f, 2.225f, 192280, 192274 },
+ { 5041.609f, 3294.399f, 382.149f, -1.631f, 192434, 192406 },
+ { 4857.970f, 3335.439f, 368.881f, -2.945f, 192280, 192274 },
+ { 4855.629f, 3297.620f, 376.739f, -3.132f, 192435, 192406 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 }
+ }
+ },
+ {
+ 192033,
+ 3703,
+ BATTLEFIELD_WG_WORKSHOP_SE,
+ BATTLEFIELD_WG_TEXT_WORKSHOP_NAME_SE,
+ { 4398.076660f, 2356.503662f, 376.190491f, 0.525406f, BATTLEFIELD_WG_GAMEOBJECT_FACTORY_BANNER_SE, BATTLEFIELD_WG_GAMEOBJECT_FACTORY_BANNER_SE },
+ 9,
+ {
+ { 4417.919922f, 2331.239990f, 370.919006f, 5.846850f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A },
+ { 4418.609863f, 2355.290039f, 372.490997f, 6.021390f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A },
+ { 4391.669922f, 2300.610107f, 374.743011f, 4.921830f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A },
+ { 4349.120117f, 2299.280029f, 374.743011f, 4.904380f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A },
+ { 4333.549805f, 2333.909912f, 376.156006f, 0.973007f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A },
+ { 4413.430176f, 2393.449951f, 376.359985f, 1.064650f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A },
+ { 4388.129883f, 2411.979980f, 374.743011f, 1.640610f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A },
+ { 4349.540039f, 2411.260010f, 374.743011f, 2.059490f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A },
+ { 4357.669922f, 2357.989990f, 382.006989f, 1.675520f, 30400, 30499 },
+ { 0, 0, 0, 0, 0, 0 }
+ },
+ 2,
+ {
+ { 4417.250f, 2301.139f, 377.213f, 0.026f, 192435, 192406 },
+ { 4417.939f, 2324.810f, 371.576f, 3.080f, 192280, 192274 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 }
+ }
+ },
+ {
+ 192032,
+ 3702,
+ BATTLEFIELD_WG_WORKSHOP_SW,
+ BATTLEFIELD_WG_TEXT_WORKSHOP_NAME_SW,
+ { 4390.776367f, 3304.094482f, 372.429077f, 6.097023f, BATTLEFIELD_WG_GAMEOBJECT_FACTORY_BANNER_SW, BATTLEFIELD_WG_GAMEOBJECT_FACTORY_BANNER_SW },
+ 9,
+ {
+ { 4425.290039f, 3291.510010f, 370.773987f, 0.122173f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A },
+ { 4424.609863f, 3321.100098f, 369.800995f, 0.034907f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A },
+ { 4392.399902f, 3354.610107f, 369.597992f, 1.570800f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A },
+ { 4370.979980f, 3355.020020f, 371.196991f, 1.675520f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A },
+ { 4394.660156f, 3231.989990f, 369.721985f, 4.625120f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A },
+ { 4366.979980f, 3233.560059f, 371.584991f, 4.939280f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A },
+ { 4337.029785f, 3261.659912f, 373.524994f, 3.263770f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A },
+ { 4323.779785f, 3287.100098f, 378.894989f, 2.862340f, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A },
+ { 4354.149902f, 3312.820068f, 378.045990f, 1.675520f, 30400, 30499 },
+ { 0, 0, 0, 0, 0, 0 }
+ },
+ 3,
+ {
+ { 4438.299f, 3361.080f, 371.567f, -0.017f, 192435, 192406 },
+ { 4448.169f, 3235.629f, 370.411f, -1.562f, 192435, 192406 },
+ { 4424.149f, 3286.540f, 371.545f, 3.124f, 192280, 192274 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 }
+ }
+ },
+ {
+ 192028,
+ 3698,
+ BATTLEFIELD_WG_WORKSHOP_KEEP_WEST,
+ 0,
+ { 0, 0, 0, 0, 0, 0 },
+ 1,
+ {
+ { 5392.910156f, 2975.260010f, 415.222992f, 4.555310f, 30400, 30499 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 }
+ },
+ 0,
+ {
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 }
+ }
+ },
+ {
+ 192029,
+ 3699,
+ BATTLEFIELD_WG_WORKSHOP_KEEP_EAST,
+ 0,
+ { 0, 0, 0, 0, 0, 0 },
+ 1,
+ {
+ { 5391.609863f, 2707.719971f, 415.050995f, 4.555310f, 30400, 30499 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 }
+ },
+ 0,
+ {
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 }
+ }
+ }
+};
+
+// ********************************************************************
+// * Structs using for Building,Graveyard,Workshop *
+// ********************************************************************
+// Structure for different buildings that can be destroyed during battle
+struct BfWGGameObjectBuilding
+{
+ BfWGGameObjectBuilding(BattlefieldWG *WG)
+ {
+ m_WG = WG;
+ m_Team = 0;
+ m_Build = NULL;
+ m_Type = 0;
+ m_WorldState = 0;
+ m_State = 0;
+ m_NameId = 0;
+ }
+
+ // the team that controls this point
+ uint8 m_Team;
+
+ // WG object
+ BattlefieldWG *m_WG;
+
+ // Linked gameobject
+ GameObject *m_Build;
+
+ // eWGGameObjectBuildingType
+ uint32 m_Type;
+
+ // WorldState
+ uint32 m_WorldState;
+
+ // eWGGameObjectState
+ uint32 m_State;
+
+ // Name id for warning text
+ uint32 m_NameId;
+
+ // GameObject associations
+ GameObjectSet m_GameObjectList[2];
+
+ // Creature associations
+ GuidSet m_CreatureBottomList[2];
+ GuidSet m_CreatureTopList[2];
+ GuidSet m_TurretBottomList;
+ GuidSet m_TurretTopList;
+
+ void Rebuild()
+ {
+ switch (m_Type)
+ {
+ case BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER:
+ case BATTLEFIELD_WG_OBJECTTYPE_DOOR_LAST:
+ case BATTLEFIELD_WG_OBJECTTYPE_DOOR:
+ case BATTLEFIELD_WG_OBJECTTYPE_WALL:
+ m_Team = m_WG->GetDefenderTeam(); // Objects that are part of the keep should be the defender's
+ break;
+ case BATTLEFIELD_WG_OBJECTTYPE_TOWER:
+ m_Team = m_WG->GetAttackerTeam(); // The towers in the south should be the attacker's
+ break;
+ default:
+ m_Team = TEAM_NEUTRAL;
+ break;
+ }
+
+ // Rebuild gameobject
+ m_Build->Rebuild();
+
+ // Update worldstate
+ m_State = BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_INTACT - (m_Team * 3);
+ m_WG->SendUpdateWorldState(m_WorldState, m_State);
+ UpdateCreatureAndGo();
+ m_Build->SetUInt32Value(GAMEOBJECT_FACTION, WintergraspFaction[m_Team]);
+ }
+
+ // Called when associated gameobject is damaged
+ void Damaged()
+ {
+ // Update worldstate
+ m_State = BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_DAMAGE - (m_Team * 3);
+ m_WG->SendUpdateWorldState(m_WorldState, m_State);
+
+ // Send warning message
+ if (m_NameId) // tower damage + name
+ m_WG->SendWarningToAllInZone(m_NameId);
+
+ for (GuidSet::const_iterator itr = m_CreatureTopList[m_WG->GetAttackerTeam()].begin(); itr != m_CreatureTopList[m_WG->GetAttackerTeam()].end(); ++itr)
+ if (Unit *unit = sObjectAccessor->FindUnit((*itr)))
+ if (Creature *creature = unit->ToCreature())
+ m_WG->HideNpc(creature);
+
+ for (GuidSet::const_iterator itr = m_TurretTopList.begin(); itr != m_TurretTopList.end(); ++itr)
+ if (Unit *unit = sObjectAccessor->FindUnit((*itr)))
+ if (Creature *creature = unit->ToCreature())
+ m_WG->HideNpc(creature);
+
+ if (m_Type == BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER)
+ m_WG->AddDamagedTower(m_WG->GetDefenderTeam());
+ else if (m_Type == BATTLEFIELD_WG_OBJECTTYPE_TOWER)
+ m_WG->AddDamagedTower(m_WG->GetAttackerTeam());
+ }
+
+ // Called when associated gameobject is destroyed
+ void Destroyed()
+ {
+ // Update worldstate
+ m_State = BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_DESTROY - (m_Team * 3);
+ m_WG->SendUpdateWorldState(m_WorldState, m_State);
+
+ // Warn players
+ if (m_NameId)
+ m_WG->SendWarningToAllInZone(m_NameId);
+
+ switch (m_Type)
+ {
+ // Inform the global wintergrasp script of the destruction of this object
+ case BATTLEFIELD_WG_OBJECTTYPE_TOWER:
+ case BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER:
+ m_WG->AddBrokenTower(TeamId(m_Team));
+ break;
+ case BATTLEFIELD_WG_OBJECTTYPE_DOOR_LAST:
+ m_WG->AllowToClickOnOrb(true);
+ if (m_WG->GetRelic())
+ m_WG->GetRelic()->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE);
+ else
+ sLog->outError("BATTLEFIELD: WG: Relic cant be clickable");
+ break;
+ }
+
+ m_WG->BrokenWallOrTower(TeamId(m_Team));
+ }
+
+ void Init(GameObject *go, uint32 type, uint32 worldstate, uint32 nameid)
+ {
+ // GameObject associated to object
+ m_Build = go;
+
+ // Type of building (WALL/TOWER/DOOR)
+ m_Type = type;
+
+ // WorldState for client (icon on map)
+ m_WorldState = worldstate;
+
+ // NameId for Warning text
+ m_NameId = nameid;
+
+ switch (m_Type)
+ {
+ case BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER:
+ case BATTLEFIELD_WG_OBJECTTYPE_DOOR_LAST:
+ case BATTLEFIELD_WG_OBJECTTYPE_DOOR:
+ case BATTLEFIELD_WG_OBJECTTYPE_WALL:
+ m_Team = m_WG->GetDefenderTeam(); // Objects that are part of the keep should be the defender's
+ break;
+ case BATTLEFIELD_WG_OBJECTTYPE_TOWER:
+ m_Team = m_WG->GetAttackerTeam(); // The towers in the south should be the attacker's
+ break;
+ default:
+ m_Team = TEAM_NEUTRAL;
+ break;
+ }
+
+ m_State = sWorld->getWorldState(m_WorldState);
+ if (m_Build)
+ {
+ switch (m_State)
+ {
+ case BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_INTACT:
+ case BATTLEFIELD_WG_OBJECTSTATE_HORDE_INTACT:
+ m_Build->Rebuild();
+ break;
+ case BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_DESTROY:
+ case BATTLEFIELD_WG_OBJECTSTATE_HORDE_DESTROY:
+ m_Build->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED);
+ m_Build->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DESTROYED);
+ m_Build->SetUInt32Value(GAMEOBJECT_DISPLAYID, m_Build->GetGOInfo()->building.destroyedDisplayId);
+ break;
+ case BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_DAMAGE:
+ case BATTLEFIELD_WG_OBJECTSTATE_HORDE_DAMAGE:
+ m_Build->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED);
+ m_Build->SetUInt32Value(GAMEOBJECT_DISPLAYID, m_Build->GetGOInfo()->building.damagedDisplayId);
+ break;
+ }
+ }
+
+ int32 towerid = -1;
+ switch (go->GetEntry())
+ {
+ case 190221:
+ towerid = 0;
+ break;
+ case 190373:
+ towerid = 1;
+ break;
+ case 190377:
+ towerid = 2;
+ break;
+ case 190378:
+ towerid = 3;
+ break;
+ case 190356:
+ towerid = 4;
+ break;
+ case 190357:
+ towerid = 5;
+ break;
+ case 190358:
+ towerid = 6;
+ break;
+ }
+
+ if (towerid > 3)
+ {
+ // Spawn associate gameobjects
+ for (uint8 i = 0; i < AttackTowers[towerid - 4].nbObject; i++)
+ {
+ BfWGObjectPosition gob = AttackTowers[towerid - 4].GameObject[i];
+ if (GameObject *go = m_WG->SpawnGameObject(gob.entryh, gob.x, gob.y, gob.z, gob.o))
+ m_GameObjectList[TEAM_HORDE].insert(go);
+ if (GameObject *go = m_WG->SpawnGameObject(gob.entrya, gob.x, gob.y, gob.z, gob.o))
+ m_GameObjectList[TEAM_ALLIANCE].insert(go);
+ }
+
+ // Spawn associate npc bottom
+ for (uint8 i = 0; i < AttackTowers[towerid - 4].nbCreatureBottom; i++)
+ {
+ BfWGObjectPosition crea = AttackTowers[towerid - 4].CreatureBottom[i];
+ if (Creature *creature = m_WG->SpawnCreature(crea.entryh, crea.x, crea.y, crea.z, crea.o, TEAM_HORDE))
+ m_CreatureBottomList[TEAM_HORDE].insert(creature->GetGUID());
+ if (Creature *creature = m_WG->SpawnCreature(crea.entrya, crea.x, crea.y, crea.z, crea.o, TEAM_ALLIANCE))
+ m_CreatureBottomList[TEAM_ALLIANCE].insert(creature->GetGUID());
+ }
+
+ // Spawn associate npc top
+ for (uint8 i = 0; i < AttackTowers[towerid - 4].nbCreatureTop; i++)
+ {
+ BfWGObjectPosition crea = AttackTowers[towerid - 4].CreatureTop[i];
+ if (Creature *creature = m_WG->SpawnCreature(crea.entryh, crea.x, crea.y, crea.z, crea.o, TEAM_HORDE))
+ m_CreatureTopList[TEAM_HORDE].insert(creature->GetGUID());
+ if (Creature *creature = m_WG->SpawnCreature(crea.entrya, crea.x, crea.y, crea.z, crea.o, TEAM_ALLIANCE))
+ m_CreatureTopList[TEAM_ALLIANCE].insert(creature->GetGUID());
+ }
+ }
+
+ if (towerid >= 0)
+ {
+ // Spawn Turret bottom
+ for (uint8 i = 0; i < TowerTurret[towerid].nbTurretBottom; i++)
+ {
+ BfWGTurretPos turretpos = TowerTurret[towerid].TurretBottom[i];
+ if (Creature *turret = m_WG->SpawnCreature(28366, turretpos.x, turretpos.y, turretpos.z, turretpos.o, TeamId(0)))
+ {
+ m_TurretBottomList.insert(turret->GetGUID());
+ switch (go->GetEntry())
+ {
+ case 190221:
+ case 190373:
+ case 190377:
+ case 190378:
+ {
+ turret->setFaction(WintergraspFaction[m_WG->GetDefenderTeam()]);
+ break;
+ }
+ case 190356:
+ case 190357:
+ case 190358:
+ {
+ turret->setFaction(WintergraspFaction[m_WG->GetAttackerTeam()]);
+ break;
+ }
+ }
+ m_WG->HideNpc(turret);
+ }
+ }
+
+ // Spawn Turret top
+ for (uint8 i = 0; i < TowerTurret[towerid].nbTurretTop; i++)
+ {
+ BfWGTurretPos turretpos = TowerTurret[towerid].TurretTop[i];
+ if (Creature *turret = m_WG->SpawnCreature(28366, turretpos.x, turretpos.y, turretpos.z, turretpos.o, TeamId(0)))
+ {
+ m_TurretTopList.insert(turret->GetGUID());
+ switch (go->GetEntry())
+ {
+ case 190221:
+ case 190373:
+ case 190377:
+ case 190378:
+ {
+ turret->setFaction(WintergraspFaction[m_WG->GetDefenderTeam()]);
+ break;
+ }
+ case 190356:
+ case 190357:
+ case 190358:
+ {
+ turret->setFaction(WintergraspFaction[m_WG->GetAttackerTeam()]);
+ break;
+ }
+ }
+ m_WG->HideNpc(turret);
+ }
+ }
+ UpdateCreatureAndGo();
+ }
+ }
+
+ void UpdateCreatureAndGo()
+ {
+ for (GuidSet::const_iterator itr = m_CreatureTopList[m_WG->GetDefenderTeam()].begin(); itr != m_CreatureTopList[m_WG->GetDefenderTeam()].end(); ++itr)
+ if (Unit *unit = sObjectAccessor->FindUnit((*itr)))
+ if (Creature *creature = unit->ToCreature())
+ m_WG->HideNpc(creature);
+
+ for (GuidSet::const_iterator itr = m_CreatureTopList[m_WG->GetAttackerTeam()].begin(); itr != m_CreatureTopList[m_WG->GetAttackerTeam()].end(); ++itr)
+ if (Unit *unit = sObjectAccessor->FindUnit((*itr)))
+ if (Creature *creature = unit->ToCreature())
+ m_WG->ShowNpc(creature, true);
+
+ for (GuidSet::const_iterator itr = m_CreatureBottomList[m_WG->GetDefenderTeam()].begin(); itr != m_CreatureBottomList[m_WG->GetDefenderTeam()].end(); ++itr)
+ if (Unit *unit = sObjectAccessor->FindUnit((*itr)))
+ if (Creature *creature = unit->ToCreature())
+ m_WG->HideNpc(creature);
+
+ for (GuidSet::const_iterator itr = m_CreatureBottomList[m_WG->GetAttackerTeam()].begin(); itr != m_CreatureBottomList[m_WG->GetAttackerTeam()].end(); ++itr)
+ if (Unit *unit = sObjectAccessor->FindUnit((*itr)))
+ if (Creature *creature = unit->ToCreature())
+ m_WG->ShowNpc(creature, true);
+
+ for (GameObjectSet::const_iterator itr = m_GameObjectList[m_WG->GetDefenderTeam()].begin(); itr != m_GameObjectList[m_WG->GetDefenderTeam()].end(); ++itr)
+ (*itr)->SetRespawnTime(RESPAWN_ONE_DAY);
+
+ for (GameObjectSet::const_iterator itr = m_GameObjectList[m_WG->GetAttackerTeam()].begin(); itr != m_GameObjectList[m_WG->GetAttackerTeam()].end(); ++itr)
+ (*itr)->SetRespawnTime(RESPAWN_IMMEDIATELY);
+ }
+
+ void UpdateTurretAttack(bool disable)
+ {
+ for (GuidSet::const_iterator itr = m_TurretBottomList.begin(); itr != m_TurretBottomList.end(); ++itr)
+ {
+ if (Unit *unit = sObjectAccessor->FindUnit((*itr)))
+ {
+ if (Creature *creature = unit->ToCreature())
+ {
+ if (m_Build)
+ {
+ if (disable)
+ {
+ switch (m_Build->GetEntry())
+ {
+ case 190221:
+ case 190373:
+ case 190377:
+ case 190378:
+ {
+ creature->setFaction(WintergraspFaction[m_WG->GetDefenderTeam()]);
+ break;
+ }
+ case 190356:
+ case 190357:
+ case 190358:
+ {
+ creature->setFaction(WintergraspFaction[m_WG->GetAttackerTeam()]);
+ break;
+ }
+ }
+ m_WG->HideNpc(creature);
+ }
+ else
+ {
+ switch (m_Build->GetEntry())
+ {
+ case 190221:
+ case 190373:
+ case 190377:
+ case 190378:
+ {
+ creature->setFaction(WintergraspFaction[m_WG->GetDefenderTeam()]);
+ break;
+ }
+ case 190356:
+ case 190357:
+ case 190358:
+ {
+ creature->setFaction(WintergraspFaction[m_WG->GetAttackerTeam()]);
+ break;
+ }
+ }
+ m_WG->ShowNpc(creature, true);
+ }
+ }
+ }
+ }
+ }
+
+ for (GuidSet::const_iterator itr = m_TurretTopList.begin(); itr != m_TurretTopList.end(); ++itr)
+ {
+ if (Unit *unit = sObjectAccessor->FindUnit((*itr)))
+ {
+ if (Creature *creature = unit->ToCreature())
+ {
+ if (m_Build)
+ {
+ if (disable)
+ {
+ switch (m_Build->GetEntry())
+ {
+ case 190221:
+ case 190373:
+ case 190377:
+ case 190378:
+ {
+ creature->setFaction(WintergraspFaction[m_WG->GetDefenderTeam()]);
+ break;
+ }
+ case 190356:
+ case 190357:
+ case 190358:
+ {
+ creature->setFaction(WintergraspFaction[m_WG->GetAttackerTeam()]);
+ break;
+ }
+ }
+ m_WG->HideNpc(creature);
+ }
+ else
+ {
+ switch (m_Build->GetEntry())
+ {
+ case 190221:
+ case 190373:
+ case 190377:
+ case 190378:
+ {
+ creature->setFaction(WintergraspFaction[m_WG->GetDefenderTeam()]);
+ break;
+ }
+ case 190356:
+ case 190357:
+ case 190358:
+ {
+ creature->setFaction(WintergraspFaction[m_WG->GetAttackerTeam()]);
+ break;
+ }
+ }
+ m_WG->ShowNpc(creature, true);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ void Save()
+ {
+ sWorld->setWorldState(m_WorldState, m_State);
+ }
+};
+
+// Structure for the 6 workshop
+struct BfWGWorkShopData
+{
+ BattlefieldWG *m_WG; // Object du joug
+ GameObject *m_Build;
+ uint32 m_Type;
+ uint32 m_State; // For worldstate
+ uint32 m_WorldState;
+ uint32 m_TeamControl; // Team witch control the workshop
+ GuidSet m_CreatureOnPoint[2]; // Contain all Creature associate to this point
+ GameObjectSet m_GameObjectOnPoint[2]; // Contain all Gameobject associate to this point
+ uint32 m_NameId; // Id of trinity_string witch contain name of this node, using for alert message
+
+ BfWGWorkShopData(BattlefieldWG * WG)
+ {
+ m_WG = WG;
+ m_Build = NULL;
+ m_Type = 0;
+ m_State = 0;
+ m_WorldState = 0;
+ m_TeamControl = 0;
+ m_NameId = 0;
+ }
+
+ // Spawning associate creature and store them
+ void AddCreature(BfWGObjectPosition obj)
+ {
+ if (Creature *creature = m_WG->SpawnCreature(obj.entryh, obj.x, obj.y, obj.z, obj.o, TEAM_HORDE))
+ m_CreatureOnPoint[TEAM_HORDE].insert(creature->GetGUID());
+
+ if (Creature *creature = m_WG->SpawnCreature(obj.entrya, obj.x, obj.y, obj.z, obj.o, TEAM_ALLIANCE))
+ m_CreatureOnPoint[TEAM_ALLIANCE].insert(creature->GetGUID());
+
+ }
+
+ // Spawning Associate gameobject and store them
+ void AddGameObject(BfWGObjectPosition obj)
+ {
+ if (GameObject *gameobject = m_WG->SpawnGameObject(obj.entryh, obj.x, obj.y, obj.z, obj.o))
+ m_GameObjectOnPoint[TEAM_HORDE].insert(gameobject);
+ if (GameObject *gameobject = m_WG->SpawnGameObject(obj.entrya, obj.x, obj.y, obj.z, obj.o))
+ m_GameObjectOnPoint[TEAM_ALLIANCE].insert(gameobject);
+ }
+
+ // Init method, setup variable
+ void Init(uint32 worldstate, uint32 type, uint32 nameid)
+ {
+ m_WorldState = worldstate;
+ m_Type = type;
+ m_NameId = nameid;
+ }
+
+ // Called on change faction in CapturePoint class
+ void ChangeControl(uint8 team, bool init /* for first call in setup */ )
+ {
+ switch (team)
+ {
+ case BATTLEFIELD_WG_TEAM_NEUTRAL:
+ {
+ // Send warning message to all player for inform a faction attack a workshop
+ // alliance / horde attacking workshop
+ m_WG->SendWarningToAllInZone(m_TeamControl ? m_NameId : m_NameId + 1);
+ break;
+ }
+ case BATTLEFIELD_WG_TEAM_ALLIANCE:
+ {
+ // Show Alliance creature
+ for (GuidSet::const_iterator itr = m_CreatureOnPoint[TEAM_ALLIANCE].begin(); itr != m_CreatureOnPoint[TEAM_ALLIANCE].end(); ++itr)
+ if (Unit *unit = sObjectAccessor->FindUnit((*itr)))
+ if (Creature *creature = unit->ToCreature())
+ m_WG->ShowNpc(creature, creature->GetEntry() != 30499);
+
+ // Hide Horde creature
+ for (GuidSet::const_iterator itr = m_CreatureOnPoint[TEAM_HORDE].begin(); itr != m_CreatureOnPoint[TEAM_HORDE].end(); ++itr)
+ if (Unit *unit = sObjectAccessor->FindUnit((*itr)))
+ if (Creature *creature = unit->ToCreature())
+ m_WG->HideNpc(creature);
+
+ // Show Alliance gameobject
+ for (GameObjectSet::const_iterator itr = m_GameObjectOnPoint[TEAM_ALLIANCE].begin(); itr != m_GameObjectOnPoint[TEAM_ALLIANCE].end(); ++itr)
+ (*itr)->SetRespawnTime(RESPAWN_IMMEDIATELY);
+
+ // Hide Horde gameobject
+ for (GameObjectSet::const_iterator itr = m_GameObjectOnPoint[TEAM_HORDE].begin(); itr != m_GameObjectOnPoint[TEAM_HORDE].end(); ++itr)
+ (*itr)->SetRespawnTime(RESPAWN_ONE_DAY);
+
+
+ // Updating worldstate
+ m_State = BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_INTACT;
+ m_WG->SendUpdateWorldState(m_WorldState, m_State);
+
+ // Warning message
+ if (!init) // workshop taken - alliance
+ m_WG->SendWarningToAllInZone(m_NameId);
+
+ // Found associate graveyard and update it
+ if (m_Type < BATTLEFIELD_WG_WORKSHOP_KEEP_WEST)
+ if (m_WG && m_WG->GetGraveYardById(m_Type))
+ m_WG->GetGraveYardById(m_Type)->ChangeControl(TEAM_ALLIANCE);
+
+ m_TeamControl = team;
+ break;
+ }
+ case BATTLEFIELD_WG_TEAM_HORDE:
+ {
+ // Show Horde creature
+ for (GuidSet::const_iterator itr = m_CreatureOnPoint[TEAM_HORDE].begin(); itr != m_CreatureOnPoint[TEAM_HORDE].end(); ++itr)
+ if (Unit *unit = sObjectAccessor->FindUnit((*itr)))
+ if (Creature *creature = unit->ToCreature())
+ m_WG->ShowNpc(creature, creature->GetEntry() != 30400);
+
+ // Hide Alliance creature
+ for (GuidSet::const_iterator itr = m_CreatureOnPoint[TEAM_ALLIANCE].begin(); itr != m_CreatureOnPoint[TEAM_ALLIANCE].end(); ++itr)
+ if (Unit *unit = sObjectAccessor->FindUnit((*itr)))
+ if (Creature *creature = unit->ToCreature())
+ m_WG->HideNpc(creature);
+
+ // Hide Alliance gameobject
+ for (GameObjectSet::const_iterator itr = m_GameObjectOnPoint[TEAM_ALLIANCE].begin(); itr != m_GameObjectOnPoint[TEAM_ALLIANCE].end(); ++itr)
+ (*itr)->SetRespawnTime(RESPAWN_ONE_DAY);
+
+ // Show Horde gameobject
+ for (GameObjectSet::const_iterator itr = m_GameObjectOnPoint[TEAM_HORDE].begin(); itr != m_GameObjectOnPoint[TEAM_HORDE].end(); ++itr)
+ (*itr)->SetRespawnTime(RESPAWN_IMMEDIATELY);
+
+ // Update worlstate
+ m_State = BATTLEFIELD_WG_OBJECTSTATE_HORDE_INTACT;
+ m_WG->SendUpdateWorldState(m_WorldState, m_State);
+
+ // Warning message
+ if (!init) // workshop taken - horde
+ m_WG->SendWarningToAllInZone(m_NameId + 1);
+
+ // Update graveyard control
+ if (m_Type < BATTLEFIELD_WG_WORKSHOP_KEEP_WEST)
+ if (m_WG && m_WG->GetGraveYardById(m_Type))
+ m_WG->GetGraveYardById(m_Type)->ChangeControl(TEAM_HORDE);
+
+ m_TeamControl = team;
+ break;
+ }
+ }
+ if (!init)
+ m_WG->UpdateCounterVehicle(false);
+ }
+
+ void UpdateGraveYardAndWorkshop()
+ {
+ if (m_Type < BATTLEFIELD_WG_WORKSHOP_KEEP_WEST)
+ m_WG->GetGraveYardById(m_Type)->ChangeControl(TeamId(m_TeamControl));
+ else
+ ChangeControl(m_WG->GetDefenderTeam(), true);
+ }
+
+ void Save()
+ {
+ sWorld->setWorldState(m_WorldState, m_State);
+ }
+};
+
+#endif
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp
index 3b96b842ff7..d4cb88983d6 100755
--- a/src/server/game/Battlegrounds/Battleground.cpp
+++ b/src/server/game/Battlegrounds/Battleground.cpp
@@ -1148,7 +1148,7 @@ void Battleground::AddOrSetPlayerToCorrectBgGroup(Player* player, uint32 team)
if (group->IsMember(playerGuid))
{
uint8 subgroup = group->GetMemberGroup(playerGuid);
- player->SetBattlegroundRaid(group, subgroup);
+ player->SetBattlegroundOrBattlefieldRaid(group, subgroup);
}
else
{
diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt
index 65ba16007d4..930cfbdf404 100644
--- a/src/server/game/CMakeLists.txt
+++ b/src/server/game/CMakeLists.txt
@@ -17,6 +17,7 @@ file(GLOB_RECURSE sources_Achievements Achievements/*.cpp Achievements/*.h)
file(GLOB_RECURSE sources_Addons Addons/*.cpp Addons/*.h)
file(GLOB_RECURSE sources_AI AI/*.cpp AI/*.h)
file(GLOB_RECURSE sources_AuctionHouse AuctionHouse/*.cpp AuctionHouse/*.h)
+file(GLOB_RECURSE sources_Battlefield Battlefield/*.cpp Battlefield/*.h)
file(GLOB_RECURSE sources_Battlegrounds Battlegrounds/*.cpp Battlegrounds/*.h)
file(GLOB_RECURSE sources_Calendar Calendar/*.cpp Calendar/*.h)
file(GLOB_RECURSE sources_Chat Chat/*.cpp Chat/*.h)
@@ -66,6 +67,7 @@ set(game_STAT_SRCS
${sources_Addons}
${sources_AI}
${sources_AuctionHouse}
+ ${sources_Battlefield}
${sources_Battlegrounds}
${sources_Calendar}
${sources_Chat}
@@ -132,6 +134,9 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/AI/ScriptedAI
${CMAKE_CURRENT_SOURCE_DIR}/AI/SmartScripts
${CMAKE_CURRENT_SOURCE_DIR}/AuctionHouse
+ ${CMAKE_CURRENT_SOURCE_DIR}/Battlefield
+
+ ${CMAKE_CURRENT_SOURCE_DIR}/Battlefield/Zones
${CMAKE_CURRENT_SOURCE_DIR}/Battlegrounds
${CMAKE_CURRENT_SOURCE_DIR}/Battlegrounds/Zones
${CMAKE_CURRENT_SOURCE_DIR}/Calendar
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index 85fa2c3e362..0726260f18d 100755
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -831,6 +831,13 @@ bool GameObject::IsDynTransport() const
return gInfo->type == GAMEOBJECT_TYPE_MO_TRANSPORT || (gInfo->type == GAMEOBJECT_TYPE_TRANSPORT && !gInfo->transport.pause);
}
+bool GameObject::IsDestructibleBuilding() const
+{
+ GameObjectTemplate const* gInfo = GetGOInfo();
+ if (!gInfo) return false;
+ return gInfo->type == GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING;
+}
+
Unit* GameObject::GetOwner() const
{
return ObjectAccessor::GetUnit(*this, GetOwnerGUID());
@@ -847,7 +854,7 @@ bool GameObject::isAlwaysVisibleFor(WorldObject const* seer) const
if (WorldObject::isAlwaysVisibleFor(seer))
return true;
- if (IsTransport())
+ if (IsTransport() || IsDestructibleBuilding())
return true;
return false;
diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h
index 95be55e595e..b817ef82f7b 100755
--- a/src/server/game/Entities/GameObject/GameObject.h
+++ b/src/server/game/Entities/GameObject/GameObject.h
@@ -631,6 +631,7 @@ class GameObject : public WorldObject, public GridObject<GameObject>
bool IsTransport() const;
bool IsDynTransport() const;
+ bool IsDestructibleBuilding() const;
uint32 GetDBTableGUIDLow() const { return m_DBTableGuid; }
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index 8694ac65eeb..a1af85dc04c 100755
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -41,7 +41,7 @@
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
#include "SpellAuraEffects.h"
-
+#include "BattlefieldMgr.h"
#include "TemporarySummon.h"
#include "Totem.h"
#include "OutdoorPvPMgr.h"
@@ -2210,7 +2210,12 @@ void WorldObject::SetZoneScript()
if (map->IsDungeon())
m_zoneScript = (ZoneScript*)((InstanceMap*)map)->GetInstanceScript();
else if (!map->IsBattlegroundOrArena())
- m_zoneScript = sOutdoorPvPMgr->GetZoneScript(GetZoneId());
+ {
+ if (Battlefield* bf = sBattlefieldMgr.GetBattlefieldToZoneId(GetZoneId()))
+ m_zoneScript = bf;
+ else
+ m_zoneScript = sOutdoorPvPMgr->GetZoneScript(GetZoneId());
+ }
}
}
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index e45d75199b2..59f0b9fb1b0 100755
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -70,6 +70,7 @@
#include "DisableMgr.h"
#include "WeatherMgr.h"
#include "LFGMgr.h"
+#include "BattlefieldMgr.h"
#include "CharacterDatabaseCleaner.h"
#include "InstanceScript.h"
#include <cmath>
@@ -2405,6 +2406,7 @@ void Player::RemoveFromWorld()
StopCastingBindSight();
UnsummonPetTemporaryIfAny();
sOutdoorPvPMgr->HandlePlayerLeaveZone(this, m_zoneUpdateId);
+ sBattlefieldMgr.HandlePlayerLeaveZone(this, m_zoneUpdateId);
}
///- Do not add/remove the player from the object storage
@@ -5483,7 +5485,12 @@ void Player::RepopAtGraveyard()
if (Battleground *bg = GetBattleground())
ClosestGrave = bg->GetClosestGraveYard(this);
else
- ClosestGrave = sObjectMgr->GetClosestGraveYard(GetPositionX(), GetPositionY(), GetPositionZ(), GetMapId(), GetTeam());
+ {
+ if (sBattlefieldMgr.GetBattlefieldToZoneId(GetZoneId()))
+ ClosestGrave = sBattlefieldMgr.GetBattlefieldToZoneId(GetZoneId())->GetClosestGraveYard(this);
+ else
+ ClosestGrave = sObjectMgr->GetClosestGraveYard(GetPositionX(), GetPositionY(), GetPositionZ(), GetMapId(), GetTeam());
+ }
// stop countdown until repop
m_deathTimer = 0;
@@ -7379,6 +7386,8 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
{
sOutdoorPvPMgr->HandlePlayerLeaveZone(this, m_zoneUpdateId);
sOutdoorPvPMgr->HandlePlayerEnterZone(this, newZone);
+ sBattlefieldMgr.HandlePlayerLeaveZone(this, m_zoneUpdateId);
+ sBattlefieldMgr.HandlePlayerEnterZone(this, newZone);
SendInitWorldStates(newZone, newArea); // only if really enters to new zone, not just area change, works strange...
}
@@ -7513,7 +7522,7 @@ void Player::CheckDuelDistance(time_t currTime)
bool Player::IsOutdoorPvPActive()
{
- return isAlive() && !HasInvisibilityAura() && !HasStealthAura() && (IsPvP() || sWorld->IsPvPRealm()) && !HasUnitMovementFlag(MOVEMENTFLAG_FLYING) && !isInFlight();
+ return isAlive() && !HasInvisibilityAura() && !HasStealthAura() && IsPvP() && !HasUnitMovementFlag(MOVEMENTFLAG_FLYING) && !isInFlight();
}
void Player::DuelComplete(DuelCompleteType type)
@@ -22547,7 +22556,7 @@ bool Player::isUsingLfg()
return sLFGMgr->GetState(guid) != LFG_STATE_NONE;
}
-void Player::SetBattlegroundRaid(Group* group, int8 subgroup)
+void Player::SetBattlegroundOrBattlefieldRaid(Group *group, int8 subgroup)
{
//we must move references from m_group to m_originalGroup
SetOriginalGroup(GetGroup(), GetSubGroup());
@@ -22557,7 +22566,7 @@ void Player::SetBattlegroundRaid(Group* group, int8 subgroup)
m_group.setSubGroup((uint8)subgroup);
}
-void Player::RemoveFromBattlegroundRaid()
+void Player::RemoveFromBattlegroundOrBattlefieldRaid()
{
//remove existing reference
m_group.unlink();
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index e84f4ea306b..5b03e8cca99 100755
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -2378,8 +2378,8 @@ class Player : public Unit, public GridObject<Player>
Player* GetNextRandomRaidMember(float radius);
PartyResult CanUninviteFromGroup() const;
// Battleground Group System
- void SetBattlegroundRaid(Group* group, int8 subgroup = -1);
- void RemoveFromBattlegroundRaid();
+ void SetBattlegroundOrBattlefieldRaid(Group *group, int8 subgroup = -1);
+ void RemoveFromBattlegroundOrBattlefieldRaid();
Group * GetOriginalGroup() { return m_originalGroup.getTarget(); }
GroupReference& GetOriginalGroupRef() { return m_originalGroup; }
uint8 GetOriginalSubGroup() const { return m_originalGroup.getSubGroup(); }
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index ff598119c37..5aafa49090f 100755
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -54,7 +54,7 @@
#include "Vehicle.h"
#include "Transport.h"
#include "InstanceScript.h"
-
+#include "BattlefieldMgr.h"
#include <math.h>
float baseMoveSpeed[MAX_MOVE_TYPE] =
@@ -15487,9 +15487,14 @@ void Unit::Kill(Unit* victim, bool durabilityLoss)
// outdoor pvp things, do these after setting the death state, else the player activity notify won't work... doh...
// handle player kill only if not suicide (spirit of redemption for example)
if (player && this != victim)
+ {
if (OutdoorPvP* pvp = player->GetOutdoorPvP())
pvp->HandleKill(player, victim);
+ if (Battlefield* bf = sBattlefieldMgr.GetBattlefieldToZoneId(player->GetZoneId()))
+ bf->HandleKill(player, victim);
+ }
+
//if (pVictim->GetTypeId() == TYPEID_PLAYER)
// if (OutdoorPvP* pvp = pVictim->ToPlayer()->GetOutdoorPvP())
// pvp->HandlePlayerActivityChangedpVictim->ToPlayer();
diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp
index ce193f798f0..f9a9a3bfc55 100755
--- a/src/server/game/Entities/Vehicle/Vehicle.cpp
+++ b/src/server/game/Entities/Vehicle/Vehicle.cpp
@@ -178,8 +178,13 @@ void Vehicle::ApplyAllImmunities()
// Different immunities for vehicles goes below
switch (GetVehicleInfo()->m_ID)
{
- case 160:
+ case 160: //Isle of conquest turret
+ case 244: //Wintergrasp turret
_me->SetControlled(true, UNIT_STAT_ROOT);
+ //me->AddUnitMovementFlag(MOVEMENTFLAG_ROOT);
+ //me->SetSpeed(MOVE_TURN_RATE, 0.7f);
+ //me->SetSpeed(MOVE_PITCH_RATE, 0.7f);
+ //me->m_movementInfo.flags2=59;
_me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_DECREASE_SPEED, true);
break;
default:
@@ -464,6 +469,20 @@ void Vehicle::Dismiss()
_me->AddObjectToRemoveList();
}
+void Vehicle::TeleportVehicle(float x, float y, float z, float ang)
+{
+ vehiclePlayers.clear();
+ for(int8 i = 0; i < 8; i++)
+ if (Unit* player = GetPassenger(i))
+ vehiclePlayers.insert(player->GetGUID());
+
+ RemoveAllPassengers(); // this can unlink Guns from Siege Engines
+ _me->NearTeleportTo(x, y, z, ang);
+ for (GuidSet::const_iterator itr = vehiclePlayers.begin(); itr != vehiclePlayers.end(); ++itr)
+ if(Unit* plr = sObjectAccessor->FindUnit(*itr))
+ plr->NearTeleportTo(x, y, z, ang);
+}
+
void Vehicle::InitMovementInfoForBase()
{
uint32 vehicleFlags = GetVehicleInfo()->m_flags;
diff --git a/src/server/game/Entities/Vehicle/Vehicle.h b/src/server/game/Entities/Vehicle/Vehicle.h
index 79d5bbb0801..a95bd14d965 100755
--- a/src/server/game/Entities/Vehicle/Vehicle.h
+++ b/src/server/game/Entities/Vehicle/Vehicle.h
@@ -98,6 +98,7 @@ struct VehicleAccessory
typedef std::vector<VehicleAccessory> VehicleAccessoryList;
typedef std::map<uint32, VehicleAccessoryList> VehicleAccessoryMap;
typedef std::map<int8, VehicleSeat> SeatMap;
+typedef std::set<uint64> GuidSet;
class Vehicle
{
@@ -129,6 +130,7 @@ class Vehicle
void RelocatePassengers(float x, float y, float z, float ang);
void RemoveAllPassengers();
void Dismiss();
+ void TeleportVehicle(float x, float y, float z, float ang);
bool IsVehicleInUse() { return Seats.begin() != Seats.end(); }
SeatMap Seats;
@@ -144,6 +146,7 @@ class Vehicle
Unit* _me;
VehicleEntry const* _vehicleInfo;
+ GuidSet vehiclePlayers;
uint32 _usableSeatNum; // Number of seats that match VehicleSeatEntry::UsableByPlayer, used for proper display flags
uint32 _creatureEntry; // Can be different than me->GetBase()->GetEntry() in case of players
};
diff --git a/src/server/game/Globals/ObjectAccessor.h b/src/server/game/Globals/ObjectAccessor.h
index 78f98ed9fca..f3192810575 100755
--- a/src/server/game/Globals/ObjectAccessor.h
+++ b/src/server/game/Globals/ObjectAccessor.h
@@ -194,6 +194,7 @@ class ObjectAccessor
// ACCESS LIKE THAT IS NOT THREAD SAFE
static Pet * FindPet(uint64);
static Player* FindPlayer(uint64);
+ static Creature* FindCreature(uint64);
static Unit* FindUnit(uint64);
Player* FindPlayerByName(const char* name);
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index e309809ef22..be24cba0375 100755
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -836,6 +836,11 @@ class ObjectMgr
return &mCreatureQuestRelations;
}
+ QuestRelations* GetCreatureQuestInvolvedRelation()
+ {
+ return &mCreatureQuestInvolvedRelations;
+ }
+
QuestRelationBounds GetCreatureQuestRelationBounds(uint32 creature_entry)
{
return mCreatureQuestRelations.equal_range(creature_entry);
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index 3c3b71deddc..4fb8e43cc7a 100755
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -57,7 +57,7 @@ Loot* Roll::getLoot()
Group::Group() : m_leaderGuid(0), m_leaderName(""), m_groupType(GROUPTYPE_NORMAL),
m_dungeonDifficulty(DUNGEON_DIFFICULTY_NORMAL), m_raidDifficulty(RAID_DIFFICULTY_10MAN_NORMAL),
-m_bgGroup(NULL), m_lootMethod(FREE_FOR_ALL), m_lootThreshold(ITEM_QUALITY_UNCOMMON), m_looterGuid(0),
+m_bgGroup(NULL), m_bfGroup(NULL), m_lootMethod(FREE_FOR_ALL), m_lootThreshold(ITEM_QUALITY_UNCOMMON), m_looterGuid(0),
m_subGroupsCounts(NULL), m_guid(0), m_counter(0), m_maxEnchantingLevel(0), m_dbStoreId(0)
{
for (uint8 i = 0; i < TARGETICONCOUNT; ++i)
@@ -102,7 +102,7 @@ bool Group::Create(Player *leader)
m_leaderGuid = leaderGuid;
m_leaderName = leader->GetName();
- m_groupType = isBGGroup() ? GROUPTYPE_BGRAID : GROUPTYPE_NORMAL;
+ m_groupType = (isBGGroup() || isBFGroup()) ? GROUPTYPE_BGRAID : GROUPTYPE_NORMAL;
if (m_groupType & GROUPTYPE_RAID)
_initRaidSubGroupsCounter();
@@ -114,7 +114,7 @@ bool Group::Create(Player *leader)
m_dungeonDifficulty = DUNGEON_DIFFICULTY_NORMAL;
m_raidDifficulty = RAID_DIFFICULTY_10MAN_NORMAL;
- if (!isBGGroup())
+ if (!isBGGroup() || !isBFGroup())
{
m_dungeonDifficulty = leader->GetDungeonDifficulty();
m_raidDifficulty = leader->GetRaidDifficulty();
@@ -200,7 +200,7 @@ void Group::ConvertToLFG()
{
m_groupType = GroupType(m_groupType | GROUPTYPE_LFG | GROUPTYPE_UNK1);
m_lootMethod = NEED_BEFORE_GREED;
- if (!isBGGroup())
+ if (!isBGGroup() && !isBFGroup())
CharacterDatabase.PExecute("UPDATE groups SET groupType='%u' WHERE guid='%u'", uint8(m_groupType), m_dbStoreId);
SendUpdate();
}
@@ -211,7 +211,7 @@ void Group::ConvertToRaid()
_initRaidSubGroupsCounter();
- if (!isBGGroup())
+ if (!isBGGroup() && !isBFGroup())
CharacterDatabase.PExecute("UPDATE groups SET groupType='%u' WHERE guid='%u'", uint8(m_groupType), m_dbStoreId);
SendUpdate();
@@ -226,7 +226,7 @@ bool Group::AddInvite(Player* player)
if (!player || player->GetGroupInvite())
return false;
Group* group = player->GetGroup();
- if (group && group->isBGGroup())
+ if (group && (group->isBGGroup() || group->isBFGroup()))
group = player->GetOriginalGroup();
if (group)
return false;
@@ -323,8 +323,8 @@ bool Group::AddMember(Player* player)
if (player)
{
player->SetGroupInvite(NULL);
- if (player->GetGroup() && isBGGroup()) //if player is in group and he is being added to BG raid group, then call SetBattlegroundRaid()
- player->SetBattlegroundRaid(this, subGroup);
+ if (player->GetGroup() && (isBGGroup() || isBFGroup())) //if player is in group and he is being added to BG raid group, then call SetBattlegroundRaid()
+ player->SetBattlegroundOrBattlefieldRaid(this, subGroup);
else if (player->GetGroup()) //if player is in bg raid and we are adding him to normal group, then call SetOriginalGroup()
player->SetOriginalGroup(this, subGroup);
else //if player is not in group, then call set group
@@ -343,7 +343,7 @@ bool Group::AddMember(Player* player)
}
// insert into the table if we're not a battleground group
- if (!isBGGroup())
+ if (!isBGGroup() || !isBFGroup())
CharacterDatabase.PExecute("INSERT INTO group_member (guid, memberGuid, memberFlags, subgroup, roles) VALUES(%u, %u, %u, %u, %u)",
m_dbStoreId, GUID_LOPART(member.guid), member.flags, member.group, member.roles);
@@ -352,7 +352,7 @@ bool Group::AddMember(Player* player)
if (player)
{
- if (!IsLeader(player->GetGUID()) && !isBGGroup())
+ if (!IsLeader(player->GetGUID()) && !isBGGroup() && !isBFGroup())
{
// reset the new member's instances, unless he is currently in one of them
// including raid/heroic instances that they are not permanently bound to!
@@ -397,15 +397,15 @@ bool Group::RemoveMember(const uint64 &guid, const RemoveMethod &method /*= GROU
if (isLFGGroup() && method == GROUP_REMOVEMETHOD_KICK)
return m_memberSlots.size();
- // remove member and change leader (if need) only if strong more 2 members _before_ member remove (BG allow 1 member group)
- if (GetMembersCount() > (isBGGroup() ? 1u : 2u))
+ // remove member and change leader (if need) only if strong more 2 members _before_ member remove (BG/BF allow 1 member group)
+ if (GetMembersCount() > ((isBGGroup() || isBFGroup()) ? 1u : 2u))
{
Player* player = sObjectMgr->GetPlayer(guid);
if (player)
{
// Battleground group handling
- if (isBGGroup())
- player->RemoveFromBattlegroundRaid();
+ if (isBGGroup() || isBFGroup())
+ player->RemoveFromBattlegroundOrBattlefieldRaid();
else
// Regular group
{
@@ -513,7 +513,7 @@ void Group::ChangeLeader(const uint64 &guid)
sScriptMgr->OnGroupChangeLeader(this, m_leaderGuid, guid);
- if (!isBGGroup())
+ if (!isBGGroup() || !isBFGroup())
{
// Remove the groups permanent instance bindings
for (uint8 i = 0; i < MAX_DIFFICULTY; ++i)
@@ -563,8 +563,8 @@ void Group::Disband(bool hideDestroy /* = false */)
//we cannot call _removeMember because it would invalidate member iterator
//if we are removing player from battleground raid
- if (isBGGroup())
- player->RemoveFromBattlegroundRaid();
+ if (isBGGroup() || isBFGroup())
+ player->RemoveFromBattlegroundOrBattlefieldRaid();
else
{
//we can remove player who is in battleground from his original group
@@ -608,7 +608,7 @@ void Group::Disband(bool hideDestroy /* = false */)
RemoveAllInvites();
- if (!isBGGroup())
+ if (!isBGGroup() || !isBFGroup())
{
SQLTransaction trans = CharacterDatabase.BeginTransaction();
trans->PAppend("DELETE FROM groups WHERE guid = %u", m_dbStoreId);
@@ -1213,7 +1213,7 @@ void Group::SendUpdate()
Player* member = sObjectMgr->GetPlayer(citr2->guid);
uint8 onlineState = (member) ? MEMBER_STATUS_ONLINE : MEMBER_STATUS_OFFLINE;
- onlineState = onlineState | ((isBGGroup()) ? MEMBER_STATUS_PVP : 0);
+ onlineState = onlineState | ((isBGGroup() || isBFGroup()) ? MEMBER_STATUS_PVP : 0);
data << citr2->name;
data << uint64(citr2->guid); // guid
@@ -1305,7 +1305,7 @@ bool Group::_setMembersGroup(const uint64 &guid, const uint8 &group)
SubGroupCounterIncrease(group);
- if (!isBGGroup())
+ if (!isBGGroup() || !isBFGroup())
CharacterDatabase.PExecute("UPDATE group_member SET subgroup='%u' WHERE memberGuid='%u'", group, GUID_LOPART(guid));
return true;
@@ -1538,7 +1538,7 @@ void Roll::targetObjectBuildLink()
void Group::SetDungeonDifficulty(Difficulty difficulty)
{
m_dungeonDifficulty = difficulty;
- if (!isBGGroup())
+ if (!isBGGroup() || !isBFGroup())
CharacterDatabase.PExecute("UPDATE groups SET difficulty = %u WHERE guid ='%u'", m_dungeonDifficulty, m_dbStoreId);
for (GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())
@@ -1555,7 +1555,7 @@ void Group::SetDungeonDifficulty(Difficulty difficulty)
void Group::SetRaidDifficulty(Difficulty difficulty)
{
m_raidDifficulty = difficulty;
- if (!isBGGroup())
+ if (!isBGGroup() || !isBFGroup())
CharacterDatabase.PExecute("UPDATE groups SET raiddifficulty = %u WHERE guid ='%u'", m_raidDifficulty, m_dbStoreId);
for (GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())
@@ -1584,7 +1584,7 @@ bool Group::InCombatToInstance(uint32 instanceId)
void Group::ResetInstances(uint8 method, bool isRaid, Player* SendMsgTo)
{
- if (isBGGroup())
+ if (isBGGroup() || isBFGroup())
return;
// method can be INSTANCE_RESET_ALL, INSTANCE_RESET_CHANGE_DIFFICULTY, INSTANCE_RESET_GROUP_DISBAND
@@ -1692,7 +1692,7 @@ InstanceGroupBind* Group::GetBoundInstance(MapEntry const* mapEntry)
InstanceGroupBind* Group::BindToInstance(InstanceSave *save, bool permanent, bool load)
{
- if (!save || isBGGroup())
+ if (!save || isBGGroup() || isBFGroup())
return NULL;
InstanceGroupBind& bind = m_boundInstances[save->GetDifficulty()][save->GetMapId()];
@@ -1807,6 +1807,11 @@ bool Group::isBGGroup() const
return m_bgGroup != NULL;
}
+bool Group::isBFGroup() const
+{
+ return m_bfGroup != NULL;
+}
+
bool Group::IsCreated() const
{
return GetMembersCount() > 0;
@@ -1922,6 +1927,11 @@ void Group::SetBattlegroundGroup(Battleground *bg)
m_bgGroup = bg;
}
+void Group::SetBattlefieldGroup(Battlefield *bg)
+{
+ m_bfGroup = bg;
+}
+
void Group::SetGroupMemberFlag(uint64 guid, const bool &apply, GroupMemberFlags flag)
{
// Assistants, main assistants and main tanks are only available in raid groups
diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h
index 25e2fb9a96f..12e3c20af17 100755
--- a/src/server/game/Groups/Group.h
+++ b/src/server/game/Groups/Group.h
@@ -26,6 +26,7 @@
#include "QueryResult.h"
#include "SharedDefines.h"
#include "Player.h"
+#include "../../Battlefield/BattlefieldMgr.h" //FIXME
class Creature;
class GroupReference;
@@ -204,6 +205,7 @@ class Group
bool IsFull() const;
bool isLFGGroup() const;
bool isRaidGroup() const;
+ bool isBFGroup() const;
bool isBGGroup() const;
bool IsCreated() const;
const uint64& GetLeaderGUID() const;
@@ -239,6 +241,7 @@ class Group
void ConvertToRaid();
void SetBattlegroundGroup(Battleground *bg);
+ void SetBattlefieldGroup(Battlefield *bf);
GroupJoinBattlegroundResult CanJoinBattlegroundQueue(Battleground const* bgOrTemplate, BattlegroundQueueTypeId bgQueueTypeId, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot);
void ChangeMembersGroup(const uint64 &guid, const uint8 &group);
@@ -319,6 +322,7 @@ class Group
GroupType m_groupType;
Difficulty m_dungeonDifficulty;
Difficulty m_raidDifficulty;
+ Battlefield* m_bfGroup;
Battleground* m_bgGroup;
uint64 m_targetIcons[TARGETICONCOUNT];
LootMethod m_lootMethod;
diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h
index 9c5e6b54440..4368e2caa58 100755
--- a/src/server/game/Quests/QuestDef.h
+++ b/src/server/game/Quests/QuestDef.h
@@ -250,7 +250,7 @@ class Quest
bool IsWeekly() const { return QuestFlags & QUEST_FLAGS_WEEKLY; }
bool IsDailyOrWeekly() const { return QuestFlags & (QUEST_FLAGS_DAILY | QUEST_FLAGS_WEEKLY); }
bool IsAutoAccept() const { return QuestFlags & QUEST_FLAGS_AUTO_ACCEPT; }
- bool IsRaidQuest() const { return Type == QUEST_TYPE_RAID || Type == QUEST_TYPE_RAID_10 || Type == QUEST_TYPE_RAID_25; }
+ bool IsRaidQuest() const { return Type == QUEST_TYPE_RAID || Type == QUEST_TYPE_RAID_10 || Type == QUEST_TYPE_RAID_25 || Type == QUEST_TYPE_PVP; }
bool IsAllowedInRaid() const;
bool IsDFQuest() const { return QuestFlags & QUEST_TRINITY_FLAGS_DF_QUEST; }
uint32 CalculateHonorGain(uint8 level) const;
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp
index 0293c350649..2fa304d2d23 100755
--- a/src/server/game/Scripting/ScriptLoader.cpp
+++ b/src/server/game/Scripting/ScriptLoader.cpp
@@ -45,6 +45,7 @@ void AddSC_SmartSCripts();
//Commands
void AddSC_account_commandscript();
void AddSC_achievement_commandscript();
+void AddSC_bf_commandscript();
void AddSC_debug_commandscript();
void AddSC_event_commandscript();
void AddSC_gm_commandscript();
@@ -644,6 +645,7 @@ void AddCommandScripts()
{
AddSC_account_commandscript();
AddSC_achievement_commandscript();
+ AddSC_bf_commandscript();
AddSC_debug_commandscript();
AddSC_event_commandscript();
AddSC_gm_commandscript();
diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp
index a14a7175522..4e92b3091c1 100755
--- a/src/server/game/Scripting/ScriptMgr.cpp
+++ b/src/server/game/Scripting/ScriptMgr.cpp
@@ -753,6 +753,14 @@ CreatureAI* ScriptMgr::GetCreatureAI(Creature* creature)
return tmpscript->GetAI(creature);
}
+GameObjectAI* ScriptMgr::GetGameObjectAI(GameObject* gameobject)
+{
+ ASSERT(gameobject);
+
+ GET_SCRIPT_RET(GameObjectScript, gameobject->GetScriptId(), tmpscript, NULL);
+ return tmpscript->GetAI(gameobject);
+}
+
void ScriptMgr::OnCreatureUpdate(Creature* creature, uint32 diff)
{
ASSERT(creature);
diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h
index fb47282e9db..75dcf161815 100755
--- a/src/server/game/Scripting/ScriptMgr.h
+++ b/src/server/game/Scripting/ScriptMgr.h
@@ -37,6 +37,7 @@ class Channel;
class ChatCommand;
class Creature;
class CreatureAI;
+class GameObjectAI;
class DynamicObject;
class GameObject;
class Guild;
@@ -468,6 +469,9 @@ class GameObjectScript : public ScriptObject, public UpdatableScript<GameObject>
virtual void OnDestroyed(GameObject* /*go*/, Player* /*player*/, uint32 /*eventId*/) { }
// Called when the gameobject is damaged (destructible buildings only).
virtual void OnDamaged(GameObject* /*go*/, Player* /*player*/, uint32 /*eventId*/) { }
+
+ // Called when a CreatureAI object is needed for the creature.
+ virtual GameObjectAI* GetAI(GameObject* /*gameobject*/) const { return NULL; }
};
class AreaTriggerScript : public ScriptObject
@@ -867,6 +871,7 @@ class ScriptMgr
uint32 GetDialogStatus(Player* player, GameObject* go);
void OnGameObjectDestroyed(GameObject* go, Player* player, uint32 eventId);
void OnGameObjectDamaged(GameObject* go, Player* player, uint32 eventId);
+ GameObjectAI* GetGameObjectAI(GameObject* gameobject);
void OnGameObjectUpdate(GameObject* go, uint32 diff);
public: /* AreaTriggerScript */
diff --git a/src/server/game/Server/Protocol/Handlers/BattleGroundHandler.cpp b/src/server/game/Server/Protocol/Handlers/BattleGroundHandler.cpp
index 59c4911ae3a..4f867b47c25 100755
--- a/src/server/game/Server/Protocol/Handlers/BattleGroundHandler.cpp
+++ b/src/server/game/Server/Protocol/Handlers/BattleGroundHandler.cpp
@@ -586,46 +586,6 @@ void WorldSession::HandleBattlefieldStatusOpcode(WorldPacket & /*recv_data*/)
}
}
-void WorldSession::HandleAreaSpiritHealerQueryOpcode(WorldPacket & recv_data)
-{
- sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_AREA_SPIRIT_HEALER_QUERY");
-
- Battleground *bg = _player->GetBattleground();
-
- uint64 guid;
- recv_data >> guid;
-
- Creature* unit = GetPlayer()->GetMap()->GetCreature(guid);
- if (!unit)
- return;
-
- if (!unit->isSpiritService()) // it's not spirit service
- return;
-
- if (bg)
- sBattlegroundMgr->SendAreaSpiritHealerQueryOpcode(_player, bg, guid);
-}
-
-void WorldSession::HandleAreaSpiritHealerQueueOpcode(WorldPacket & recv_data)
-{
- sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_AREA_SPIRIT_HEALER_QUEUE");
-
- Battleground *bg = _player->GetBattleground();
-
- uint64 guid;
- recv_data >> guid;
-
- Creature* unit = GetPlayer()->GetMap()->GetCreature(guid);
- if (!unit)
- return;
-
- if (!unit->isSpiritService()) // it's not spirit service
- return;
-
- if (bg)
- bg->AddPlayerToResurrectQueue(guid, _player->GetGUID());
-}
-
void WorldSession::HandleBattlemasterJoinArena(WorldPacket & recv_data)
{
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_BATTLEMASTER_JOIN_ARENA");
diff --git a/src/server/game/Server/Protocol/Handlers/MiscHandler.cpp b/src/server/game/Server/Protocol/Handlers/MiscHandler.cpp
index 81f771fdada..a30bdbca0a8 100755
--- a/src/server/game/Server/Protocol/Handlers/MiscHandler.cpp
+++ b/src/server/game/Server/Protocol/Handlers/MiscHandler.cpp
@@ -36,7 +36,8 @@
#include "zlib.h"
#include "ObjectAccessor.h"
#include "Object.h"
-#include "Battleground.h"
+#include "BattlegroundMgr.h"
+#include "BattlefieldMgr.h"
#include "OutdoorPvP.h"
#include "Pet.h"
#include "SocialMgr.h"
@@ -1723,11 +1724,64 @@ void WorldSession::SendSetPhaseShift(uint32 PhaseShift)
SendPacket(&data);
}
+//Battlefield and Battleground
+void WorldSession::HandleAreaSpiritHealerQueryOpcode(WorldPacket & recv_data)
+{
+ sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_AREA_SPIRIT_HEALER_QUERY");
+
+ Battleground* bg = _player->GetBattleground();
+
+ uint64 guid;
+ recv_data >> guid;
+
+ Creature* unit = GetPlayer()->GetMap()->GetCreature(guid);
+ if (!unit)
+ return;
+
+ if (!unit->isSpiritService()) // it's not spirit service
+ return;
+
+ if (bg)
+ sBattlegroundMgr->SendAreaSpiritHealerQueryOpcode(_player, bg, guid);
+
+ if (Battlefield* bf = sBattlefieldMgr.GetBattlefieldToZoneId(_player->GetZoneId()))
+ bf->SendAreaSpiritHealerQueryOpcode(_player,guid);
+}
+
+void WorldSession::HandleAreaSpiritHealerQueueOpcode(WorldPacket & recv_data)
+{
+ sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_AREA_SPIRIT_HEALER_QUEUE");
+
+ Battleground* bg = _player->GetBattleground();
+
+ uint64 guid;
+ recv_data >> guid;
+
+ Creature* unit = GetPlayer()->GetMap()->GetCreature(guid);
+ if (!unit)
+ return;
+
+ if (!unit->isSpiritService()) // it's not spirit service
+ return;
+
+ if (bg)
+ bg->AddPlayerToResurrectQueue(guid, _player->GetGUID());
+
+ if (Battlefield* bf = sBattlefieldMgr.GetBattlefieldToZoneId(_player->GetZoneId()))
+ bf->AddPlayerToResurrectQueue(guid, _player->GetGUID());
+}
+
void WorldSession::HandleHearthAndResurrect(WorldPacket& /*recv_data*/)
{
if (_player->isInFlight())
return;
+ if(Battlefield* bf = sBattlefieldMgr.GetBattlefieldToZoneId(_player->GetZoneId()))
+ {
+ // bf->PlayerAskToLeave(_player); FIXME
+ return;
+ }
+
AreaTableEntry const *atEntry = GetAreaEntryByAreaID(_player->GetAreaId());
if (!atEntry || !(atEntry->flags & AREA_FLAG_WINTERGRASP_2))
return;
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index 235f349e1ea..9e7de1b5f7e 100755
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -1273,15 +1273,15 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
/*0x4DC*/ { "UMSG_UNKNOWN_1244", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
/*0x4DD*/ { "UMSG_UNKNOWN_1245", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
/*0x4DE*/ { "SMSG_BATTLEFIELD_MGR_ENTRY_INVITE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4DF*/ { "CMSG_BATTLEFIELD_MGR_ENTRY_INVITE_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
+ /*0x4DF*/ { "CMSG_BATTLEFIELD_MGR_ENTRY_INVITE_RESPONSE", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleBfEntryInviteResponse },
/*0x4E0*/ { "SMSG_BATTLEFIELD_MGR_ENTERED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x4E1*/ { "SMSG_BATTLEFIELD_MGR_QUEUE_INVITE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4E2*/ { "CMSG_BATTLEFIELD_MGR_QUEUE_INVITE_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
+ /*0x4E2*/ { "CMSG_BATTLEFIELD_MGR_QUEUE_INVITE_RESPONSE", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleBfQueueInviteResponse },
/*0x4E3*/ { "CMSG_BATTLEFIELD_MGR_QUEUE_REQUEST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
/*0x4E4*/ { "SMSG_BATTLEFIELD_MGR_QUEUE_REQUEST_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x4E5*/ { "SMSG_BATTLEFIELD_MGR_EJECT_PENDING", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x4E6*/ { "SMSG_BATTLEFIELD_MGR_EJECTED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
- /*0x4E7*/ { "CMSG_BATTLEFIELD_MGR_EXIT_REQUEST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
+ /*0x4E7*/ { "CMSG_BATTLEFIELD_MGR_EXIT_REQUEST", STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleBfExitRequest },
/*0x4E8*/ { "SMSG_BATTLEFIELD_MGR_STATE_CHANGE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x4E9*/ { "UMSG_UNKNOWN_1257", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
/*0x4EA*/ { "UMSG_UNKNOWN_1258", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index f45ee79847c..78fe186450e 100755
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -785,6 +785,16 @@ class WorldSession
void HandleHearthAndResurrect(WorldPacket& recv_data);
void HandleInstanceLockResponse(WorldPacket& recvPacket);
+ // Battlefield
+ void SendBfInvitePlayerToWar(uint32 BattleId,uint32 ZoneId,uint32 time);
+ void SendBfInvitePlayerToQueue(uint32 BattleId);
+ void SendBfQueueInviteResponce(uint32 BattleId,uint32 ZoneId);
+ void SendBfEntered(uint32 BattleId);
+ void SendBfLeaveMessage(uint32 BattleId);
+ void HandleBfQueueInviteResponse(WorldPacket &recv_data);
+ void HandleBfEntryInviteResponse(WorldPacket &recv_data);
+ void HandleBfExitRequest(WorldPacket &recv_data);
+
// Looking for Dungeon/Raid
void HandleLfgSetCommentOpcode(WorldPacket & recv_data);
void HandleLfgPlayerLockInfoRequestOpcode(WorldPacket& recv_data);
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 27a34bb8740..5742620c3f3 100755
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -35,6 +35,7 @@
#include "GridNotifiersImpl.h"
#include "CellImpl.h"
#include "ScriptMgr.h"
+#include "BattlefieldMgr.h"
class Aura;
//
@@ -4815,8 +4816,12 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
case 2584: // Waiting to Resurrect
// Waiting to resurrect spell cancel, we must remove player from resurrect queue
if (target->GetTypeId() == TYPEID_PLAYER)
- if (Battleground *bg = target->ToPlayer()->GetBattleground())
+ {
+ if (Battleground* bg = target->ToPlayer()->GetBattleground())
bg->RemovePlayerFromResurrectQueue(target->GetGUID());
+ if(Battlefield* bf = sBattlefieldMgr.GetBattlefieldToZoneId(target->GetZoneId()))
+ bf->RemovePlayerFromResurrectQueue(target->GetGUID());
+ }
break;
case 36730: // Flame Strike
{
@@ -4853,6 +4858,7 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
target->CastSpell((Unit*)NULL, GetAmount(), true, NULL, this);
break;
case 58600: // Restricted Flight Area
+ case 58730: // Restricted Flight Area
if (aurApp->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
target->CastSpell(target, 58601, true);
break;
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 797a8ecfcbe..feb0686f05f 100755
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -52,6 +52,7 @@
#include "DisableMgr.h"
#include "SpellScript.h"
#include "InstanceScript.h"
+#include "BattlefieldMgr.h"
extern pEffect SpellEffects[TOTAL_SPELL_EFFECTS];
@@ -5472,8 +5473,9 @@ SpellCastResult Spell::CheckCast(bool strict)
// allow always ghost flight spells
if (m_originalCaster && m_originalCaster->GetTypeId() == TYPEID_PLAYER && m_originalCaster->isAlive())
{
+ Battlefield* Bf = sBattlefieldMgr.GetBattlefieldToZoneId(m_originalCaster->GetZoneId());
if (AreaTableEntry const* pArea = GetAreaEntryByAreaID(m_originalCaster->GetAreaId()))
- if (pArea->flags & AREA_FLAG_NO_FLY_ZONE)
+ if ((pArea->flags & AREA_FLAG_NO_FLY_ZONE) || (Bf && !Bf->CanFlyIn()))
return m_IsTriggeredSpell ? SPELL_FAILED_DONT_REPORT : SPELL_FAILED_NOT_HERE;
}
break;
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index b9cd951d479..14c3975a018 100755
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -6976,6 +6976,7 @@ void Spell::EffectPlayerNotification(SpellEffIndex effIndex)
case 58730: // Restricted Flight Area
case 58600: // Restricted Flight Area
unitTarget->ToPlayer()->GetSession()->SendNotification(LANG_ZONE_NOFLYZONE);
+ unitTarget->PlayDirectSound(9417); // Fel Reaver sound
break;
}
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index f1879099a0a..b519dad28c2 100755
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -25,6 +25,7 @@
#include "Chat.h"
#include "Spell.h"
#include "BattlegroundMgr.h"
+#include "BattlefieldMgr.h"
#include "CreatureAI.h"
#include "MapManager.h"
#include "BattlegroundIC.h"
@@ -3289,6 +3290,26 @@ bool SpellArea::IsFitToRequirements(Player const* player, uint32 newZone, uint32
return false;
break;
}
+ case 58730: // No fly Zone - Wintergrasp
+ {
+ if (!player)
+ return false;
+
+ Battlefield* Bf = sBattlefieldMgr.GetBattlefieldToZoneId(player->GetZoneId());
+ if (!Bf || Bf->CanFlyIn() || (!player->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) && !player->HasAuraType(SPELL_AURA_FLY)))
+ return false;
+ break;
+ }
+ case 57940: // Essence of Wintergrasp - Northrend
+ {
+ if (!player)
+ return false;
+
+ Battlefield* Bf = sBattlefieldMgr.GetBattlefieldToZoneId(4197);
+ if (!Bf || player->GetTeamId() != Bf->GetDefenderTeam())
+ return false;
+ break;
+ }
case SPELL_OIL_REFINERY: // Oil Refinery - Isle of Conquest.
case SPELL_QUARRY: // Quarry - Isle of Conquest.
{
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 15cc7c9abaf..186d0cdc381 100755
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -50,6 +50,7 @@
#include "MapManager.h"
#include "CreatureAIRegistry.h"
#include "BattlegroundMgr.h"
+#include "BattlefieldMgr.h"
#include "OutdoorPvPMgr.h"
#include "TemporarySummon.h"
#include "WaypointMovementGenerator.h"
@@ -1184,6 +1185,15 @@ void World::LoadConfigSettings(bool reload)
// MySQL ping time interval
m_int_configs[CONFIG_DB_PING_INTERVAL] = sConfig->GetIntDefault("MaxPingTime", 30);
+ // Wintergrasp
+ m_bool_configs[CONFIG_WINTERGRASP_ENABLE] = sConfig->GetBoolDefault("Wintergrasp.Enable", false);
+ m_int_configs[CONFIG_WINTERGRASP_PLR_MAX] = sConfig->GetIntDefault("Wintergrasp.PlayerMax", 100);
+ m_int_configs[CONFIG_WINTERGRASP_PLR_MIN] = sConfig->GetIntDefault("Wintergrasp.PlayerMin", 0);
+ m_int_configs[CONFIG_WINTERGRASP_PLR_MIN_LVL] = sConfig->GetIntDefault("Wintergrasp.PlayerMinLvl", 77);
+ m_int_configs[CONFIG_WINTERGRASP_BATTLETIME] = sConfig->GetIntDefault("Wintergrasp.BattleTimer", 30);
+ m_int_configs[CONFIG_WINTERGRASP_NOBATTLETIME] = sConfig->GetIntDefault("Wintergrasp.NoBattleTimer", 150);
+ m_int_configs[CONFIG_WINTERGRASP_RESTART_AFTER_CRASH] = sConfig->GetIntDefault("Wintergrasp.CrashRestartTimer", 10);
+
sScriptMgr->OnConfigLoad(reload);
}
@@ -1698,6 +1708,10 @@ void World::SetInitialWorldSettings()
sLog->outString("Starting Outdoor PvP System");
sOutdoorPvPMgr->InitOutdoorPvP();
+ ///- Initialize Battlefield
+ sLog->outString("Starting Battlefield System");
+ sBattlefieldMgr.InitBattlefield();
+
sLog->outString("Loading Transports...");
sMapMgr->LoadTransports();
@@ -1948,6 +1962,9 @@ void World::Update(uint32 diff)
sOutdoorPvPMgr->Update(diff);
RecordTimeDiff("UpdateOutdoorPvPMgr");
+ sBattlefieldMgr.Update(diff);
+ RecordTimeDiff("BattlefieldMgr");
+
///- Delete all characters which have been deleted X days before
if (m_timers[WUPDATE_DELETECHARS].Passed())
{
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index 1f3cd3ccd99..9a2f7df3c9e 100755
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -158,6 +158,7 @@ enum WorldBoolConfigs
CONFIG_ALLOW_TICKETS,
CONFIG_DBC_ENFORCE_ITEM_ATTRIBUTES,
CONFIG_PRESERVE_CUSTOM_CHANNELS,
+ CONFIG_WINTERGRASP_ENABLE,
BOOL_CONFIG_VALUE_COUNT
};
@@ -306,6 +307,12 @@ enum WorldIntConfigs
CONFIG_PRESERVE_CUSTOM_CHANNEL_DURATION,
CONFIG_PERSISTENT_CHARACTER_CLEAN_FLAGS,
CONFIG_MAX_INSTANCES_PER_HOUR,
+ CONFIG_WINTERGRASP_PLR_MAX,
+ CONFIG_WINTERGRASP_PLR_MIN,
+ CONFIG_WINTERGRASP_PLR_MIN_LVL,
+ CONFIG_WINTERGRASP_BATTLETIME,
+ CONFIG_WINTERGRASP_NOBATTLETIME,
+ CONFIG_WINTERGRASP_RESTART_AFTER_CRASH,
INT_CONFIG_VALUE_COUNT
};
diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt
index de660b8f106..9e384502ee9 100644
--- a/src/server/scripts/CMakeLists.txt
+++ b/src/server/scripts/CMakeLists.txt
@@ -82,6 +82,9 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/server/game/AI/ScriptedAI
${CMAKE_SOURCE_DIR}/src/server/game/AI/SmartScripts
${CMAKE_SOURCE_DIR}/src/server/game/AuctionHouse
+ ${CMAKE_SOURCE_DIR}/src/server/game/Battlefield
+
+ ${CMAKE_SOURCE_DIR}/src/server/game/Battlefield/Zones
${CMAKE_SOURCE_DIR}/src/server/game/Battlegrounds
${CMAKE_SOURCE_DIR}/src/server/game/Battlegrounds/Zones
${CMAKE_SOURCE_DIR}/src/server/game/Calendar
diff --git a/src/server/scripts/Commands/CMakeLists.txt b/src/server/scripts/Commands/CMakeLists.txt
index 809e78204f4..bf86ada75f9 100644
--- a/src/server/scripts/Commands/CMakeLists.txt
+++ b/src/server/scripts/Commands/CMakeLists.txt
@@ -12,6 +12,7 @@ set(scripts_STAT_SRCS
${scripts_STAT_SRCS}
Commands/cs_account.cpp
Commands/cs_achievement.cpp
+ Commands/cs_bf.cpp
Commands/cs_gm.cpp
Commands/cs_npc.cpp
Commands/cs_go.cpp
diff --git a/src/server/scripts/Commands/cs_bf.cpp b/src/server/scripts/Commands/cs_bf.cpp
new file mode 100644
index 00000000000..76e6665f0b4
--- /dev/null
+++ b/src/server/scripts/Commands/cs_bf.cpp
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2008-2011 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+/* ScriptData
+Name: bf_commandscript
+%Complete: 100
+Comment: All bf related commands
+Category: commandscripts
+EndScriptData */
+
+#include "ScriptMgr.h"
+#include "Chat.h"
+#include "BattlefieldMgr.h"
+
+class bf_commandscript : public CommandScript
+{
+public:
+ bf_commandscript() : CommandScript("bf_commandscript") { }
+
+ ChatCommand* GetCommands() const
+ {
+ static ChatCommand battlefieldcommandTable[] =
+ {
+ { "start", SEC_ADMINISTRATOR, false, &HandleBattlefieldStart, "", NULL },
+ { "stop", SEC_ADMINISTRATOR, false, &HandleBattlefieldEnd, "", NULL },
+ { "switch", SEC_ADMINISTRATOR, false, &HandleBattlefieldSwitch, "", NULL },
+ { "timer", SEC_ADMINISTRATOR, false, &HandleBattlefieldTimer, "", NULL },
+ { "enable", SEC_ADMINISTRATOR, false, &HandleBattlefieldEnable, "", NULL },
+ { NULL, 0, false, NULL, "", NULL }
+ };
+ static ChatCommand commandTable[] =
+ {
+ { "bf", SEC_ADMINISTRATOR, false, NULL, "", battlefieldcommandTable },
+ { NULL, 0, false, NULL, "", NULL }
+ };
+ return commandTable;
+ }
+
+ static bool HandleBattlefieldStart(ChatHandler* handler, const char* args)
+ {
+ uint32 battleid = 0;
+ char* battleid_str = strtok((char*)args, " ");
+ if (!battleid_str)
+ return false;
+
+ battleid = atoi(battleid_str);
+
+ Battlefield* bf = sBattlefieldMgr.GetBattlefieldByBattleId(battleid);
+
+ if (!bf)
+ return false;
+
+ bf->StartBattle();
+
+ if (battleid == 1)
+ handler->SendGlobalGMSysMessage("Wintergrasp (Command start used)");
+
+ return true;
+ }
+
+ static bool HandleBattlefieldEnd(ChatHandler* handler, const char* args)
+ {
+ uint32 battleid = 0;
+ char* battleid_str = strtok((char*)args, " ");
+ if (!battleid_str)
+ return false;
+
+ battleid = atoi(battleid_str);
+
+ Battlefield* bf = sBattlefieldMgr.GetBattlefieldByBattleId(battleid);
+
+ if (!bf)
+ return false;
+
+ bf->EndBattle(true);
+
+ if (battleid == 1)
+ handler->SendGlobalGMSysMessage("Wintergrasp (Command stop used)");
+
+ return true;
+ }
+
+ static bool HandleBattlefieldEnable(ChatHandler* handler, const char* args)
+ {
+ uint32 battleid = 0;
+ char* battleid_str = strtok((char*)args, " ");
+ if (!battleid_str)
+ return false;
+
+ battleid = atoi(battleid_str);
+
+ Battlefield* bf = sBattlefieldMgr.GetBattlefieldByBattleId(battleid);
+
+ if (!bf)
+ return false;
+
+ if (bf->GetEnable())
+ {
+ bf->SetEnable(false);
+ if (battleid == 1)
+ handler->SendGlobalGMSysMessage("Wintergrasp is disabled");
+ }
+ else
+ {
+ bf->SetEnable(true);
+ if (battleid == 1)
+ handler->SendGlobalGMSysMessage("Wintergrasp is enabled");
+ }
+
+ return true;
+ }
+
+ static bool HandleBattlefieldSwitch(ChatHandler* handler, const char* args)
+ {
+ uint32 battleid = 0;
+ char* battleid_str = strtok((char*)args, " ");
+ if (!battleid_str)
+ return false;
+
+ battleid = atoi(battleid_str);
+
+ Battlefield* bf = sBattlefieldMgr.GetBattlefieldByBattleId(battleid);
+
+ if (!bf)
+ return false;
+
+ bf->EndBattle(false);
+ if (battleid == 1)
+ handler->SendGlobalGMSysMessage("Wintergrasp (Command switch used)");
+
+ return true;
+ }
+
+ static bool HandleBattlefieldTimer(ChatHandler* handler, const char* args)
+ {
+ uint32 battleid = 0;
+ uint32 time = 0;
+ char* battleid_str = strtok((char*)args, " ");
+ if (!battleid_str)
+ return false;
+ char* time_str = strtok(NULL, " ");
+ if (!time_str)
+ return false;
+
+ battleid = atoi(battleid_str);
+
+ time = atoi(time_str);
+
+ Battlefield* bf = sBattlefieldMgr.GetBattlefieldByBattleId(battleid);
+
+ if (!bf)
+ return false;
+
+ bf->SetTimer(time * IN_MILLISECONDS);
+ bf->SendInitWorldStatesToAll();
+ if (battleid == 1)
+ handler->SendGlobalGMSysMessage("Wintergrasp (Command timer used)");
+
+ return true;
+ }
+};
+
+void AddSC_bf_commandscript()
+{
+ new bf_commandscript();
+}
diff --git a/src/server/scripts/Northrend/CMakeLists.txt b/src/server/scripts/Northrend/CMakeLists.txt
index 3e1f500ebce..14924d89c96 100644
--- a/src/server/scripts/Northrend/CMakeLists.txt
+++ b/src/server/scripts/Northrend/CMakeLists.txt
@@ -174,6 +174,7 @@ set(scripts_STAT_SRCS
Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp
Northrend/IcecrownCitadel/boss_sindragosa.cpp
Northrend/zuldrak.cpp
+ Northrend/wintergrasp.cpp
Northrend/icecrown.cpp
Northrend/Gundrak/boss_slad_ran.cpp
Northrend/Gundrak/instance_gundrak.cpp
diff --git a/src/server/scripts/Northrend/wintergrasp.cpp b/src/server/scripts/Northrend/wintergrasp.cpp
new file mode 100644
index 00000000000..10a6716d3f2
--- /dev/null
+++ b/src/server/scripts/Northrend/wintergrasp.cpp
@@ -0,0 +1,418 @@
+/* Copyright (C) 2008 - 2009 Trinity <http://www.trinitycore.org/>
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "ScriptPCH.h"
+#include "BattlefieldMgr.h"
+#include "BattlefieldWG.h"
+#include "Battlefield.h"
+#include "ScriptSystem.h"
+#include "WorldSession.h"
+#include "ObjectMgr.h"
+
+#define GOSSIP_HELLO_DEMO1 "Build catapult."
+#define GOSSIP_HELLO_DEMO2 "Build demolisher."
+#define GOSSIP_HELLO_DEMO3 "Build siege engine."
+#define GOSSIP_HELLO_DEMO4 "I cannot build more!"
+
+enum eWGqueuenpctext
+{
+ WG_NPCQUEUE_TEXT_H_NOWAR = 14775,
+ WG_NPCQUEUE_TEXT_H_QUEUE = 14790,
+ WG_NPCQUEUE_TEXT_H_WAR = 14777,
+ WG_NPCQUEUE_TEXT_A_NOWAR = 14782,
+ WG_NPCQUEUE_TEXT_A_QUEUE = 14791,
+ WG_NPCQUEUE_TEXT_A_WAR = 14781,
+ WG_NPCQUEUE_TEXTOPTION_JOIN = -1850507,
+};
+
+class npc_demolisher_engineerer : public CreatureScript
+{
+ public:
+ npc_demolisher_engineerer() : CreatureScript("npc_demolisher_engineerer")
+ {
+ }
+
+ bool OnGossipHello(Player * pPlayer, Creature * pCreature)
+ {
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ BattlefieldWG *BfWG = (BattlefieldWG *) sBattlefieldMgr.GetBattlefieldByBattleId(1);
+
+ if (!BfWG)
+ return true;
+
+ if (BfWG->GetData(pCreature->GetEntry() == 30400 ? BATTLEFIELD_WG_DATA_MAX_VEHICLE_H : BATTLEFIELD_WG_DATA_MAX_VEHICLE_A) >
+ BfWG->GetData(pCreature->GetEntry() == 30400 ? BATTLEFIELD_WG_DATA_VEHICLE_H : BATTLEFIELD_WG_DATA_VEHICLE_A))
+ {
+ if (pPlayer->HasAura(SPELL_CORPORAL))
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_DEMO1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
+ else if (pPlayer->HasAura(SPELL_LIEUTENANT))
+ {
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_DEMO1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_DEMO2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_DEMO3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
+ }
+ }
+ else
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_DEMO4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9);
+
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+ return true;
+ }
+
+ bool OnGossipSelect(Player * pPlayer, Creature * pCreature, uint32 /*uiSender */ , uint32 uiAction)
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+
+ BattlefieldWG *BfWG = (BattlefieldWG *) sBattlefieldMgr.GetBattlefieldByBattleId(1);
+
+ if (!BfWG)
+ return true;
+
+ if (BfWG->GetData(pCreature->GetEntry() == 30400 ? BATTLEFIELD_WG_DATA_MAX_VEHICLE_H : BATTLEFIELD_WG_DATA_MAX_VEHICLE_A) >
+ BfWG->GetData(pCreature->GetEntry() == 30400 ? BATTLEFIELD_WG_DATA_VEHICLE_H : BATTLEFIELD_WG_DATA_VEHICLE_A))
+ {
+ switch (uiAction - GOSSIP_ACTION_INFO_DEF)
+ {
+ case 0:
+ pPlayer->CastSpell(pPlayer, 56663, false, NULL, NULL, pCreature->GetGUID());
+ break;
+ case 1:
+ pPlayer->CastSpell(pPlayer, 56575, false, NULL, NULL, pCreature->GetGUID());
+ break;
+ case 2:
+ pPlayer->CastSpell(pPlayer, pPlayer->GetTeamId()? 61408 : 56661, false, NULL, NULL, pCreature->GetGUID());
+ break;
+ }
+ //spell 49899 Emote : 406 from sniff
+ //INSERT INTO `spell_scripts` (`id`, `delay`, `command`, `datalong`, `datalong2`, `dataint`, `x`, `y`, `z`, `o`) VALUES ('49899', '0', '1', '406', '0', '0', '0', '0', '0', '0');
+ if (Creature * creature = pCreature->FindNearestCreature(27852, 30.0f, true))
+ creature->CastSpell(creature, 49899, true);
+ }
+ return true;
+ }
+};
+
+class npc_wg_spiritguide : public CreatureScript
+{
+ public:
+ npc_wg_spiritguide() : CreatureScript("npc_wg_spiritguide")
+ {
+ }
+
+ bool OnGossipHello(Player * pPlayer, Creature * pCreature)
+ {
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ BattlefieldWG *BfWG = (BattlefieldWG *) sBattlefieldMgr.GetBattlefieldByBattleId(BATTLEFIELD_BATTLEID_WG);
+ if (BfWG)
+ {
+ GraveYardVect gy = BfWG->GetGraveYardVect();
+ for (uint8 i = 0; i < gy.size(); i++)
+ {
+ if (gy[i]->GetControlTeamId() == pPlayer->GetTeamId())
+ {
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, sObjectMgr->GetTrinityStringForDBCLocale(((BfGraveYardWG *) gy[i])->GetTextId()), GOSSIP_SENDER_MAIN,
+ GOSSIP_ACTION_INFO_DEF + i);
+ }
+ }
+ }
+
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+ return true;
+ }
+
+ bool OnGossipSelect(Player * pPlayer, Creature * /*pCreature */ , uint32 /*uiSender */ , uint32 uiAction)
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+
+ BattlefieldWG *BfWG = (BattlefieldWG *) sBattlefieldMgr.GetBattlefieldByBattleId(BATTLEFIELD_BATTLEID_WG);
+ if (BfWG)
+ {
+ GraveYardVect gy = BfWG->GetGraveYardVect();
+ for (uint8 i = 0; i < gy.size(); i++)
+ {
+ if (uiAction - GOSSIP_ACTION_INFO_DEF == i && gy[i]->GetControlTeamId() == pPlayer->GetTeamId())
+ {
+ const WorldSafeLocsEntry *ws = sWorldSafeLocsStore.LookupEntry(gy[i]->GetGraveYardId());
+ pPlayer->TeleportTo(ws->map_id, ws->x, ws->y, ws->z, 0);
+ }
+ }
+ }
+ return true;
+ }
+};
+
+class npc_wg_dalaran_queue : public CreatureScript
+{
+ public:
+ npc_wg_dalaran_queue() : CreatureScript("npc_wg_dalaran_queue")
+ {
+ }
+
+ bool OnGossipHello(Player * pPlayer, Creature * pCreature)
+ {
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ BattlefieldWG *BfWG = (BattlefieldWG *) sBattlefieldMgr.GetBattlefieldByBattleId(BATTLEFIELD_BATTLEID_WG);
+ if (BfWG)
+ {
+
+ if (BfWG->IsWarTime())
+ {
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, sObjectMgr->GetTrinityStringForDBCLocale(WG_NPCQUEUE_TEXTOPTION_JOIN), GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
+ pPlayer->SEND_GOSSIP_MENU(BfWG->GetDefenderTeam()? WG_NPCQUEUE_TEXT_H_WAR : WG_NPCQUEUE_TEXT_A_WAR, pCreature->GetGUID());
+ }
+ else
+ {
+ uint32 uiTime = BfWG->GetTimer() / 1000;
+ pPlayer->SendUpdateWorldState(4354, time(NULL) + uiTime);
+ if (uiTime < 15 * MINUTE)
+ {
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, sObjectMgr->GetTrinityStringForDBCLocale(WG_NPCQUEUE_TEXTOPTION_JOIN), GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
+ pPlayer->SEND_GOSSIP_MENU(BfWG->GetDefenderTeam()? WG_NPCQUEUE_TEXT_H_QUEUE : WG_NPCQUEUE_TEXT_A_QUEUE, pCreature->GetGUID());
+ }
+ else
+ {
+ pPlayer->SEND_GOSSIP_MENU(BfWG->GetDefenderTeam()? WG_NPCQUEUE_TEXT_H_NOWAR : WG_NPCQUEUE_TEXT_A_NOWAR, pCreature->GetGUID());
+ }
+ }
+ }
+ return true;
+ }
+
+ bool OnGossipSelect(Player * pPlayer, Creature * /*pCreature */ , uint32 /*uiSender */ , uint32 /*uiAction */ )
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+
+ BattlefieldWG *BfWG = (BattlefieldWG *) sBattlefieldMgr.GetBattlefieldByBattleId(BATTLEFIELD_BATTLEID_WG);
+ if (BfWG)
+ {
+ if (BfWG->IsWarTime())
+ {
+ BfWG->InvitePlayerToWar(pPlayer);
+ }
+ else
+ {
+ uint32 uiTime = BfWG->GetTimer() / 1000;
+ if (uiTime < 15 * MINUTE)
+ BfWG->InvitePlayerToQueue(pPlayer);
+ }
+ }
+ return true;
+ }
+};
+
+const uint32 Vehicules[4] = { 32627, 28312, 28094, 27881 };
+
+#define SPELL_VEHICLE_TELEPORT 49759
+
+class go_wintergrasp_teleporter : public GameObjectScript
+{
+ public:
+ go_wintergrasp_teleporter() : GameObjectScript("go_wintergrasp_teleporter")
+ {
+ }
+
+ struct go_wintergrasp_teleporterAI : public GameObjectAI
+ {
+ go_wintergrasp_teleporterAI(GameObject * g) : GameObjectAI(g)
+ {
+ uiCheckTimer = 1000;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (uiCheckTimer <= diff)
+ {
+ for (uint8 i = 0; i < 4; i++)
+ if (Creature * pVehicle = go->FindNearestCreature(Vehicules[i], 3.0f, true))
+ if (!pVehicle->HasAura(SPELL_VEHICLE_TELEPORT))
+ {
+ if (pVehicle->GetVehicle())
+ {
+ if (Unit * player = pVehicle->GetVehicle()->GetPassenger(0))
+ {
+ uint32 gofaction = go->GetUInt32Value(GAMEOBJECT_FACTION);
+ uint32 plfaction = player->getFaction();
+ if (gofaction == plfaction)
+ {
+ pVehicle->CastSpell(pVehicle, SPELL_VEHICLE_TELEPORT, true);
+ if (Creature * TargetTeleport = pVehicle->FindNearestCreature(23472, 100.0f, true))
+ {
+ float x, y, z, o;
+ TargetTeleport->GetPosition(x, y, z, o);
+ pVehicle->GetVehicle()->TeleportVehicle(x, y, z, o);
+ }
+ }
+ }
+ }
+ }
+ uiCheckTimer = 1000;
+ }
+ else
+ uiCheckTimer -= diff;
+ }
+ private:
+ uint32 uiCheckTimer;
+ };
+
+ GameObjectAI *GetAI(GameObject * go) const
+ {
+ return new go_wintergrasp_teleporterAI(go);
+ }
+};
+
+class npc_wintergrasp_quest_giver : public CreatureScript
+{
+ public:
+ npc_wintergrasp_quest_giver() : CreatureScript("npc_wintergrasp_quest_giver")
+ {
+ }
+
+ bool OnGossipHello(Player * pPlayer, Creature * pCreature)
+ {
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ BattlefieldWG *BfWG = (BattlefieldWG *) sBattlefieldMgr.GetBattlefieldByBattleId(BATTLEFIELD_BATTLEID_WG);
+ if (BfWG)
+ {
+ if (pCreature->isQuestGiver())
+ {
+ Object* pObject = (Object *) pCreature;
+ QuestRelations* pObjectQR = sObjectMgr->GetCreatureQuestRelationMap();
+ QuestRelations* pObjectQIR = sObjectMgr->GetCreatureQuestInvolvedRelation();
+
+ QuestMenu & qm = pPlayer->PlayerTalkClass->GetQuestMenu();
+ qm.ClearMenu();
+
+ for (QuestRelations::const_iterator i = pObjectQIR->lower_bound(pObject->GetEntry()); i != pObjectQIR->upper_bound(pObject->GetEntry()); ++i)
+ {
+ uint32 quest_id = i->second;
+ QuestStatus status = pPlayer->GetQuestStatus(quest_id);
+ if (status == QUEST_STATUS_COMPLETE && !pPlayer->GetQuestRewardStatus(quest_id))
+ qm.AddMenuItem(quest_id, 4);
+ else if (status == QUEST_STATUS_INCOMPLETE)
+ qm.AddMenuItem(quest_id, 4);
+ }
+
+ for (QuestRelations::const_iterator i = pObjectQR->lower_bound(pObject->GetEntry()); i != pObjectQR->upper_bound(pObject->GetEntry()); ++i)
+ {
+ uint32 quest_id = i->second;
+ Quest const* pQuest = sObjectMgr->GetQuestTemplate(quest_id);
+ if (!pQuest)
+ continue;
+
+ switch (quest_id)
+ {
+ // Horde attacker
+ case 13193:
+ case 13202:
+ case 13180:
+ case 13200:
+ case 13201:
+ case 13223:
+ if (BfWG->GetAttackerTeam() == TEAM_HORDE)
+ {
+ QuestStatus status = pPlayer->GetQuestStatus(quest_id);
+
+ if (pQuest->IsAutoComplete() && pPlayer->CanTakeQuest(pQuest, false))
+ qm.AddMenuItem(quest_id, 4);
+ else if (status == QUEST_STATUS_NONE && pPlayer->CanTakeQuest(pQuest, false))
+ qm.AddMenuItem(quest_id, 2);
+ }
+ break;
+ // Horde defender
+ case 13199:
+ case 13192:
+ case 13178:
+ case 13191:
+ case 13194:
+ case 13539:
+ case 13185:
+ if (BfWG->GetDefenderTeam() == TEAM_HORDE)
+ {
+ QuestStatus status = pPlayer->GetQuestStatus(quest_id);
+
+ if (pQuest->IsAutoComplete() && pPlayer->CanTakeQuest(pQuest, false))
+ qm.AddMenuItem(quest_id, 4);
+ else if (status == QUEST_STATUS_NONE && pPlayer->CanTakeQuest(pQuest, false))
+ qm.AddMenuItem(quest_id, 2);
+ }
+ break;
+ // Alliance attacker
+ case 13196:
+ case 13198:
+ case 13179:
+ case 13222:
+ case 13195:
+ if (BfWG->GetAttackerTeam() == TEAM_ALLIANCE)
+ {
+ QuestStatus status = pPlayer->GetQuestStatus(quest_id);
+
+ if (pQuest->IsAutoComplete() && pPlayer->CanTakeQuest(pQuest, false))
+ qm.AddMenuItem(quest_id, 4);
+ else if (status == QUEST_STATUS_NONE && pPlayer->CanTakeQuest(pQuest, false))
+ qm.AddMenuItem(quest_id, 2);
+ }
+ break;
+ // Alliance defender
+ case 13154:
+ case 13153:
+ case 13177:
+ case 13538:
+ case 13186:
+ case 13156:
+ if (BfWG->GetDefenderTeam() == TEAM_ALLIANCE)
+ {
+ QuestStatus status = pPlayer->GetQuestStatus(quest_id);
+
+ if (pQuest->IsAutoComplete() && pPlayer->CanTakeQuest(pQuest, false))
+ qm.AddMenuItem(quest_id, 4);
+ else if (status == QUEST_STATUS_NONE && pPlayer->CanTakeQuest(pQuest, false))
+ qm.AddMenuItem(quest_id, 2);
+ }
+ break;
+ default:
+ QuestStatus status = pPlayer->GetQuestStatus(quest_id);
+
+ if (pQuest->IsAutoComplete() && pPlayer->CanTakeQuest(pQuest, false))
+ qm.AddMenuItem(quest_id, 4);
+ else if (status == QUEST_STATUS_NONE && pPlayer->CanTakeQuest(pQuest, false))
+ qm.AddMenuItem(quest_id, 2);
+ break;
+ }
+ }
+ }
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+ return true;
+ }
+ return true;
+ }
+};
+
+void AddSC_wintergrasp()
+{
+ new npc_wg_dalaran_queue();
+ new npc_wg_spiritguide();
+ new npc_demolisher_engineerer();
+ new go_wintergrasp_teleporter();
+ new npc_wintergrasp_quest_giver();
+}
diff --git a/src/server/scripts/PrecompiledHeaders/ScriptPCH.h b/src/server/scripts/PrecompiledHeaders/ScriptPCH.h
index 1cd25309055..e73771b49e5 100644
--- a/src/server/scripts/PrecompiledHeaders/ScriptPCH.h
+++ b/src/server/scripts/PrecompiledHeaders/ScriptPCH.h
@@ -18,6 +18,7 @@
#include "InstanceScript.h"
#include "CombatAI.h"
#include "PassiveAI.h"
+#include "GameObjectAI.h"
#include "Chat.h"
#include "DBCStructure.h"
#include "DBCStores.h"
diff --git a/src/server/shared/Logging/Log.h b/src/server/shared/Logging/Log.h
index 94e0491229b..9d2035a6c5c 100755
--- a/src/server/shared/Logging/Log.h
+++ b/src/server/shared/Logging/Log.h
@@ -50,6 +50,7 @@ enum DebugLogFilters
LOG_FILTER_LOOT = 0x00100000, // Loot related
LOG_FILTER_GUILD = 0x00200000, // Guild related
LOG_FILTER_TRANSPORTS = 0x00400000, // Transport related
+ LOG_FILTER_BATTLEFIELD = 0x00800000, // Battlefield related
};
enum LogTypes
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
index eb1e33626c6..229f159fb59 100644
--- a/src/server/worldserver/worldserver.conf.dist
+++ b/src/server/worldserver/worldserver.conf.dist
@@ -1388,6 +1388,57 @@ AllowTickets = 1
DungeonFinder.Enable = 0
#
+# Wintergrasp.Enable
+# Description: Enable the Wintergrasp battlefield.
+# Default: 0 - (Disabled)
+# 1 - (Enabled, Experimental as of still being in development)
+
+Wintergrasp.Enable = 0
+
+#
+# Wintergrasp.PlayerMax
+# Description: Maximum number of players allowed in Wintergrasp.
+# Default: 100
+
+Wintergrasp.PlayerMax = 100
+
+#
+# Wintergrasp.PlayerMin
+# Description: Minimum number of players required for Wintergrasp.
+# Default: 0
+
+Wintergrasp.PlayerMin = 0
+
+#
+# Wintergrasp.PlayerMinLvl
+# Description: Required character level for the Wintergrasp battle.
+# Default: 77
+
+Wintergrasp.PlayerMinLvl = 77
+
+#
+# Wintergrasp.BattleTimer
+# Description: Time (in minutes) for the Wintergrasp battle to last.
+# Default: 30
+
+Wintergrasp.BattleTimer = 30
+
+#
+# Wintergrasp.NoBattleTimer
+# Description: Time (in minutes) between Wintergrasp battles.
+# Default: 150
+
+Wintergrasp.NoBattleTimer = 150
+
+#
+# Wintergrasp.CrashRestartTimer
+# Description: Time (in minutes) to delay the restart of Wintergrasp if the world server
+# crashed during a running battle.
+# Default: 10
+
+Wintergrasp.CrashRestartTimer = 10
+
+#
# DBC.EnforceItemAttributes
# Description: Disallow overriding item attributes stored in DBC files with values from the
# database.