aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Wintergrasp_TODO.txt12
-rw-r--r--Wintergrasp_spells.txt18
-rw-r--r--sql/updates/Wintergrasp_spawning.sql474
-rw-r--r--sql/updates/world_WinterGrasp.sql341
-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
49 files changed, 6739 insertions, 83 deletions
diff --git a/Wintergrasp_TODO.txt b/Wintergrasp_TODO.txt
new file mode 100644
index 00000000000..9d6729c432e
--- /dev/null
+++ b/Wintergrasp_TODO.txt
@@ -0,0 +1,12 @@
+TODO (add new things to sort out here) :
+- Move spawns to database : NPCs / GOs
+- Spawn NPC/GO in their correct phase
+- Fix teleport spells for vehicles/drivers
+- Get official texts for horde in db
+- Clean up code to use phases-system / spells instead of hardcoded spawn/despawn functionality
+- Remove hardcoded entities from headerfile
+- Spawn horde/alliance spiritguides spawn/change depending on holder
+- Clean up some minor hacks
+
+COMPLETED (move completed things from the above list here) :
+
diff --git a/Wintergrasp_spells.txt b/Wintergrasp_spells.txt
new file mode 100644
index 00000000000..1db15ce5069
--- /dev/null
+++ b/Wintergrasp_spells.txt
@@ -0,0 +1,18 @@
+Spell 56617 "Alliance Controls Factory Phase Shift" Adds Phase 32
+Spell 56618 "Horde Controls Factory Phase Shift" Adds Phase 16
+
+Spell 55773 "Horde Control Phase Shift" Adds Phase 64
+Spell 55774 "Alliance Control Phase Shift" Adds Phase 128
+
+Spell 58045 "Essence of Wintergrasp" Adds Phase 256
+
+Spell 37795 "Recruit" Gained when joining WG battle
+
+Spell 74411 "Battleground - Dampening" Gained when joining WG battle
+
+
+Wintergrasp Vehicle On spawn entries: 28312,27881,28094,32627
+set x,y,z,o to nearest trigger entry: 23472
+make player cast 60968 on vehicle
+aura 14267 on self if player is horde
+aura 14268 on self if player is alliance \ No newline at end of file
diff --git a/sql/updates/Wintergrasp_spawning.sql b/sql/updates/Wintergrasp_spawning.sql
new file mode 100644
index 00000000000..7e157229279
--- /dev/null
+++ b/sql/updates/Wintergrasp_spawning.sql
@@ -0,0 +1,474 @@
+-- Replace Wintergrasp spawns with properly phased spawns
+SET @GUID := 290000;
+DELETE FROM `creature` WHERE `id` IN (31841,31842,30400,30499,30489,30869,31036,31051,31052,31054,31108,31109,31153,39172,30870,31053,31091,31101,31102,31106,31107,31151,32294,39173,32296,30488);
+INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`DeathState`,`MovementType`) VALUES
+-- Horde Spirt Guides
+(@GUID+0,31841,571,1,0x00000010,0,0,4318.436,2408.06738,392.675751,6.23082542,120,0,0,1,0,0,0), -- Eastspark Workshop
+(@GUID+1,31841,571,1,0x00000010,0,0,4336.25439,3235.51978,390.334,0.628318548,120,0,0,1,0,0,0), -- Westspark Workshop
+(@GUID+2,31841,571,1,0x00000010,0,0,5104.753,2300.9458,368.568054,0.7330383,120,0,0,1,0,0,0), -- The Sunken Ring
+(@GUID+3,31841,571,1,0x00000010,0,0,5103.133,3462.128,368.568054,5.270895,120,0,0,1,0,0,0), -- The Chilled Quagmire "Outside broker Temple"
+(@GUID+4,31841,571,1,0x00000040,0,0,5537.482,2898.90674,517.2589,4.86946869,120,0,0,1,0,0,0), -- Fortress
+(@GUID+5,31841,571,1,0x00000001,0,0,5031.84131,3710.74878,372.4835,0,120,5,0,1,0,0,0), -- Horde Landing Zone
+-- Alliance Spirt Guides
+(@GUID+6,31842,571,1,0x00000020,0,0,4318.436,2408.06738,392.675751,6.23082542,120,0,0,1,0,0,0), -- Eastspark Workshop
+(@GUID+7,31842,571,1,0x00000020,0,0,4336.25439,3235.51978,390.334,0.628318548,120,0,0,1,0,0,0), -- Westspark Workshop
+(@GUID+8,31842,571,1,0x00000020,0,0,5104.753,2300.9458,368.568054,0.7330383,120,0,0,1,0,0,0), -- The Sunken Ring
+(@GUID+9,31842,571,1,0x00000020,0,0,5103.133,3462.128,368.568054,5.270895,120,0,0,1,0,0,0), -- The Chilled Quagmire "Outside The Broken Temple"
+(@GUID+10,31842,571,1,0x00000080,0,0,5537.482,2898.90674,517.2589,4.86946869,120,0,0,1,0,0,0), -- Fortress
+(@GUID+11,31842,571,1,0x00000001,0,0,5140.7876,2179.12451,390.9512,1.97222209,120,0,0,1,0,0,0), -- Aliance Landing Zone
+-- Horde Engineers
+(@GUID+12,30400,571,1,0x00000010,0,0,4964.89,3383.06,382.911,6.12611,180,0,0,1,0,0,0), -- The Broken Temple
+(@GUID+13,30400,571,1,0x00000010,0,0,4939.76,2389.06,326.153,3.26377,180,0,0,1,0,0,0), -- The Sunken Ring
+(@GUID+14,30400,571,1,0x00000010,0,0,4357.67,2357.99,382.007,1.67552,180,0,0,1,0,0,0), -- Eastspark Workshop
+(@GUID+15,30400,571,1,0x00000010,0,0,4354.15,3312.82,378.046,1.67552,180,0,0,1,0,0,0), -- Westspark Workshop
+(@GUID+16,30400,571,1,0x00000040,0,0,5391.61,2707.72,415.051,4.55531,180,0,0,1,0,0,0), -- Wintergrasp Fortress
+(@GUID+17,30400,571,1,0x00000040,0,0,5392.91,2975.26,415.223,4.55531,180,0,0,1,0,0,0), -- Wintergrasp Fortress
+-- Alliance Engineers
+(@GUID+18,30499,571,1,0x00000020,0,0,4964.89,3383.06,382.911,6.12611,180,0,0,1,0,0,0), -- The Broken Temple
+(@GUID+19,30499,571,1,0x00000020,0,0,4939.76,2389.06,326.153,3.26377,180,0,0,1,0,0,0), -- The Sunken Ring
+(@GUID+20,30499,571,1,0x00000020,0,0,4357.67,2357.99,382.007,1.67552,180,0,0,1,0,0,0), -- Eastspark Workshop
+(@GUID+21,30499,571,1,0x00000020,0,0,4354.15,3312.82,378.046,1.67552,180,0,0,1,0,0,0), -- Westspark Workshop
+(@GUID+22,30499,571,1,0x00000080,0,0,5391.61,2707.72,415.051,4.55531,180,0,0,1,0,0,0), -- Wintergrasp Fortress
+(@GUID+23,30499,571,1,0x00000080,0,0,5392.91,2975.26,415.223,4.55531,180,0,0,1,0,0,0), -- Wintergrasp Fortress
+-- Alliance NPC's
+(@GUID+24,30489,571,1,0x00000080,0,0,5369.973,2874.83081,409.3225,3.12413931,120,0,0,1,0,0,0),
+(@GUID+25,30869,571,1,0x00000001,0,0,5102.75049,2187.82837,365.707855,3.996804,120,0,0,1,0,0,0),
+(@GUID+26,31036,571,1,0x00000040,0,0,5078.281,2183.704,365.028564,1.46607661,120,0,0,1,0,0,0),
+(@GUID+27,31036,571,1,0x00000080,0,0,5358.641,2841.76416,409.3225,1.13262534,120,0,0,1,0,0,0),
+(@GUID+28,31051,571,1,0x00000040,0,0,5081.697,2173.73,365.8777,0.8552113,120,0,0,1,0,0,0),
+(@GUID+29,31051,571,1,0x00000080,0,0,5296.869,2887.67114,409.274658,5.60250664,120,0,0,1,0,0,0),
+(@GUID+30,31052,571,1,0x00000040,0,0,5100.06543,2168.89,365.7788,1.97222209,120,0,0,1,0,0,0),
+(@GUID+31,31052,571,1,0x00000080,0,0,5302.57373,2750.40332,409.274658,5.46288061,120,0,0,1,0,0,0),
+(@GUID+32,31054,571,1,0x00000040,0,0,5088.611,2167.66235,365.688751,0.6806784,120,0,0,1,0,0,0),
+(@GUID+33,31054,571,1,0x00000080,0,0,5372.05859,3028.33618,409.206024,0.012565271,120,0,0,1,0,0,0),
+(@GUID+34,31108,571,1,0x00000040,0,0,5095.673,2193.284,365.9236,4.939282,120,0,0,1,0,0,0),
+(@GUID+35,31108,571,1,0x00000080,0,0,5298.267,2924.97632,409.274658,0.9075712,120,0,0,1,0,0,0),
+(@GUID+36,31109,571,1,0x00000040,0,0,5080.403,2199.00244,359.4894,2.96705961,120,0,0,1,0,0,0),
+(@GUID+37,31109,571,1,0x00000080,0,0,5228.2915,2809.888,409.274658,3.19395256,120,0,0,1,0,0,0),
+(@GUID+38,31153,571,1,0x00000040,0,0,5088.48633,2188.17871,365.646973,5.253441,120,0,0,1,0,0,0),
+(@GUID+39,31153,571,1,0x00000080,0,0,5364.784,2835.135,409.3225,3.12413931,120,0,0,1,0,0,0),
+(@GUID+40,32294,571,1,0x00000080,0,0,5374.568,2790.784,409.3225,2.72271371,120,0,0,1,0,0,0),
+(@GUID+41,39172,571,1,0x00000080,0,0,5372.672,2786.74048,409.4423,2.80998015,120,0,0,1,0,0,0),
+(@GUID+42,30488,571,1,0x00000080,0,0,5370.428,2814.274,409.3225,3.054326,120,0,0,1,0,0,0),
+-- Horde NPC's
+(@GUID+43,30870,571,1,0x00000001,0,0,5023.4043,3686.03345,363.1192,5.131268,120,0,0,1,0,0,0),
+(@GUID+44,31053,571,1,0x00000040,0,0,5379.875,3027.43359,409.206024,0,120,0,0,1,0,0,0),
+(@GUID+45,31053,571,1,0x00000080,0,0,5034.703125,3666.703125,363.273865,4.310963,120,0,0,1,0,0,0),
+(@GUID+46,31091,571,1,0x00000040,0,0,5347.7915,2837.38574,409.3466,2.62603331,120,0,0,1,0,0,0),
+(@GUID+47,31091,571,1,0x00000080,0,0,5018.662109,3672.279541,362.862885,2.209141,120,0,0,1,0,0,0),
+(@GUID+48,31101,571,1,0x00000040,0,0,5296.564,2789.87378,409.274658,0.7330383,120,0,0,1,0,0,0),
+(@GUID+49,31101,571,1,0x00000080,0,0,5014.065430,3678.846436,362.995575,5.096361,120,0,0,1,0,0,0),
+(@GUID+50,31102,571,1,0x00000040,0,0,5295.455,2732.87549,409.274658,4.7211113,120,0,0,1,0,0,0),
+(@GUID+51,31102,571,1,0x00000080,0,0,5031.676270,3655.820801,362.234558,5.131268,120,0,0,1,0,0,0),
+(@GUID+52,31106,571,1,0x00000040,0,0,5295.56348,2926.67188,409.274658,0.87266463,120,0,0,1,0,0,0),
+(@GUID+53,31106,571,1,0x00000080,0,0,5037.602051,3675.459717,363.147888,3.176499,120,0,0,1,0,0,0),
+(@GUID+54,31107,571,1,0x00000040,0,0,5230.09033,2876.635,409.316254,-2.19854617,120,0,0,1,0,0,0),
+(@GUID+55,31107,571,1,0x00000080,0,0,5004.455078,3661.089111,361.335785,3.979351,120,0,0,1,0,0,0),
+(@GUID+56,31151,571,1,0x00000040,0,0,5363.2876,2834.52954,409.3606,2.76273036,120,0,0,1,0,0,0),
+(@GUID+57,31151,571,1,0x00000080,0,0,5034.698242,3683.268799,363.129120,4.310963,120,0,0,1,0,0,0),
+(@GUID+58,32296,571,1,0x00000040,0,0,5374.568,2790.784,409.3225,2.60054,120,0,0,1,0,0,0),
+-- Missing noc in fortress
+(@GUID+60,39173,571,1,0x00000040,0,0,5372.672,2786.74048,409.4423,2.80998015,120,0,0,1,0,0,0);
+
+DELETE FROM `creature_addon` WHERE `guid` IN (@GUID+26,@GUID+27,@GUID+38,@GUID+39,@GUID+40,@GUID+41,@GUID+57,@GUID+58,@GUID+59,@GUID+60);
+INSERT INTO `creature_addon` (`guid`,`mount`,`path_id`,`bytes2`) VALUES
+(@GUID+26,14337,0,257), -- Commander Zanneth "Horde Controlled"
+(@GUID+27,14337,0,257), -- Commander Zanneth "Alliance Controlled"
+(@GUID+38,6569,0,257), -- Tactical Officer Ahbramis "Horde Controlled"
+(@GUID+39,6569,0,257), -- Tactical Officer Ahbramis "Alliance Controlled"
+(@GUID+40,27247,0,1), -- Knight Dameron "Alliance Controlled"
+(@GUID+41,28912,0,1), -- Marshal Magruder "Alliance Controlled"
+(@GUID+58,27245,0,1), -- Stone Guard Mukar "Horde Controlled"
+(@GUID+60,29261,0,1); -- Champion Ros'slai "Horde Controlled"
+
+-- Pathing for Anchorite Tessa Entry: 31054
+SET @NPC := @GUID+33;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `MovementType`=2 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes2`,`mount`,`auras`) VALUES (@NPC,@PATH,1,0, '');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES
+(@PATH,1,5382.507,3028.468,409.206,0,0,0,100,0),
+(@PATH,2,5392.744,3028.737,409.206,0,0,0,100,0),
+(@PATH,3,5382.507,3028.468,409.206,0,0,0,100,0),
+(@PATH,4,5371.491,3028.329,409.206,0,0,0,100,0),
+(@PATH,5,5360.032,3028.516,409.3161,0,0,0,100,0),
+(@PATH,6,5371.491,3028.329,409.206,0,0,0,100,0);
+
+-- Pathing for Commander Zanneth Entry: 31036
+SET @NPC := @GUID+27;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=5358.854,`position_y`=2859.232,`position_z`=409.5425 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes2`,`mount`,`auras`) VALUES (@NPC,@PATH,1,14337, '');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES
+(@PATH,1,5359.788,2846.359,409.3642,0,0,0,100,0),
+(@PATH,2,5359.187,2839.211,409.3642,0,0,0,100,0),
+(@PATH,3,5360.083,2823.116,409.5381,0,0,0,100,0),
+(@PATH,4,5359.187,2839.211,409.3642,0,0,0,100,0),
+(@PATH,5,5359.788,2846.359,409.3642,0,0,0,100,0),
+(@PATH,6,5358.854,2859.232,409.5425,0,0,0,100,0);
+
+-- Pathing for Commander Dardosh Entry: 31091
+SET @NPC := @GUID+46;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `MovementType`=2,`position_x`=5359.546,`position_y`=2858.049,`position_z`=409.3642 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes2`,`mount`,`auras`) VALUES (@NPC,@PATH,257,0, '');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES
+(@PATH,1,5359.202,2843.208,409.3642,0,0,0,100,0),
+(@PATH,2,5358.997,2827.974,409.3639,0,0,0,100,0),
+(@PATH,3,5359.202,2843.208,409.3642,0,0,0,100,0),
+(@PATH,4,5359.546,2858.049,409.3642,0,0,0,100,0);
+
+-- Pathing for Commander Dardosh Entry: 31091
+SET @NPC := @GUID+47;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `MovementType`=2,`position_x`=5018.411133,`position_y`=3672.615967,`position_z`=362.863525 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes2`,`mount`,`auras`) VALUES (@NPC,@PATH,257,0, '');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES
+(@PATH,1,5022.827637,3666.665771,362.205750,0,0,0,100,0),
+(@PATH,2,5024.270508,3658.739258,361.705750,0,0,0,100,0),
+(@PATH,3,5022.827637,3666.665771,362.205750,0,0,0,100,0),
+(@PATH,4,5018.411133,3672.615967,362.863525,0,0,0,100,0);
+
+-- Pathing for Primalist Mulfort Entry: 31053
+SET @NPC := @GUID+44;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `MovementType`=2 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes2`,`mount`,`auras`) VALUES (@NPC,@PATH,257,0, '');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES
+(@PATH,1,5390.624,3027.994,409.206,0,0,0,100,0),
+(@PATH,2,5379.875,3027.434,409.206,0,0,0,100,0),
+(@PATH,3,5371.404,3026.511,409.206,0,0,0,100,0),
+(@PATH,4,5379.875,3027.434,409.206,0,0,0,100,0);
+
+-- Pathing for Vieron Blazefeather Entry: 31102
+SET @NPC := @GUID+50;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `MovementType`=2,`position_x`=5296.644,`position_y`=2731.107,`position_z`=409.3163 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes2`,`mount`,`auras`) VALUES (@NPC,@PATH,1,0, '');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES
+(@PATH,1,5295.544,2722.631,409.3163,0,0,0,100,0),
+(@PATH,2,5296.644,2731.107,409.3163,0,0,0,100,0),
+(@PATH,3,5297.874,2738.155,409.3163,0,0,0,100,0),
+(@PATH,4,5305.192,2746.161,409.3061,0,0,0,100,0),
+(@PATH,5,5297.874,2738.155,409.3163,0,0,0,100,0),
+(@PATH,6,5296.644,2731.107,409.3163,0,0,0,100,0);
+
+DELETE FROM `creature_template_addon` WHERE `entry` IN (30740);
+INSERT INTO `creature_template_addon` (`entry`,`bytes2`,`emote`) VALUES
+(30740,257,375); -- Guards "Alliance"
+
+-- Guards "Alliance"
+SET @GUID := 291000;
+DELETE FROM `creature` WHERE `id` IN (30740);
+INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`DeathState`,`MovementType`) VALUES
+-- Fortress
+(@GUID+0,30740,571,1,0x00000080,0,0,5150.26855,2786.02173,409.5469,3.22885919,120,0,0,1,0,0,0),
+(@GUID+1,30740,571,1,0x00000080,0,0,5150.657,2777.9502,409.4053,2.94960642,120,0,0,1,0,0,0),
+(@GUID+2,30740,571,1,0x00000080,0,0,5193.632,2734.172,409.272552,4.694936,120,0,0,1,0,0,0),
+(@GUID+3,30740,571,1,0x00000080,0,0,5200.497,2733.88843,409.272552,4.677482,120,0,0,1,0,0,0),
+(@GUID+4,30740,571,1,0x00000080,0,0,5264.64648,2670.1936,409.1819,3.07177949,120,0,0,1,0,0,0),
+(@GUID+5,30740,571,1,0x00000080,0,0,5265.30566,2663.15381,409.1819,3.12413931,120,0,0,1,0,0,0),
+(@GUID+6,30740,571,1,0x00000080,0,0,5307.02051,2613.89771,409.172363,4.694936,120,0,0,1,0,0,0),
+(@GUID+7,30740,571,1,0x00000080,0,0,5311.133,3061.04248,408.809937,1.50098312,120,0,0,1,0,0,0),
+(@GUID+8,30740,571,1,0x00000080,0,0,5315.87354,2614.21924,408.972748,4.677482,120,0,0,1,0,0,0),
+(@GUID+9,30740,571,1,0x00000080,0,0,5318.09,3060.634,408.882782,1.62315619,120,0,0,1,0,0,0),
+(@GUID+10,30740,571,1,0x00000080,0,0,5149.395,2897.044,409.304443,3.03687286,120,0,0,1,0,0,0),
+(@GUID+11,30740,571,1,0x00000080,0,0,5149.51953,2904.19336,409.276062,3.07177949,120,0,0,1,0,0,0),
+(@GUID+12,30740,571,1,0x00000080,0,0,5192.79248,2948.454,409.2746,1.50098312,120,0,0,1,0,0,0),
+(@GUID+13,30740,571,1,0x00000080,0,0,5201.645,2948.77612,409.2746,1.62315619,120,0,0,1,0,0,0),
+(@GUID+14,30740,571,1,0x00000080,0,0,5265.28,3010.10083,408.895782,2.82743335,120,0,0,1,0,0,0),
+(@GUID+15,30740,571,1,0x00000080,0,0,5265.47559,3017.39941,408.582977,3.07177949,120,0,0,1,0,0,0),
+(@GUID+16,30740,571,1,0x00000080,0,0,5367.91455,2826.52026,409.3225,3.33357882,120,0,0,1,0,0,0),
+(@GUID+17,30740,571,1,0x00000080,0,0,5368.71338,2856.36035,409.3225,2.94960642,120,0,0,1,0,0,0),
+(@GUID+18,30740,571,1,0x00000080,0,0,5388.56,2834.76782,418.7585,3.07177949,120,0,0,1,0,0,0),
+(@GUID+19,30740,571,1,0x00000080,0,0,5389.272,2847.36816,418.7585,3.106686,120,0,0,1,0,0,0),
+(@GUID+20,30740,571,1,0x00000080,0,0,4684.475,2414.28979,369.9621,-2.85779858,120,0,0,1,0,0,0),
+(@GUID+21,30740,571,1,0x00000080,0,0,4692.75635,2392.88574,369.0177,-2.82921553,120,0,0,1,0,0,0),
+(@GUID+22,30740,571,1,0x00000080,0,0,5327.264648,2659.455322,409.178711,3.069901,120,0,0,1,0,0,0), -- F1307814000A2DAD path
+(@GUID+23,30740,571,1,0x00000080,0,0,5154.225586,2833.824219,409.262451,3.124139,120,0,0,1,0,0,0),
+(@GUID+24,30740,571,1,0x00000080,0,0,5154.119629,2847.892822,409.247559,3.071779,120,0,0,1,0,0,0),
+(@GUID+25,30740,571,1,0x00000080,0,0,5179.111328,2837.129639,409.274658,3.211406,120,0,0,1,0,0,0),
+(@GUID+26,30740,571,1,0x00000080,0,0,5179.666504,2846.597900,409.274658,3.089233,120,0,0,1,0,0,0),
+(@GUID+27,30740,571,1,0x00000080,0,0,5270.163086,2833.479248,409.274658,3.124139,120,0,0,1,0,0,0),
+(@GUID+28,30740,571,1,0x00000080,0,0,5270.057129,2847.547607,409.274658,3.071779,120,0,0,1,0,0,0),
+(@GUID+29,30740,571,1,0x00000080,0,0,5307.750000,3008.872559,409.193024,4.781681,120,0,0,1,0,0,0), -- F1307814000A43AE path
+(@GUID+30,30740,571,1,0x00000080,0,0,5335.117188,2916.802002,409.443756,1.500983,120,0,0,1,0,0,0),
+(@GUID+31,30740,571,1,0x00000080,0,0,5350.681152,2917.011719,409.274658,1.466077,120,0,0,1,0,0,0),
+(@GUID+32,30740,571,1,0x00000080,0,0,5335.306152,2764.110352,409.274567,4.834562,120,0,0,1,0,0,0),
+(@GUID+33,30740,571,1,0x00000080,0,0,5349.811523,2763.634766,409.333374,4.660029,120,0,0,1,0,0,0),
+-- -- Eastspark Workshop
+(@GUID+34,30740,571,1,0x00000080,0,0,4349.537,2411.25781,374.743317,2.05948853,120,0,0,1,0,0,0),
+(@GUID+35,30740,571,1,0x00000080,0,0,4388.13135,2411.97827,374.743317,1.6406095,120,0,0,1,0,0,0),
+(@GUID+36,30740,571,1,0x00000080,0,0,4391.6665,2300.60913,374.7433,4.92182827,120,0,0,1,0,0,0),
+(@GUID+37,30740,571,1,0x00000080,0,0,4413.42969,2393.44946,376.3599,1.06465089,120,0,0,1,0,0,0),
+(@GUID+38,30740,571,1,0x00000080,0,0,4417.92,2331.237,370.9189,5.846853,120,0,0,1,0,0,0),
+(@GUID+39,30740,571,1,0x00000080,0,0,4349.11768,2299.27954,374.7433,4.904375,120,0,0,1,0,0,0),
+(@GUID+40,30740,571,1,0x00000080,0,0,4418.608,2355.28735,372.4907,6.02138567,120,0,0,1,0,0,0);
+
+-- banners
+SET @OGUID := 281000;
+DELETE FROM `gameobject` WHERE `id` IN (192269,192284,192285,192338,192339,192488,192254,192255,192336,192501,192502);
+DELETE FROM `gameobject` WHERE `id` BETWEEN 192349 AND 192379;
+DELETE FROM `gameobject` WHERE `guid` BETWEEN @OGUID AND @OGUID+115;
+INSERT INTO `gameobject` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`position_x`,`position_y`,`position_z`,`orientation`,`rotation0`,`rotation1`,`rotation2`,`rotation3`,`spawntimesecs`,`animprogress`,`state`) VALUES
+-- Fortress Banners "Alliance"
+(@OGUID+0,192286,571,1,128,5371.44873,2820.79346,409.426575,3.124123,0,0,0,0,120,0,1),
+(@OGUID+1,192287,571,1,128,5372.42432,2862.47925,409.3659,3.14159274,0,0,0,0,120,0,1),
+(@OGUID+2,192292,571,1,128,5154.35059,2862.08423,445.0105,3.14159274,0,0,0,0,120,0,1),
+(@OGUID+3,192299,571,1,128,5155.21631,2820.63013,444.9789,-3.115388,0,0,0,0,120,0,1),
+(@OGUID+4,192304,571,1,128,5398.03564,2873.013,455.203552,3.132858,0,0,0,0,120,0,1),
+(@OGUID+5,192305,571,1,128,5397.31348,2809.264,455.101624,3.132858,0,0,0,0,120,0,1),
+(@OGUID+6,192306,571,1,128,5270.55469,2861.68237,444.917236,-3.124123,0,0,0,0,120,0,1),
+(@OGUID+7,192307,571,1,128,5271.16064,2820.10864,445.109,-3.132858,0,0,0,0,120,0,1),
+(@OGUID+8,192308,571,1,128,5235.12744,2942.12329,444.2792,1.58824873,0,0,0,0,120,0,1),
+(@OGUID+9,192309,571,1,128,5272.549,2976.54175,444.493,3.132858,0,0,0,0,120,0,1),
+(@OGUID+10,192310,571,1,128,5352.19775,3055.0166,444.5646,1.57952213,0,0,0,0,120,0,1),
+(@OGUID+11,192312,571,1,128,5236.315,2739.21533,444.992828,-1.60570168,0,0,0,0,120,0,1),
+(@OGUID+12,192313,571,1,128,5271.634,2704.829,445.182617,-3.124123,0,0,0,0,120,0,1),
+(@OGUID+13,192314,571,1,128,5350.905,2622.48,444.649323,-1.56206989,0,0,0,0,120,0,1),
+(@OGUID+14,192316,571,1,128,5322.013,2781.13281,435.6727,1.57952213,0,0,0,0,120,0,1),
+(@OGUID+15,192317,571,1,128,5363.387,2781.27856,435.634125,1.58824873,0,0,0,0,120,0,1),
+(@OGUID+16,192318,571,1,128,5322.24854,2898.94629,435.642975,-1.57952213,0,0,0,0,120,0,1),
+(@OGUID+17,192319,571,1,128,5364.30371,2899.216,435.690826,-1.55334139,0,0,0,0,120,0,1),
+(@OGUID+18,192320,571,1,128,5289.048,2820.22656,435.6738,0,0,0,0,0,120,0,1),
+(@OGUID+19,192321,571,1,128,5288.847,2861.82128,435.590485,0.0261791088,0,0,0,0,120,0,1),
+(@OGUID+20,192322,571,1,128,5322.89258,2917.14233,445.1543,1.56206989,0,0,0,0,120,0,1),
+(@OGUID+21,192323,571,1,128,5364.283,2917.264,445.332184,1.58824611,0,0,0,0,120,0,1),
+(@OGUID+22,192324,571,1,128,5290.514,2976.56177,435.087463,0.008724241,0,0,0,0,120,0,1),
+(@OGUID+23,192325,571,1,128,5352.37744,3036.95483,435.111053,-1.56206989,0,0,0,0,120,0,1),
+(@OGUID+24,192326,571,1,128,5392.64063,3036.967,433.648682,-1.51843357,0,0,0,0,120,0,1),
+(@OGUID+25,192327,571,1,128,5172.336,2862.57544,435.65802,0,0,0,0,0,120,0,1),
+(@OGUID+26,192328,571,1,128,5173.12842,2820.95654,435.657623,0.0261791088,0,0,0,0,120,0,1),
+(@OGUID+27,192329,571,1,128,5235.32227,2924.31079,434.8981,-1.56206989,0,0,0,0,120,0,1),
+(@OGUID+28,192330,571,1,128,5237.02344,2757.35669,435.625641,1.55334139,0,0,0,0,120,0,1),
+(@OGUID+29,192331,571,1,128,5289.78125,2704.62158,435.714325,0.008724241,0,0,0,0,120,0,1),
+(@OGUID+30,192332,571,1,128,5350.93945,2640.43066,435.2642,1.56206989,0,0,0,0,120,0,1),
+(@OGUID+31,192333,571,1,128,5392.28027,2639.84033,435.207916,1.52716041,0,0,0,0,120,0,1),
+(@OGUID+32,192334,571,1,128,5322.17041,2763.20142,444.9744,-1.56206715,0,0,0,0,120,0,1),
+(@OGUID+33,192335,571,1,128,5363.71631,2763.24731,445.023132,-1.54461551,0,0,0,0,120,0,1),
+(@OGUID+34,192487,571,1,128,5145.11133,2934.948,433.254852,-3.10665226,0,0,0,0,120,0,1),
+(@OGUID+35,192487,571,1,128,5146.04443,2747.30249,433.527039,3.124123,0,0,0,0,120,0,1),
+(@OGUID+36,192487,571,1,128,5158.71,2882.90161,431.27417,3.14159274,0,0,0,0,120,0,1),
+(@OGUID+37,192487,571,1,128,5160.28369,2798.59766,430.6037,-3.124123,0,0,0,0,120,0,1),
+(@OGUID+38,192487,571,1,128,5162.90674,2952.59766,433.368,1.57079577,0,0,0,0,120,0,1),
+(@OGUID+39,192487,571,1,128,5163.85,2729.677,433.327545,-1.60570168,0,0,0,0,120,0,1),
+(@OGUID+40,192487,571,1,128,5260.82471,2631.81763,433.181061,3.124123,0,0,0,0,120,0,1),
+(@OGUID+41,192487,571,1,128,5262.544,3047.93018,431.96524,3.124123,0,0,0,0,120,0,1),
+(@OGUID+42,192487,571,1,128,5278.43066,2613.83276,433.294434,-1.62315571,0,0,0,0,120,0,1),
+(@OGUID+43,192487,571,1,128,5280.894,3064.95386,431.9758,1.55334139,0,0,0,0,120,0,1),
+-- Fortress Banners "Horde"
+(@OGUID+44,192269,571,1,64,4526.46,2810.18,391.2,-2.99322,0,0,0,1,180,0,1),
+(@OGUID+45,192284,571,1,64,5372.48,2862.5,409.049,3.14159,0,0,0,1,180,0,1),
+(@OGUID+46,192285,571,1,64,5371.49,2820.8,409.177,3.14159,0,0,0,1,180,0,1),
+(@OGUID+47,192338,571,1,64,5397.76,2873.08,455.461,3.10665,0,0,0,1,180,0,1),
+(@OGUID+48,192339,571,1,64,5397.39,2809.33,455.344,3.10665,0,0,0,1,180,0,1),
+(@OGUID+49,192349,571,1,64,5155.31,2820.74,444.979,-3.13286,0,0,0,1,180,0,1),
+(@OGUID+50,192350,571,1,64,5270.69,2861.78,445.058,-3.11539,0,0,0,1,180,0,1),
+(@OGUID+51,192351,571,1,64,5271.28,2820.16,445.201,-3.13286,0,0,0,1,180,0,1),
+(@OGUID+52,192352,571,1,64,5173.02,2820.93,435.72,0.017452,0,0,0,1,180,0,1),
+(@OGUID+53,192353,571,1,64,5172.11,2862.57,435.721,0.017452,0,0,0,1,180,0,1),
+(@OGUID+54,192354,571,1,64,5288.41,2861.79,435.721,0.017452,0,0,0,1,180,0,1),
+(@OGUID+55,192355,571,1,64,5288.92,2820.22,435.721,0.017452,0,0,0,1,180,0,1),
+(@OGUID+56,192356,571,1,64,5237.07,2757.03,435.796,1.51844,0,0,0,1,180,0,1),
+(@OGUID+57,192357,571,1,64,5235.34,2924.34,435.04,-1.5708,0,0,0,1,180,0,1),
+(@OGUID+58,192358,571,1,64,5322.23,2899.43,435.808,-1.58825,0,0,0,1,180,0,1),
+(@OGUID+59,192359,571,1,64,5364.35,2899.4,435.839,-1.5708,0,0,0,1,180,0,1),
+(@OGUID+60,192360,571,1,64,5352.37,3037.09,435.252,-1.5708,0,0,0,1,180,0,1),
+(@OGUID+61,192361,571,1,64,5392.65,3037.11,433.713,-1.52716,0,0,0,1,180,0,1),
+(@OGUID+62,192362,571,1,64,5322.12,2763.61,444.974,-1.55334,0,0,0,1,180,0,1),
+(@OGUID+63,192363,571,1,64,5363.61,2763.39,445.024,-1.54462,0,0,0,1,180,0,1),
+(@OGUID+64,192364,571,1,64,5350.88,2622.72,444.686,-1.5708,0,0,0,1,180,0,1),
+(@OGUID+65,192366,571,1,64,5236.27,2739.46,444.992,-1.59698,0,0,0,1,180,0,1),
+(@OGUID+66,192367,571,1,64,5271.8,2704.87,445.183,-3.13286,0,0,0,1,180,0,1),
+(@OGUID+67,192368,571,1,64,5289.46,2704.68,435.875,-0.017451,0,0,0,1,180,0,1),
+(@OGUID+68,192369,571,1,64,5350.95,2640.36,435.408,1.5708,0,0,0,1,180,0,1),
+(@OGUID+69,192370,571,1,64,5392.27,2639.74,435.331,1.50971,0,0,0,1,180,0,1),
+(@OGUID+70,192371,571,1,64,5364.29,2916.94,445.331,1.57952,0,0,0,1,180,0,1),
+(@OGUID+71,192372,571,1,64,5322.86,2916.95,445.154,1.56207,0,0,0,1,180,0,1),
+(@OGUID+72,192373,571,1,64,5290.35,2976.56,435.221,0.017452,0,0,0,1,180,0,1),
+(@OGUID+73,192374,571,1,64,5272.94,2976.55,444.492,3.12412,0,0,0,1,180,0,1),
+(@OGUID+74,192375,571,1,64,5235.19,2941.9,444.278,1.58825,0,0,0,1,180,0,1),
+(@OGUID+75,192376,571,1,64,5352.19775,3055.0166,444.5646,1.57952,0,0,0,0,120,0,1),
+(@OGUID+76,192377,571,1,64,5414.19,3069.8,415.187,1.64061,0,0,0,1,180,0,1),
+(@OGUID+77,192378,571,1,64,5322.02,2781.13,435.811,1.5708,0,0,0,1,180,0,1),
+(@OGUID+78,192379,571,1,64,5363.42,2781.03,435.763,1.5708,0,0,0,1,180,0,1),
+(@OGUID+79,192254,571,1,64,5154.46,2828.94,409.189,3.14159,0,0,0,1,180,0,1),
+(@OGUID+80,192255,571,1,64,5154.52,2853.31,409.183,3.14159,0,0,0,1,180,0,1),
+(@OGUID+81,192336,571,1,64,5154.49,2862.15,445.012,3.14159,0,0,0,1,180,0,1),
+(@OGUID+82,192488,571,1,64,5160.34,2798.61,430.769,3.14159,0,0,0,1,180,0,1),
+(@OGUID+83,192488,571,1,64,5158.81,2883.13,431.618,3.14159,0,0,0,1,180,0,1),
+(@OGUID+84,192488,571,1,64,5278.38,2613.83,433.409,-1.58825,0,0,0,1,180,0,1),
+(@OGUID+85,192488,571,1,64,5260.82,2631.8,433.324,3.05433,0,0,0,1,180,0,1),
+(@OGUID+86,192488,571,1,64,5163.13,2952.59,433.503,1.53589,0,0,0,1,180,0,1),
+(@OGUID+87,192488,571,1,64,5145.11,2935,433.386,3.14159,0,0,0,1,180,0,1),
+(@OGUID+88,192488,571,1,64,5262.54,3047.95,432.055,3.10665,0,0,0,1,180,0,1),
+(@OGUID+89,192488,571,1,64,5146.04,2747.21,433.584,3.07177,0,0,0,1,180,0,1),
+(@OGUID+90,192488,571,1,64,5163.78,2729.68,433.394,-1.58825,0,0,0,1,180,0,1),
+(@OGUID+91,192488,571,1,64,5280.894,3064.95386,431.9758,1.55334139,0,0,0,0,120,0,1),
+-- Tower Banners "Alliance"
+(@OGUID+92,192501,571,1,64,4398.82,2804.7,429.792,-1.58825,0,0,0,1,180,0,1),
+(@OGUID+93,192501,571,1,64,4416,2822.67,429.851,-0.017452,0,0,0,1,180,0,1),
+(@OGUID+94,192501,571,1,64,4559.11,3606.22,419.999,-1.48353,0,0,0,1,180,0,1),
+(@OGUID+95,192501,571,1,64,4539.42,3622.49,420.034,-3.07177,0,0,0,1,180,0,1),
+(@OGUID+96,192501,571,1,64,4555.26,3641.65,419.974,1.67551,0,0,0,1,180,0,1),
+(@OGUID+97,192501,571,1,64,4574.87,3625.91,420.079,0.087266,0,0,0,1,180,0,1),
+(@OGUID+98,192501,571,1,64,4466.79,1960.42,459.144,1.15192,0,0,0,1,180,0,1),
+(@OGUID+99,192501,571,1,64,4475.35,1937.03,459.07,-0.436332,0,0,0,1,180,0,1),
+(@OGUID+100,192501,571,1,64,4451.76,1928.1,459.076,-2.00713,0,0,0,1,180,0,1),
+(@OGUID+101,192501,571,1,64,4442.99,1951.9,459.093,2.74016,0,0,0,1,180,0,1),
+(@OGUID+102,192501,571,1,64,4380.36328,2822.38013,429.8818,-3.106652,0,0,0,0,120,0,1),
+(@OGUID+103,192501,571,1,64,4397.6626,2840.299,429.921661,1.58824873,0,0,0,0,120,0,1),
+-- Tower Banners "Horde"
+(@OGUID+104,192502,571,1,128,4398.82,2804.7,429.792,-1.58825,0,0,0,1,180,0,1),
+(@OGUID+105,192502,571,1,128,4416,2822.67,429.851,-0.017452,0,0,0,1,180,0,1),
+(@OGUID+106,192502,571,1,128,4559.11,3606.22,419.999,-1.48353,0,0,0,1,180,0,1),
+(@OGUID+107,192502,571,1,128,4539.42,3622.49,420.034,-3.07177,0,0,0,1,180,0,1),
+(@OGUID+108,192502,571,1,128,4555.26,3641.65,419.974,1.67551,0,0,0,1,180,0,1),
+(@OGUID+109,192502,571,1,128,4574.87,3625.91,420.079,0.087266,0,0,0,1,180,0,1),
+(@OGUID+110,192502,571,1,128,4466.79,1960.42,459.144,1.15192,0,0,0,1,180,0,1),
+(@OGUID+111,192502,571,1,128,4475.35,1937.03,459.07,-0.436332,0,0,0,1,180,0,1),
+(@OGUID+112,192502,571,1,128,4451.76,1928.1,459.076,-2.00713,0,0,0,1,180,0,1),
+(@OGUID+113,192502,571,1,128,4442.99,1951.9,459.093,2.74016,0,0,0,1,180,0,1),
+(@OGUID+114,192502,571,1,128,4380.36328,2822.38013,429.8818,-3.106652,0,0,0,0,120,0,1),
+(@OGUID+115,192502,571,1,128,4397.6626,2840.299,429.921661,1.58824873,0,0,0,0,120,0,1);
+
+SET @OGUID := 280000;
+DELETE FROM `gameobject` WHERE `id` IN (192458,192459,192460,192461,192289,192290,192434,192435,192280,192283,192425,192426,192427,192428,192288,192291);
+INSERT INTO `gameobject` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`position_x`,`position_y`,`position_z`,`orientation`,`rotation0`,`rotation1`,`rotation2`,`rotation3`,`spawntimesecs`,`animprogress`,`state`) VALUES
+-- The Sunken Ring "Horde"
+(@OGUID+0,192458,571,1,16,4811.4,2441.9,358.207,-2.0333,0,0,0,1,180,0,1),
+(@OGUID+1,192459,571,1,16,4805.67,2407.48,358.191,1.78023,0,0,0,1,180,0,1),
+(@OGUID+2,192460,571,1,16,5004.35,2486.36,358.449,2.17294,0,0,0,1,180,0,1),
+(@OGUID+3,192461,571,1,16,4983.28,2503.09,358.177,-0.427603,0,0,0,1,180,0,1),
+(@OGUID+4,192289,571,1,16,4778.19,2438.06,345.644,-2.94088,0,0,0,1,180,0,1),
+(@OGUID+5,192290,571,1,16,5024.57,2532.75,344.023,-1.93732,0,0,0,1,180,0,1),
+-- The Sunken Ring "Alliance"
+(@OGUID+6,192425,571,1,32,4811.435,2441.84546,357.982483,-2.02457881,0,0,0,0,120,0,1),
+(@OGUID+7,192426,571,1,32,4805.514,2407.84375,357.940765,1.7715075,0,0,0,0,120,0,1),
+(@OGUID+8,192427,571,1,32,5004.35,2486.36,358.449,2.17294,0,0,0,1,180,0,1),
+(@OGUID+9,192428,571,1,32,4983.221,2503.27271,357.959534,-0.43633157,0,0,0,0,120,0,1),
+(@OGUID+10,192288,571,1,32,4778.065,2438.02441,345.7063,-2.932139,0,0,0,0,120,0,1),
+(@OGUID+11,192291,571,1,32,5024.608,2532.72583,344.4308,-1.94604158,0,0,0,0,120,0,1),
+-- The Broken Temple "Horde"
+(@OGUID+12,192434,571,1,16,5041.61,3294.4,382.15,-1.63188,0,0,0,1,180,0,1),
+(@OGUID+13,192435,571,1,16,4855.63,3297.62,376.739,-3.13286,0,0,0,1,180,0,1),
+(@OGUID+14,192280,571,1,16,4857.97,3335.44,368.881,-2.94959,0,0,0,1,180,0,1),
+(@OGUID+15,192283,571,1,16,5006.34,3280.4,371.163,2.22529,0,0,0,1,180,0,1),
+-- The Broken Temple "Alliance"
+(@OGUID+16,192400,571,1,32,5041.650879,3294.318604,381.919952,-1.605702,0,0,0,1,180,0,1),
+(@OGUID+17,192401,571,1,32,4855.444336,3297.600830,376.495758,-3.115388,0,0,0,1,180,0,1),
+(@OGUID+18,192281,571,1,32,4857.971191,3335.415771,369.291901,-2.888511,0,0,0,1,180,0,1),
+(@OGUID+19,192282,571,1,32,5006.322754,3280.362061,371.242249,2.242746,0,0,0,1,180,0,1);
+
+-- EVERYTHING UNDER HERE IS WIP
+
+-- Eastspark Workshop "Horde"
+(@OGUID+20,192452,571,1,16,4416.7993,2414.0383,377.4869,0.0087,0,0,0,0,120,0,1),
+-- Eastspark Workshop "Alliance"
+(@OGUID+21,192416,571,1,32,4408.57,2422.61,377.179,1.58825,0,0,0,1,180,0,1),
+(@OGUID+22,192417,571,1,32,4416.59,2414.08,377.196,0,0,0,0,1,180,0,1),
+(@OGUID+23,192418,571,1,32,4417.25,2301.14,377.214,0.026179,0,0,0,1,180,0,1),
+(@OGUID+24,192273,571,1,32,4417.94,2324.81,371.577,3.08051,0,0,0,1,180,0,1),
+-- Westspark Workshop "Horde"
+
+-- Westspark Workshop "Alliance"
+(@OGUID+25,192274,571,1,32,4424.15,3286.54,371.546,3.12412,0,0,0,1,180,0,1),
+(@OGUID+26,192406,571,1,32,4438.3,3361.08,371.568,-0.017451,0,0,0,1,180,0,1),
+(@OGUID+27,192407,571,1,32,4448.17,3235.63,370.412,-1.56207,0,0,0,1,180,0,1),
+(@OGUID+28,192433,571,1,32,4401.63,3377.46,363.365,1.55334,0,0,0,1,180,0,1),
+
+-- *** in progress zone horde banner in phase 128 + 32
+
+-- Winters Edge tower alliance
+(192429,571,1,64,4464.123535 2855.453125 406.110596,0.829032,0,0,0,0,120,0,1);
+(192430,571,1,64,4434.555664,2883.448730,406.025299,0.759217,0,0,0,0,120,0,1);
+(192431,571,1,64,4349.900391,2885.561768,406.104889,1.605702,0,0,0,0,120,0,1);
+(192414,571,1,64,4387.621582 2719.565918 389.935120,-1.544616,0,0,0,0,120,0,1);
+-- Winters Edge tower horde
+(192442,571,1,128,4350.039,2885.61377,406.3287,1.58824873,0,0,0,0,120,0,1);
+(192443,571,1,128,4434.32568,2883.244,406.3456,0.767943859,0,0,0,0,120,0,1);
+(192444,571,1,128,4464.17432,2855.3186,406.390961,0.802850962,0,0,0,0,120,0,1);
+(192450,571,1,128,4387.59033,2719.90015,390.200531,-1.51843357,0,0,0,0,120,0,1);
+
+(192449,571,1,129,4517.75342,2717.231,387.811981,-1.53588688,0,0,0,0,120,0,1);
+(192424,571,1,417,4563.70166,2171.03125,367.607056,-1.82386875,0,0,0,0,120,0,1),
+(192626,571,1,65,4938.364,2454.59863,320.391785,-2.513274,0,0,0,0,120,0,1);
+(192627,571,1,65,4939.48535,3339.65259,376.874939,0.890116632,0,0,0,0,120,0,1);
+
+192271 4424.741211 2975.604980 367.226807 1.701696 -- banner pole shawdowsight
+
+
+-- Misc objects in fortress phased properly
+SET @OGUID := 282000;
+DELETE FROM `gameobject` WHERE `guid` IN (67165,67224,67222,67190,67195,67216,67193,67182,67186,67192,67161,67164,67180,67187);
+DELETE FROM `gameobject` WHERE `guid` BETWEEN @OGUID AND @OGUID+55;
+INSERT INTO `gameobject` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`position_x`,`position_y`,`position_z`,`orientation`,`rotation0`,`rotation1`,`rotation2`,`rotation3`,`spawntimesecs`,`animprogress`,`state`) VALUES
+(@OGUID+0,193096,571,1,128,5379.885,3008.093,409.181915,-3.124123,0,0,0,0,120,0,1),
+(@OGUID+1,193097,571,1,128,5381.73975,3008.15454,409.181915,2.98449826,0,0,0,0,120,0,1),
+(@OGUID+2,193098,571,1,128,5383.672,3008.02783,409.181915,-3.115388,0,0,0,0,120,0,1),
+(@OGUID+3,193099,571,1,128,5386.25342,3007.79614,409.181915,2.932139,0,0,0,0,120,0,1),
+(@OGUID+4,193100,571,1,128,5387.354,3009.64941,409.181915,-1.30899549,0,0,0,0,120,0,1),
+(@OGUID+5,193101,571,1,128,5381.12744,3010.09717,409.181915,-2.72271276,0,0,0,0,120,0,1),
+(@OGUID+6,193102,571,1,128,5383.12061,3007.90967,410.8231,-2.530723,0,0,0,0,120,0,1),
+(@OGUID+7,193103,571,1,128,5381.105,3007.89575,410.8231,-3.09791875,0,0,0,0,120,0,1),
+(@OGUID+8,193104,571,1,128,5376.777,3010.619,409.191742,-2.60926127,0,0,0,0,120,0,1),
+(@OGUID+9,193105,571,1,128,5381.47559,3010.24731,410.8231,-2.80997539,0,0,0,0,120,0,1),
+(@OGUID+10,193106,571,1,128,5381.059,3009.85864,410.8231,2.66161919,0,0,0,0,120,0,1),
+(@OGUID+11,193107,571,1,128,5381.038,3010.44263,410.8157,-2.0507617,0,0,0,0,120,0,1),
+(@OGUID+12,193108,571,1,128,5379.83154,3007.82373,410.8161,-2.02457881,0,0,0,0,120,0,1),
+(@OGUID+13,193109,571,1,128,5379.99463,3008.40356,410.815918,-3.03687477,0,0,0,0,120,0,1),
+(@OGUID+14,193124,571,1,128,5293.65869,2924.44019,409.29306,1.20427489,0,0,0,0,120,0,1),
+(@OGUID+15,193125,571,1,1,5293.28,2932.32813,409.065247,-2.49581814,0,0,0,0,120,0,1),
+(@OGUID+16,193126,571,1,1,5292.30469,2930.5105,409.157135,-3.06302428,0,0,0,0,120,0,1),
+(@OGUID+17,193127,571,1,64,5293.349,2923.712,409.844757,-1.8762306,0,0,0,0,120,0,1),
+(@OGUID+18,193128,571,1,128,5293.12256,2895.22754,409.208771,-0.9861096,0,0,0,0,120,0,1),
+(@OGUID+19,193129,571,1,128,5292.913,2895.54346,410.419617,-0.122171074,0,0,0,0,120,0,1),
+(@OGUID+20,193130,571,1,128,5294.09473,2894.191,409.164063,-0.7330382,0,0,0,0,120,0,1),
+(@OGUID+21,193131,571,1,128,5295.1875,2895.382,409.143219,-0.349065244,0,0,0,0,120,0,1),
+(@OGUID+22,193132,571,1,128,5294.527,2895.57471,410.6591,-1.92858779,0,0,0,0,120,0,1),
+(@OGUID+23,193133,571,1,128,5295.3916,2895.05737,410.6686,0.6894028,0,0,0,0,120,0,1),
+(@OGUID+24,193134,571,1,128,5295.13525,2895.68481,410.618866,-2.22529364,0,0,0,0,120,0,1),
+(@OGUID+25,193135,571,1,128,5294.97559,2895.33521,410.657684,-2.73143482,0,0,0,0,120,0,1),
+(@OGUID+26,193136,571,1,128,5293.22559,2895.46436,410.413483,-0.802850962,0,0,0,0,120,0,1),
+(@OGUID+27,193137,571,1,128,5295.56,2895.24146,410.628052,-2.11184788,0,0,0,0,120,0,1),
+(@OGUID+28,193138,571,1,128,5293.741,2894.48169,409.183167,-2.72271276,0,0,0,0,120,0,1),
+(@OGUID+29,193139,571,1,64,5294.599,2786.85254,409.8877,-2.356195,0,0,0,0,120,0,1),
+(@OGUID+30,193140,571,1,64,5294.37939,2785.03833,409.175018,-2.33873963,0,0,0,0,120,0,1),
+(@OGUID+31,193141,571,1,64,5293.205,2787.03052,409.218872,3.03687477,0,0,0,0,120,0,1),
+(@OGUID+32,193142,571,1,64,5294.241,2786.42456,409.174347,0.0174524616,0,0,0,0,120,0,1),
+(@OGUID+33,193143,571,1,64,5291.705,2785.86646,409.282135,-2.03330517,0,0,0,0,120,0,1),
+(@OGUID+34,193144,571,1,64,5293.03369,2785.632,409.22522,-1.2915417,0,0,0,0,120,0,1),
+(@OGUID+35,193145,571,1,64,5295.866,2787.7666,409.1923,2.155478,0,0,0,0,120,0,1),
+(@OGUID+36,193146,571,1,64,5293.56445,2787.31079,410.55954,0.261798173,0,0,0,0,120,0,1),
+(@OGUID+37,193147,571,1,128,5233.12061,2920.362,409.163544,-0.7243115,0,0,0,0,120,0,1),
+(@OGUID+38,193148,571,1,128,5238.27539,2920.67358,409.256439,-0.418878615,0,0,0,0,120,0,1),
+(@OGUID+39,193149,571,1,128,5235.902,2920.751,409.224457,-0.951203167,0,0,0,0,120,0,1),
+(@OGUID+40,193150,571,1,128,5237.36963,2919.89771,409.556641,0.8202983,0,0,0,0,120,0,1),
+(@OGUID+41,193151,571,1,128,5234.19775,2918.99731,409.322754,-2.33873963,0,0,0,0,120,0,1),
+(@OGUID+42,193152,571,1,128,5234.52344,2921.76221,409.175781,-2.2165668,0,0,0,0,120,0,1),
+(@OGUID+43,193153,571,1,128,5234.119,2918.93921,409.1339,-3.098036,0,0,0,0,120,0,1),
+(@OGUID+44,193154,571,1,128,5234.26758,2919.40015,409.502869,-2.18166113,0,0,0,0,120,0,1),
+(@OGUID+45,193155,571,1,128,5293.37939,2746.05566,409.22052,-0.06981169,0,0,0,0,120,0,1),
+(@OGUID+46,193156,571,1,128,5293.65039,2755.67529,409.1913,-0.43633157,0,0,0,0,120,0,1),
+(@OGUID+47,193157,571,1,128,5292.23535,2753.59473,409.0867,-0.357789934,0,0,0,0,120,0,1),
+(@OGUID+48,193158,571,1,128,5292.42969,2748.62427,409.131042,0.253072351,0,0,0,0,120,0,1),
+(@OGUID+49,193159,571,1,128,5293.384,2750.90283,409.234924,-0.0610866137,0,0,0,0,120,0,1),
+(@OGUID+50,193160,571,1,64,5371.89746,2805.47583,409.3072,0.0610866137,0,0,0,0,120,0,1),
+(@OGUID+51,193161,571,1,64,5376.616,2875.105,409.254822,1.59697616,0,0,0,0,120,0,1),
+(@OGUID+52,193162,571,1,128,5377.54932,2870.92456,409.239166,-0.549776852,0,0,0,0,120,0,1),
+(@OGUID+53,193163,571,1,128,5378.068,2813.61719,409.239166,1.55334139,0,0,0,0,120,0,1),
+(@OGUID+54,193164,571,1,128,5378.921,2805.43677,409.239166,1.53588688,0,0,0,0,120,0,1),
+(@OGUID+55,193165,571,1,128,5378.452,2876.67456,409.239166,1.54461825,0,0,0,0,120,0,1);
+
diff --git a/sql/updates/world_WinterGrasp.sql b/sql/updates/world_WinterGrasp.sql
new file mode 100644
index 00000000000..0433c4b8b17
--- /dev/null
+++ b/sql/updates/world_WinterGrasp.sql
@@ -0,0 +1,341 @@
+-- Unused yet:
+-- Wintergrasp is under attack!
+-- Wintergrasp Fortress is under attack!
+-- Winter's Edge Tower is under attack!
+-- Eastern Bridge is under attack!
+-- Western Bridge is under attack!
+-- Westspark Bridge is under attack!
+-- Flamewatch Tower is under attack!
+
+-- 'You have reached Rank 1: Corporal' Sent to player by raid leader
+-- 'You have reached Rank 2: First Lieutenant' Sent to player by raid leader
+
+-- Wintergrasp coreside texts
+DELETE FROM trinity_string WHERE entry BETWEEN 12050 AND 12072;
+INSERT INTO `trinity_string` (`entry`,`content_default`,`content_loc1`,`content_loc2`,`content_loc3`,`content_loc4`,`content_loc5`,`content_loc6`,`content_loc7`,`content_loc8`)VALUES
+(12050, '%s has been captured by %s ', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+(12051, '%s is under attack by %s', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+(12052, 'The Broken Temple siege workshop', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+(12053, 'Eastspark siege workshop', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+(12054, 'Westspark siege workshop', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+(12055, 'The Sunken Ring siege workshop', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+(12057, 'Alliance', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+(12056, 'Horde', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+(12058, 'The battle for Wintergrasp is about to begin!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+(12059, 'You have reached Rank 1: Corporal', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+(12060, 'You have reached Rank 2: First Lieutenant', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+(12061, 'The south-eastern keep tower', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+(12062, 'The north-eastern keep tower', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+(12063, 'The south-western keep tower', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+(12064, 'The north-western keep tower', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+(12065, '%s has been damaged !', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+(12066, '%s has been destroyed!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+(12067, 'The battle for Wintergrasp begin!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+(12068, '%s has successfully defended the Wintergrasp fortress!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+(12069, 'The southern tower', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+(12070, 'The eastern tower', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+(12071, 'The western tower', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+(12072, 'The Wintergrasp fortress has been captured by %s !', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+
+-- Wintergrasp script texts
+DELETE FROM `script_texts` WHERE entry BETWEEN -1850500 AND -1850507;
+INSERT INTO `script_texts` (`npc_entry`,`entry`,`content_default`,`content_loc1`,`content_loc2`,`content_loc3`,`content_loc4`,`content_loc5`,`content_loc6`,`content_loc7`,`content_loc8`,`sound`,`type`,`language`,`emote`,`comment`)VALUES
+(0, -1850500, 'Guide me to the Fortress Graveyard.', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, ''),
+(0, -1850501, 'Guide me to the Sunken Ring Graveyard.', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, ''),
+(0, -1850502, 'Guide me to the Broken Temple Graveyard.', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, ''),
+(0, -1850503, 'Guide me to the Westspark Graveyard.', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, ''),
+(0, -1850504, 'Guide me to the Eastspark Graveyard.', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, ''),
+(0, -1850505, 'Guide me back to the Horde landing camp.', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, ''),
+(0, -1850506, 'Guide me back to the Alliance landing camp.', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, ''),
+(0, -1850507, 'Se mettre dans la file pour le Joug-d''hiver.', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, ''); -- (Needs proper english text)
+
+-- Wintergrasp queue template NPCs
+UPDATE `creature_template` SET `ScriptName`= 'npc_wg_dalaran_queue' WHERE `entry` IN (32169,32170,35599,35596,35600,35601,35598,35603,35602,35597,35612,35611);
+
+-- 54640 Teleport (Teleports defenders behind the walls on the Isle of Ulduran, Strand of the Ancients) - FIX THIS?
+DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=54640;
+INSERT INTO `spell_linked_spell` (`spell_trigger`,`spell_effect`,`type`,`comment`) VALUES (54640,54643,0, 'WG teleporter');
+
+-- ???
+DELETE FROM `gameobject` WHERE `id` IN (194162,192951,192273,192274,192277,192280,192283,192289,192290,192338,192339,192406,192407,192414,192417,192418,192429,192433,192434,192435,192458,192459,192460,192461,192819,190475,190487,194959,194962,192829,190219,190220,191795,191796,191799,191800,191801,191802,191803,191804,191806,191807,191808,191809,190369,190370,190371,190372,190374,190376,190221,190373,190377,190378,191797,191798,191805,190356,190357,190358,190375,191810, 192488,192501,192374,192416,192375,192336,192255,192269,192254,192349,192366,192367,192364,192370,192369,192368,192362,192363,192379,192378,192355,192354,192358,192359,192284,192285,192371,192372,192373,192360,192361,192356,192352,192353,192357,192350,192351,190763,192501,192488,192269,192278) AND `map`=571;
+DELETE FROM `creature` WHERE `id` IN (30739,30740,31102,31841,31151,31153,32296,31051,31106,31108,31109,31053,30489,39172,31107,32294,31101,30499,31842,31036,31091,39173,31052,30400,31054) AND `map`=571;
+
+-- ???
+UPDATE `creature_template` SET `InhabitType`=7 WHERE `entry`=27852;
+
+-- Wintergrasp spiritguide NPC script
+UPDATE `creature_template` SET `ScriptName`= 'npc_wg_spiritguide' WHERE `entry` IN (31841,31842);
+
+-- Wintergrasp demolisher engineer NPC script
+UPDATE `creature_template` SET `ScriptName`= 'npc_demolisher_engineerer' WHERE `entry` IN (30400,30499);
+
+-- 58730 Restricted Flight Area (Wintergrasp Eject)
+DELETE FROM `spell_area` WHERE `spell`=58730;
+INSERT INTO `spell_area` (`spell`,`area`,`quest_start`,`quest_start_active`,`quest_end`,`aura_spell`,`racemask`,`gender`,`autocast`)VALUES
+(58730,4581,0,0,0,0,0,2,1),
+(58730,4539,0,0,0,0,0,2,1),
+(58730,4197,0,0,0,0,0,2,1),
+(58730,4585,0,0,0,0,0,2,1),
+(58730,4612,0,0,0,0,0,2,1),
+(58730,4582,0,0,0,0,0,2,1),
+(58730,4583,0,0,0,0,0,2,1),
+(58730,4589,0,0,0,0,0,2,1),
+(58730,4575,0,0,0,0,0,2,1),
+(58730,4538,0,0,0,0,0,2,1),
+(58730,4577,0,0,0,0,0,2,1);
+
+-- 57940 Essence of Wintergrasp
+DELETE FROM `spell_area` WHERE `spell`=57940;
+INSERT INTO `spell_area` (`spell`,`area`,`quest_start`,`quest_start_active`,`quest_end`,`aura_spell`,`racemask`,`gender`,`autocast`)VALUES
+(57940,65,0,0,0,0,0,2,1),
+(57940,66,0,0,0,0,0,2,1),
+(57940,67,0,0,0,0,0,2,1),
+(57940,206,0,0,0,0,0,2,1),
+(57940,210,0,0,0,0,0,2,1),
+(57940,394,0,0,0,0,0,2,1),
+(57940,395,0,0,0,0,0,2,1),
+(57940,1196,0,0,0,0,0,2,1),
+(57940,2817,0,0,0,0,0,2,1),
+(57940,3456,0,0,0,0,0,2,1),
+(57940,3477,0,0,0,0,0,2,1),
+(57940,3537,0,0,0,0,0,2,1),
+(57940,3711,0,0,0,0,0,2,1),
+(57940,4100,0,0,0,0,0,2,1),
+(57940,4196,0,0,0,0,0,2,1),
+(57940,4228,0,0,0,0,0,2,1),
+(57940,4264,0,0,0,0,0,2,1),
+(57940,4265,0,0,0,0,0,2,1),
+(57940,4272,0,0,0,0,0,2,1),
+(57940,4273,0,0,0,0,0,2,1),
+(57940,4395,0,0,0,0,0,2,1),
+(57940,4415,0,0,0,0,0,2,1),
+(57940,4416,0,0,0,0,0,2,1),
+(57940,4493,0,0,0,0,0,2,1),
+(57940,4494,0,0,0,0,0,2,1),
+(57940,4603,0,0,0,0,0,2,1);
+
+-- Wintergrasp Cannons (Spell 51421 : Fire Cannon)
+UPDATE `creature_template` SET `faction_A`=1732,`faction_H`=1735,`spell1`=51421 WHERE `entry`=28366; -- *** WRONG ****
+UPDATE `creature_template` SET `faction_A`=1732,`faction_H`=1732 WHERE `entry` IN (30499,30740, 28319); -- Alliance
+UPDATE `creature_template` SET `faction_A`=1735,`faction_H`=1735 WHERE `entry` IN (30400,30739, 32629); -- Horde
+
+-- Added by Malcrom
+UPDATE `creature_template` SET `faction_A`=1732,`faction_H`=1732 WHERE `entry` IN (28312); -- Alliance
+UPDATE `creature_template` SET `faction_A`=1735,`faction_H`=1735 WHERE `entry` IN (32627); -- Horde
+
+-- New support-commands for battlefield class
+DELETE FROM `command` WHERE name IN ('bf start', 'bf stop', 'bf enable', 'bf switch', 'bf timer');
+INSERT INTO `command` (`name`,`security`,`help`) VALUES ('bf start',3,'Syntaxe: .bf start #battleid');
+INSERT INTO `command` (`name`,`security`,`help`) VALUES ('bf stop',3,'Syntaxe: .bf stop #battleid');
+INSERT INTO `command` (`name`,`security`,`help`) VALUES ('bf enable',3,'Syntaxe: .bf enable #battleid');
+INSERT INTO `command` (`name`,`security`,`help`) VALUES ('bf switch',3,'Syntaxe: .bf switch #battleid');
+INSERT INTO `command` (`name`,`security`,`help`) VALUES ('bf timer',3,'Syntaxe: .bf timer #battleid #timer');
+
+-- 49899 Activate Robotic Arms
+DELETE FROM `spell_scripts` WHERE `id`=49899;
+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);
+
+-- Wintergrasp creature addon cleanups
+DELETE FROM `creature_addon` WHERE `guid` BETWEEN 131258 AND 131322;
+DELETE FROM `creature_addon` WHERE `guid` BETWEEN 131326 AND 131328;
+DELETE FROM `creature_addon` WHERE `guid` BETWEEN 131350 AND 131353;
+DELETE FROM `creature_addon` WHERE `guid` BETWEEN 131376 AND 131380;
+DELETE FROM `creature_addon` WHERE `guid`=131392;
+DELETE FROM `creature_addon` WHERE `guid`=131437;
+DELETE FROM `creature_addon` WHERE `guid`=131458;
+DELETE FROM `creature_addon` WHERE `guid` BETWEEN 131631 AND 131634;
+DELETE FROM `creature_addon` WHERE `guid`=131706;
+DELETE FROM `creature_addon` WHERE `guid` BETWEEN 131727 AND 131731;
+
+-- Wintergrasp vehicle teleport
+UPDATE `gameobject_template` SET `ScriptName`= 'go_wintergrasp_teleporter' WHERE `entry`=192951;
+
+-- Wintergrasp Quests - Horde
+UPDATE `quest_template` SET `ExclusiveGroup`=13180 WHERE `entry` IN (13180, 13178);
+UPDATE `quest_template` SET `ExclusiveGroup`=13185 WHERE `entry` IN (13185, 13223);
+UPDATE `quest_template` SET `ExclusiveGroup`=13192 WHERE `entry` IN (13192, 13202);
+UPDATE `quest_template` SET `ExclusiveGroup`=13199 WHERE `entry` IN (13193, 13199);
+UPDATE `quest_template` SET `ExclusiveGroup`=13200 WHERE `entry` IN (13200, 13191);
+UPDATE `quest_template` SET `ExclusiveGroup`=13201 WHERE `entry` IN (13201, 13194);
+
+-- Wintergrasp Quests - Alliance
+UPDATE `quest_template` SET `ExclusiveGroup`=13179 WHERE `entry` IN (13179, 13177);
+UPDATE `quest_template` SET `ExclusiveGroup`=13186 WHERE `entry` IN (13186, 13222);
+UPDATE `quest_template` SET `ExclusiveGroup`=13195 WHERE `entry` IN (13195, 13156);
+UPDATE `quest_template` SET `ExclusiveGroup`=13196 WHERE `entry` IN (13196, 13154);
+UPDATE `quest_template` SET `ExclusiveGroup`=13198 WHERE `entry` IN (13198, 13153);
+
+-- Wintergrasp Questgiver NPCs - requires binding to Wintergrasp questgiver script
+UPDATE `creature_template` SET `ScriptName`= 'npc_wintergrasp_quest_giver' WHERE `entry` IN (31054, 31052, 31091, 31036, 31101, 31107, 31053, 31051, 31153, 31151, 31102, 31106);
+
+-- Wintergrasp Catapult speed adjustments
+UPDATE `creature_template` SET `speed_walk`=2.8,`speed_run`=1.6 WHERE `entry`=27881;
+
+-- Add Missing Horde Spirt Healer options Wintergrasp
+DELETE FROM `gossip_menu_option` WHERE `menu_id`=10129 AND `id` IN (2,4);
+INSERT INTO `gossip_menu_option` (`menu_id`,`id`,`option_icon`,`option_text`,`option_id`,`npc_option_npcflag`,`action_menu_id`,`action_poi_id`,`action_script_id`,`box_coded`,`box_money`,`box_text`) VALUES
+(10129,2,0, 'Guide me to the Broken Temple Graveyard.',1,1,0,0,0,0,0, ''),
+(10129,4,0, 'Guide me to the Eastspark Graveyard.',1,1,0,0,0,0,0, '');
+
+-- Add Spell Target position for Wintergrasp Graveyard spells
+DELETE FROM `spell_target_position` WHERE `id` IN (59760,59762,59763,59765,59766,59767,59769);
+INSERT INTO `spell_target_position` (`id`,`target_map`,`target_position_x`,`target_position_y`,`target_position_z`,`target_orientation`) VALUES
+(59760,571,5537.986,2897.493,517.057,4.819249), -- Teleport: Fortress Graveyard
+(59762,571,5104.750,2300.940,368.579,0.733038), -- Teleport: Sunken Ring "area 4538"
+(59763,571,5099.120,3466.036,368.484,5.317802), -- Teleport: Broken Temple "area 4539 & 4589"
+(59765,571,5032.454,3711.382,372.468,3.971623), -- Teleport: Horde Landing Zone
+(59766,571,4331.716,3235.695,390.251,0.008500), -- Teleport: Westspark Factory Graveyard "area 4611"
+(59767,571,4314.648,2408.522,392.642,6.268125), -- Teleport: Eastspark Factory Graveyard "area 4612"
+(59769,571,5140.790,2179.120,390.950,1.972220); -- Teleport: Alliance Landing Zone
+
+-- Add scripts to Wintergrasp spirit guide gossip
+UPDATE `gossip_menu_option` SET `action_script_id`=1012800 WHERE `menu_id` IN (10128,10129) AND `id`=0;
+UPDATE `gossip_menu_option` SET `action_script_id`=1012801 WHERE `menu_id` IN (10128,10129) AND `id`=1;
+UPDATE `gossip_menu_option` SET `action_script_id`=1012802 WHERE `menu_id` IN (10128,10129) AND `id`=2;
+UPDATE `gossip_menu_option` SET `action_script_id`=1012803 WHERE `menu_id` IN (10128,10129) AND `id`=3;
+UPDATE `gossip_menu_option` SET `action_script_id`=1012804 WHERE `menu_id` IN (10128,10129) AND `id`=4;
+UPDATE `gossip_menu_option` SET `action_script_id`=1012805 WHERE `menu_id`=10128 AND `id`=5;
+UPDATE `gossip_menu_option` SET `action_script_id`=1012806 WHERE `menu_id`=10129 AND `id`=5;
+
+-- Add Teleport graveyard Spells to gossip scripts
+DELETE FROM `gossip_scripts` WHERE `id` IN (1012800,1012801,1012802,1012803,1012804,1012805,1012806);
+INSERT INTO `gossip_scripts` (`id`,`delay`,`command`,`datalong`,`datalong2`) VALUES
+(1012800,0,33,0,0),(1012800,0,15,59760,1),
+(1012801,0,33,0,0),(1012801,0,15,59762,1),
+(1012802,0,33,0,0),(1012802,0,15,59763,1),
+(1012803,0,33,0,0),(1012803,0,15,59766,1),
+(1012804,0,33,0,0),(1012804,0,15,59767,1),
+(1012805,0,33,0,0),(1012805,0,15,59769,1),
+(1012806,0,33,0,0),(1012806,0,15,59765,1);
+
+-- Taunka Spirit Guide SAI
+SET @ENTRY := 31841;
+UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`=@ENTRY;
+DELETE FROM `creature_addon` WHERE `guid` IN (SELECT `guid` FROM `creature` WHERE `id`=@ENTRY);
+DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=@ENTRY;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,0,0,0,11,0,100,0,0,0,0,0,11,58729,0,0,0,0,0,1,0,0,0,0,0,0,0, 'on spawn aura self'),
+(@ENTRY,0,1,0,1,0,100,0,0,0,30000,30000,11,22011,0,0,0,0,0,1,0,0,0,0,0,0,0, 'cast Spirit Heal Channel every 30 sec');
+-- Dwarven Spirit Guide SAI
+SET @ENTRY := 31842;
+UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`=@ENTRY;
+DELETE FROM `creature_addon` WHERE `guid` IN (SELECT `guid` FROM `creature` WHERE `id`=@ENTRY);
+DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=@ENTRY;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,0,0,0,11,0,100,0,0,0,0,0,11,58729,0,0,0,0,0,1,0,0,0,0,0,0,0, 'on spawn aura self'),
+(@ENTRY,0,1,0,1,0,100,0,0,0,30000,30000,11,22011,0,0,0,0,0,1,0,0,0,0,0,0,0, 'cast Spirit Heal Channel every 30 sec');
+
+-- Gossip Menu insert from sniff
+DELETE FROM `gossip_menu` WHERE `entry`=9904 AND `text_id`=13759;
+INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES (9904,13759);
+DELETE FROM `gossip_menu` WHERE `entry`=9904 AND `text_id`=13761;
+INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES (9904,13761);
+DELETE FROM `gossip_menu` WHERE `entry`=9923 AND `text_id`=14172;
+INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES (9923,14172);
+DELETE FROM `gossip_menu` WHERE `entry`=10229 AND `text_id`=14221;
+INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES (10229,14221);
+
+-- Creature Gossip_menu_id Update from sniff
+UPDATE `creature_template` SET `gossip_menu_id`=9904 WHERE `entry`=30400;
+UPDATE `creature_template` SET `gossip_menu_id`=10229 WHERE `entry`=31091;
+-- Creature Gossip_menu_option Update from sniff
+DELETE FROM `gossip_menu_option` WHERE `menu_id` IN (9904);
+INSERT INTO `gossip_menu_option` (`menu_id`,`id`,`option_icon`,`option_text`,`option_id`,`npc_option_npcflag`,`action_menu_id`,`action_poi_id`,`action_script_id`,`box_coded`,`box_money`,`box_text`) VALUES
+(9904,0,0, 'I would like to build a catapult.',1,1,0,0,0,0,0, ''),
+(9904,1,0, 'I would like to build a demolisher.',1,1,0,0,0,0,0, ''),
+(9904,2,0, 'I would like to build a siege engine.',1,1,0,0,0,0,0, '');
+-- Add gossip_menu condition for 9904 Horde
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=9904;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`) VALUES
+(14,9904,13759,0,1,33280), -- Must have Rank 1: Corporal
+(14,9904,13759,1,1,55629), -- Or must have Rank 2: First Lieutenant
+(14,9904,13761,0,11,33280), -- Must not have Rank 1: Corporal
+(14,9904,13761,0,11,55629); -- Must not have Rank 2: First Lieutenant
+-- Add gossip_menu condition for 9923 Alliance
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=9923;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`) VALUES
+(14,9923,13798,0,1,33280), -- Must have Rank 1: Corporal
+(14,9923,13798,1,1,55629), -- Or must have Rank 2: First Lieutenant
+(14,9923,14172,0,11,33280), -- Must not have Rank 1: Corporal
+(14,9923,14172,0,11,55629); -- Must not have Rank 2: First Lieutenant
+-- Add conditions to gossip options horde
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=9904;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`) VALUES
+(15,9904,0,0,1,33280,0), -- Must have reached Rank 1: Corporal
+(15,9904,0,1,1,55629,0), -- Or must have reached Rank 2: First Lieutenant
+(15,9904,1,0,1,55629,0), -- Must have reached Rank 2: First Lieutenant
+(15,9904,2,0,1,55629,0); -- Must have reached Rank 2: First Lieutenant
+-- Add conditions to gossip options alliance
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=9923;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`) VALUES
+(15,9923,0,0,1,33280,0), -- Must have reached Rank 1: Corporal
+(15,9923,0,1,1,55629,0), -- Or must have reached Rank 2: First Lieutenant
+(15,9923,1,0,1,55629,0), -- Must have reached Rank 2: First Lieutenant
+(15,9923,2,0,1,55629,0); -- Must have reached Rank 2: First Lieutenant
+
+-- Add scripts to Wintergrasp engineers
+UPDATE `gossip_menu_option` SET `action_script_id`=990400 WHERE `menu_id` IN (9904,9923) AND `id`=0;
+UPDATE `gossip_menu_option` SET `action_script_id`=990401 WHERE `menu_id` IN (9904,9923) AND `id`=1;
+UPDATE `gossip_menu_option` SET `action_script_id`=990402 WHERE `menu_id` IN (9904) AND `id`=2;
+UPDATE `gossip_menu_option` SET `action_script_id`=990403 WHERE `menu_id` IN (9923) AND `id`=2;
+-- Add create vehicle Spells to gossip scripts
+DELETE FROM `gossip_scripts` WHERE `id` IN (990400,990401,990402);
+INSERT INTO `gossip_scripts` (`id`,`delay`,`command`,`datalong`,`datalong2`) VALUES
+(990400,0,33,0,0),(990400,0,15,56663,1),
+(990401,0,33,0,0),(990401,0,15,56575,1),
+(990402,0,33,0,0),(990402,0,15,61408,1),
+(990403,0,33,0,0),(990403,0,15,56661,1);
+
+-- NPC talk text insert from sniff
+DELETE FROM `creature_text` WHERE `entry`=15214 AND `groupid` BETWEEN 0 AND 30;
+DELETE FROM `creature_text` WHERE `entry` IN (31036,31091) AND `groupid` BETWEEN 0 AND 3;
+DELETE FROM `creature_text` WHERE `entry` IN (31108,31109,34924) AND `groupid`=0;
+INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES
+(15214,0,0, 'Let the battle begin!',3,0,100,0,0,0, 'Invisible Stalker'),
+(15214,1,0, 'The southern tower has been damaged!',3,0,100,0,0,0, 'Invisible Stalker'),
+(15214,2,0, 'The southern tower has been destroyed!',3,0,100,0,0,0, 'Invisible Stalker'),
+(15214,3,0, 'The eastern tower has been damaged!',3,0,100,0,0,0, 'Invisible Stalker'),
+(15214,4,0, 'The eastern tower has been destroyed!',3,0,100,0,0,0, 'Invisible Stalker'),
+(15214,5,0, 'The western tower has been damaged!',3,0,100,0,0,0, 'Invisible Stalker'),
+(15214,6,0, 'The western tower has been destroyed!',3,0,100,0,0,0, 'Invisible Stalker'),
+(15214,7,0, 'The north-western keep tower has been damaged!',3,0,100,0,0,0, 'Invisible Stalker'),
+(15214,8,0, 'The north-western keep tower has been destroyed!',3,0,100,0,0,0, 'Invisible Stalker'),
+(15214,9,0, 'The south-eastern keep tower has been damaged!',3,0,100,0,0,0, 'Invisible Stalker'),
+(15214,10,0, 'The south-eastern keep tower has been destroyed!',3,0,100,0,0,0, 'Invisible Stalker'),
+(15214,11,0, 'The Broken Temple siege workshop has been attacked by the Alliance!',3,0,100,0,0,0, 'Invisible Stalker'),
+(15214,12,0, 'The Broken Temple siege workshop has been captured by the Alliance!',3,0,100,0,0,0, 'Invisible Stalker'),
+(15214,13,0, 'The Broken Temple siege workshop has been attacked by the Horde!',3,0,100,0,0,0, 'Invisible Stalker'),
+(15214,14,0, 'The Broken Temple siege workshop has been captured by the Horde!',3,0,100,0,0,0, 'Invisible Stalker'),
+(15214,15,0, 'The Eastspark siege workshop has been attacked by the Alliance!',3,0,100,0,0,0, 'Invisible Stalker'),
+(15214,16,0, 'The Eastspark siege workshop has been captured by the Alliance!',3,0,100,0,0,0, 'Invisible Stalker'),
+(15214,17,0, 'The Eastspark siege workshop has been attacked by the Horde!',3,0,100,0,0,0, 'Invisible Stalker'),
+(15214,18,0, 'The Eastspark siege workshop has been captured by the Horde!',3,0,100,0,0,0, 'Invisible Stalker'),
+(15214,19,0, 'The Sunken Ring siege workshop has been attacked by the Alliance!',3,0,100,0,0,0, 'Invisible Stalker'),
+(15214,20,0, 'The Sunken Ring siege workshop has been captured by the Alliance!',3,0,100,0,0,0, 'Invisible Stalker'),
+(15214,21,0, 'The Sunken Ring siege workshop has been attacked by the Horde!',3,0,100,0,0,0, 'Invisible Stalker'),
+(15214,22,0, 'The Sunken Ring siege workshop has been captured by the Horde!',3,0,100,0,0,0, 'Invisible Stalker'),
+(15214,23,0, 'The Westspark siege workshop has been attacked by the Alliance!',3,0,100,0,0,0, 'Invisible Stalker'),
+(15214,24,0, 'The Westspark siege workshop has been captured by the Alliance!',3,0,100,0,0,0, 'Invisible Stalker'),
+(15214,25,0, 'The Westspark siege workshop has been attacked by the Horde!',3,0,100,0,0,0, 'Invisible Stalker'),
+(15214,26,0, 'The Westspark siege workshop has been captured by the Horde!',3,0,100,0,0,0, 'Invisible Stalker'),
+(15214,27,0, 'The Alliance has defended Wintergrasp Fortress!',3,0,100,0,0,0, 'Invisible Stalker'),
+(15214,28,0, 'The Alliance has captured Wintergrasp Fortress!',3,0,100,0,0,0, 'Invisible Stalker'),
+(15214,29,0, 'The Horde has defended Wintergrasp Fortress!',3,0,100,0,0,0, 'Invisible Stalker'),
+(15214,30,0, 'The Horde has captured Wintergrasp Fortress!',3,0,100,0,0,0, 'Invisible Stalker'),
+-- Not sure if all Alliance text is here, need horde text
+(31036,0,0, 'The first of the Horde towers has fallen! Destroy all three and we will hasten their retreat!',1,7,100,0,0,0, 'Commander Zanneth'),
+(31036,1,0, 'The second tower has fallen! Destroy the final tower and we will hasten their retreat!',1,7,100,0,0,0, 'Commander Zanneth'),
+(31036,2,0, 'The Horde towers have fallen! We have forced their hand. Finish off the remaining forces!',1,7,100,0,0,0, 'Commander Zanneth'),
+(31036,3,0, 'Show those animals no mercy, $n!',0,7,100,0,0,0, 'Commander Zanneth'),
+(31091,0,0, 'The first of the Alliance towers has fallen! Destroy all three and we will hasten their retreat!',1,7,100,0,0,0, 'Commander Dardosh'),
+(31091,1,0, 'Lok''tar! The second tower falls! Destroy the final tower and we will hasten their retreat!',1,7,100,0,0,0, 'Commander Dardosh'),
+(31091,2,0, 'The Alliance towers have fallen! We have forced their hand. Finish off the remaining forces!',1,7,100,0,0,0, 'Commander Dardosh'),
+(31091,3,0, 'Show those animals no mercy, $n!',0,7,100,0,0,0, 'Commander Dardosh'), -- ???
+(31108,0,0, 'Stop the Horde from retrieving the embers, $n. We cannot risk them having the advantage when the battle resumes!',0,7,100,0,0,0, 'Siege Master Stouthandle'),
+(31109,0,0, 'Destroy their foul machines of war, $n!',0,7,100,0,0,0, 'Senior Demolitionist Legoso'),
+(34924,0,0, 'The gates have been breached! Defend the keep!',1,0,100,0,0,0, 'High Commander Halford Wyrmbane');
+
+
+
+
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.