aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/world/3.3.5/2016_08_21_00_world.sql20
-rw-r--r--sql/updates/world/3.3.5/2016_08_21_01_world.sql3
-rw-r--r--sql/updates/world/3.3.5/2016_08_21_02_world.sql3
-rw-r--r--sql/updates/world/3.3.5/2016_08_21_03_world.sql6
-rw-r--r--sql/updates/world/3.3.5/2016_08_21_04_world.sql2
-rw-r--r--sql/updates/world/3.3.5/2016_08_21_05_world.sql11
-rw-r--r--sql/updates/world/3.3.5/2016_08_21_06_world.sql2
-rw-r--r--sql/updates/world/3.3.5/2016_08_21_07_world.sql2
-rw-r--r--sql/updates/world/3.3.5/2016_08_22_00_world.sql5
-rw-r--r--sql/updates/world/3.3.5/2016_08_23_00_world.sql4
-rw-r--r--sql/updates/world/3.3.5/2016_08_23_01_world.sql5
-rw-r--r--sql/updates/world/3.3.5/2016_08_23_02_world.sql2
-rw-r--r--sql/updates/world/3.3.5/2016_08_23_03_world.sql5
-rw-r--r--sql/updates/world/3.3.5/2016_08_23_04_world.sql10
-rw-r--r--sql/updates/world/3.3.5/2016_08_23_05_world.sql63
-rw-r--r--sql/updates/world/3.3.5/2016_08_24_00_world.sql33
-rw-r--r--sql/updates/world/3.3.5/2016_08_24_01_world.sql2
-rw-r--r--sql/updates/world/3.3.5/2016_08_24_02_world.sql2
-rw-r--r--sql/updates/world/3.3.5/2016_08_24_03_world.sql2
-rw-r--r--sql/updates/world/3.3.5/2016_08_24_04_world.sql7
-rw-r--r--sql/updates/world/3.3.5/2016_08_24_05_world.sql2
-rw-r--r--sql/updates/world/3.3.5/2016_08_24_06_world.sql5
-rw-r--r--sql/updates/world/3.3.5/2016_08_24_07_world.sql6
-rw-r--r--sql/updates/world/3.3.5/2016_08_24_08_world.sql190
-rw-r--r--sql/updates/world/3.3.5/2016_08_24_09_world.sql30
-rw-r--r--src/server/game/AI/PlayerAI/PlayerAI.cpp8
-rw-r--r--src/server/game/AI/PlayerAI/PlayerAI.h7
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp7
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.h1
-rw-r--r--src/server/game/Achievements/AchievementMgr.cpp18
-rw-r--r--src/server/game/Achievements/AchievementMgr.h14
-rw-r--r--src/server/game/Battlefield/Battlefield.cpp88
-rw-r--r--src/server/game/Battlefield/Battlefield.h5
-rw-r--r--src/server/game/Battlefield/BattlefieldMgr.cpp8
-rw-r--r--src/server/game/Battlefield/Zones/BattlefieldWG.cpp575
-rw-r--r--src/server/game/Battlefield/Zones/BattlefieldWG.h586
-rw-r--r--src/server/game/Conditions/ConditionMgr.cpp13
-rw-r--r--src/server/game/Conditions/ConditionMgr.h3
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp70
-rw-r--r--src/server/game/Entities/Creature/Creature.h11
-rw-r--r--src/server/game/Entities/Player/Player.cpp19
-rw-r--r--src/server/game/Entities/Player/Player.h2
-rw-r--r--src/server/game/Entities/Unit/StatSystem.cpp2
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp15
-rw-r--r--src/server/game/Entities/Unit/Unit.h2
-rw-r--r--src/server/game/Events/GameEventMgr.cpp14
-rw-r--r--src/server/game/Grids/Notifiers/GridNotifiers.h2
-rw-r--r--src/server/game/Handlers/BattleGroundHandler.cpp2
-rw-r--r--src/server/game/Spells/Spell.cpp34
-rw-r--r--src/server/game/Spells/Spell.h1
-rw-r--r--src/server/game/Spells/SpellMgr.cpp11
-rw-r--r--src/server/game/Spells/SpellMgr.h4
-rw-r--r--src/server/scripts/Commands/cs_cheat.cpp1
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp1
-rw-r--r--src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp16
-rw-r--r--src/server/scripts/EasternKingdoms/Uldaman/instance_uldaman.cpp8
-rw-r--r--src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp3
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp10
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp6
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp1382
-rw-r--r--src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp19
-rw-r--r--src/server/scripts/Northrend/Naxxramas/naxxramas.h11
-rw-r--r--src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp9
-rw-r--r--src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp15
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp3
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp21
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp6
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp2
-rw-r--r--src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp3
-rw-r--r--src/server/scripts/Northrend/zone_dalaran.cpp1
-rw-r--r--src/server/scripts/Northrend/zone_icecrown.cpp15
-rw-r--r--src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp3
-rw-r--r--src/server/scripts/Spells/spell_holiday.cpp37
-rw-r--r--src/server/scripts/Spells/spell_quest.cpp71
-rw-r--r--src/server/scripts/World/npcs_special.cpp52
-rw-r--r--src/tools/mmaps_generator/MapBuilder.cpp22
-rw-r--r--src/tools/mmaps_generator/MapBuilder.h5
77 files changed, 2184 insertions, 1482 deletions
diff --git a/sql/updates/world/3.3.5/2016_08_21_00_world.sql b/sql/updates/world/3.3.5/2016_08_21_00_world.sql
new file mode 100644
index 00000000000..6a6e7a9a22c
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_08_21_00_world.sql
@@ -0,0 +1,20 @@
+--
+UPDATE `creature_template` SET `mechanic_immune_mask`=`mechanic_immune_mask`|4 WHERE `entry`=34045;
+UPDATE `creature_template` SET `mechanic_immune_mask`=`mechanic_immune_mask`|1536 WHERE `entry`=21574;
+UPDATE `creature_template` SET `mechanic_immune_mask`=`mechanic_immune_mask`|16384 WHERE `entry` IN (32104,37425,31990,37309);
+UPDATE `creature_template` SET `mechanic_immune_mask`=`mechanic_immune_mask`|65536 WHERE `entry`=20175;
+UPDATE `creature_template` SET `mechanic_immune_mask`=`mechanic_immune_mask`|13108096 WHERE `entry`=19886;
+UPDATE `creature_template` SET `mechanic_immune_mask`=`mechanic_immune_mask`|71970058 WHERE `entry`=30600;
+UPDATE `creature_template` SET `mechanic_immune_mask`=`mechanic_immune_mask`|80358666 WHERE `entry` IN (37243,37244);
+UPDATE `creature_template` SET `mechanic_immune_mask`=`mechanic_immune_mask`|268435456 WHERE `entry` IN (38973,38974,38975,38970,38971,38972,38233,38459,38460);
+UPDATE `creature_template` SET `mechanic_immune_mask`=`mechanic_immune_mask`|277165934 WHERE `entry`=32796;
+UPDATE `creature_template` SET `mechanic_immune_mask`=`mechanic_immune_mask`|344276858 WHERE `entry` IN (35427,35410);
+UPDATE `creature_template` SET `mechanic_immune_mask`=`mechanic_immune_mask`|541800015 WHERE `entry` IN (39299,39300,39301);
+UPDATE `creature_template` SET `mechanic_immune_mask`=`mechanic_immune_mask`|617299835 WHERE `entry` IN (38483,37341,37363,33911,33910);
+
+UPDATE `creature_template` SET `unit_flags2`=`unit_flags2`|32 WHERE `entry`=30794;
+
+UPDATE `creature_template` SET `flags_extra`=`flags_extra`|2 WHERE `entry` IN (37628,30808,25546,25543,30769,30758,30768,30776,30813,30812,30811,30800,30792,30796,30801,30797,30799,31997,37316,31995,37314,21620,20665,19901,31979,37298,32092,37413,32003,37322,32032,37352,32137,37465,37484,37483,37480,32044,37365,32056,37377,37320,32112,37433,37315,37482,37481,37479,37323,37236,37305,37420,37301,37416,37399,37485,37809,37348,37427,37344,37349,37242,37373,34140,37318,34256,34257,34254,33191,37486);
+
+UPDATE `creature_template` SET `flags_extra`=`flags_extra`|64 WHERE `entry` IN (31585,31183,31635);
+UPDATE `creature_template` SET `flags_extra`=`flags_extra`|128 WHERE `entry` IN (25558,25557);
diff --git a/sql/updates/world/3.3.5/2016_08_21_01_world.sql b/sql/updates/world/3.3.5/2016_08_21_01_world.sql
new file mode 100644
index 00000000000..37ce1e9809f
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_08_21_01_world.sql
@@ -0,0 +1,3 @@
+--
+UPDATE `creature_template` SET `flags_extra`=`flags_extra`|2 WHERE `entry`=30808;
+UPDATE `creature_template` SET `mechanic_immune_mask`=`mechanic_immune_mask`|4 WHERE `entry` IN (33911,33910);
diff --git a/sql/updates/world/3.3.5/2016_08_21_02_world.sql b/sql/updates/world/3.3.5/2016_08_21_02_world.sql
new file mode 100644
index 00000000000..9ae243c4db1
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_08_21_02_world.sql
@@ -0,0 +1,3 @@
+--
+UPDATE `creature_template` SET `flags_extra`=`flags_extra`|2 WHERE `entry`=27339;
+UPDATE `gameobject_addon` SET `parent_rotation0`=0, `parent_rotation1`=0, `parent_rotation2`=0.333807, `parent_rotation3`=0.9426414 WHERE `guid`=57849;
diff --git a/sql/updates/world/3.3.5/2016_08_21_03_world.sql b/sql/updates/world/3.3.5/2016_08_21_03_world.sql
new file mode 100644
index 00000000000..c8b1f0f1c2e
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_08_21_03_world.sql
@@ -0,0 +1,6 @@
+--
+DELETE FROM `spell_ranks` WHERE `first_spell_id` = 34453 AND `rank` IN (1,2);
+UPDATE `creature_template` SET `flags_extra`=`flags_extra`|2 WHERE `entry` IN (32117,37440,32113,37436,32116,37439,32115,37438,32114,37437,32118,37441);
+UPDATE `creature_template` SET `flags_extra`=`flags_extra`|128 WHERE `entry` IN (22582);
+UPDATE `creature_template` SET `flags_extra`=`flags_extra`|130 WHERE `entry` IN (30780,30782,30784,30786);
+UPDATE `creature_template` SET `mechanic_immune_mask`=`mechanic_immune_mask`|80358666 WHERE `entry` IN (37283,37444);
diff --git a/sql/updates/world/3.3.5/2016_08_21_04_world.sql b/sql/updates/world/3.3.5/2016_08_21_04_world.sql
new file mode 100644
index 00000000000..7d7fbd23005
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_08_21_04_world.sql
@@ -0,0 +1,2 @@
+--
+UPDATE `gameobject` SET `spawntimesecs` = 2 WHERE `id` = 188489;
diff --git a/sql/updates/world/3.3.5/2016_08_21_05_world.sql b/sql/updates/world/3.3.5/2016_08_21_05_world.sql
new file mode 100644
index 00000000000..e7327102a1f
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_08_21_05_world.sql
@@ -0,0 +1,11 @@
+--
+UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry` IN (25686,25684,25699,25701);
+DELETE FROM `smart_scripts` WHERE `entryorguid` IN (25686,25701,25684,25699) AND `source_type`=0;
+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
+-- DB/Creature: Add missing SAI Gorloc Gibberer and Gorloc Dredger
+(25686, 0, 0, 0, 0, 0, 100, 0, 0, 4000, 4000, 6000, 11, 50520, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gorloc Gibberer - In Combat - Cast \'Deep Dredge\''),
+(25701, 0, 0, 0, 0, 0, 100, 0, 0, 4000, 4000, 6000, 11, 50520, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gorloc Dredger - In Combat - Cast \'Deep Dredge\''),
+-- DB/Creature: Add missing SAI Talramas Abomination
+(25684, 0, 0, 0, 0, 0, 100, 0, 0, 2000, 20000, 20000, 11, 50366, 32, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Talramas Abomination - In Combat - Cast \'Plague Cloud\''),
+-- DB/Creature: Add missing SAI Gorloc Mud Splasher
+(25699, 0, 0, 0, 0, 0, 100, 0, 0, 2000, 12000, 20000, 11, 50522, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Gorloc Mud Splasher - In Combat - Cast \'Gorloc Stomp\'');
diff --git a/sql/updates/world/3.3.5/2016_08_21_06_world.sql b/sql/updates/world/3.3.5/2016_08_21_06_world.sql
new file mode 100644
index 00000000000..22fce10b220
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_08_21_06_world.sql
@@ -0,0 +1,2 @@
+--
+UPDATE `gossip_menu_option` SET `option_text`='I require training', `OptionBroadcastTextID` =6503 WHERE `menu_id`=4762 AND `id`=0;
diff --git a/sql/updates/world/3.3.5/2016_08_21_07_world.sql b/sql/updates/world/3.3.5/2016_08_21_07_world.sql
new file mode 100644
index 00000000000..62d1963db90
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_08_21_07_world.sql
@@ -0,0 +1,2 @@
+--
+UPDATE `creature_template` SET `mechanic_immune_mask`=8388672 WHERE `entry`=23777;
diff --git a/sql/updates/world/3.3.5/2016_08_22_00_world.sql b/sql/updates/world/3.3.5/2016_08_22_00_world.sql
new file mode 100644
index 00000000000..3b741e03565
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_08_22_00_world.sql
@@ -0,0 +1,5 @@
+--
+DELETE FROM `conditions` WHERE `SourceEntry`=42793 AND `SourceTypeOrReferenceId`=13;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(13, 1, 42793, 0, 0, 31, 0, 3, 24009, 0, 0, 0, 0, "", "Spell Burn Body targets Alliance Corpse"),
+(13, 1, 42793, 0, 1, 31, 0, 3, 24010, 0, 0, 0, 0, "", "Spell Burn Body targets Forsaken Corpse");
diff --git a/sql/updates/world/3.3.5/2016_08_23_00_world.sql b/sql/updates/world/3.3.5/2016_08_23_00_world.sql
new file mode 100644
index 00000000000..22a4ef95f4e
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_08_23_00_world.sql
@@ -0,0 +1,4 @@
+--
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` IN(17) AND `SourceEntry`=13982;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(17,0,13982,0,0,29,0,9016,10,1,0,0,0,'',"Spell 'Bael'Gar's Fiery Essence' requires Bael'Gar's corpse");
diff --git a/sql/updates/world/3.3.5/2016_08_23_01_world.sql b/sql/updates/world/3.3.5/2016_08_23_01_world.sql
new file mode 100644
index 00000000000..0c266a2e88f
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_08_23_01_world.sql
@@ -0,0 +1,5 @@
+--
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=39246 AND `ConditionTypeOrReference`=36;
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=17 AND `SourceEntry`=39246;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(17,0,39246,0,0,29,0,22105,10,1,0,11,0,'',"Spell 'Fumping' requires dead Decrepit Clefthoof");
diff --git a/sql/updates/world/3.3.5/2016_08_23_02_world.sql b/sql/updates/world/3.3.5/2016_08_23_02_world.sql
new file mode 100644
index 00000000000..144a4aa4377
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_08_23_02_world.sql
@@ -0,0 +1,2 @@
+--
+UPDATE `conditions` SET `ConditionValue2`=33844 WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=62709 AND `ElseGroup`=0;
diff --git a/sql/updates/world/3.3.5/2016_08_23_03_world.sql b/sql/updates/world/3.3.5/2016_08_23_03_world.sql
new file mode 100644
index 00000000000..727544cd88c
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_08_23_03_world.sql
@@ -0,0 +1,5 @@
+DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=66512;
+DELETE FROM `spell_script_names` WHERE `ScriptName` IN('spell_q14076_14092_pound_drum','spell_q12279_cast_net');
+INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
+(66512,'spell_q14076_14092_pound_drum'),
+(48794,'spell_q12279_cast_net');
diff --git a/sql/updates/world/3.3.5/2016_08_23_04_world.sql b/sql/updates/world/3.3.5/2016_08_23_04_world.sql
new file mode 100644
index 00000000000..d7697d28ad7
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_08_23_04_world.sql
@@ -0,0 +1,10 @@
+-- NPC ID / entry 35646 Wormhole (summoned by item 48933 Wormhole Generator: Northrend)
+
+DELETE FROM `gossip_menu_option` WHERE `menu_id`= 10668;
+INSERT INTO `gossip_menu_option` (`menu_id`,`id`,`option_icon`,`option_text`,`OptionBroadcastTextID`,`option_id`,`npc_option_npcflag`,`action_menu_id`,`action_poi_id`,`box_coded`,`box_money`,`box_text`,`BoxBroadcastTextID`,`VerifiedBuild`) VALUES
+(10668, 0, 0, 'Borean Tundra', 35939, 1, 1, 0, 0, 0, 0, '', 0, 0),
+(10668, 1, 0, 'Howling Fjord', 35943, 1, 1, 0, 0, 0, 0, '', 0, 0),
+(10668, 2, 0, 'Sholazar Basin', 35940, 1, 1, 0, 0, 0, 0, '', 0, 0),
+(10668, 3, 0, 'Icecrown', 35941, 1, 1, 0, 0, 0, 0, '', 0, 0),
+(10668, 4, 0, 'Storm Peaks', 35942, 1, 1, 0, 0, 0, 0, '', 0, 0),
+(10668, 5, 0, 'Underground...', 36022, 1, 1, 0, 0, 0, 0, '', 0, 0);
diff --git a/sql/updates/world/3.3.5/2016_08_23_05_world.sql b/sql/updates/world/3.3.5/2016_08_23_05_world.sql
new file mode 100644
index 00000000000..cab7e8f3a20
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_08_23_05_world.sql
@@ -0,0 +1,63 @@
+--
+DELETE FROM `spell_script_names` WHERE `ScriptName`="spell_brewfest_relay_race_turn_in";
+INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
+(43755, "spell_brewfest_relay_race_turn_in");
+
+DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=-43880;
+INSERT INTO `spell_linked_spell` (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES
+(-43880, -43332, 0, "On removal of aura 'Ramsteins Swift Work Ram' also remove aura 'Exhausted'"),
+(-43880, -43310, 0, "On removal of aura 'Ramsteins Swift Work Ram' also remove aura 'Ram Level - Neutral'"),
+(-43880, -43052, 0, "On removal of aura 'Ramsteins Swift Work Ram' also remove aura 'Ram Fatigue'"),
+(-43880, -42994, 0, "On removal of aura 'Ramsteins Swift Work Ram' also remove aura 'Ram - Gallop'"),
+(-43880, -42993, 0, "On removal of aura 'Ramsteins Swift Work Ram' also remove aura 'Ram - Canter'"),
+(-43880, -42992, 0, "On removal of aura 'Ramsteins Swift Work Ram' also remove aura 'Ram - Trot'"),
+(-43880, -42146, 0, "On removal of aura 'Ramsteins Swift Work Ram' also remove aura 'Brewfest Racing Ram Aura [DND]'");
+
+DELETE FROM `gossip_menu_option` WHERE `id`=4 AND `menu_id` IN (8934, 8976);
+INSERT INTO `gossip_menu_option` (`menu_id`, `id`, `option_icon`, `option_text`, `OptionBroadcastTextID`, `option_id`, `npc_option_npcflag`, `action_menu_id`, `action_poi_id`, `box_coded`, `box_money`, `box_text`, `BoxBroadcastTextID`, `VerifiedBuild`) VALUES
+(8934, 4, 0, "I want to race for tokens!", 0, 1, 1, 0, 0, 0, 0, "", 0, -1),
+(8976, 4, 0, "I want to race for tokens!", 0, 1, 1, 0, 0, 0, 0, "", 0, -1);
+
+UPDATE `smart_scripts` SET `link`=2 WHERE `id`=1 AND `entryorguid` IN (24468, 24510);
+DELETE FROM `smart_scripts` WHERE `id`=2 AND `entryorguid` IN (24468, 24510);
+DELETE FROM `smart_scripts` WHERE `entryorguid`=23558 AND `id` IN (6, 7, 8, 9);
+DELETE FROM `smart_scripts` WHERE `entryorguid`=24497 AND `id` IN (8, 9, 10, 11);
+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
+(24468, 0, 2, 0, 61, 0, 100, 0, 0, 0, 0, 0, 85, 43755, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, "Pol Amberstill <Ram Racing Apprentice> - Within 0-25 Range - Cast 'Brewfest - Daily - Relay Race - Player - Increase Mount Duration - DND'"),
+(24510, 0, 2, 0, 61, 0, 100, 0, 0, 0, 0, 0, 85, 43755, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, "Driz Tumblequick <Ram Racing Apprentice> - Within 0-25 Range - Cast 'Brewfest - Daily - Relay Race - Player - Increase Mount Duration - DND'"),
+(23558, 0, 6, 7, 62, 0, 100, 0, 8934, 4, 0, 0, 72, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, "Neill Ramstein <Ram Racing Master> - On Gossip Option 4 Selected - Close Gossip"),
+(23558, 0, 7, 8, 61, 0, 100, 0, 0, 0, 0, 0, 85, 43880, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, "Neill Ramstein <Ram Racing Master> - On Gossip Option 4 Selected - Cast Spell 'Ramstein's Swift Work Ram'"),
+(23558, 0, 8, 9, 61, 0, 100, 0, 0, 0, 0, 0, 85, 44689, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, "Neill Ramstein <Ram Racing Master> - On Gossip Option 4 Selected - Cast Spell 'Relay Race Accept Hidden Debuff - DND'"),
+(23558, 0, 9, 0, 61, 0, 100, 0, 0, 0, 0, 0, 85, 44262, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, "Neill Ramstein <Ram Racing Master> - On Gossip Option 4 Selected - Cast Spell 'Brewfest - Create Ram Racing Crop'"),
+(24497, 0, 8, 9, 62, 0, 100, 0, 8976, 4, 0, 0, 72, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, "Ram Master Ray <Ram Racing Master> - On Gossip Option 4 Selected - Close Gossip"),
+(24497, 0, 9, 10, 61, 0, 100, 0, 0, 0, 0, 0, 85, 43880, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, "Ram Master Ray <Ram Racing Master> - On Gossip Option 4 Selected - Cast Spell 'Ramstein's Swift Work Ram'"),
+(24497, 0, 10, 11, 61, 0, 100, 0, 0, 0, 0, 0, 85, 44689, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, "Ram Master Ray <Ram Racing Master> - On Gossip Option 4 Selected - Cast Spell 'Relay Race Accept Hidden Debuff - DND'"),
+(24497, 0, 11, 0, 61, 0, 100, 0, 0, 0, 0, 0, 85, 44262, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, "Ram Master Ray <Ram Racing Master> - On Gossip Option 4 Selected - Cast Spell 'Brewfest - Create Ram Racing Crop'");
+
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup` IN (8934, 8976) AND `SourceEntry`=4;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(15, 8934, 4, 0, 0, 8, 0, 11122, 0, 0, 0, 0, 0, "", "Brewfest Relay Race - Show gossip if player has turned in the quest 'There and Back Again'"),
+(15, 8934, 4, 0, 0, 1, 0, 44689, 0, 0, 1, 0, 0, "", "Brewfest Relay Race - Show gossip if player does not have aura 'Relay Race Accept Hidden Debuff - DND'"),
+(15, 8934, 4, 0, 0, 1, 0, 43883, 0, 0, 1, 0, 0, "", "Brewfest Relay Race - Show gossip if player does not have aura 'Rental Racing Ram'"),
+(15, 8976, 4, 0, 0, 8, 0, 11412, 0, 0, 0, 0, 0, "", "Brewfest Relay Race - Show gossip if player has turned in the quest 'There and Back Again'"),
+(15, 8976, 4, 0, 0, 1, 0, 44689, 0, 0, 1, 0, 0, "", "Brewfest Relay Race - Show gossip if player does not have aura 'Relay Race Accept Hidden Debuff - DND'"),
+(15, 8976, 4, 0, 0, 1, 0, 43883, 0, 0, 1, 0, 0, "", "Brewfest Relay Race - Show gossip if player does not have aura 'Rental Racing Ram'");
+
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=22 AND `SourceEntry` IN (24468, 24510, 24364, 24527) AND `ElseGroup`=1;
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=22 AND `SourceEntry` IN (24468, 24510) AND `SourceGroup`=3;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(22, 1, 24468, 0, 1, 1, 0, 43880, 0, 0, 0, 0, 0, "", "SAI triggers only if player has aura 'Ramsteins Swift Work Ram'"),
+(22, 1, 24468, 0, 1, 2, 0, 33797, 1, 0, 0, 0, 0, "", "SAI triggers only if player has item 'Portable Brewfest Keg'"),
+(22, 1, 24510, 0, 1, 1, 0, 43880, 0, 0, 0, 0, 0, "", "SAI triggers only if player has aura 'Ramsteins Swift Work Ram'"),
+(22, 1, 24510, 0, 1, 2, 0, 33797, 1, 0, 0, 0, 0, "", "SAI triggers only if player has item 'Portable Brewfest Keg'"),
+(22, 1, 24364, 0, 1, 1, 0, 43880, 0, 0, 0, 0, 0, "", "SAI triggers only if player has aura 'Ramsteins Swift Work Ram'"),
+(22, 1, 24364, 0, 1, 2, 0, 33797, 1, 0, 1, 0, 0, "", "SAI triggers only if player does not have item 'Portable Brewfest Keg'"),
+(22, 1, 24527, 0, 1, 1, 0, 43880, 0, 0, 0, 0, 0, "", "SAI triggers only if player has aura 'Ramsteins Swift Work Ram'"),
+(22, 1, 24527, 0, 1, 2, 0, 33797, 1, 0, 1, 0, 0, "", "SAI triggers only if player does not have item 'Portable Brewfest Keg'"),
+(22, 3, 24468, 0, 0, 1, 0, 43880, 0, 0, 0, 0, 0, "", "SAI triggers only if player has aura 'Ramsteins Swift Work Ram'"),
+(22, 3, 24510, 0, 0, 1, 0, 43880, 0, 0, 0, 0, 0, "", "SAI triggers only if player has aura 'Ramstein's Swift Work Ram'");
+
+-- Update wrong comments
+UPDATE `conditions` SET `Comment`="SAI triggers only if player has aura 'Rental Racing Ram'" WHERE `SourceTypeOrReferenceId`=22 AND `SourceEntry`=24510 AND `ConditionTypeOrReference`=1 AND `ConditionValue1`=43883;
+UPDATE `conditions` SET `Comment`="SAI triggers only if player has item 'Portable Brewfest Keg'" WHERE `SourceTypeOrReferenceId`=22 AND `SourceEntry`=24510 AND `ConditionTypeOrReference`=2;
+UPDATE `smart_scripts` SET `Comment`="Driz Tumblequick <Ram Racing Apprentice> - Within 0-25 Range - Cast 'Brewfest - Throw Keg - DND'" WHERE `entryorguid`=24510 AND `id`=0;
diff --git a/sql/updates/world/3.3.5/2016_08_24_00_world.sql b/sql/updates/world/3.3.5/2016_08_24_00_world.sql
new file mode 100644
index 00000000000..db20add8d90
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_08_24_00_world.sql
@@ -0,0 +1,33 @@
+--
+DELETE FROM `conditions` WHERE `SourceEntry`=43189 AND `SourceTypeOrReferenceId`=17;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(17, 0, 43189, 0, 0, 29, 0, 24173, 100, 0, 1, 0, 0, "", "Spell 'Test Horn' cannot be cast if NPC 'Frostgore' is nearby"),
+(17, 0, 43189, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, "", "Spell 'Test Horn' cannot be cast if nearby NPC 'Frostgore' is alive");
+
+UPDATE `event_scripts` SET `x`=2932.631, `y`=-4488.105, `z`=285.6876, `o`=3.298672 WHERE `id`=15726;
+
+DELETE FROM `waypoints` WHERE `entry`=24173;
+INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `point_comment`) VALUES
+(24173, 1, 2918.373, -4505.415, 280.0419, ""),
+(24173, 2, 2920.935, -4521.924, 276.0025, ""),
+(24173, 3, 2923.956, -4535.499, 274.4535, ""),
+(24173, 4, 2944.427, -4555.303, 273.6897, "");
+
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=24173;
+DELETE FROM `smart_scripts` WHERE `entryorguid` IN (24173, 2417300);
+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
+(24173, 0, 0, 0, 0, 0, 100, 0, 5000, 10000, 10000, 20000, 11, 52058, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, "Frostgore - In Combat - Cast 'Ground Slam'"),
+(24173, 0, 1, 2, 11, 0, 100, 0, 0, 0, 0, 0, 18, 256, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Frostgore - On Spawn - Add UNIT_FLAG_IMMUNE_TO_PC"),
+(24173, 0, 2, 0, 61, 0, 100, 0, 0, 0, 0, 0, 53, 1, 24173, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Frostgore - On Spawn - Start Waypoint"),
+(24173, 0, 3, 0, 40, 0, 100, 0, 4, 0, 0, 0, 80, 2417300, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Frostgore - On WP 4 Reached - Start Script"),
+(2417300, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 101, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, "Frostgore - On Script - Set home position to summoner's position"),
+(2417300, 9, 1, 0, 0, 0, 100, 0, 2000, 2000, 0, 0, 66, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, "Frostgore - On Script - Turn to summoner"),
+(2417300, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Frostgore - On Script - Say Text 0"),
+(2417300, 9, 3, 0, 0, 0, 100, 0, 5000, 5000, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Frostgore - On Script - Say Text 1"),
+(2417300, 9, 4, 0, 0, 0, 100, 0, 5000, 5000, 0, 0, 19, 256, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Frostgore - On Script - Remove UNIT_FLAG_IMMUNE_TO_PC"),
+(2417300, 9, 5, 0, 0, 0, 100, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, "Frostgore - On Script - Attack summoner");
+
+DELETE FROM `creature_text` WHERE `entry`=24173;
+INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
+(24173, 0, 0, (SELECT MaleText FROM broadcast_text WHERE ID = 22876), 12, 0, 100, 1, 0, 0, 22876, 0, "Frostgore"),
+(24173, 1, 0, (SELECT MaleText FROM broadcast_text WHERE ID = 22877), 12, 0, 100, 25, 0, 0, 22877, 0, "Frostgore");
diff --git a/sql/updates/world/3.3.5/2016_08_24_01_world.sql b/sql/updates/world/3.3.5/2016_08_24_01_world.sql
new file mode 100644
index 00000000000..65efdb08659
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_08_24_01_world.sql
@@ -0,0 +1,2 @@
+--
+UPDATE `smart_scripts` SET `target_type`=27 WHERE `entryorguid`=30423 AND `id`=1;
diff --git a/sql/updates/world/3.3.5/2016_08_24_02_world.sql b/sql/updates/world/3.3.5/2016_08_24_02_world.sql
new file mode 100644
index 00000000000..e1407e23780
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_08_24_02_world.sql
@@ -0,0 +1,2 @@
+-- fix random incorrect unit flag on dragonkin type
+UPDATE `creature_template` SET `unit_flags`=(`unit_flags`&~(0x100|0x200|0x2000000)) WHERE `entry`=31403;
diff --git a/sql/updates/world/3.3.5/2016_08_24_03_world.sql b/sql/updates/world/3.3.5/2016_08_24_03_world.sql
new file mode 100644
index 00000000000..68b4d9274ec
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_08_24_03_world.sql
@@ -0,0 +1,2 @@
+-- Scarlet Mine Car must have UNIT_FIELD_FLAGS UNIT_FLAG_IMMUNE_TO_PC
+UPDATE `creature_template` SET `unit_flags`= `unit_flags`| 520 WHERE `entry`= 28817;
diff --git a/sql/updates/world/3.3.5/2016_08_24_04_world.sql b/sql/updates/world/3.3.5/2016_08_24_04_world.sql
new file mode 100644
index 00000000000..5076e7f521d
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_08_24_04_world.sql
@@ -0,0 +1,7 @@
+-- fix sons of hodir reputation amounts to correspond to 3.3.5 retail
+UPDATE `quest_template` SET `RewardFactionOverride1`=65000 WHERE `id` IN (13559,13108,13003); -- Hodir's Tribute awards 650 rep per turn-in; Whatever it Takes! and Thrusing Hodir's Spear also award 650 rep
+UPDATE `quest_template` SET `RewardFactionOverride1`=2860000 WHERE `id` IN (12915,12924); -- Mending Fences and A Spark of Hope award 28600 rep
+UPDATE `quest_template` SET `RewardFactionOverride1`=32500 WHERE `id` IN (12924,13011,12975,12985,13001); -- Forging an Alliance, Jormuttar is Soo Fat..., In Memoriam, Forging a Head, Raising Hodir's Spear reward 325 rep each
+UPDATE `quest_template` SET `RewardFactionOverride1`=45500 WHERE `id` IN (12981,12977,13010,13420,13421,13006,12994,13046); -- Hot and Cold, Blowing Hodir's Horn, 'Krolmir, Hammer of Storms', Everfrost, Remember Everfrost!, Polishing the Helm, Spy Hunter, Feeding Arngrim each award 455 reputation
+UPDATE `quest_template` SET `RewardFactionOverride1`=32500 WHERE `id` = 12987; -- Mounting Hodir's Helm awards 325 rep
+UPDATE `quest_template` SET `RewardFactionOverride1`=97 WHERE `id` = 12976; -- A Monument to the Fallen awards 97 rep
diff --git a/sql/updates/world/3.3.5/2016_08_24_05_world.sql b/sql/updates/world/3.3.5/2016_08_24_05_world.sql
new file mode 100644
index 00000000000..34b2dc925a3
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_08_24_05_world.sql
@@ -0,0 +1,2 @@
+-- fix typo in previous update. nobody saw that!
+UPDATE `quest_template` SET `RewardFactionOverride1`=9700 WHERE `id` = 12976; -- A Monument to the Fallen awards 97 rep
diff --git a/sql/updates/world/3.3.5/2016_08_24_06_world.sql b/sql/updates/world/3.3.5/2016_08_24_06_world.sql
new file mode 100644
index 00000000000..7df954dec3b
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_08_24_06_world.sql
@@ -0,0 +1,5 @@
+--
+UPDATE `quest_template` SET `RewardFactionID1`=67 WHERE `ID`=5237;
+UPDATE `quest_template` SET `RewardFactionID1`=469 WHERE `ID`=5238;
+
+UPDATE `quest_offer_reward` SET `RewardText`="$N, your successful re-engineering of the cauldrons is a tremendous victory for us!$B$B<The high executor clears his throat and begins to bellow loudly.>$B$BLet all within my presence hear: for service to the Forsaken and to the Horde as a whole above and beyond what was expected - in the face of overwhelming odds and incredible danger, might I add - I give $N this, and I extend upon $Ghim:her; our undying gratitude as a true hero of the Horde. Huzzah!" WHERE `ID`=5237;
diff --git a/sql/updates/world/3.3.5/2016_08_24_07_world.sql b/sql/updates/world/3.3.5/2016_08_24_07_world.sql
new file mode 100644
index 00000000000..2c1c2941dc2
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_08_24_07_world.sql
@@ -0,0 +1,6 @@
+-- move sons of hodir reputation changes to reputation_reward_rate table
+-- also add multipliers to Argent Crusade, Alliance Vanguard, Horde Expedition, Kirin Tor, Knights of the Ebon Blade and Wyrmrest Accord as per 3.3.0 retail patch notes
+UPDATE `quest_template` SET `RewardFactionOverride1`=0 WHERE `RewardFactionID1`=1119;
+UPDATE `quest_template` SET `RewardFactionOverride1`=2200000 WHERE `id` IN (12915,12924);
+INSERT INTO `reputation_reward_rate` (`faction`) VALUES (1106),(1037),(1052),(1091),(1090),(1098) ON DUPLICATE KEY UPDATE `faction`=`faction`;
+UPDATE `reputation_reward_rate` SET `quest_rate`=1.3,`quest_daily_rate`=1.3,`quest_weekly_rate`=1.3,`quest_monthly_rate`=1.3,`quest_repeatable_rate`=1.3 WHERE `faction` IN (1106,1037,1052,1091,1090,1098);
diff --git a/sql/updates/world/3.3.5/2016_08_24_08_world.sql b/sql/updates/world/3.3.5/2016_08_24_08_world.sql
new file mode 100644
index 00000000000..45b28c4d1d6
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_08_24_08_world.sql
@@ -0,0 +1,190 @@
+-- !!!!!!!!!!!!!!!!!!!!!!!!!!! --
+-- KEL'THUZAD ENCOUNTER REWORK --
+-- !!!!!!!!!!!!!!!!!!!!!!!!!!! --
+
+
+-- =============== --
+-- Difficulty data --
+-- =============== --
+DELETE FROM `spelldifficulty_dbc` WHERE `id` IN (28478,28479,28457,28459);
+INSERT INTO `spelldifficulty_dbc` (`id`,`spellid0`,`spellid1`) VALUES
+(28478,28478,55802),
+(28479,28479,55807),
+(28457,28457,55714),
+(28459,28459,55765);
+
+-- ======================================================================== --
+-- Summon groups: --
+-- groups 1 to 4 are the 4 guardian of icecrown spawns for P3 --
+-- groups 5 to 11 are the spawn groups for each of the minion pockets in P1 --
+-- ======================================================================== --
+DELETE FROM `creature_summon_groups` WHERE `summonerId`=15990;
+INSERT INTO `creature_summon_groups` (`summonerId`,`summonerType`,`groupId`,`entry`,`position_x`,`position_y`,`position_z`,`orientation`,`summonType`,`summonTime`) VALUES
+(15990,0, 1,16441,3700.7,-5182.372,144.0006,3.525565,5,0),
+(15990,0, 2,16441,3759.62,-5172.79,143.835,2.275546,5,0),
+(15990,0, 3,16441,3777.213,-5066.177,143.7245,3.854439,5,0),
+(15990,0, 4,16441,3732.598,-5028.03,144.1175,5.951573,5,0),
+(15990,0, 5,23561,3767.448,-5085.221,143.3204,1.099557,6,2500),
+(15990,0, 5,23561,3763.589,-5077.779,143.2613,3.263766,6,2500),
+(15990,0, 5,23561,3778.311,-5070.924,143.6698,0.383972,6,2500),
+(15990,0, 5,23561,3777.016,-5076.336,143.6931,2.443461,6,2500),
+(15990,0, 5,23561,3768.994,-5072.449,143.2920,1.221730,6,2500),
+(15990,0, 5,23561,3765.200,-5066.542,143.5911,5.969026,6,2500),
+(15990,0, 5,23561,3760.120,-5071.032,143.2545,4.049164,6,2500),
+(15990,0, 5,23561,3772.377,-5065.624,143.5756,3.595378,6,2500),
+(15990,0, 5,23561,3769.112,-5080.867,143.4122,3.473205,6,2500),
+(15990,0, 5,23561,3777.380,-5061.792,143.7722,3.246312,6,2500),
+(15990,0, 5,23562,3760.199,-5065.446,143.6439,1.762783,6,2500),
+(15990,0, 5,23562,3770.308,-5079.318,143.4988,0.261799,6,2500),
+(15990,0, 5,23562,3768.820,-5068.979,143.4071,1.518436,6,2500),
+(15990,0, 5,23563,3769.489,-5073.855,143.3546,5.253441,6,2500),
+(15990,0, 6,23561,3737.419,-5052.975,143.7604,1.169371,6,2500),
+(15990,0, 6,23561,3727.097,-5048.372,143.4038,3.857178,6,2500),
+(15990,0, 6,23561,3737.439,-5041.781,143.7740,3.857178,6,2500),
+(15990,0, 6,23561,3732.787,-5045.659,143.5814,1.937315,6,2500),
+(15990,0, 6,23561,3721.843,-5044.510,143.6988,2.827433,6,2500),
+(15990,0, 6,23561,3728.000,-5031.103,143.8964,0.750492,6,2500),
+(15990,0, 6,23561,3732.647,-5051.030,143.5529,3.246312,6,2500),
+(15990,0, 6,23561,3733.721,-5032.996,143.8625,6.021386,6,2500),
+(15990,0, 6,23561,3728.706,-5043.684,143.4527,1.483530,6,2500),
+(15990,0, 6,23561,3725.062,-5036.629,143.7767,3.874631,6,2500),
+(15990,0, 6,23562,3729.237,-5039.866,143.5873,4.607669,6,2500),
+(15990,0, 6,23562,3718.425,-5046.168,143.7998,5.480334,6,2500),
+(15990,0, 6,23562,3735.658,-5045.499,143.7014,3.595378,6,2500),
+(15990,0, 6,23563,3730.488,-5043.493,143.4955,0.541052,6,2500),
+(15990,0, 7,23561,3681.355,-5048.864,143.5021,6.195919,6,2500),
+(15990,0, 7,23561,3681.005,-5062.944,143.2552,5.131268,6,2500),
+(15990,0, 7,23561,3678.148,-5062.077,143.3822,0.663225,6,2500),
+(15990,0, 7,23561,3679.336,-5055.365,143.3906,4.118977,6,2500),
+(15990,0, 7,23561,3687.639,-5053.579,143.3244,4.736891,6,2500),
+(15990,0, 7,23561,3686.921,-5045.933,143.7372,2.373648,6,2500),
+(15990,0, 7,23561,3683.435,-5059.344,143.2643,3.979351,6,2500),
+(15990,0, 7,23561,3673.546,-5053.107,143.6368,3.595378,6,2500),
+(15990,0, 7,23561,3682.695,-5052.478,143.3708,4.293510,6,2500),
+(15990,0, 7,23561,3689.501,-5058.241,143.2562,2.251475,6,2500),
+(15990,0, 7,23562,3691.315,-5055.122,143.3179,0.191986,6,2500),
+(15990,0, 7,23562,3676.070,-5064.142,143.5163,2.548181,6,2500),
+(15990,0, 7,23562,3682.844,-5058.052,143.2656,5.393067,6,2500),
+(15990,0, 7,23563,3683.868,-5047.447,143.5984,3.176499,6,2500),
+(15990,0, 8,23561,3645.270,-5095.199,143.5504,5.044002,6,2500),
+(15990,0, 8,23561,3649.625,-5084.568,143.7628,5.899213,6,2500),
+(15990,0, 8,23561,3653.785,-5104.293,143.8255,0.314159,6,2500),
+(15990,0, 8,23561,3652.523,-5094.354,143.4423,5.270895,6,2500),
+(15990,0, 8,23561,3660.487,-5089.280,143.6040,3.071779,6,2500),
+(15990,0, 8,23561,3657.886,-5092.163,143.4859,5.201081,6,2500),
+(15990,0, 8,23561,3652.059,-5098.256,143.6083,0.488692,6,2500),
+(15990,0, 8,23561,3654.281,-5085.585,143.7745,3.787364,6,2500),
+(15990,0, 8,23561,3659.438,-5098.578,143.4740,0.890118,6,2500),
+(15990,0, 8,23561,3648.554,-5088.838,143.5358,2.914700,6,2500),
+(15990,0, 8,23562,3655.752,-5101.823,143.6867,1.500983,6,2500),
+(15990,0, 8,23562,3660.398,-5085.446,143.7791,0.959931,6,2500),
+(15990,0, 8,23562,3653.763,-5092.355,143.4888,1.832596,6,2500),
+(15990,0, 8,23563,3648.262,-5095.589,143.5233,2.356194,6,2500),
+(15990,0, 9,23561,3658.025,-5142.342,143.5081,5.305801,6,2500),
+(15990,0, 9,23561,3669.560,-5134.747,143.2598,1.535890,6,2500),
+(15990,0, 9,23561,3661.139,-5135.697,143.5744,4.450590,6,2500),
+(15990,0, 9,23561,3664.328,-5145.051,143.4375,3.124139,6,2500),
+(15990,0, 9,23561,3667.805,-5142.171,143.2627,3.019420,6,2500),
+(15990,0, 9,23561,3664.311,-5132.388,143.3373,2.391101,6,2500),
+(15990,0, 9,23561,3672.570,-5140.829,143.2567,0.261799,6,2500),
+(15990,0, 9,23561,3670.688,-5145.027,143.4145,1.588250,6,2500),
+(15990,0, 9,23561,3663.013,-5138.814,143.3694,2.164208,6,2500),
+(15990,0, 9,23561,3665.966,-5146.641,143.5444,6.195919,6,2500),
+(15990,0, 9,23562,3657.254,-5134.812,143.7300,3.403392,6,2500),
+(15990,0, 9,23562,3668.447,-5147.539,143.6403,1.919862,6,2500),
+(15990,0, 9,23562,3668.889,-5138.345,143.2660,5.393067,6,2500),
+(15990,0, 9,23563,3657.367,-5146.094,143.5471,4.537856,6,2500),
+(15990,0,10,23561,3711.224,-5164.672,143.6237,3.246312,6,2500),
+(15990,0,10,23561,3700.833,-5172.231,143.5864,5.201081,6,2500),
+(15990,0,10,23561,3699.030,-5176.604,143.7459,1.832596,6,2500),
+(15990,0,10,23561,3697.229,-5170.590,143.6790,0.296706,6,2500),
+(15990,0,10,23561,3704.382,-5182.113,143.8819,1.535890,6,2500),
+(15990,0,10,23561,3703.449,-5161.482,143.3858,1.169371,6,2500),
+(15990,0,10,23561,3705.811,-5165.041,143.4159,5.096361,6,2500),
+(15990,0,10,23561,3709.738,-5173.312,143.7188,3.385939,6,2500),
+(15990,0,10,23561,3699.682,-5163.227,143.5664,2.722714,6,2500),
+(15990,0,10,23561,3705.211,-5171.760,143.5495,6.003932,6,2500),
+(15990,0,10,23562,3713.235,-5169.006,143.7999,5.096361,6,2500),
+(15990,0,10,23562,3701.653,-5167.655,143.4993,5.026548,6,2500),
+(15990,0,10,23562,3692.469,-5163.676,143.8974,4.468043,6,2500),
+(15990,0,10,23563,3704.658,-5178.262,143.7575,0.541052,6,2500),
+(15990,0,11,23561,3744.357,-5156.203,143.2584,6.265732,6,2500),
+(15990,0,11,23561,3749.947,-5158.716,143.2683,5.916666,6,2500),
+(15990,0,11,23561,3751.198,-5167.764,143.6369,3.979351,6,2500),
+(15990,0,11,23561,3756.085,-5155.776,143.5713,1.413717,6,2500),
+(15990,0,11,23561,3753.844,-5153.094,143.3717,2.129302,6,2500),
+(15990,0,11,23561,3757.361,-5169.438,143.6923,3.595378,6,2500),
+(15990,0,11,23561,3756.383,-5148.479,143.4877,4.188790,6,2500),
+(15990,0,11,23561,3746.525,-5152.034,143.2641,1.483530,6,2500),
+(15990,0,11,23561,3743.098,-5161.342,143.5548,1.396263,6,2500),
+(15990,0,11,23561,3757.974,-5164.038,143.6063,2.775074,6,2500),
+(15990,0,11,23562,3753.185,-5160.274,143.3716,0.680678,6,2500),
+(15990,0,11,23562,3757.442,-5152.137,143.6637,2.565634,6,2500),
+(15990,0,11,23562,3744.791,-5162.307,143.6026,3.508112,6,2500),
+(15990,0,11,23563,3750.655,-5162.939,143.4338,3.176499,6,2500);
+
+-- =============================== --
+-- Creature hitbox fixes (sniffed) --
+-- =============================== --
+UPDATE `creature_model_info` SET `BoundingRadius`=4,`CombatReach`=6 WHERE `DisplayID`=15945;
+UPDATE `creature_model_info` SET `BoundingRadius`=1.25,`CombatReach`=3.125 WHERE `DisplayID`=16178;
+UPDATE `creature_model_info` SET `BoundingRadius`=0.25,`CombatReach`=5 WHERE `DisplayID`=16586;
+
+-- ==================================================== --
+-- New creature_text for Guardian of Icecrown (sniffed) --
+-- ==================================================== --
+DELETE FROM `creature_text` WHERE `entry`=16441;
+INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`probability`,`BroadcastTextId`,`TextRange`,`comment`) VALUES
+(16441,0,0,"%s fleets after seeing Kel'thuzad fall!",16,100,12391,3,"Guardian of Icecrown EMOTE_FLEE"),
+(16441,1,0,"A Guardian of Icecrown enters the fight!",41,100,32804,3,"Guardian of Icecrown EMOTE_APPEAR");
+
+-- =============================== --
+-- Fix Void Zone delay from sniffs --
+-- =============================== --
+UPDATE `creature_template` SET `BaseAttackTime`=5500 WHERE `entry`=16129;
+
+-- ====================================== --
+-- New AI Names & correct movement speeds --
+-- ====================================== --
+DELETE FROM `smart_scripts` WHERE `entryorguid` in (16427,16428,16429,16441,23561,23562,23563) AND `source_type`=0;
+UPDATE `creature_template` SET `speed_walk`=0.25,`speed_run`=0.285715,`ScriptName`="npc_kelthuzad_skeleton",`AIName`="" WHERE `Entry` in (16427,23561);
+UPDATE `creature_template` SET `speed_walk`=0.1,`speed_run`=0.114286,`ScriptName`="npc_kelthuzad_banshee",`AIName`="" WHERE `Entry` in (16429,23563);
+UPDATE `creature_template` SET `speed_walk`=0.7,`speed_run`=0.800002,`ScriptName`="npc_kelthuzad_abomination",`AIName`="" WHERE `Entry` in (16428,23562);
+UPDATE `creature_template` SET `ScriptName`="npc_kelthuzad_guardian",`AIName`="" WHERE `Entry`=16441;
+
+-- ========================================================= --
+-- Trigger aura for Skeleton explosion and Banshee knockback --
+-- ========================================================= --
+DELETE FROM `creature_template_addon` WHERE `entry` in (16427,23561,16429,23563,30015,30016,30018,30047);
+INSERT INTO `creature_template_addon` (`entry`,`auras`) VALUES
+(16427,"28458"),
+(30015,"28458"),
+(23561,"28458"),
+(30016,"28458"),
+(16429,"28460"),
+(30018,"28460"),
+(23563,"28460"),
+(30047,"28460");
+
+-- ======================================================= --
+-- Sniffed spawn positions for various objects in the room --
+-- ======================================================= --
+UPDATE `gameobject` SET `position_x`=3635.355, `position_y`=-5090.291, `position_z`=142.9834, `rotation0`=0, `rotation1`=0, `rotation2`=-0.7743921, `rotation3`=0.632706 WHERE `guid`=150159; -- door
+UPDATE `gameobject` SET `position_x`=3716.382, `position_y`=-5106.474, `position_z`=141.2899, `rotation0`=0, `rotation1`=0, `rotation2`=-0.6819983, `rotation3`=0.7313538 WHERE `guid`=150160; -- throne
+UPDATE `gameobject` SET `position_x`=3732.656, `position_y`=-5026.173, `position_z`=152.7197, `rotation0`=0, `rotation1`=0, `rotation2`=-0.7743921, `rotation3`=0.632706 WHERE `guid`=150155; -- portal 01
+UPDATE `gameobject` SET `position_x`=3784.165, `position_y`=-5062.077, `position_z`=152.5704, `rotation0`=0, `rotation1`=0, `rotation2`=-0.957571, `rotation3`=0.2881973 WHERE `guid`=150156; -- portal 02
+UPDATE `gameobject` SET `position_x`=3760.238, `position_y`=-5175.256, `position_z`=152.5706, `rotation0`=0, `rotation1`=0, `rotation2`=0.8698883, `rotation3`=0.4932488 WHERE `guid`=150157; -- portal 03
+UPDATE `gameobject` SET `position_x`=3698.601, `position_y`=-5187.073, `position_z`=152.7199, `rotation0`=0, `rotation1`=0, `rotation2`=0.6149149, `rotation3`=0.7885935 WHERE `guid`=150158; -- portal 04
+
+-- ================================== --
+-- Chains spell script (scale factor) --
+-- ================================== --
+DELETE FROM `spell_script_names` WHERE `ScriptName`="spell_kelthuzad_chains";
+INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
+(28410,"spell_kelthuzad_chains");
+
+-- ================================================= --
+-- Fix throne to only be interactable after KT death --
+-- Also fix end of wing portals while we're at it --
+-- ================================================= --
+UPDATE `gameobject_template` SET `flags`=16 WHERE `entry`=181640;
diff --git a/sql/updates/world/3.3.5/2016_08_24_09_world.sql b/sql/updates/world/3.3.5/2016_08_24_09_world.sql
new file mode 100644
index 00000000000..0f8055841f0
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_08_24_09_world.sql
@@ -0,0 +1,30 @@
+--
+DELETE FROM `achievement_criteria_data` WHERE `criteria_id` IN (6140, 6141, 6142);
+INSERT INTO `achievement_criteria_data` (`criteria_id`, `type`, `value1`, `value2`, `ScriptName`) VALUES
+(6140, 24, 4, 0, ""),
+(6141, 24, 5, 0, ""),
+(6142, 24, 4, 0, "");
+
+DELETE FROM `disables` WHERE `sourceType`=4 AND `entry` BETWEEN 4768 AND 4786;
+
+DELETE FROM `achievement_criteria_data` WHERE `criteria_id` BETWEEN 4768 AND 4786;
+INSERT INTO `achievement_criteria_data` (`criteria_id`, `type`, `value1`, `value2`, `ScriptName`) VALUES
+(4768, 24, 4, 0, ""),
+(4769, 24, 4, 0, ""),
+(4770, 24, 4, 0, ""),
+(4771, 24, 4, 0, ""),
+(4772, 24, 4, 0, ""),
+(4773, 24, 4, 0, ""),
+(4774, 24, 4, 0, ""),
+(4775, 24, 4, 0, ""),
+(4776, 24, 4, 0, ""),
+(4777, 24, 4, 0, ""),
+(4778, 24, 4, 0, ""),
+(4779, 24, 4, 0, ""),
+(4780, 24, 4, 0, ""),
+(4781, 24, 4, 0, ""),
+(4782, 24, 4, 0, ""),
+(4783, 24, 4, 0, ""),
+(4784, 24, 4, 0, ""),
+(4785, 24, 4, 0, ""),
+(4786, 24, 4, 0, "");
diff --git a/src/server/game/AI/PlayerAI/PlayerAI.cpp b/src/server/game/AI/PlayerAI/PlayerAI.cpp
index d5c17cce3ad..ee10242262b 100644
--- a/src/server/game/AI/PlayerAI/PlayerAI.cpp
+++ b/src/server/game/AI/PlayerAI/PlayerAI.cpp
@@ -817,7 +817,7 @@ PlayerAI::TargetedSpell SimpleCharmedPlayerAI::SelectAppropriateCastForSpec()
VerifyAndPushSpellCast(spells, SPELL_HAMMER_OF_JUSTICE, TARGET_VICTIM, 6);
VerifyAndPushSpellCast(spells, SPELL_HAND_OF_FREEDOM, TARGET_SELF, 3);
VerifyAndPushSpellCast(spells, SPELL_HAND_OF_PROTECTION, TARGET_SELF, 1);
- if (Creature* creatureCharmer = ObjectAccessor::GetCreature(*me, me->GetCharmerGUID()))
+ if (Creature* creatureCharmer = GetCharmer())
{
if (creatureCharmer->IsDungeonBoss() || creatureCharmer->isWorldBoss())
VerifyAndPushSpellCast(spells, SPELL_HAND_OF_SACRIFICE, creatureCharmer, 10);
@@ -1002,7 +1002,7 @@ PlayerAI::TargetedSpell SimpleCharmedPlayerAI::SelectAppropriateCastForSpec()
case SPEC_DEATH_KNIGHT_BLOOD:
VerifyAndPushSpellCast(spells, SPELL_RUNE_TAP, TARGET_NONE, 2);
VerifyAndPushSpellCast(spells, SPELL_HYSTERIA, TARGET_SELF, 5);
- if (Creature* creatureCharmer = ObjectAccessor::GetCreature(*me, me->GetCharmerGUID()))
+ if (Creature* creatureCharmer = GetCharmer())
if (!creatureCharmer->IsDungeonBoss() && !creatureCharmer->isWorldBoss())
VerifyAndPushSpellCast(spells, SPELL_HYSTERIA, creatureCharmer, 15);
VerifyAndPushSpellCast(spells, SPELL_HEART_STRIKE, TARGET_VICTIM, 2);
@@ -1180,7 +1180,7 @@ PlayerAI::TargetedSpell SimpleCharmedPlayerAI::SelectAppropriateCastForSpec()
}
VerifyAndPushSpellCast(spells, SPELL_TRANQUILITY, TARGET_NONE, 10);
VerifyAndPushSpellCast(spells, SPELL_NATURE_SWIFTNESS, TARGET_NONE, 7);
- if (Creature* creatureCharmer = ObjectAccessor::GetCreature(*me, me->GetCharmerGUID()))
+ if (Creature* creatureCharmer = GetCharmer())
{
VerifyAndPushSpellCast(spells, SPELL_NOURISH, creatureCharmer, 5);
VerifyAndPushSpellCast(spells, SPELL_WILD_GROWTH, creatureCharmer, 5);
@@ -1260,7 +1260,7 @@ PlayerAI::TargetedSpell SimpleCharmedPlayerAI::SelectAppropriateCastForSpec()
static const float CASTER_CHASE_DISTANCE = 28.0f;
void SimpleCharmedPlayerAI::UpdateAI(const uint32 diff)
{
- Creature* charmer = me->GetCharmer() ? me->GetCharmer()->ToCreature() : nullptr;
+ Creature* charmer = GetCharmer();
if (!charmer)
return;
diff --git a/src/server/game/AI/PlayerAI/PlayerAI.h b/src/server/game/AI/PlayerAI/PlayerAI.h
index 18f65485161..b36c0471718 100644
--- a/src/server/game/AI/PlayerAI/PlayerAI.h
+++ b/src/server/game/AI/PlayerAI/PlayerAI.h
@@ -30,6 +30,13 @@ class TC_GAME_API PlayerAI : public UnitAI
void OnCharmed(bool /*apply*/) override { } // charm AI application for players is handled by Unit::SetCharmedBy / Unit::RemoveCharmedBy
+ Creature* GetCharmer() const
+ {
+ if (ObjectGuid charmerGUID = me->GetCharmerGUID())
+ if (charmerGUID.IsCreature())
+ return ObjectAccessor::GetCreature(*me, charmerGUID);
+ return nullptr;
+ }
// helper functions to determine player info
// Return values range from 0 (left-most spec) to 2 (right-most spec). If two specs have the same number of talent points, the left-most of those specs is returned.
static uint8 GetPlayerSpec(Player const* who);
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index 90fad46c21b..f1beca149d1 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -1013,7 +1013,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
if (IsCreature(*itr))
- (*itr)->ToCreature()->UpdateEntry(e.action.updateTemplate.creature);
+ (*itr)->ToCreature()->UpdateEntry(e.action.updateTemplate.creature, nullptr, e.action.updateTemplate.updateLevel != 0);
delete targets;
break;
@@ -2758,6 +2758,11 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /*
ObjectGuid charmerOrOwnerGuid = me->GetCharmerOrOwnerGUID();
if (!charmerOrOwnerGuid)
+ if (TempSummon* tempSummon = me->ToTempSummon())
+ if (Unit* summoner = tempSummon->GetSummoner())
+ charmerOrOwnerGuid = summoner->GetGUID();
+
+ if (!charmerOrOwnerGuid)
charmerOrOwnerGuid = me->GetCreatorGUID();
if (Unit* owner = ObjectAccessor::GetUnit(*me, charmerOrOwnerGuid))
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
index e0f5dac4f5e..28d434ad988 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
@@ -740,6 +740,7 @@ struct SmartAction
struct
{
uint32 creature;
+ uint32 updateLevel;
} updateTemplate;
struct
diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp
index 2356b2098ff..37b44b3d952 100644
--- a/src/server/game/Achievements/AchievementMgr.cpp
+++ b/src/server/game/Achievements/AchievementMgr.cpp
@@ -77,6 +77,8 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
case ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN:
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM:
+ case ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM:
break;
default:
if (dataType != ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT)
@@ -237,11 +239,12 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
return true;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE:
return true; // not check correctness node indexes
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPED_ITEM:
+ case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPPED_ITEM:
+ case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_ITEM_QUALITY:
if (equipped_item.item_quality >= MAX_ITEM_QUALITY)
{
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPED_ITEM (%u) contains an unknown quality state value in value1 (%u), ignored.",
- criteria->ID, criteria->Type, dataType, equipped_item.item_quality);
+ TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type %s (%u) contains an unknown quality state value in value1 (%u), ignored.",
+ criteria->ID, criteria->Type, (dataType == ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPPED_ITEM ? "ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPPED_ITEM" : "ACHIEVEMENT_CRITERIA_DATA_TYPE_S_ITEM_QUALITY"), dataType, equipped_item.item_quality);
return false;
}
return true;
@@ -390,7 +393,7 @@ bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Un
}
return instance->CheckAchievementCriteriaMeet(criteria_id, source, target, miscvalue1);
}
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPED_ITEM:
+ case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPPED_ITEM:
{
ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(miscvalue1);
if (!pProto)
@@ -418,6 +421,13 @@ bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Un
return source->HasTitle(titleInfo->bit_index);
return false;
}
+ case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_ITEM_QUALITY:
+ {
+ ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(miscvalue1);
+ if (!pProto)
+ return false;
+ return pProto->Quality == item.item_quality;
+ }
default:
break;
}
diff --git a/src/server/game/Achievements/AchievementMgr.h b/src/server/game/Achievements/AchievementMgr.h
index bdbd9e04446..21ff1b234d8 100644
--- a/src/server/game/Achievements/AchievementMgr.h
+++ b/src/server/game/Achievements/AchievementMgr.h
@@ -66,14 +66,15 @@ enum AchievementCriteriaDataType
ACHIEVEMENT_CRITERIA_DATA_TYPE_HOLIDAY = 16, // holiday_id 0 event in holiday time
ACHIEVEMENT_CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE = 17, // min_score max_score player's team win bg and opposition team have team score in range
ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT = 18, // 0 0 maker instance script call for check current criteria requirements fit
- ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPED_ITEM = 19, // item_level item_quality for equipped item in slot to check item level and quality
+ ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPPED_ITEM = 19, // item_level item_quality for equipped item in slot to check item level and quality
ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_ID = 20, // map_id 0 player must be on map with id in map_id
ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE = 21, // class_id race_id
ACHIEVEMENT_CRITERIA_DATA_TYPE_NTH_BIRTHDAY = 22, // N login on day of N-th Birthday
- ACHIEVEMENT_CRITERIA_DATA_TYPE_S_KNOWN_TITLE = 23 // title_id known (pvp) title, values from dbc
+ ACHIEVEMENT_CRITERIA_DATA_TYPE_S_KNOWN_TITLE = 23, // title_id known (pvp) title, values from dbc
+ ACHIEVEMENT_CRITERIA_DATA_TYPE_S_ITEM_QUALITY = 24 // item_quality
};
-#define MAX_ACHIEVEMENT_CRITERIA_DATA_TYPE 24 // maximum value in AchievementCriteriaDataType enum
+#define MAX_ACHIEVEMENT_CRITERIA_DATA_TYPE 25 // maximum value in AchievementCriteriaDataType enum
struct AchievementCriteriaData
{
@@ -164,7 +165,7 @@ struct AchievementCriteriaData
uint32 max_score;
} bg_loss_team_score;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT = 18 (no data)
- // ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPED_ITEM = 19
+ // ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPPED_ITEM = 19
struct
{
uint32 item_level;
@@ -185,6 +186,11 @@ struct AchievementCriteriaData
{
uint32 title_id;
} known_title;
+ // ACHIEVEMENT_CRITERIA_DATA_TYPE_S_ITEM_QUALITY = 23
+ struct
+ {
+ uint32 item_quality;
+ } item;
// ...
struct
{
diff --git a/src/server/game/Battlefield/Battlefield.cpp b/src/server/game/Battlefield/Battlefield.cpp
index f44099f6037..85e1c701aff 100644
--- a/src/server/game/Battlefield/Battlefield.cpp
+++ b/src/server/game/Battlefield/Battlefield.cpp
@@ -39,7 +39,7 @@ Battlefield::Battlefield()
m_TypeId = 0;
m_BattleId = 0;
m_ZoneId = 0;
- m_Map = NULL;
+ m_Map = nullptr;
m_MapId = 0;
m_MaxPlayer = 0;
m_MinPlayer = 0;
@@ -79,7 +79,7 @@ void Battlefield::HandlePlayerEnterZone(Player* player, uint32 /*zone*/)
else // No more vacant places
{
/// @todo Send a packet to announce it to player
- m_PlayersWillBeKick[player->GetTeamId()][player->GetGUID()] = time(NULL) + 10;
+ m_PlayersWillBeKick[player->GetTeamId()][player->GetGUID()] = time(nullptr) + 10;
InvitePlayerToQueue(player);
}
}
@@ -158,14 +158,14 @@ bool Battlefield::Update(uint32 diff)
// Kick players who chose not to accept invitation to the battle
if (m_uiKickDontAcceptTimer <= diff)
{
- time_t now = time(NULL);
- for (int team = 0; team < 2; team++)
+ time_t now = time(nullptr);
+ for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team)
for (PlayerTimerMap::iterator itr = m_InvitedPlayers[team].begin(); itr != m_InvitedPlayers[team].end(); ++itr)
if (itr->second <= now)
KickPlayerFromBattlefield(itr->first);
InvitePlayersInZoneToWar();
- for (int team = 0; team < 2; team++)
+ for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team)
for (PlayerTimerMap::iterator itr = m_PlayersWillBeKick[team].begin(); itr != m_PlayersWillBeKick[team].end(); ++itr)
if (itr->second <= now)
KickPlayerFromBattlefield(itr->first);
@@ -196,7 +196,7 @@ bool Battlefield::Update(uint32 diff)
void Battlefield::InvitePlayersInZoneToQueue()
{
- for (uint8 team = 0; team < 2; ++team)
+ 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* player = ObjectAccessor::FindPlayer(*itr))
InvitePlayerToQueue(player);
@@ -243,7 +243,7 @@ void Battlefield::InvitePlayersInZoneToWar()
if (m_PlayersInWar[player->GetTeamId()].size() + m_InvitedPlayers[player->GetTeamId()].size() < m_MaxPlayer)
InvitePlayerToWar(player);
else // Battlefield is full of players
- m_PlayersWillBeKick[player->GetTeamId()][player->GetGUID()] = time(NULL) + 10;
+ m_PlayersWillBeKick[player->GetTeamId()][player->GetGUID()] = time(nullptr) + 10;
}
}
}
@@ -267,7 +267,7 @@ void Battlefield::InvitePlayerToWar(Player* player)
if (player->getLevel() < m_MinLevel)
{
if (m_PlayersWillBeKick[player->GetTeamId()].count(player->GetGUID()) == 0)
- m_PlayersWillBeKick[player->GetTeamId()][player->GetGUID()] = time(NULL) + 10;
+ m_PlayersWillBeKick[player->GetTeamId()][player->GetGUID()] = time(nullptr) + 10;
return;
}
@@ -276,13 +276,13 @@ void Battlefield::InvitePlayerToWar(Player* player)
return;
m_PlayersWillBeKick[player->GetTeamId()].erase(player->GetGUID());
- m_InvitedPlayers[player->GetTeamId()][player->GetGUID()] = time(NULL) + m_TimeForAcceptInvite;
+ m_InvitedPlayers[player->GetTeamId()][player->GetGUID()] = time(nullptr) + m_TimeForAcceptInvite;
player->GetSession()->SendBfInvitePlayerToWar(m_BattleId, m_ZoneId, m_TimeForAcceptInvite);
}
void Battlefield::InitStalker(uint32 entry, Position const& pos)
{
- if (Creature* creature = SpawnCreature(entry, pos, TEAM_NEUTRAL))
+ if (Creature* creature = SpawnCreature(entry, pos))
StalkerGuid = creature->GetGUID();
else
TC_LOG_ERROR("bg.battlefield", "Battlefield::InitStalker: Could not spawn Stalker (Creature entry %u), zone messages will be unavailable!", entry);
@@ -309,7 +309,7 @@ void Battlefield::StartBattle()
if (m_isActive)
return;
- for (int team = 0; team < BG_TEAMS_COUNT; team++)
+ for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team)
{
m_PlayersInWar[team].clear();
m_Groups[team].clear();
@@ -487,7 +487,7 @@ Group* Battlefield::GetFreeBfRaid(TeamId TeamId)
if (!group->IsFull())
return group;
- return NULL;
+ return nullptr;
}
Group* Battlefield::GetGroupPlayer(ObjectGuid guid, TeamId TeamId)
@@ -497,7 +497,7 @@ Group* Battlefield::GetGroupPlayer(ObjectGuid guid, TeamId TeamId)
if (group->IsMember(guid))
return group;
- return NULL;
+ return nullptr;
}
bool Battlefield::AddOrSetPlayerToCorrectBfGroup(Player* player)
@@ -549,12 +549,12 @@ BfGraveyard* Battlefield::GetGraveyardById(uint32 id) const
else
TC_LOG_ERROR("bg.battlefield", "Battlefield::GetGraveyardById Id:%u could not be found.", id);
- return NULL;
+ return nullptr;
}
WorldSafeLocsEntry const* Battlefield::GetClosestGraveYard(Player* player)
{
- BfGraveyard* closestGY = NULL;
+ BfGraveyard* closestGY = nullptr;
float maxdist = -1;
for (uint8 i = 0; i < m_GraveyardList.size(); i++)
{
@@ -575,7 +575,7 @@ WorldSafeLocsEntry const* Battlefield::GetClosestGraveYard(Player* player)
if (closestGY)
return sWorldSafeLocsStore.LookupEntry(closestGY->GetGraveyardId());
- return NULL;
+ return nullptr;
}
void Battlefield::AddPlayerToResurrectQueue(ObjectGuid npcGuid, ObjectGuid playerGuid)
@@ -625,8 +625,6 @@ BfGraveyard::BfGraveyard(Battlefield* battlefield)
m_Bf = battlefield;
m_GraveyardId = 0;
m_ControlTeam = TEAM_NEUTRAL;
- m_SpiritGuide[0].Clear();
- m_SpiritGuide[1].Clear();
}
void BfGraveyard::Initialize(TeamId startControl, uint32 graveyardId)
@@ -649,7 +647,7 @@ void BfGraveyard::SetSpirit(Creature* spirit, TeamId team)
float BfGraveyard::GetDistance(Player* player)
{
- const WorldSafeLocsEntry* safeLoc = sWorldSafeLocsStore.LookupEntry(m_GraveyardId);
+ WorldSafeLocsEntry const* safeLoc = sWorldSafeLocsStore.LookupEntry(m_GraveyardId);
return player->GetDistance2d(safeLoc->x, safeLoc->y);
}
@@ -718,7 +716,7 @@ void BfGraveyard::GiveControlTo(TeamId team)
void BfGraveyard::RelocateDeadPlayers()
{
- WorldSafeLocsEntry const* closestGrave = NULL;
+ WorldSafeLocsEntry const* closestGrave = nullptr;
for (GuidSet::const_iterator itr = m_ResurrectQueue.begin(); itr != m_ResurrectQueue.end(); ++itr)
{
Player* player = ObjectAccessor::FindPlayer(*itr);
@@ -738,14 +736,14 @@ void BfGraveyard::RelocateDeadPlayers()
bool BfGraveyard::HasNpc(ObjectGuid guid)
{
- if (!m_SpiritGuide[0] || !m_SpiritGuide[1])
+ if (!m_SpiritGuide[TEAM_ALLIANCE] || !m_SpiritGuide[TEAM_HORDE])
return false;
- if (!m_Bf->GetCreature(m_SpiritGuide[0]) ||
- !m_Bf->GetCreature(m_SpiritGuide[1]))
+ if (!m_Bf->GetCreature(m_SpiritGuide[TEAM_ALLIANCE]) ||
+ !m_Bf->GetCreature(m_SpiritGuide[TEAM_HORDE]))
return false;
- return (m_SpiritGuide[0] == guid || m_SpiritGuide[1] == guid);
+ return (m_SpiritGuide[TEAM_ALLIANCE] == guid || m_SpiritGuide[TEAM_HORDE] == guid);
}
// *******************************************************
@@ -754,12 +752,7 @@ bool BfGraveyard::HasNpc(ObjectGuid guid)
// ********************** Misc ***************************
// *******************************************************
-Creature* Battlefield::SpawnCreature(uint32 entry, Position const& pos, TeamId teamId)
-{
- return SpawnCreature(entry, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), teamId);
-}
-
-Creature* Battlefield::SpawnCreature(uint32 entry, float x, float y, float z, float o, TeamId /*teamId*/)
+Creature* Battlefield::SpawnCreature(uint32 entry, Position const& pos)
{
//Get map object
Map* map = sMapMgr->CreateBaseMap(m_MapId);
@@ -769,6 +762,9 @@ Creature* Battlefield::SpawnCreature(uint32 entry, float x, float y, float z, fl
return nullptr;
}
+ float x, y, z, o;
+ pos.GetPosition(x, y, z, o);
+
Creature* creature = new Creature();
if (!creature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, PHASEMASK_NORMAL, entry, x, y, z, o))
{
@@ -779,13 +775,6 @@ Creature* Battlefield::SpawnCreature(uint32 entry, float x, float y, float z, fl
creature->SetHomePosition(x, y, z, o);
- CreatureTemplate const* cinfo = sObjectMgr->GetCreatureTemplate(entry);
- if (!cinfo)
- {
- TC_LOG_ERROR("bg.battlefield", "Battlefield::SpawnCreature: Entry %u does not exist.", entry);
- return nullptr;
- }
-
// Set creature in world
map->AddToMap(creature);
creature->setActive(true);
@@ -794,19 +783,16 @@ Creature* Battlefield::SpawnCreature(uint32 entry, float x, float y, float z, fl
}
// Method for spawning gameobject on map
-GameObject* Battlefield::SpawnGameObject(uint32 entry, float x, float y, float z, float o)
+GameObject* Battlefield::SpawnGameObject(uint32 entry, Position const& pos, G3D::Quat const& rot)
{
// Get map object
Map* map = sMapMgr->CreateBaseMap(m_MapId);
if (!map)
- return 0;
-
- // Calculate rotation
- G3D::Quat rot = G3D::Matrix3::fromEulerAnglesZYX(o, 0.f, 0.f);
+ return nullptr;
// Create gameobject
GameObject* go = new GameObject;
- if (!go->Create(map->GenerateLowGuid<HighGuid::GameObject>(), entry, map, PHASEMASK_NORMAL, Position(x, y, z, o), rot, 255, GO_STATE_READY))
+ if (!go->Create(map->GenerateLowGuid<HighGuid::GameObject>(), entry, map, PHASEMASK_NORMAL, pos, rot, 255, GO_STATE_READY))
{
TC_LOG_ERROR("bg.battlefield", "Battlefield::SpawnGameObject: Gameobject template %u could not be found in the database! Battlefield has not been created!", entry);
TC_LOG_ERROR("bg.battlefield", "Battlefield::SpawnGameObject: Could not create gameobject template %u! Battlefield has not been created!", entry);
@@ -824,14 +810,14 @@ GameObject* Battlefield::SpawnGameObject(uint32 entry, float x, float y, float z
Creature* Battlefield::GetCreature(ObjectGuid guid)
{
if (!m_Map)
- return NULL;
+ return nullptr;
return m_Map->GetCreature(guid);
}
GameObject* Battlefield::GetGameObject(ObjectGuid guid)
{
if (!m_Map)
- return NULL;
+ return nullptr;
return m_Map->GetGameObject(guid);
}
@@ -947,7 +933,7 @@ bool BfCapturePoint::DelCapturePoint()
{
capturePoint->SetRespawnTime(0); // not save respawn time
capturePoint->Delete();
- capturePoint = NULL;
+ capturePoint = nullptr;
}
m_capturePointGUID.Clear();
}
@@ -964,7 +950,7 @@ bool BfCapturePoint::Update(uint32 diff)
{
float radius = capturePoint->GetGOInfo()->capturePoint.radius;
- for (uint8 team = 0; team < 2; ++team)
+ for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team)
{
for (GuidSet::iterator itr = m_activePlayers[team].begin(); itr != m_activePlayers[team].end();)
{
@@ -992,7 +978,7 @@ bool BfCapturePoint::Update(uint32 diff)
}
// get the difference of numbers
- float fact_diff = ((float) m_activePlayers[0].size() - (float) m_activePlayers[1].size()) * diff / BATTLEFIELD_OBJECTIVE_UPDATE_INTERVAL;
+ float fact_diff = ((float) m_activePlayers[TEAM_ALLIANCE].size() - (float) m_activePlayers[TEAM_HORDE].size()) * diff / BATTLEFIELD_OBJECTIVE_UPDATE_INTERVAL;
if (G3D::fuzzyEq(fact_diff, 0.0f))
return false;
@@ -1079,7 +1065,7 @@ bool BfCapturePoint::Update(uint32 diff)
void BfCapturePoint::SendUpdateWorldState(uint32 field, uint32 value)
{
- for (uint8 team = 0; team < 2; ++team)
+ for (uint8 team = 0; team < BG_TEAMS_COUNT; ++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* player = ObjectAccessor::FindPlayer(*itr))
player->SendUpdateWorldState(field, value);
@@ -1091,10 +1077,10 @@ void BfCapturePoint::SendObjectiveComplete(uint32 id, ObjectGuid guid)
switch (m_State)
{
case BF_CAPTUREPOINT_OBJECTIVESTATE_ALLIANCE:
- team = 0;
+ team = TEAM_ALLIANCE;
break;
case BF_CAPTUREPOINT_OBJECTIVESTATE_HORDE:
- team = 1;
+ team = TEAM_HORDE;
break;
default:
return;
diff --git a/src/server/game/Battlefield/Battlefield.h b/src/server/game/Battlefield/Battlefield.h
index 6968e31c7bd..99d92f7a545 100644
--- a/src/server/game/Battlefield/Battlefield.h
+++ b/src/server/game/Battlefield/Battlefield.h
@@ -280,9 +280,8 @@ class TC_GAME_API Battlefield : public ZoneScript
BfGraveyard* GetGraveyardById(uint32 id) const;
// Misc methods
- virtual Creature* SpawnCreature(uint32 entry, float x, float y, float z, float o, TeamId /*teamId*/);
- Creature* SpawnCreature(uint32 entry, Position const& pos, TeamId /*teamId*/);
- GameObject* SpawnGameObject(uint32 entry, float x, float y, float z, float o);
+ Creature* SpawnCreature(uint32 entry, Position const& pos);
+ GameObject* SpawnGameObject(uint32 entry, Position const& pos, G3D::Quat const& rot);
Creature* GetCreature(ObjectGuid guid);
GameObject* GetGameObject(ObjectGuid guid);
diff --git a/src/server/game/Battlefield/BattlefieldMgr.cpp b/src/server/game/Battlefield/BattlefieldMgr.cpp
index 1df87fe1d6f..8eae2f2d9d0 100644
--- a/src/server/game/Battlefield/BattlefieldMgr.cpp
+++ b/src/server/game/Battlefield/BattlefieldMgr.cpp
@@ -109,11 +109,11 @@ Battlefield* BattlefieldMgr::GetBattlefieldToZoneId(uint32 zoneId)
if (itr == _battlefieldMap.end())
{
// no handle for this zone, return
- return NULL;
+ return nullptr;
}
if (!itr->second->IsEnabled())
- return NULL;
+ return nullptr;
return itr->second;
}
@@ -125,7 +125,7 @@ Battlefield* BattlefieldMgr::GetBattlefieldByBattleId(uint32 battleId)
if ((*itr)->GetBattleId() == battleId)
return *itr;
}
- return NULL;
+ return nullptr;
}
ZoneScript* BattlefieldMgr::GetZoneScript(uint32 zoneId)
@@ -134,7 +134,7 @@ ZoneScript* BattlefieldMgr::GetZoneScript(uint32 zoneId)
if (itr != _battlefieldMap.end())
return itr->second;
- return NULL;
+ return nullptr;
}
void BattlefieldMgr::Update(uint32 diff)
diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp
index 3c9bf40f66c..2cf7059f7a8 100644
--- a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp
+++ b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp
@@ -31,6 +31,452 @@
#include "TemporarySummon.h"
#include "WorldSession.h"
+struct BfWGCoordGY
+{
+ Position Pos;
+ uint32 GraveyardID;
+ uint32 TextID; // for gossip menu
+ TeamId StartControl;
+};
+
+// 7 in sql, 7 in header
+BfWGCoordGY const WGGraveYard[BATTLEFIELD_WG_GRAVEYARD_MAX] =
+{
+ { { 5104.750f, 2300.940f, 368.579f, 0.733038f }, 1329, BATTLEFIELD_WG_GOSSIPTEXT_GY_NE, TEAM_NEUTRAL },
+ { { 5099.120f, 3466.036f, 368.484f, 5.317802f }, 1330, BATTLEFIELD_WG_GOSSIPTEXT_GY_NW, TEAM_NEUTRAL },
+ { { 4314.648f, 2408.522f, 392.642f, 6.268125f }, 1333, BATTLEFIELD_WG_GOSSIPTEXT_GY_SE, TEAM_NEUTRAL },
+ { { 4331.716f, 3235.695f, 390.251f, 0.008500f }, 1334, BATTLEFIELD_WG_GOSSIPTEXT_GY_SW, TEAM_NEUTRAL },
+ { { 5537.986f, 2897.493f, 517.057f, 4.819249f }, 1285, BATTLEFIELD_WG_GOSSIPTEXT_GY_KEEP, TEAM_NEUTRAL },
+ { { 5032.454f, 3711.382f, 372.468f, 3.971623f }, 1331, BATTLEFIELD_WG_GOSSIPTEXT_GY_HORDE, TEAM_HORDE },
+ { { 5140.790f, 2179.120f, 390.950f, 1.972220f }, 1332, BATTLEFIELD_WG_GOSSIPTEXT_GY_ALLIANCE, TEAM_ALLIANCE },
+};
+
+uint32 const ClockWorldState[] = { 3781, 4354 };
+uint32 const WintergraspFaction[] = { 1732, 1735, 35 };
+
+Position const WintergraspStalkerPos = { 4948.985f, 2937.789f, 550.5172f, 1.815142f };
+
+Position const WintergraspRelicPos = { 5440.379f, 2840.493f, 430.2816f, -1.832595f };
+G3D::Quat const WintergraspRelicRot = { 0.f, 0.f, -0.7933531f, 0.6087617f };
+
+uint8 const WG_MAX_OBJ = 32;
+uint8 const WG_MAX_TURRET = 15;
+uint8 const WG_MAX_KEEP_NPC = 39;
+uint8 const WG_MAX_OUTSIDE_NPC = 14;
+uint8 const WG_OUTSIDE_ALLIANCE_NPC = 7;
+uint8 const WG_MAX_TELEPORTER = 12;
+uint8 const WG_MAX_WORKSHOP = 6;
+uint8 const WG_MAX_TOWER = 7;
+
+// *****************************************************
+// ************ Destructible (Wall, Tower..) ***********
+// *****************************************************
+
+struct WintergraspBuildingSpawnData
+{
+ uint32 entry;
+ uint32 WorldState;
+ Position pos;
+ G3D::Quat rot;
+ WintergraspGameObjectBuildingType type;
+};
+
+WintergraspBuildingSpawnData const WGGameObjectBuilding[WG_MAX_OBJ] =
+{
+ // Wall (Not spawned in db)
+ // Entry WS X Y Z O rX rY rZ rW Type
+ { 190219, 3749, { 5371.457f, 3047.472f, 407.5710f, 3.14159300f }, { 0.f, 0.f, -1.000000000f, 0.00000000f }, BATTLEFIELD_WG_OBJECTTYPE_WALL },
+ { 190220, 3750, { 5331.264f, 3047.105f, 407.9228f, 0.05235888f }, { 0.f, 0.f, 0.026176450f, 0.99965730f }, BATTLEFIELD_WG_OBJECTTYPE_WALL },
+ { 191795, 3764, { 5385.841f, 2909.490f, 409.7127f, 0.00872424f }, { 0.f, 0.f, 0.004362106f, 0.99999050f }, BATTLEFIELD_WG_OBJECTTYPE_WALL },
+ { 191796, 3772, { 5384.452f, 2771.835f, 410.2704f, 3.14159300f }, { 0.f, 0.f, -1.000000000f, 0.00000000f }, BATTLEFIELD_WG_OBJECTTYPE_WALL },
+ { 191799, 3762, { 5371.436f, 2630.610f, 408.8163f, 3.13285800f }, { 0.f, 0.f, 0.999990500f, 0.00436732f }, BATTLEFIELD_WG_OBJECTTYPE_WALL },
+ { 191800, 3766, { 5301.838f, 2909.089f, 409.8661f, 0.00872424f }, { 0.f, 0.f, 0.004362106f, 0.99999050f }, BATTLEFIELD_WG_OBJECTTYPE_WALL },
+ { 191801, 3770, { 5301.063f, 2771.411f, 409.9014f, 3.14159300f }, { 0.f, 0.f, -1.000000000f, 0.00000000f }, BATTLEFIELD_WG_OBJECTTYPE_WALL },
+ { 191802, 3751, { 5280.197f, 2995.583f, 408.8249f, 1.61442800f }, { 0.f, 0.f, 0.722363500f, 0.69151360f }, BATTLEFIELD_WG_OBJECTTYPE_WALL },
+ { 191803, 3752, { 5279.136f, 2956.023f, 408.6041f, 1.57079600f }, { 0.f, 0.f, 0.707106600f, 0.70710690f }, BATTLEFIELD_WG_OBJECTTYPE_WALL },
+ { 191804, 3767, { 5278.685f, 2882.513f, 409.5388f, 1.57079600f }, { 0.f, 0.f, 0.707106600f, 0.70710690f }, BATTLEFIELD_WG_OBJECTTYPE_WALL },
+ { 191806, 3769, { 5279.502f, 2798.945f, 409.9983f, 1.57079600f }, { 0.f, 0.f, 0.707106600f, 0.70710690f }, BATTLEFIELD_WG_OBJECTTYPE_WALL },
+ { 191807, 3759, { 5279.937f, 2724.766f, 409.9452f, 1.56207000f }, { 0.f, 0.f, 0.704014800f, 0.71018530f }, BATTLEFIELD_WG_OBJECTTYPE_WALL },
+ { 191808, 3760, { 5279.601f, 2683.786f, 409.8488f, 1.55334100f }, { 0.f, 0.f, 0.700908700f, 0.71325110f }, BATTLEFIELD_WG_OBJECTTYPE_WALL },
+ { 191809, 3761, { 5330.955f, 2630.777f, 409.2826f, 3.13285800f }, { 0.f, 0.f, 0.999990500f, 0.00436732f }, BATTLEFIELD_WG_OBJECTTYPE_WALL },
+ { 190369, 3753, { 5256.085f, 2933.963f, 409.3571f, 3.13285800f }, { 0.f, 0.f, 0.999990500f, 0.00436732f }, BATTLEFIELD_WG_OBJECTTYPE_WALL },
+ { 190370, 3758, { 5257.463f, 2747.327f, 409.7427f, -3.13285800f }, { 0.f, 0.f, -0.999990500f, 0.00436732f }, BATTLEFIELD_WG_OBJECTTYPE_WALL },
+ { 190371, 3754, { 5214.960f, 2934.089f, 409.1905f, -0.00872424f }, { 0.f, 0.f, -0.004362106f, 0.99999050f }, BATTLEFIELD_WG_OBJECTTYPE_WALL },
+ { 190372, 3757, { 5215.821f, 2747.566f, 409.1884f, -3.13285800f }, { 0.f, 0.f, -0.999990500f, 0.00436732f }, BATTLEFIELD_WG_OBJECTTYPE_WALL },
+ { 190374, 3755, { 5162.273f, 2883.043f, 410.2556f, 1.57952200f }, { 0.f, 0.f, 0.710185100f, 0.70401500f }, BATTLEFIELD_WG_OBJECTTYPE_WALL },
+ { 190376, 3756, { 5163.724f, 2799.838f, 409.2270f, 1.57952200f }, { 0.f, 0.f, 0.710185100f, 0.70401500f }, BATTLEFIELD_WG_OBJECTTYPE_WALL },
+
+ // Tower of keep (Not spawned in db)
+ { 190221, 3711, { 5281.154f, 3044.588f, 407.8434f, 3.115388f }, { 0.f, 0.f, 0.9999142f, 0.013101960f }, BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER }, // NW
+ { 190373, 3713, { 5163.757f, 2932.228f, 409.1904f, 3.124123f }, { 0.f, 0.f, 0.9999619f, 0.008734641f }, BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER }, // SW
+ { 190377, 3714, { 5166.397f, 2748.368f, 409.1884f, -1.570796f }, { 0.f, 0.f, -0.7071066f, 0.707106900f }, BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER }, // SE
+ { 190378, 3712, { 5281.192f, 2632.479f, 409.0985f, -1.588246f }, { 0.f, 0.f, -0.7132492f, 0.700910500f }, BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER }, // NE
+
+ // Wall (with passage) (Not spawned in db)
+ { 191797, 3765, { 5343.290f, 2908.860f, 409.5757f, 0.00872424f }, { 0.f, 0.f, 0.004362106f, 0.9999905f }, BATTLEFIELD_WG_OBJECTTYPE_WALL },
+ { 191798, 3771, { 5342.719f, 2771.386f, 409.6249f, 3.14159300f }, { 0.f, 0.f, -1.000000000f, 0.0000000f }, BATTLEFIELD_WG_OBJECTTYPE_WALL },
+ { 191805, 3768, { 5279.126f, 2840.797f, 409.7826f, 1.57952200f }, { 0.f, 0.f, 0.710185100f, 0.7040150f }, BATTLEFIELD_WG_OBJECTTYPE_WALL },
+
+ // South tower (Not spawned in db)
+ { 190356, 3704, { 4557.173f, 3623.943f, 395.8828f, 1.675516f }, { 0.f, 0.f, 0.7431450f, 0.669130400f }, BATTLEFIELD_WG_OBJECTTYPE_TOWER }, // W
+ { 190357, 3705, { 4398.172f, 2822.497f, 405.6270f, -3.124123f }, { 0.f, 0.f, -0.9999619f, 0.008734641f }, BATTLEFIELD_WG_OBJECTTYPE_TOWER }, // S
+ { 190358, 3706, { 4459.105f, 1944.326f, 434.9912f, -2.002762f }, { 0.f, 0.f, -0.8422165f, 0.539139500f }, BATTLEFIELD_WG_OBJECTTYPE_TOWER }, // E
+
+ // Door of forteress (Not spawned in db)
+ { GO_WINTERGRASP_FORTRESS_GATE, 3763, { 5162.991f, 2841.232f, 410.1892f, -3.132858f }, { 0.f, 0.f, -0.9999905f, 0.00436732f }, BATTLEFIELD_WG_OBJECTTYPE_DOOR },
+
+ // Last door (Not spawned in db)
+ { GO_WINTERGRASP_VAULT_GATE, 3773, { 5397.108f, 2841.54f, 425.9014f, 3.141593f }, { 0.f, 0.f, -1.f, 0.f }, BATTLEFIELD_WG_OBJECTTYPE_DOOR_LAST },
+};
+
+struct StaticWintergraspTowerInfo
+{
+ uint8 TowerId;
+
+ struct
+ {
+ uint8 Damaged;
+ uint8 Destroyed;
+ } TextIds;
+};
+
+StaticWintergraspTowerInfo const TowerData[WG_MAX_TOWER] =
+{
+ { BATTLEFIELD_WG_TOWER_FORTRESS_NW, { BATTLEFIELD_WG_TEXT_NW_KEEPTOWER_DAMAGE, BATTLEFIELD_WG_TEXT_NW_KEEPTOWER_DESTROY } },
+ { BATTLEFIELD_WG_TOWER_FORTRESS_SW, { BATTLEFIELD_WG_TEXT_SW_KEEPTOWER_DAMAGE, BATTLEFIELD_WG_TEXT_SW_KEEPTOWER_DESTROY } },
+ { BATTLEFIELD_WG_TOWER_FORTRESS_SE, { BATTLEFIELD_WG_TEXT_SE_KEEPTOWER_DAMAGE, BATTLEFIELD_WG_TEXT_SE_KEEPTOWER_DESTROY } },
+ { BATTLEFIELD_WG_TOWER_FORTRESS_NE, { BATTLEFIELD_WG_TEXT_NE_KEEPTOWER_DAMAGE, BATTLEFIELD_WG_TEXT_NE_KEEPTOWER_DESTROY } },
+ { BATTLEFIELD_WG_TOWER_SHADOWSIGHT, { BATTLEFIELD_WG_TEXT_WESTERN_TOWER_DAMAGE, BATTLEFIELD_WG_TEXT_WESTERN_TOWER_DESTROY } },
+ { BATTLEFIELD_WG_TOWER_WINTER_S_EDGE, { BATTLEFIELD_WG_TEXT_SOUTHERN_TOWER_DAMAGE, BATTLEFIELD_WG_TEXT_SOUTHERN_TOWER_DESTROY } },
+ { BATTLEFIELD_WG_TOWER_FLAMEWATCH, { BATTLEFIELD_WG_TEXT_EASTERN_TOWER_DAMAGE, BATTLEFIELD_WG_TEXT_EASTERN_TOWER_DESTROY } }
+};
+
+Position const 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 },
+};
+
+struct WintergraspObjectPositionData
+{
+ Position Pos;
+ uint32 HordeEntry;
+ uint32 AllianceEntry;
+};
+
+// Here there is all npc keeper spawn point
+WintergraspObjectPositionData const 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 Blazefeather
+ { { 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
+};
+
+WintergraspObjectPositionData const 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 WintergraspTeleporterData
+{
+ uint32 Entry;
+ Position Pos;
+ G3D::Quat Rot;
+};
+
+WintergraspTeleporterData const WGPortalDefenderData[WG_MAX_TELEPORTER + 10] =
+{
+ // Player teleporter
+ { 190763, { 5153.408f, 2901.349f, 409.1913f, -0.06981169f }, { 0.f, 0.f, -0.03489876f, 0.9993908f } },
+ { 191575, { 5153.408f, 2901.349f, 409.1913f, -0.06981169f }, { 0.f, 0.f, -0.03489876f, 0.9993908f } },
+ { 190763, { 5153.931f, 2781.671f, 409.2455f, 1.65806200f }, { 0.f, 0.f, 0.73727700f, 0.6755905f } },
+ { 191575, { 5153.931f, 2781.671f, 409.2455f, 1.65806200f }, { 0.f, 0.f, 0.73727700f, 0.6755905f } },
+ { 190763, { 5196.671f, 2737.345f, 409.1892f, -2.93213900f }, { 0.f, 0.f, -0.99452110f, 0.1045355f } },
+ { 191575, { 5196.671f, 2737.345f, 409.1892f, -2.93213900f }, { 0.f, 0.f, -0.99452110f, 0.1045355f } },
+ { 190763, { 5197.050f, 2944.814f, 409.1913f, 2.33874000f }, { 0.f, 0.f, 0.92050460f, 0.3907318f } },
+ { 191575, { 5197.050f, 2944.814f, 409.1913f, 2.33874000f }, { 0.f, 0.f, 0.92050460f, 0.3907318f } },
+ { 190763, { 5268.698f, 2666.421f, 409.0985f, -0.71558490f }, { 0.f, 0.f, -0.35020730f, 0.9366722f } },
+ { 191575, { 5268.698f, 2666.421f, 409.0985f, -0.71558490f }, { 0.f, 0.f, -0.35020730f, 0.9366722f } },
+ { 190763, { 5269.208f, 3013.838f, 408.8276f, -1.76278200f }, { 0.f, 0.f, -0.77162460f, 0.6360782f } },
+ { 191575, { 5269.208f, 3013.839f, 408.7695f, -1.76277900f }, { 0.f, 0.f, -0.77162360f, 0.6360794f } },
+ { 190763, { 5269.208f, 3013.839f, 408.7695f, 4.52040600f }, { 0.f, 0.f, -0.77162360f, 0.6360794f } },
+ { 190763, { 5311.445f, 2618.931f, 409.0916f, -2.37364400f }, { 0.f, 0.f, -0.92718320f, 0.3746083f } },
+ { 191575, { 5311.445f, 2618.931f, 409.0916f, -2.37364400f }, { 0.f, 0.f, -0.92718320f, 0.3746083f } },
+ { 190763, { 5314.580f, 3055.852f, 408.8620f, 0.54105060f }, { 0.f, 0.f, 0.26723770f, 0.9636307f } },
+ { 191575, { 5314.580f, 3055.852f, 408.8620f, 0.54105060f }, { 0.f, 0.f, 0.26723770f, 0.9636307f } },
+ { 190763, { 5391.277f, 2828.094f, 418.6752f, -2.16420600f }, { 0.f, 0.f, -0.88294700f, 0.4694727f } },
+ { 191575, { 5391.277f, 2828.094f, 418.6752f, -2.16420600f }, { 0.f, 0.f, -0.88294700f, 0.4694727f } },
+ { 192819, { 5401.634f, 2853.667f, 418.6748f, 2.63544400f }, { 0.f, 0.f, 0.96814730f, 0.2503814f } },
+ // Vehicle teleporter
+ { 192951, { 5314.515f, 2703.687f, 408.5502f, -0.89011660f }, { 0.f, 0.f, -0.43051050f, 0.9025856f } },
+ { 192951, { 5316.252f, 2977.042f, 408.5385f, -0.82030330f }, { 0.f, 0.f, -0.39874840f, 0.9170604f } }
+};
+
+// *********************************************************
+// **********Tower Element(GameObject, Creature)************
+// *********************************************************
+
+struct WintergraspGameObjectData
+{
+ Position Pos;
+ G3D::Quat Rot;
+ uint32 HordeEntry;
+ uint32 AllianceEntry;
+};
+
+struct WintergraspTowerData
+{
+ uint32 towerEntry; // Gameobject id of tower
+ std::vector<WintergraspGameObjectData> GameObject; // Gameobject position and entry (Horde/Alliance)
+
+ // Creature: Turrets and Guard /// @todo: Killed on Tower destruction ? Tower damage ? Requires confirming
+ std::vector<WintergraspObjectPositionData> CreatureBottom;
+};
+
+uint8 const WG_MAX_ATTACKTOWERS = 3;
+// 192414 : 0 in sql, 1 in header
+// 192278 : 0 in sql, 3 in header
+WintergraspTowerData const AttackTowers[WG_MAX_ATTACKTOWERS] =
+{
+ // West tower
+ {
+ 190356,
+ {
+ { { 4559.113f, 3606.216f, 419.9992f, 4.799657f }, { 0.f, 0.f, -0.67558960f, 0.73727790f }, 192488, 192501 }, // Flag on tower
+ { { 4539.420f, 3622.490f, 420.0342f, 3.211419f }, { 0.f, 0.f, -0.99939060f, 0.03490613f }, 192488, 192501 }, // Flag on tower
+ { { 4555.258f, 3641.648f, 419.9740f, 1.675514f }, { 0.f, 0.f, 0.74314400f, 0.66913150f }, 192488, 192501 }, // Flag on tower
+ { { 4574.872f, 3625.911f, 420.0792f, 0.087266f }, { 0.f, 0.f, 0.04361916f, 0.99904820f }, 192488, 192501 }, // Flag on tower
+ { { 4433.899f, 3534.142f, 360.2750f, 4.433136f }, { 0.f, 0.f, -0.79863550f, 0.60181500f }, 192269, 192278 }, // Flag near workshop
+ { { 4572.933f, 3475.519f, 363.0090f, 1.422443f }, { 0.f, 0.f, 0.65275960f, 0.75756520f }, 192269, 192277 } // Flag near bridge
+ },
+ {
+ { { 4418.688477f, 3506.251709f, 358.975494f, 4.293305f }, BATTLEFIELD_WG_NPC_GUARD_H, BATTLEFIELD_WG_NPC_GUARD_A } // Roaming Guard
+ }
+ },
+ // South Tower
+ {
+ 190357,
+ {
+ { { 4416.004f, 2822.666f, 429.8512f, 6.2657330f }, { 0.f, 0.f, -0.00872612f, 0.99996190f }, 192488, 192501 }, // Flag on tower
+ { { 4398.819f, 2804.698f, 429.7920f, 4.6949370f }, { 0.f, 0.f, -0.71325020f, 0.70090960f }, 192488, 192501 }, // Flag on tower
+ { { 4387.622f, 2719.566f, 389.9351f, 4.7385700f }, { 0.f, 0.f, -0.69779010f, 0.71630230f }, 192366, 192414 }, // Flag near tower
+ { { 4464.124f, 2855.453f, 406.1106f, 0.8290324f }, { 0.f, 0.f, 0.40274720f, 0.91531130f }, 192366, 192429 }, // Flag near tower
+ { { 4526.457f, 2810.181f, 391.1997f, 3.2899610f }, { 0.f, 0.f, -0.99724960f, 0.07411628f }, 192269, 192278 } // Flag near bridge
+ },
+ {
+ { { 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
+ }
+ },
+ // East Tower
+ {
+ 190358,
+ {
+ { { 4466.793f, 1960.418f, 459.1437f, 1.151916f }, { 0.f, 0.f, 0.5446386f, 0.8386708f }, 192488, 192501 }, // Flag on tower
+ { { 4475.351f, 1937.031f, 459.0702f, 5.846854f }, { 0.f, 0.f, -0.2164392f, 0.9762961f }, 192488, 192501 }, // Flag on tower
+ { { 4451.758f, 1928.104f, 459.0759f, 4.276057f }, { 0.f, 0.f, -0.8433914f, 0.5372996f }, 192488, 192501 }, // Flag on tower
+ { { 4442.987f, 1951.898f, 459.0930f, 2.740162f }, { 0.f, 0.f, 0.9799242f, 0.1993704f }, 192488, 192501 } // Flag on tower
+ },
+ {
+ { { 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
+ }
+ }
+};
+
+struct WintergraspTowerCannonData
+{
+ uint32 towerEntry;
+ std::vector<Position> TowerCannonBottom;
+ std::vector<Position> TurretTop;
+};
+
+uint8 const WG_MAX_TOWER_CANNON = 7;
+
+WintergraspTowerCannonData const TowerCannon[WG_MAX_TOWER_CANNON] =
+{
+ {
+ 190221,
+ {
+ // no cannons at bottom
+ },
+ {
+ { 5255.88f, 3047.63f, 438.499f, 3.13677f },
+ { 5280.90f, 3071.32f, 438.499f, 1.62879f }
+ }
+ },
+ {
+ 190373,
+ {
+ // no cannons at bottom
+ },
+ {
+ { 5138.59f, 2935.16f, 439.845f, 3.11723f },
+ { 5163.06f, 2959.52f, 439.846f, 1.47258f }
+ }
+ },
+ {
+ 190377,
+ {
+ // no cannons at bottom
+ },
+ {
+ { 5163.84f, 2723.74f, 439.844f, 1.39940f },
+ { 5139.69f, 2747.40f, 439.844f, 3.17221f }
+ }
+ },
+ {
+ 190378,
+ {
+ // no cannons at bottom
+ },
+ {
+ { 5278.21f, 2607.23f, 439.755f, 4.71944f },
+ { 5255.01f, 2631.98f, 439.755f, 3.15257f }
+ }
+ },
+ {
+ 190356,
+ {
+ { 4537.380371f, 3599.531738f, 402.886993f, 3.998462f },
+ { 4581.497559f, 3604.087158f, 402.886963f, 5.651723f }
+ },
+ {
+ { 4469.448242f, 1966.623779f, 465.647217f, 1.153573f },
+ { 4581.895996f, 3626.438477f, 426.539062f, 0.117806f }
+ }
+ },
+ {
+ 190357,
+ {
+ { 4421.640137f, 2799.935791f, 412.630920f, 5.459298f },
+ { 4420.263184f, 2845.340332f, 412.630951f, 0.742197f }
+ },
+ {
+ { 4423.430664f, 2822.762939f, 436.283142f, 6.223487f },
+ { 4397.825684f, 2847.629639f, 436.283325f, 1.579430f },
+ { 4398.814941f, 2797.266357f, 436.283051f, 4.703747f }
+ }
+ },
+ {
+ 190358,
+ {
+ { 4448.138184f, 1974.998779f, 441.995911f, 1.967238f },
+ { 4448.713379f, 1955.148682f, 441.995178f, 0.380733f }
+ },
+ {
+ { 4469.448242f, 1966.623779f, 465.647217f, 1.153573f },
+ { 4481.996582f, 1933.658325f, 465.647186f, 5.873029f }
+ }
+ }
+};
+
+// *********************************************************
+// *****************WorkShop Data & Element*****************
+// *********************************************************
+
+struct StaticWintergraspWorkshopInfo
+{
+ uint8 WorkshopId;
+ uint32 WorldStateId;
+
+ struct
+ {
+ uint8 AllianceCapture;
+ uint8 AllianceAttack;
+ uint8 HordeCapture;
+ uint8 HordeAttack;
+ } TextIds;
+};
+
+StaticWintergraspWorkshopInfo const WorkshopData[WG_MAX_WORKSHOP] =
+{
+ { BATTLEFIELD_WG_WORKSHOP_NE, WORLDSTATE_WORKSHOP_NE, { BATTLEFIELD_WG_TEXT_SUNKEN_RING_CAPTURE_ALLIANCE, BATTLEFIELD_WG_TEXT_SUNKEN_RING_ATTACK_ALLIANCE, BATTLEFIELD_WG_TEXT_SUNKEN_RING_CAPTURE_HORDE, BATTLEFIELD_WG_TEXT_SUNKEN_RING_ATTACK_HORDE } },
+ { BATTLEFIELD_WG_WORKSHOP_NW, WORLDSTATE_WORKSHOP_NW, { BATTLEFIELD_WG_TEXT_BROKEN_TEMPLE_CAPTURE_ALLIANCE, BATTLEFIELD_WG_TEXT_BROKEN_TEMPLE_ATTACK_ALLIANCE, BATTLEFIELD_WG_TEXT_BROKEN_TEMPLE_CAPTURE_HORDE, BATTLEFIELD_WG_TEXT_BROKEN_TEMPLE_ATTACK_HORDE } },
+ { BATTLEFIELD_WG_WORKSHOP_SE, WORLDSTATE_WORKSHOP_SE, { BATTLEFIELD_WG_TEXT_EASTSPARK_CAPTURE_ALLIANCE, BATTLEFIELD_WG_TEXT_EASTSPARK_ATTACK_ALLIANCE, BATTLEFIELD_WG_TEXT_EASTSPARK_CAPTURE_HORDE, BATTLEFIELD_WG_TEXT_EASTSPARK_ATTACK_HORDE } },
+ { BATTLEFIELD_WG_WORKSHOP_SW, WORLDSTATE_WORKSHOP_SW, { BATTLEFIELD_WG_TEXT_WESTSPARK_CAPTURE_ALLIANCE, BATTLEFIELD_WG_TEXT_WESTSPARK_ATTACK_ALLIANCE, BATTLEFIELD_WG_TEXT_WESTSPARK_CAPTURE_HORDE, BATTLEFIELD_WG_TEXT_WESTSPARK_ATTACK_HORDE } },
+ // KEEP WORKSHOPS - It can't be taken, so it doesn't have a textids
+ { BATTLEFIELD_WG_WORKSHOP_KEEP_WEST, WORLDSTATE_WORKSHOP_K_W, { 0, 0, 0, 0 } },
+ { BATTLEFIELD_WG_WORKSHOP_KEEP_EAST, WORLDSTATE_WORKSHOP_K_E, { 0, 0, 0, 0 } }
+};
+
BattlefieldWG::~BattlefieldWG()
{
for (WintergraspWorkshop* workshop : Workshops)
@@ -95,17 +541,22 @@ bool BattlefieldWG::SetupBattlefield()
m_Timer = m_RestartAfterCrash;
}
+ SetData(BATTLEFIELD_WG_DATA_WON_A, uint32(sWorld->getWorldState(BATTLEFIELD_WG_WORLD_STATE_ATTACKED_A)));
+ SetData(BATTLEFIELD_WG_DATA_DEF_A, uint32(sWorld->getWorldState(BATTLEFIELD_WG_WORLD_STATE_DEFENDED_A)));
+ SetData(BATTLEFIELD_WG_DATA_WON_H, uint32(sWorld->getWorldState(BATTLEFIELD_WG_WORLD_STATE_ATTACKED_H)));
+ SetData(BATTLEFIELD_WG_DATA_DEF_H, uint32(sWorld->getWorldState(BATTLEFIELD_WG_WORLD_STATE_DEFENDED_H)));
+
for (uint8 i = 0; i < BATTLEFIELD_WG_GRAVEYARD_MAX; i++)
{
BfGraveyardWG* graveyard = new BfGraveyardWG(this);
// When between games, the graveyard is controlled by the defending team
- if (WGGraveYard[i].startcontrol == TEAM_NEUTRAL)
- graveyard->Initialize(m_DefenderTeam, WGGraveYard[i].gyid);
+ if (WGGraveYard[i].StartControl == TEAM_NEUTRAL)
+ graveyard->Initialize(m_DefenderTeam, WGGraveYard[i].GraveyardID);
else
- graveyard->Initialize(WGGraveYard[i].startcontrol, WGGraveYard[i].gyid);
+ graveyard->Initialize(WGGraveYard[i].StartControl, WGGraveYard[i].GraveyardID);
- graveyard->SetTextId(WGGraveYard[i].textid);
+ graveyard->SetTextId(WGGraveYard[i].TextID);
m_GraveyardList[i] = graveyard;
}
@@ -124,13 +575,14 @@ bool BattlefieldWG::SetupBattlefield()
}
// Spawn NPCs in the defender's keep, both Horde and Alliance
- for (uint8 i = 0; i < WG_MAX_KEEP_NPC; i++)
+ for (uint8 i = 0; i < WG_MAX_KEEP_NPC; ++i)
{
// Horde npc
- if (Creature* creature = SpawnCreature(WGKeepNPC[i].entryHorde, WGKeepNPC[i].x, WGKeepNPC[i].y, WGKeepNPC[i].z, WGKeepNPC[i].o, TEAM_HORDE))
+ if (Creature* creature = SpawnCreature(WGKeepNPC[i].HordeEntry, WGKeepNPC[i].Pos))
KeepCreature[TEAM_HORDE].insert(creature->GetGUID());
+
// Alliance npc
- if (Creature* creature = SpawnCreature(WGKeepNPC[i].entryAlliance, WGKeepNPC[i].x, WGKeepNPC[i].y, WGKeepNPC[i].z, WGKeepNPC[i].o, TEAM_ALLIANCE))
+ if (Creature* creature = SpawnCreature(WGKeepNPC[i].AllianceEntry, WGKeepNPC[i].Pos))
KeepCreature[TEAM_ALLIANCE].insert(creature->GetGUID());
}
@@ -140,13 +592,13 @@ bool BattlefieldWG::SetupBattlefield()
HideNpc(creature);
// Spawn Horde NPCs outside the keep
- for (uint8 i = 0; i < WG_OUTSIDE_ALLIANCE_NPC; i++)
- if (Creature* creature = SpawnCreature(WGOutsideNPC[i].entryHorde, WGOutsideNPC[i].x, WGOutsideNPC[i].y, WGOutsideNPC[i].z, WGOutsideNPC[i].o, TEAM_HORDE))
+ for (uint8 i = 0; i < WG_OUTSIDE_ALLIANCE_NPC; ++i)
+ if (Creature* creature = SpawnCreature(WGOutsideNPC[i].HordeEntry, WGOutsideNPC[i].Pos))
OutsideCreature[TEAM_HORDE].insert(creature->GetGUID());
// Spawn Alliance NPCs outside the keep
- for (uint8 i = WG_OUTSIDE_ALLIANCE_NPC; i < WG_MAX_OUTSIDE_NPC; i++)
- if (Creature* creature = SpawnCreature(WGOutsideNPC[i].entryAlliance, WGOutsideNPC[i].x, WGOutsideNPC[i].y, WGOutsideNPC[i].z, WGOutsideNPC[i].o, TEAM_ALLIANCE))
+ for (uint8 i = WG_OUTSIDE_ALLIANCE_NPC; i < WG_MAX_OUTSIDE_NPC; ++i)
+ if (Creature* creature = SpawnCreature(WGOutsideNPC[i].AllianceEntry, WGOutsideNPC[i].Pos))
OutsideCreature[TEAM_ALLIANCE].insert(creature->GetGUID());
// Hide units outside the keep that are defenders
@@ -158,7 +610,7 @@ bool BattlefieldWG::SetupBattlefield()
for (uint8 i = 0; i < WG_MAX_TURRET; i++)
{
Position towerCannonPos = WGTurret[i].GetPosition();
- if (Creature* creature = SpawnCreature(NPC_WINTERGRASP_TOWER_CANNON, towerCannonPos, TEAM_ALLIANCE))
+ if (Creature* creature = SpawnCreature(NPC_WINTERGRASP_TOWER_CANNON, towerCannonPos))
{
CanonList.insert(creature->GetGUID());
HideNpc(creature);
@@ -168,7 +620,7 @@ bool BattlefieldWG::SetupBattlefield()
// Spawn all gameobjects
for (uint8 i = 0; i < WG_MAX_OBJ; i++)
{
- if (GameObject* go = SpawnGameObject(WGGameObjectBuilding[i].entry, WGGameObjectBuilding[i].x, WGGameObjectBuilding[i].y, WGGameObjectBuilding[i].z, WGGameObjectBuilding[i].o))
+ if (GameObject* go = SpawnGameObject(WGGameObjectBuilding[i].entry, WGGameObjectBuilding[i].pos, WGGameObjectBuilding[i].rot))
{
BfWGGameObjectBuilding* b = new BfWGGameObjectBuilding(this, WGGameObjectBuilding[i].type, WGGameObjectBuilding[i].WorldState);
b->Init(go);
@@ -179,9 +631,10 @@ bool BattlefieldWG::SetupBattlefield()
}
// Spawning portal defender
- for (uint8 i = 0; i < WG_MAX_TELEPORTER; i++)
+ for (uint8 i = 0; i < WG_MAX_TELEPORTER; ++i)
{
- if (GameObject* go = SpawnGameObject(WGPortalDefenderData[i].entry, WGPortalDefenderData[i].x, WGPortalDefenderData[i].y, WGPortalDefenderData[i].z, WGPortalDefenderData[i].o))
+ WintergraspTeleporterData const& teleporter = WGPortalDefenderData[i];
+ if (GameObject* go = SpawnGameObject(teleporter.Entry, teleporter.Pos, teleporter.Rot))
{
DefenderPortalList.insert(go->GetGUID());
go->SetFaction(WintergraspFaction[GetDefenderTeam()]);
@@ -200,6 +653,10 @@ bool BattlefieldWG::Update(uint32 diff)
sWorld->setWorldState(BATTLEFIELD_WG_WORLD_STATE_ACTIVE, m_isActive);
sWorld->setWorldState(BATTLEFIELD_WG_WORLD_STATE_DEFENDER, m_DefenderTeam);
sWorld->setWorldState(ClockWorldState[0], m_Timer);
+ sWorld->setWorldState(BATTLEFIELD_WG_WORLD_STATE_ATTACKED_A, GetData(BATTLEFIELD_WG_DATA_WON_A));
+ sWorld->setWorldState(BATTLEFIELD_WG_WORLD_STATE_DEFENDED_A, GetData(BATTLEFIELD_WG_DATA_DEF_A));
+ sWorld->setWorldState(BATTLEFIELD_WG_WORLD_STATE_ATTACKED_H, GetData(BATTLEFIELD_WG_DATA_WON_H));
+ sWorld->setWorldState(BATTLEFIELD_WG_WORLD_STATE_DEFENDED_H, GetData(BATTLEFIELD_WG_DATA_DEF_H));
m_saveTimer = 60 * IN_MILLISECONDS;
}
else
@@ -211,7 +668,7 @@ bool BattlefieldWG::Update(uint32 diff)
void BattlefieldWG::OnBattleStart()
{
// Spawn titan relic
- if (GameObject* relic = SpawnGameObject(GO_WINTERGRASP_TITAN_S_RELIC, 5440.0f, 2840.8f, 430.43f, 0))
+ if (GameObject* relic = SpawnGameObject(GO_WINTERGRASP_TITAN_S_RELIC, WintergraspRelicPos, WintergraspRelicRot))
{
// Update faction of relic, only attacker can click on
relic->SetFaction(WintergraspFaction[GetAttackerTeam()]);
@@ -297,6 +754,13 @@ void BattlefieldWG::OnBattleEnd(bool endByTimer)
relic->RemoveFromWorld();
m_titansRelicGUID.Clear();
+ // successful defense
+ if (endByTimer)
+ UpdateData(GetDefenderTeam() == TEAM_HORDE ? BATTLEFIELD_WG_DATA_DEF_H : BATTLEFIELD_WG_DATA_DEF_A, 1);
+ // successful attack (note that teams have already been swapped, so defender team is the one who won)
+ else
+ UpdateData(GetDefenderTeam() == TEAM_HORDE ? BATTLEFIELD_WG_DATA_WON_H : BATTLEFIELD_WG_DATA_WON_A, 1);
+
// Remove turret
for (GuidSet::const_iterator itr = CanonList.begin(); itr != CanonList.end(); ++itr)
{
@@ -809,18 +1273,22 @@ uint32 BattlefieldWG::GetData(uint32 data) const
void BattlefieldWG::FillInitialWorldStates(WorldPacket& data)
{
+ data << uint32(BATTLEFIELD_WG_WORLD_STATE_DEFENDED_A) << uint32(GetData(BATTLEFIELD_WG_DATA_DEF_A));
+ data << uint32(BATTLEFIELD_WG_WORLD_STATE_DEFENDED_H) << uint32(GetData(BATTLEFIELD_WG_DATA_DEF_H));
+ data << uint32(BATTLEFIELD_WG_WORLD_STATE_ATTACKED_A) << uint32(GetData(BATTLEFIELD_WG_DATA_WON_A));
+ data << uint32(BATTLEFIELD_WG_WORLD_STATE_ATTACKED_H) << uint32(GetData(BATTLEFIELD_WG_DATA_WON_H));
data << uint32(BATTLEFIELD_WG_WORLD_STATE_ATTACKER) << uint32(GetAttackerTeam());
data << uint32(BATTLEFIELD_WG_WORLD_STATE_DEFENDER) << uint32(GetDefenderTeam());
data << uint32(BATTLEFIELD_WG_WORLD_STATE_ACTIVE) << uint32(IsWarTime() ? 0 : 1); // Note: cleanup these two, their names look awkward
data << uint32(BATTLEFIELD_WG_WORLD_STATE_SHOW_WORLDSTATE) << uint32(IsWarTime() ? 1 : 0);
for (uint32 i = 0; i < 2; ++i)
- data << ClockWorldState[i] << uint32(time(NULL) + (m_Timer / 1000));
+ data << ClockWorldState[i] << uint32(time(nullptr) + (m_Timer / 1000));
data << uint32(BATTLEFIELD_WG_WORLD_STATE_VEHICLE_H) << uint32(GetData(BATTLEFIELD_WG_DATA_VEHICLE_H));
- data << uint32(BATTLEFIELD_WG_WORLD_STATE_MAX_VEHICLE_H) << GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_H);
+ data << uint32(BATTLEFIELD_WG_WORLD_STATE_MAX_VEHICLE_H) << uint32(GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_H));
data << uint32(BATTLEFIELD_WG_WORLD_STATE_VEHICLE_A) << uint32(GetData(BATTLEFIELD_WG_DATA_VEHICLE_A));
- data << uint32(BATTLEFIELD_WG_WORLD_STATE_MAX_VEHICLE_A) << GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_A);
+ data << uint32(BATTLEFIELD_WG_WORLD_STATE_MAX_VEHICLE_A) << uint32(GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_A));
for (BfWGGameObjectBuilding* building : BuildingsInZone)
building->FillInitialWorldStates(data);
@@ -831,12 +1299,12 @@ void BattlefieldWG::FillInitialWorldStates(WorldPacket& data)
void BattlefieldWG::SendInitWorldStatesTo(Player* player)
{
- WorldPacket data(SMSG_INIT_WORLD_STATES, 4 + 4 + 4 + 2 + (BuildingsInZone.size() * 8) + (Workshops.size() * 8));
+ WorldPacket data(SMSG_INIT_WORLD_STATES, 4 + 4 + 4 + 2 + (14 + WG_MAX_OBJ + WG_MAX_WORKSHOP) * 8);
data << uint32(m_MapId);
data << uint32(m_ZoneId);
data << uint32(0); // AreaId
- data << uint16(10 + BuildingsInZone.size() + Workshops.size()); // Number of fields
+ data << uint16(14 + BuildingsInZone.size() + Workshops.size()); // Number of fields
FillInitialWorldStates(data);
@@ -853,6 +1321,14 @@ void BattlefieldWG::SendInitWorldStatesToAll()
void BattlefieldWG::BrokenWallOrTower(TeamId /*team*/)
{
+/*
+uint32 const WGQuest[2][6] =
+{
+ { 13186, 13181, 13222, 13538, 13177, 13179 },
+ { 13185, 13183, 13223, 13539, 13178, 13180 },
+};
+*/
+
// might be some use for this in the future. old code commented out below. KL
/* if (team == GetDefenderTeam())
{
@@ -1087,7 +1563,7 @@ void BfWGGameObjectBuilding::Rebuild()
// Rebuild gameobject
if (build->IsDestructibleBuilding())
{
- build->SetDestructibleState(GO_DESTRUCTIBLE_REBUILDING, NULL, true);
+ build->SetDestructibleState(GO_DESTRUCTIBLE_REBUILDING, nullptr, true);
if (build->GetEntry() == GO_WINTERGRASP_VAULT_GATE)
if (GameObject* go = build->FindNearestGameObject(GO_WINTERGRASP_KEEP_COLLISION_WALL, 50.0f))
go->SetGoState(GO_STATE_READY);
@@ -1189,7 +1665,7 @@ void BfWGGameObjectBuilding::Init(GameObject* go)
case BATTLEFIELD_WG_OBJECTSTATE_NEUTRAL_INTACT:
case BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_INTACT:
case BATTLEFIELD_WG_OBJECTSTATE_HORDE_INTACT:
- go->SetDestructibleState(GO_DESTRUCTIBLE_REBUILDING, NULL, true);
+ go->SetDestructibleState(GO_DESTRUCTIBLE_REBUILDING, nullptr, true);
break;
case BATTLEFIELD_WG_OBJECTSTATE_NEUTRAL_DESTROY:
case BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_DESTROY:
@@ -1234,33 +1710,23 @@ void BfWGGameObjectBuilding::Init(GameObject* go)
if (towerId > 3) // Attacker towers
{
// Spawn associate gameobjects
- for (uint8 i = 0; i < AttackTowers[towerId - 4].nbObject; i++)
+ for (WintergraspGameObjectData const& gobData : AttackTowers[towerId - 4].GameObject)
{
- WintergraspObjectPositionData const& gobData = AttackTowers[towerId - 4].GameObject[i];
- if (GameObject* goHorde = _wg->SpawnGameObject(gobData.entryHorde, gobData.x, gobData.y, gobData.z, gobData.o))
+ if (GameObject* goHorde = _wg->SpawnGameObject(gobData.HordeEntry, gobData.Pos, gobData.Rot))
m_GameObjectList[TEAM_HORDE].insert(goHorde->GetGUID());
- if (GameObject* goAlliance = _wg->SpawnGameObject(gobData.entryAlliance, gobData.x, gobData.y, gobData.z, gobData.o))
+
+ if (GameObject* goAlliance = _wg->SpawnGameObject(gobData.AllianceEntry, gobData.Pos, gobData.Rot))
m_GameObjectList[TEAM_ALLIANCE].insert(goAlliance->GetGUID());
}
// Spawn associate npc bottom
- for (uint8 i = 0; i < AttackTowers[towerId - 4].nbCreatureBottom; i++)
+ for (WintergraspObjectPositionData const& creatureData : AttackTowers[towerId - 4].CreatureBottom)
{
- WintergraspObjectPositionData const& creatureData = AttackTowers[towerId - 4].CreatureBottom[i];
- if (Creature* creature = _wg->SpawnCreature(creatureData.entryHorde, creatureData.x, creatureData.y, creatureData.z, creatureData.o, TEAM_HORDE))
+ if (Creature* creature = _wg->SpawnCreature(creatureData.HordeEntry, creatureData.Pos))
m_CreatureBottomList[TEAM_HORDE].insert(creature->GetGUID());
- if (Creature* creature = _wg->SpawnCreature(creatureData.entryAlliance, creatureData.x, creatureData.y, creatureData.z, creatureData.o, TEAM_ALLIANCE))
- m_CreatureBottomList[TEAM_ALLIANCE].insert(creature->GetGUID());
- }
- // Spawn associate npc top
- for (uint8 i = 0; i < AttackTowers[towerId - 4].nbCreatureTop; i++)
- {
- WintergraspObjectPositionData const& creatureData = AttackTowers[towerId - 4].CreatureTop[i];
- if (Creature* creature = _wg->SpawnCreature(creatureData.entryHorde, creatureData.x, creatureData.y, creatureData.z, creatureData.o, TEAM_HORDE))
- m_CreatureTopList[TEAM_HORDE].insert(creature->GetGUID());
- if (Creature* creature = _wg->SpawnCreature(creatureData.entryAlliance, creatureData.x, creatureData.y, creatureData.z, creatureData.o, TEAM_ALLIANCE))
- m_CreatureTopList[TEAM_ALLIANCE].insert(creature->GetGUID());
+ if (Creature* creature = _wg->SpawnCreature(creatureData.AllianceEntry, creatureData.Pos))
+ m_CreatureBottomList[TEAM_ALLIANCE].insert(creature->GetGUID());
}
}
@@ -1270,10 +1736,9 @@ void BfWGGameObjectBuilding::Init(GameObject* go)
_staticTowerInfo = &TowerData[towerId];
// Spawn Turret bottom
- for (uint8 i = 0; i < TowerCannon[towerId].nbTowerCannonBottom; i++)
+ for (Position const& turretPos : TowerCannon[towerId].TowerCannonBottom)
{
- Position const& turretPos = TowerCannon[towerId].TowerCannonBottom[i];
- if (Creature* turret = _wg->SpawnCreature(NPC_WINTERGRASP_TOWER_CANNON, turretPos, TEAM_ALLIANCE))
+ if (Creature* turret = _wg->SpawnCreature(NPC_WINTERGRASP_TOWER_CANNON, turretPos))
{
m_TowerCannonBottomList.insert(turret->GetGUID());
switch (go->GetEntry())
@@ -1290,15 +1755,15 @@ void BfWGGameObjectBuilding::Init(GameObject* go)
turret->setFaction(WintergraspFaction[_wg->GetAttackerTeam()]);
break;
}
+
_wg->HideNpc(turret);
}
}
// Spawn Turret top
- for (uint8 i = 0; i < TowerCannon[towerId].nbTurretTop; i++)
+ for (Position const& towerCannonPos : TowerCannon[towerId].TurretTop)
{
- Position const& towerCannonPos = TowerCannon[towerId].TurretTop[i];
- if (Creature* turret = _wg->SpawnCreature(NPC_WINTERGRASP_TOWER_CANNON, towerCannonPos, TeamId(0)))
+ if (Creature* turret = _wg->SpawnCreature(NPC_WINTERGRASP_TOWER_CANNON, towerCannonPos))
{
m_TurretTopList.insert(turret->GetGUID());
switch (go->GetEntry())
@@ -1432,21 +1897,9 @@ WintergraspWorkshop::WintergraspWorkshop(BattlefieldWG* wg, uint8 type)
_staticInfo = &WorkshopData[type];
}
-void WintergraspWorkshop::AddCreature(WintergraspObjectPositionData const& obj)
-{
- if (Creature* creature = _wg->SpawnCreature(obj.entryHorde, obj.x, obj.y, obj.z, obj.o, TEAM_HORDE))
- _creatureOnPoint[TEAM_HORDE].insert(creature->GetGUID());
-
- if (Creature* creature = _wg->SpawnCreature(obj.entryAlliance, obj.x, obj.y, obj.z, obj.o, TEAM_ALLIANCE))
- _creatureOnPoint[TEAM_ALLIANCE].insert(creature->GetGUID());
-}
-
-void WintergraspWorkshop::AddGameObject(WintergraspObjectPositionData const& obj)
+uint8 WintergraspWorkshop::GetId() const
{
- if (GameObject* go = _wg->SpawnGameObject(obj.entryHorde, obj.x, obj.y, obj.z, obj.o))
- _gameObjectOnPoint[TEAM_HORDE].insert(go->GetGUID());
- if (GameObject* go = _wg->SpawnGameObject(obj.entryAlliance, obj.x, obj.y, obj.z, obj.o))
- _gameObjectOnPoint[TEAM_ALLIANCE].insert(go->GetGUID());
+ return _staticInfo->WorkshopId;
}
void WintergraspWorkshop::GiveControlTo(TeamId teamId, bool init /*= false*/)
diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.h b/src/server/game/Battlefield/Zones/BattlefieldWG.h
index 52789d38d8e..b95a6c93d5c 100644
--- a/src/server/game/Battlefield/Zones/BattlefieldWG.h
+++ b/src/server/game/Battlefield/Zones/BattlefieldWG.h
@@ -26,6 +26,9 @@ class WintergraspCapturePoint;
struct BfWGGameObjectBuilding;
struct WintergraspWorkshop;
+struct StaticWintergraspTowerInfo;
+struct StaticWintergraspWorkshopInfo;
+struct WintergraspObjectPositionData;
typedef std::set<GameObject*> GameObjectSet;
typedef std::set<BfWGGameObjectBuilding*> GameObjectBuildingSet;
@@ -33,6 +36,12 @@ typedef std::set<WintergraspWorkshop*> WorkshopSet;
typedef std::set<Group*> GroupSet;
//typedef std::set<WintergraspCapturePoint *> CapturePointSet; unused ?
+// used in Player.cpp
+extern uint32 const ClockWorldState[];
+
+// used in zone_wintergrasp.cpp
+TC_GAME_API extern uint32 const WintergraspFaction[];
+
enum WintergrastData
{
BATTLEFIELD_WG_ZONEID = 4197, // Wintergrasp
@@ -93,6 +102,10 @@ enum WintergraspData
BATTLEFIELD_WG_DATA_MAX_VEHICLE_H,
BATTLEFIELD_WG_DATA_VEHICLE_A,
BATTLEFIELD_WG_DATA_VEHICLE_H,
+ BATTLEFIELD_WG_DATA_WON_A,
+ BATTLEFIELD_WG_DATA_DEF_A,
+ BATTLEFIELD_WG_DATA_WON_H,
+ BATTLEFIELD_WG_DATA_DEF_H,
BATTLEFIELD_WG_DATA_MAX
};
@@ -125,7 +138,11 @@ enum WintergraspWorldStates
BATTLEFIELD_WG_WORLD_STATE_ACTIVE = 3801,
BATTLEFIELD_WG_WORLD_STATE_DEFENDER = 3802,
BATTLEFIELD_WG_WORLD_STATE_ATTACKER = 3803,
- BATTLEFIELD_WG_WORLD_STATE_SHOW_WORLDSTATE = 3710
+ BATTLEFIELD_WG_WORLD_STATE_SHOW_WORLDSTATE = 3710,
+ BATTLEFIELD_WG_WORLD_STATE_ATTACKED_H = 4022,
+ BATTLEFIELD_WG_WORLD_STATE_ATTACKED_A = 4023,
+ BATTLEFIELD_WG_WORLD_STATE_DEFENDED_H = 4024,
+ BATTLEFIELD_WG_WORLD_STATE_DEFENDED_A = 4025
};
enum WintergraspAreaIds
@@ -214,36 +231,6 @@ enum WintergraspNpcs
NPC_WINTERGRASP_TOWER_CANNON = 28366
};
-struct BfWGCoordGY
-{
- float x;
- float y;
- float z;
- float o;
- uint32 gyid;
- uint8 type;
- uint32 textid; // for gossip menu
- TeamId startcontrol;
-};
-
-uint32 const WGQuest[2][6] =
-{
- { 13186, 13181, 13222, 13538, 13177, 13179 },
- { 13185, 13183, 13223, 13539, 13178, 13180 },
-};
-
-// 7 in sql, 7 in header
-BfWGCoordGY const WGGraveYard[BATTLEFIELD_WG_GRAVEYARD_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 },
-};
-
/* ######################### *
* WintergraspCapturePoint *
* ######################### */
@@ -432,22 +419,6 @@ class TC_GAME_API BattlefieldWG : public Battlefield
ObjectGuid m_titansRelicGUID;
};
-uint32 const VehNumWorldState[] = { 3680, 3490 };
-uint32 const MaxVehNumWorldState[] = { 3681, 3491 };
-uint32 const ClockWorldState[] = { 3781, 4354 };
-uint32 const WintergraspFaction[] = { 1732, 1735, 35 };
-
-Position const WintergraspStalkerPos = { 4948.985f, 2937.789f, 550.5172f, 1.815142f };
-
-uint8 const WG_MAX_OBJ = 32;
-uint8 const WG_MAX_TURRET = 15;
-uint8 const WG_MAX_KEEP_NPC = 39;
-uint8 const WG_MAX_OUTSIDE_NPC = 14;
-uint8 const WG_OUTSIDE_ALLIANCE_NPC = 7;
-uint8 const WG_MAX_TELEPORTER = 12;
-uint8 const WG_MAX_WORKSHOP = 6;
-uint8 const WG_MAX_TOWER = 7;
-
enum WintergraspGameObjectBuildingType
{
BATTLEFIELD_WG_OBJECTTYPE_DOOR,
@@ -580,519 +551,6 @@ enum WintergraspGameObject
GO_WINTERGRASP_KEEP_COLLISION_WALL = 194323
};
-// *****************************************************
-// ************ Destructible (Wall, Tower..) ***********
-// *****************************************************
-
-struct WintergraspBuildingSpawnData
-{
- uint32 entry;
- uint32 WorldState;
- float x;
- float y;
- float z;
- float o;
- WintergraspGameObjectBuildingType type;
-};
-
-struct WintergraspObjectPositionData
-{
- float x;
- float y;
- float z;
- float o;
- uint32 entryHorde;
- uint32 entryAlliance;
-};
-
-WintergraspBuildingSpawnData const WGGameObjectBuilding[WG_MAX_OBJ] =
-{
- // Wall (Not spawned in db)
- // Entry WS X Y Z O Type
- { 190219, 3749, 5371.46f, 3047.47f, 407.571f, 3.14159f, BATTLEFIELD_WG_OBJECTTYPE_WALL },
- { 190220, 3750, 5331.26f, 3047.1f, 407.923f, 0.052359f, BATTLEFIELD_WG_OBJECTTYPE_WALL },
- { 191795, 3764, 5385.84f, 2909.49f, 409.713f, 0.00872f, BATTLEFIELD_WG_OBJECTTYPE_WALL },
- { 191796, 3772, 5384.45f, 2771.84f, 410.27f, 3.14159f, BATTLEFIELD_WG_OBJECTTYPE_WALL },
- { 191799, 3762, 5371.44f, 2630.61f, 408.816f, 3.13286f, BATTLEFIELD_WG_OBJECTTYPE_WALL },
- { 191800, 3766, 5301.84f, 2909.09f, 409.866f, 0.008724f, BATTLEFIELD_WG_OBJECTTYPE_WALL },
- { 191801, 3770, 5301.06f, 2771.41f, 409.901f, 3.14159f, BATTLEFIELD_WG_OBJECTTYPE_WALL },
- { 191802, 3751, 5280.2f, 2995.58f, 408.825f, 1.61443f, BATTLEFIELD_WG_OBJECTTYPE_WALL },
- { 191803, 3752, 5279.14f, 2956.02f, 408.604f, 1.5708f, BATTLEFIELD_WG_OBJECTTYPE_WALL },
- { 191804, 3767, 5278.69f, 2882.51f, 409.539f, 1.5708f, BATTLEFIELD_WG_OBJECTTYPE_WALL },
- { 191806, 3769, 5279.5f, 2798.94f, 409.998f, 1.5708f, BATTLEFIELD_WG_OBJECTTYPE_WALL },
- { 191807, 3759, 5279.94f, 2724.77f, 409.945f, 1.56207f, BATTLEFIELD_WG_OBJECTTYPE_WALL },
- { 191808, 3760, 5279.6f, 2683.79f, 409.849f, 1.55334f, BATTLEFIELD_WG_OBJECTTYPE_WALL },
- { 191809, 3761, 5330.96f, 2630.78f, 409.283f, 3.13286f, BATTLEFIELD_WG_OBJECTTYPE_WALL },
- { 190369, 3753, 5256.08f, 2933.96f, 409.357f, 3.13286f, BATTLEFIELD_WG_OBJECTTYPE_WALL },
- { 190370, 3758, 5257.46f, 2747.33f, 409.743f, -3.13286f, BATTLEFIELD_WG_OBJECTTYPE_WALL },
- { 190371, 3754, 5214.96f, 2934.09f, 409.19f, -0.008724f, BATTLEFIELD_WG_OBJECTTYPE_WALL },
- { 190372, 3757, 5215.82f, 2747.57f, 409.188f, -3.13286f, BATTLEFIELD_WG_OBJECTTYPE_WALL },
- { 190374, 3755, 5162.27f, 2883.04f, 410.256f, 1.57952f, BATTLEFIELD_WG_OBJECTTYPE_WALL },
- { 190376, 3756, 5163.72f, 2799.84f, 409.227f, 1.57952f, BATTLEFIELD_WG_OBJECTTYPE_WALL },
-
- // Tower of keep (Not spawned in db)
- { 190221, 3711, 5281.15f, 3044.59f, 407.843f, 3.11539f, BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER }, // NW
- { 190373, 3713, 5163.76f, 2932.23f, 409.19f, 3.12412f, BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER }, // SW
- { 190377, 3714, 5166.4f, 2748.37f, 409.188f, -1.5708f, BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER }, // SE
- { 190378, 3712, 5281.19f, 2632.48f, 409.099f, -1.58825f, BATTLEFIELD_WG_OBJECTTYPE_KEEP_TOWER }, // NE
-
- // Wall (with passage) (Not spawned in db)
- { 191797, 3765, 5343.29f, 2908.86f, 409.576f, 0.008724f, BATTLEFIELD_WG_OBJECTTYPE_WALL },
- { 191798, 3771, 5342.72f, 2771.39f, 409.625f, 3.14159f, BATTLEFIELD_WG_OBJECTTYPE_WALL },
- { 191805, 3768, 5279.13f, 2840.8f, 409.783f, 1.57952f, BATTLEFIELD_WG_OBJECTTYPE_WALL },
-
- // South tower (Not spawned in db)
- { 190356, 3704, 4557.17f, 3623.94f, 395.883f, 1.67552f, BATTLEFIELD_WG_OBJECTTYPE_TOWER }, // W
- { 190357, 3705, 4398.17f, 2822.5f, 405.627f, -3.12412f, BATTLEFIELD_WG_OBJECTTYPE_TOWER }, // S
- { 190358, 3706, 4459.1f, 1944.33f, 434.991f, -2.00276f, BATTLEFIELD_WG_OBJECTTYPE_TOWER }, // E
-
- // Door of forteress (Not spawned in db)
- { GO_WINTERGRASP_FORTRESS_GATE, 3763, 5162.99f, 2841.23f, 410.162f, -3.13286f, BATTLEFIELD_WG_OBJECTTYPE_DOOR },
-
- // Last door (Not spawned in db)
- { GO_WINTERGRASP_VAULT_GATE, 3773, 5397.11f, 2841.54f, 425.899f, 3.14159f, BATTLEFIELD_WG_OBJECTTYPE_DOOR_LAST },
-};
-
-struct StaticWintergraspTowerInfo
-{
- uint8 TowerId;
-
- struct
- {
- uint8 Damaged;
- uint8 Destroyed;
- } TextIds;
-};
-
-StaticWintergraspTowerInfo const TowerData[WG_MAX_TOWER] =
-{
- { BATTLEFIELD_WG_TOWER_FORTRESS_NW, { BATTLEFIELD_WG_TEXT_NW_KEEPTOWER_DAMAGE, BATTLEFIELD_WG_TEXT_NW_KEEPTOWER_DESTROY } },
- { BATTLEFIELD_WG_TOWER_FORTRESS_SW, { BATTLEFIELD_WG_TEXT_SW_KEEPTOWER_DAMAGE, BATTLEFIELD_WG_TEXT_SW_KEEPTOWER_DESTROY } },
- { BATTLEFIELD_WG_TOWER_FORTRESS_SE, { BATTLEFIELD_WG_TEXT_SE_KEEPTOWER_DAMAGE, BATTLEFIELD_WG_TEXT_SE_KEEPTOWER_DESTROY } },
- { BATTLEFIELD_WG_TOWER_FORTRESS_NE, { BATTLEFIELD_WG_TEXT_NE_KEEPTOWER_DAMAGE, BATTLEFIELD_WG_TEXT_NE_KEEPTOWER_DESTROY } },
- { BATTLEFIELD_WG_TOWER_SHADOWSIGHT, { BATTLEFIELD_WG_TEXT_WESTERN_TOWER_DAMAGE, BATTLEFIELD_WG_TEXT_WESTERN_TOWER_DESTROY } },
- { BATTLEFIELD_WG_TOWER_WINTER_S_EDGE, { BATTLEFIELD_WG_TEXT_SOUTHERN_TOWER_DAMAGE, BATTLEFIELD_WG_TEXT_SOUTHERN_TOWER_DESTROY } },
- { BATTLEFIELD_WG_TOWER_FLAMEWATCH, { BATTLEFIELD_WG_TEXT_EASTERN_TOWER_DAMAGE, BATTLEFIELD_WG_TEXT_EASTERN_TOWER_DESTROY } }
-};
-
-Position const 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
-WintergraspObjectPositionData const 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 Blazefeather
- { 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
-};
-
-const WintergraspObjectPositionData 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 WintergraspTeleporterData
-{
- uint32 entry;
- float x;
- float y;
- float z;
- float o;
-};
-
-WintergraspTeleporterData const 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 WintergraspTowerData
-{
- uint32 towerEntry; // Gameobject id of tower
- uint8 nbObject; // Number of gameobjects spawned on this point
- WintergraspObjectPositionData GameObject[6]; // Gameobject position and entry (Horde/Alliance)
-
- // Creature: Turrets and Guard /// @todo: Killed on Tower destruction ? Tower damage ? Requires confirming
- uint8 nbCreatureBottom;
- WintergraspObjectPositionData CreatureBottom[9];
- uint8 nbCreatureTop;
- WintergraspObjectPositionData CreatureTop[5];
-};
-
-uint8 const WG_MAX_ATTACKTOWERS = 3;
-// 192414 : 0 in sql, 1 in header
-// 192278 : 0 in sql, 3 in header
-const WintergraspTowerData 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 WintergraspTowerCannonData
-{
- uint32 towerEntry;
- uint8 nbTowerCannonBottom;
- Position TowerCannonBottom[5];
- uint8 nbTurretTop;
- Position TurretTop[5];
-};
-
-const uint8 WG_MAX_TOWER_CANNON = 7;
-
-const WintergraspTowerCannonData TowerCannon[WG_MAX_TOWER_CANNON] =
-{
- {
- 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 StaticWintergraspWorkshopInfo
-{
- uint8 WorkshopId;
- uint32 WorldStateId;
-
- struct
- {
- uint8 AllianceCapture;
- uint8 AllianceAttack;
- uint8 HordeCapture;
- uint8 HordeAttack;
- } TextIds;
-};
-
-StaticWintergraspWorkshopInfo const WorkshopData[WG_MAX_WORKSHOP] =
-{
- { BATTLEFIELD_WG_WORKSHOP_NE, WORLDSTATE_WORKSHOP_NE, { BATTLEFIELD_WG_TEXT_SUNKEN_RING_CAPTURE_ALLIANCE, BATTLEFIELD_WG_TEXT_SUNKEN_RING_ATTACK_ALLIANCE, BATTLEFIELD_WG_TEXT_SUNKEN_RING_CAPTURE_HORDE, BATTLEFIELD_WG_TEXT_SUNKEN_RING_ATTACK_HORDE } },
- { BATTLEFIELD_WG_WORKSHOP_NW, WORLDSTATE_WORKSHOP_NW, { BATTLEFIELD_WG_TEXT_BROKEN_TEMPLE_CAPTURE_ALLIANCE, BATTLEFIELD_WG_TEXT_BROKEN_TEMPLE_ATTACK_ALLIANCE, BATTLEFIELD_WG_TEXT_BROKEN_TEMPLE_CAPTURE_HORDE, BATTLEFIELD_WG_TEXT_BROKEN_TEMPLE_ATTACK_HORDE } },
- { BATTLEFIELD_WG_WORKSHOP_SE, WORLDSTATE_WORKSHOP_SE, { BATTLEFIELD_WG_TEXT_EASTSPARK_CAPTURE_ALLIANCE, BATTLEFIELD_WG_TEXT_EASTSPARK_ATTACK_ALLIANCE, BATTLEFIELD_WG_TEXT_EASTSPARK_CAPTURE_HORDE, BATTLEFIELD_WG_TEXT_EASTSPARK_ATTACK_HORDE } },
- { BATTLEFIELD_WG_WORKSHOP_SW, WORLDSTATE_WORKSHOP_SW, { BATTLEFIELD_WG_TEXT_WESTSPARK_CAPTURE_ALLIANCE, BATTLEFIELD_WG_TEXT_WESTSPARK_ATTACK_ALLIANCE, BATTLEFIELD_WG_TEXT_WESTSPARK_CAPTURE_HORDE, BATTLEFIELD_WG_TEXT_WESTSPARK_ATTACK_HORDE } },
- // KEEP WORKSHOPS - It can't be taken, so it doesn't have a textids
- { BATTLEFIELD_WG_WORKSHOP_KEEP_WEST, WORLDSTATE_WORKSHOP_K_W, { 0, 0, 0, 0 } },
- { BATTLEFIELD_WG_WORKSHOP_KEEP_EAST, WORLDSTATE_WORKSHOP_K_E, { 0, 0, 0, 0 } }
-};
-
// ********************************************************************
// * Structs using for Building, Graveyard, Workshop *
// ********************************************************************
@@ -1165,15 +623,9 @@ private:
public:
WintergraspWorkshop(BattlefieldWG* wg, uint8 type);
- uint8 GetId() const { return _staticInfo->WorkshopId; }
+ uint8 GetId() const;
TeamId GetTeamControl() const { return _teamControl; }
- // Spawning associate creature and store them
- void AddCreature(WintergraspObjectPositionData const& obj);
-
- // Spawning Associate gameobject and store them
- void AddGameObject(WintergraspObjectPositionData const& obj);
-
// Called on change faction in CapturePoint class
void GiveControlTo(TeamId teamId, bool init = false);
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp
index 2629013585a..a31d73b6dfb 100644
--- a/src/server/game/Conditions/ConditionMgr.cpp
+++ b/src/server/game/Conditions/ConditionMgr.cpp
@@ -107,7 +107,8 @@ ConditionMgr::ConditionTypeInfo const ConditionMgr::StaticConditionTypeData[COND
{ "Sit/stand state", true, true, false },
{ "Daily Quest Completed",true, false, false },
{ "Charmed", false, false, false },
- { "Pet type", true, false, false }
+ { "Pet type", true, false, false },
+ { "On Taxi", false, false, false }
};
// Checks if object meets the condition
@@ -471,6 +472,12 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo) const
condMeets = (((1 << pet->getPetType()) & ConditionValue1) != 0);
break;
}
+ case CONDITION_TAXI:
+ {
+ if (Player* player = object->ToPlayer())
+ condMeets = player->IsInFlight();
+ break;
+ }
default:
condMeets = false;
break;
@@ -653,6 +660,9 @@ uint32 Condition::GetSearcherTypeMaskForCondition() const
case CONDITION_PET_TYPE:
mask |= GRID_MAP_TYPE_MASK_PLAYER;
break;
+ case CONDITION_TAXI:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
default:
ASSERT(false && "Condition::GetSearcherTypeMaskForCondition - missing condition handling!");
break;
@@ -2185,6 +2195,7 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) const
break;
case CONDITION_IN_WATER:
case CONDITION_CHARMED:
+ case CONDITION_TAXI:
default:
break;
}
diff --git a/src/server/game/Conditions/ConditionMgr.h b/src/server/game/Conditions/ConditionMgr.h
index 659cec02d37..f4068842765 100644
--- a/src/server/game/Conditions/ConditionMgr.h
+++ b/src/server/game/Conditions/ConditionMgr.h
@@ -76,7 +76,8 @@ enum ConditionTypes
CONDITION_DAILY_QUEST_DONE = 43, // quest id 0 0 true if daily quest has been completed for the day
CONDITION_CHARMED = 44, // 0 0 0 true if unit is currently charmed
CONDITION_PET_TYPE = 45, // mask 0 0 true if player has a pet of given type(s)
- CONDITION_MAX = 46 // MAX
+ CONDITION_TAXI = 46, // 0 0 0 true if player is on taxi
+ CONDITION_MAX = 47 // MAX
};
/*! Documentation on implementing a new ConditionSourceType:
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index b556fde1705..05ba2211752 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -183,7 +183,7 @@ m_lootRecipient(), m_lootRecipientGroup(0), _skinner(), _pickpocketLootRestore(0
m_respawnDelay(300), m_corpseDelay(60), m_respawnradius(0.0f), m_boundaryCheckTime(2500), m_combatPulseTime(0), m_combatPulseDelay(0), m_reactState(REACT_AGGRESSIVE),
m_defaultMovementType(IDLE_MOTION_TYPE), m_spawnId(0), m_equipmentId(0), m_originalEquipmentId(0), m_AlreadyCallAssistance(false),
m_AlreadySearchedAssistance(false), m_regenHealth(true), m_cannotReachTarget(false), m_cannotReachTimer(0), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),
-m_originalEntry(0), m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), m_waypointID(0), m_path_id(0), m_formation(nullptr), m_focusSpell(nullptr), m_focusDelay(0)
+m_originalEntry(0), m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), m_waypointID(0), m_path_id(0), m_formation(nullptr), m_focusSpell(nullptr), m_focusDelay(0), m_shouldReacquireTarget(false), m_suppressedOrientation(0.0f)
{
m_regenTimer = CREATURE_REGEN_INTERVAL;
m_valuesCount = UNIT_END;
@@ -400,7 +400,7 @@ bool Creature::InitEntry(uint32 entry, CreatureData const* data /*= nullptr*/)
return true;
}
-bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/)
+bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/, bool updateLevel /* = true */)
{
if (!InitEntry(entry, data))
return false;
@@ -434,7 +434,8 @@ bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/)
SetAttackTime(OFF_ATTACK, cInfo->BaseAttackTime);
SetAttackTime(RANGED_ATTACK, cInfo->RangeAttackTime);
- SelectLevel();
+ if (updateLevel)
+ SelectLevel();
SetMeleeDamageSchool(SpellSchools(cInfo->dmgschool));
CreatureBaseStats const* stats = sObjectMgr->GetCreatureBaseStats(getLevel(), cInfo->unit_class);
@@ -571,6 +572,19 @@ void Creature::Update(uint32 diff)
if (!IsAlive())
break;
+ if (m_shouldReacquireTarget && !IsFocusing(nullptr, true))
+ {
+ SetTarget(m_suppressedTarget);
+ if (m_suppressedTarget)
+ {
+ if (WorldObject const* objTarget = ObjectAccessor::GetWorldObject(*this, m_suppressedTarget))
+ SetFacingToObject(objTarget);
+ }
+ else
+ SetFacingTo(m_suppressedOrientation);
+ m_shouldReacquireTarget = false;
+ }
+
// if creature is charmed, switch to charmed AI (and back)
if (NeedChangeAI)
{
@@ -2781,31 +2795,39 @@ void Creature::SetDisplayId(uint32 modelId)
void Creature::SetTarget(ObjectGuid guid)
{
- if (!IsFocusing())
+ if (IsFocusing(nullptr, true))
+ m_suppressedTarget = guid;
+ else
SetGuidValue(UNIT_FIELD_TARGET, guid);
}
-bool Creature::FocusTarget(Spell const* focusSpell, WorldObject const* target)
+void Creature::FocusTarget(Spell const* focusSpell, WorldObject const* target)
{
// already focused
if (m_focusSpell)
- return false;
+ return;
+
+ // don't use spell focus for vehicle spells
+ if (focusSpell->GetSpellInfo()->HasAura(SPELL_AURA_CONTROL_VEHICLE))
+ return;
if ((!target || target == this) && !focusSpell->GetCastTime()) // instant cast, untargeted (or self-targeted) spell doesn't need any facing updates
- return false;
+ return;
- m_focusSpell = focusSpell;
+ // store pre-cast values for target and orientation (used to later restore)
+ if (!IsFocusing(nullptr, true))
+ { // only overwrite these fields if we aren't transitioning from one spell focus to another
+ m_suppressedTarget = GetGuidValue(UNIT_FIELD_TARGET);
+ m_suppressedOrientation = GetOrientation();
+ }
- // "instant" creature casts that require re-targeting will be delayed by a short moment to prevent facing bugs
- bool shouldDelay = false;
+ m_focusSpell = focusSpell;
// set target, then force send update packet to players if it changed to provide appropriate facing
ObjectGuid newTarget = target ? target->GetGUID() : ObjectGuid::Empty;
if (GetGuidValue(UNIT_FIELD_TARGET) != newTarget)
{
SetGuidValue(UNIT_FIELD_TARGET, newTarget);
- if (target)
- SetFacingToObject(target);
if ( // here we determine if the (relatively expensive) forced update is worth it, or whether we can afford to wait until the scheduled update tick
( // only require instant update for spells that actually have a visual
@@ -2823,28 +2845,21 @@ bool Creature::FocusTarget(Spell const* focusSpell, WorldObject const* target)
{
// only update players that are known to the client (have already been created)
if (player->HaveAtClient(this))
- {
SendUpdateToPlayer(player);
- shouldDelay = true;
- }
}
- if (shouldDelay)
- shouldDelay = !(focusSpell->IsTriggered() || focusSpell->GetCastTime() || focusSpell->GetSpellInfo()->IsChanneled());
}
}
bool canTurnDuringCast = !focusSpell->GetSpellInfo()->HasAttribute(SPELL_ATTR5_DONT_TURN_DURING_CAST);
// Face the target - we need to do this before the unit state is modified for no-turn spells
if (target)
- SetInFront(target);
+ SetFacingTo(GetAngle(target));
else if (!canTurnDuringCast)
if (Unit* victim = GetVictim())
- SetInFront(victim); // ensure server-side orientation is correct at beginning of cast
+ SetFacingTo(GetAngle(victim)); // ensure orientation is correct at beginning of cast
if (!canTurnDuringCast)
AddUnitState(UNIT_STATE_CANNOT_TURN);
-
- return shouldDelay;
}
bool Creature::IsFocusing(Spell const* focusSpell, bool withDelay)
@@ -2882,9 +2897,18 @@ void Creature::ReleaseFocus(Spell const* focusSpell, bool withDelay)
return;
if (IsPet()) // player pets do not use delay system
- SetGuidValue(UNIT_FIELD_TARGET, GetVictim() ? EnsureVictim()->GetGUID() : ObjectGuid::Empty);
+ {
+ SetGuidValue(UNIT_FIELD_TARGET, m_suppressedTarget);
+ if (m_suppressedTarget)
+ {
+ if (WorldObject const* objTarget = ObjectAccessor::GetWorldObject(*this, m_suppressedTarget))
+ SetFacingTo(GetAngle(objTarget));
+ }
+ else
+ SetFacingTo(m_suppressedOrientation);
+ }
else
- // tell the creature that it should reacquire its actual target after the delay expires (this is handled in ::Attack)
+ // tell the creature that it should reacquire its actual target after the delay expires (this is handled in ::Update)
// player pets don't need to do this, as they automatically reacquire their target on focus release
MustReacquireTarget();
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index 57a025fdd88..7e8d5e3a9ad 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -501,7 +501,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
bool HasSpell(uint32 spellID) const override;
- bool UpdateEntry(uint32 entry, CreatureData const* data = nullptr);
+ bool UpdateEntry(uint32 entry, CreatureData const* data = nullptr, bool updateLevel = true);
void UpdateMovementFlags();
@@ -689,7 +689,8 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
// Handling caster facing during spellcast
void SetTarget(ObjectGuid guid) override;
- bool FocusTarget(Spell const* focusSpell, WorldObject const* target);
+ void MustReacquireTarget() { m_shouldReacquireTarget = true; } // flags the Creature for forced (client displayed) target reacquisition in the next ::Update call
+ void FocusTarget(Spell const* focusSpell, WorldObject const* target);
bool IsFocusing(Spell const* focusSpell = nullptr, bool withDelay = false);
void ReleaseFocus(Spell const* focusSpell = nullptr, bool withDelay = true);
@@ -765,8 +766,12 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
CreatureGroup* m_formation;
bool m_TriggerJustRespawned;
- Spell const* m_focusSpell; ///> Locks the target during spell cast for proper facing
+ /* Spell focus system */
+ Spell const* m_focusSpell; // Locks the target during spell cast for proper facing
uint32 m_focusDelay;
+ bool m_shouldReacquireTarget;
+ ObjectGuid m_suppressedTarget; // Stores the creature's "real" target while casting
+ float m_suppressedOrientation; // Stores the creature's "real" orientation while casting
CreatureTextRepeatGroup m_textRepeat;
};
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index e77e20d323a..dce0d9b6ad7 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -14821,7 +14821,7 @@ void Player::AddQuest(Quest const* quest, Object* questGiver)
StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_QUEST, quest_id);
- SendQuestUpdate();
+ SendQuestUpdate(quest_id);
if (sWorld->getBoolConfig(CONFIG_QUEST_ENABLE_QUEST_TRACKER)) // check if Quest Tracker is enabled
{
@@ -15071,7 +15071,7 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
UpdatePvPState();
}
- SendQuestUpdate();
+ SendQuestUpdate(quest_id);
SendQuestGiverStatusMultiple();
@@ -15735,7 +15735,7 @@ void Player::SetQuestStatus(uint32 questId, QuestStatus status, bool update /*=
}
if (update)
- SendQuestUpdate();
+ SendQuestUpdate(questId);
sScriptMgr->OnQuestStatusChange(this, questId, status);
}
@@ -15750,7 +15750,7 @@ void Player::RemoveActiveQuest(uint32 questId, bool update /*= true*/)
}
if (update)
- SendQuestUpdate();
+ SendQuestUpdate(questId);
}
void Player::RemoveRewardedQuest(uint32 questId, bool update /*= true*/)
@@ -15763,19 +15763,19 @@ void Player::RemoveRewardedQuest(uint32 questId, bool update /*= true*/)
}
if (update)
- SendQuestUpdate();
+ SendQuestUpdate(questId);
}
-void Player::SendQuestUpdate()
+void Player::SendQuestUpdate(uint32 questId)
{
uint32 zone = 0, area = 0;
GetZoneAndAreaId(zone, area);
- SpellAreaForQuestMapBounds saBounds = sSpellMgr->GetSpellAreaForAreaMapBounds(area);
+ SpellAreaForQuestAreaMapBounds saBounds = sSpellMgr->GetSpellAreaForQuestAreaMapBounds(area, questId);
if (saBounds.first != saBounds.second)
{
- for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
+ for (SpellAreaForQuestAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
{
if (!itr->second->IsFitToRequirements(this, zone, area))
RemoveAurasDueToSpell(itr->second->spellId);
@@ -17113,7 +17113,10 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
{
// leave bg
if (player_at_bg)
+ {
+ player_at_bg = false;
currentBg->RemovePlayerAtLeave(GetGUID(), false, true);
+ }
// Do not look for instance if bg not found
WorldLocation const& _loc = GetBattlegroundEntryPoint();
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 1559963ef92..a6af559b519 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1364,7 +1364,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void SetQuestStatus(uint32 questId, QuestStatus status, bool update = true);
void RemoveActiveQuest(uint32 questId, bool update = true);
void RemoveRewardedQuest(uint32 questId, bool update = true);
- void SendQuestUpdate();
+ void SendQuestUpdate(uint32 questId);
QuestGiverStatus GetQuestDialogStatus(Object* questGiver);
void SetDailyQuestStatus(uint32 quest_id);
diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp
index def6c382893..d1984da9648 100644
--- a/src/server/game/Entities/Unit/StatSystem.cpp
+++ b/src/server/game/Entities/Unit/StatSystem.cpp
@@ -1426,7 +1426,7 @@ void Guardian::UpdateDamagePhysical(WeaponAttackType attType)
float maxdamage = ((base_value + weapon_maxdamage) * base_pct + total_value) * total_pct;
// Pet's base damage changes depending on happiness
- if (IsHunterPet() && attType == BASE_ATTACK)
+ if (IsHunterPet())
{
switch (ToPet()->GetHappinessState())
{
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 6ab10158b3c..e004ef25411 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -247,7 +247,6 @@ Unit::Unit(bool isWorldObject) :
m_createStats[i] = 0.0f;
m_attacking = nullptr;
- m_shouldReacquireTarget = false;
m_modMeleeHitChance = 0.0f;
m_modRangedHitChance = 0.0f;
m_modSpellHitChance = 0.0f;
@@ -882,10 +881,6 @@ void Unit::CastSpell(SpellCastTargets const& targets, SpellInfo const* spellInfo
return;
}
- /// @todo this is a workaround - not needed anymore, but required for some scripts :(
- if (!originalCaster && triggeredByAura)
- originalCaster = triggeredByAura->GetCasterGUID();
-
Spell* spell = new Spell(this, spellInfo, triggerFlags, originalCaster);
if (value)
@@ -8558,12 +8553,6 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
if (HasAuraType(SPELL_AURA_MOD_UNATTACKABLE))
RemoveAurasByType(SPELL_AURA_MOD_UNATTACKABLE);
- if (m_shouldReacquireTarget)
- {
- SetTarget(victim->GetGUID());
- m_shouldReacquireTarget = false;
- }
-
if (m_attacking)
{
if (m_attacking == victim)
@@ -12731,7 +12720,7 @@ float Unit::GetSpellMaxRangeForTarget(Unit const* target, SpellInfo const* spell
return 0;
if (spellInfo->RangeEntry->maxRangeFriend == spellInfo->RangeEntry->maxRangeHostile)
return spellInfo->GetMaxRange();
- if (target == NULL)
+ if (!target)
return spellInfo->GetMaxRange(true);
return spellInfo->GetMaxRange(!IsHostileTo(target));
}
@@ -12742,6 +12731,8 @@ float Unit::GetSpellMinRangeForTarget(Unit const* target, SpellInfo const* spell
return 0;
if (spellInfo->RangeEntry->minRangeFriend == spellInfo->RangeEntry->minRangeHostile)
return spellInfo->GetMinRange();
+ if (!target)
+ return spellInfo->GetMinRange(true);
return spellInfo->GetMinRange(!IsHostileTo(target));
}
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 8441252bef6..61b7665254b 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -1300,7 +1300,6 @@ class TC_GAME_API Unit : public WorldObject
void _removeAttacker(Unit* pAttacker); // must be called only from Unit::AttackStop()
Unit* getAttackerForHelper() const; // If someone wants to help, who to give them
bool Attack(Unit* victim, bool meleeAttack);
- void MustReacquireTarget() { m_shouldReacquireTarget = true; } // flags the Unit for forced (client displayed) target reacquisition in the next ::Attack call
void CastStop(uint32 except_spellid = 0);
bool AttackStop();
void RemoveAllAttackers();
@@ -2203,7 +2202,6 @@ class TC_GAME_API Unit : public WorldObject
AttackerSet m_attackers;
Unit* m_attacking;
- bool m_shouldReacquireTarget;
DeathState m_deathState;
diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp
index bb8e89d4829..39d55ef784e 100644
--- a/src/server/game/Events/GameEventMgr.cpp
+++ b/src/server/game/Events/GameEventMgr.cpp
@@ -139,6 +139,9 @@ bool GameEventMgr::StartEvent(uint16 event_id, bool overwrite)
if (data.end <= data.start)
data.end = data.start + data.length;
}
+
+ // When event is started, set its worldstate to current time
+ sWorld->setWorldState(event_id, time(NULL));
return false;
}
else
@@ -174,6 +177,9 @@ void GameEventMgr::StopEvent(uint16 event_id, bool overwrite)
RemoveActiveEvent(event_id);
UnApplyEvent(event_id);
+ // When event is stopped, clean up its worldstate
+ sWorld->setWorldState(event_id, 0);
+
if (overwrite && !serverwide_evt)
{
data.start = time(NULL) - data.length * MINUTE;
@@ -1033,6 +1039,8 @@ uint32 GameEventMgr::Update() // return the next e
}
else
{
+ // If event is inactive, periodically clean up its worldstate
+ sWorld->setWorldState(itr, 0);
//TC_LOG_DEBUG("misc", "GameEvent %u is not active", itr->first);
if (IsActiveEvent(itr))
deactivate.insert(itr);
@@ -1115,8 +1123,10 @@ void GameEventMgr::ApplyNewEvent(uint16 event_id)
UpdateEventNPCVendor(event_id, true);
// update bg holiday
UpdateBattlegroundSettings();
- // check for seasonal quest reset.
- sWorld->ResetEventSeasonalQuests(event_id);
+ // If event's worldstate is 0, it means the event hasn't been started yet. In that case, reset seasonal quests.
+ // When event ends (if it expires or if it's stopped via commands) worldstate will be set to 0 again, ready for another seasonal quest reset.
+ if (sWorld->getWorldState(event_id) == 0)
+ sWorld->ResetEventSeasonalQuests(event_id);
}
void GameEventMgr::UpdateEventNPCFlags(uint16 event_id)
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h
index 5283805c59d..8304054c663 100644
--- a/src/server/game/Grids/Notifiers/GridNotifiers.h
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.h
@@ -1156,7 +1156,7 @@ namespace Trinity
bool operator()(Creature* u)
{
- if (u->GetEntry() == i_entry && u->IsAlive() == i_alive && i_obj.IsWithinDistInMap(u, i_range))
+ if (u->getDeathState() != DEAD && u->GetEntry() == i_entry && u->IsAlive() == i_alive && i_obj.IsWithinDistInMap(u, i_range))
{
i_range = i_obj.GetDistance(u); // use found unit range as new range limit for next check
return true;
diff --git a/src/server/game/Handlers/BattleGroundHandler.cpp b/src/server/game/Handlers/BattleGroundHandler.cpp
index 55bfb93c1c4..2de9ff2bc46 100644
--- a/src/server/game/Handlers/BattleGroundHandler.cpp
+++ b/src/server/game/Handlers/BattleGroundHandler.cpp
@@ -777,7 +777,7 @@ void WorldSession::HandleReportPvPAFK(WorldPacket& recvData)
if (!reportedPlayer)
{
- TC_LOG_INFO("bg.reportpvpafk", "WorldSession::HandleReportPvPAFK: %s [IP: %s] reported %s [IP: %s]", _player->GetName().c_str(), _player->GetSession()->GetRemoteAddress().c_str(), reportedPlayer->GetName().c_str(), reportedPlayer->GetSession()->GetRemoteAddress().c_str());
+ TC_LOG_INFO("bg.reportpvpafk", "WorldSession::HandleReportPvPAFK: %s [IP: %s] reported %s", _player->GetName().c_str(), _player->GetSession()->GetRemoteAddress().c_str(), playerGuid.ToString().c_str());
return;
}
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 9545b957c57..ce5d3c9f8a1 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -603,8 +603,6 @@ m_caster((info->HasAttribute(SPELL_ATTR6_CAST_BY_CHARMER) && caster->GetCharmerO
//Auto Shot & Shoot (wand)
m_autoRepeat = m_spellInfo->IsAutoRepeatRangedSpell();
- m_isDelayedInstantCast = false;
-
m_runesState = 0;
m_powerCost = 0; // setup to correct value in Spell::prepare, must not be used before.
m_casttime = 0; // setup to correct value in Spell::prepare, must not be used before.
@@ -2977,21 +2975,9 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered
if (!(IsNextMeleeSwingSpell() || IsAutoRepeat() || _triggeredCastFlags & TRIGGERED_IGNORE_SET_FACING))
{
if (m_targets.GetObjectTarget() && m_caster != m_targets.GetObjectTarget())
- {
- if (m_caster->ToCreature()->FocusTarget(this, m_targets.GetObjectTarget()))
- {
- m_isDelayedInstantCast = true;
- m_timer = 100; // 100ms delay ensures client has updated creature orientation when cast goes off
- }
- }
+ m_caster->ToCreature()->FocusTarget(this, m_targets.GetObjectTarget());
else if (m_spellInfo->HasAttribute(SPELL_ATTR5_DONT_TURN_DURING_CAST))
- {
- if (m_caster->ToCreature()->FocusTarget(this, nullptr))
- {
- m_isDelayedInstantCast = true;
- m_timer = 100;
- }
- }
+ m_caster->ToCreature()->FocusTarget(this, nullptr);
}
// don't allow channeled spells / spells with cast time to be cast while moving
@@ -3034,14 +3020,13 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered
}
m_caster->SetCurrentCastSpell(this);
- if (!m_isDelayedInstantCast)
- SendSpellStart();
+ SendSpellStart();
if (!(_triggeredCastFlags & TRIGGERED_IGNORE_GCD))
TriggerGlobalCooldown();
//item: first cast may destroy item and second cast causes crash
- if (!m_casttime && !m_isDelayedInstantCast && !m_spellInfo->StartRecoveryTime && !m_castItemGUID && GetCurrentContainer() == CURRENT_GENERIC_SPELL)
+ if (!m_casttime && !m_spellInfo->StartRecoveryTime && !m_castItemGUID && GetCurrentContainer() == CURRENT_GENERIC_SPELL)
cast(true);
}
}
@@ -3050,9 +3035,6 @@ void Spell::cancel()
{
if (m_spellState == SPELL_STATE_FINISHED)
return;
- // delayed instant casts are used for client-side visual orientation; they are treated as instant for all intents and purposes server-side, and thus cannot be interrupted by another cast
- if (m_isDelayedInstantCast)
- return;
uint32 oldState = m_spellState;
m_spellState = SPELL_STATE_FINISHED;
@@ -3122,9 +3104,6 @@ void Spell::cast(bool skipCheck)
return;
}
- if (m_isDelayedInstantCast)
- SendSpellStart();
-
if (Player* playerCaster = m_caster->ToPlayer())
{
// now that we've done the basic check, now run the scripts
@@ -3209,10 +3188,7 @@ void Spell::cast(bool skipCheck)
if (m_caster->GetTypeId() == TYPEID_UNIT && !m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED))
if (!m_spellInfo->HasAttribute(SPELL_ATTR5_DONT_TURN_DURING_CAST))
if (WorldObject* objTarget = m_targets.GetObjectTarget())
- {
m_caster->SetInFront(objTarget);
- m_caster->SetFacingToObject(objTarget);
- }
SelectSpellTargets();
@@ -4773,7 +4749,7 @@ SpellCastResult Spell::CheckCast(bool strict)
// Check global cooldown
if (strict && !(_triggeredCastFlags & TRIGGERED_IGNORE_GCD) && HasGlobalCooldown())
- return SPELL_FAILED_NOT_READY;
+ return !m_spellInfo->HasAttribute(SPELL_ATTR0_DISABLED_WHILE_ACTIVE) ? SPELL_FAILED_NOT_READY : SPELL_FAILED_DONT_REPORT;
// only triggered spells can be processed an ended battleground
if (!IsTriggered() && m_caster->GetTypeId() == TYPEID_PLAYER)
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index c834d187720..016af275141 100644
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -527,7 +527,6 @@ class TC_GAME_API Spell
int32 m_channeledDuration; // Calculated channeled spell duration in order to calculate correct pushback.
bool m_canReflect; // can reflect this spell?
bool m_autoRepeat;
- bool m_isDelayedInstantCast; // whether this is a creature's delayed instant cast
uint8 m_runesState;
uint8 m_delayAtDamageCount;
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index ed0d95f0a58..be2d11fdf52 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -1125,6 +1125,11 @@ SpellAreaForAreaMapBounds SpellMgr::GetSpellAreaForAreaMapBounds(uint32 area_id)
return mSpellAreaForAreaMap.equal_range(area_id);
}
+SpellAreaForQuestAreaMapBounds SpellMgr::GetSpellAreaForQuestAreaMapBounds(uint32 area_id, uint32 quest_id) const
+{
+ return mSpellAreaForQuestAreaMap.equal_range(std::pair<uint32, uint32>(area_id, quest_id));
+}
+
bool SpellArea::IsFitToRequirements(Player const* player, uint32 newZone, uint32 newArea) const
{
if (gender != GENDER_NONE) // is not expected gender
@@ -2720,6 +2725,12 @@ void SpellMgr::LoadSpellAreas()
if (spellArea.auraSpell)
mSpellAreaForAuraMap.insert(SpellAreaForAuraMap::value_type(abs(spellArea.auraSpell), sa));
+ if (spellArea.areaId && spellArea.questStart)
+ mSpellAreaForQuestAreaMap.insert(SpellAreaForQuestAreaMap::value_type(std::pair<uint32, uint32>(spellArea.areaId, spellArea.questStart), sa));
+
+ if (spellArea.areaId && spellArea.questEnd)
+ mSpellAreaForQuestAreaMap.insert(SpellAreaForQuestAreaMap::value_type(std::pair<uint32, uint32>(spellArea.areaId, spellArea.questEnd), sa));
+
++count;
} while (result->NextRow());
diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h
index 75da933636c..23329c1ff1e 100644
--- a/src/server/game/Spells/SpellMgr.h
+++ b/src/server/game/Spells/SpellMgr.h
@@ -509,10 +509,12 @@ typedef std::multimap<uint32, SpellArea> SpellAreaMap;
typedef std::multimap<uint32, SpellArea const*> SpellAreaForQuestMap;
typedef std::multimap<uint32, SpellArea const*> SpellAreaForAuraMap;
typedef std::multimap<uint32, SpellArea const*> SpellAreaForAreaMap;
+typedef std::multimap<std::pair<uint32, uint32>, SpellArea const*> SpellAreaForQuestAreaMap;
typedef std::pair<SpellAreaMap::const_iterator, SpellAreaMap::const_iterator> SpellAreaMapBounds;
typedef std::pair<SpellAreaForQuestMap::const_iterator, SpellAreaForQuestMap::const_iterator> SpellAreaForQuestMapBounds;
typedef std::pair<SpellAreaForAuraMap::const_iterator, SpellAreaForAuraMap::const_iterator> SpellAreaForAuraMapBounds;
typedef std::pair<SpellAreaForAreaMap::const_iterator, SpellAreaForAreaMap::const_iterator> SpellAreaForAreaMapBounds;
+typedef std::pair<SpellAreaForQuestAreaMap::const_iterator, SpellAreaForQuestAreaMap::const_iterator> SpellAreaForQuestAreaMapBounds;
// Spell rank chain (accessed using SpellMgr functions)
struct SpellChainNode
@@ -688,6 +690,7 @@ class TC_GAME_API SpellMgr
SpellAreaForQuestMapBounds GetSpellAreaForQuestEndMapBounds(uint32 quest_id) const;
SpellAreaForAuraMapBounds GetSpellAreaForAuraMapBounds(uint32 spell_id) const;
SpellAreaForAreaMapBounds GetSpellAreaForAreaMapBounds(uint32 area_id) const;
+ SpellAreaForQuestAreaMapBounds GetSpellAreaForQuestAreaMapBounds(uint32 area_id, uint32 quest_id) const;
// SpellInfo object management
SpellInfo const* GetSpellInfo(uint32 spellId) const { return spellId < GetSpellInfoStoreSize() ? mSpellInfoMap[spellId] : NULL; }
@@ -759,6 +762,7 @@ class TC_GAME_API SpellMgr
SpellAreaForQuestMap mSpellAreaForQuestEndMap;
SpellAreaForAuraMap mSpellAreaForAuraMap;
SpellAreaForAreaMap mSpellAreaForAreaMap;
+ SpellAreaForQuestAreaMap mSpellAreaForQuestAreaMap;
SkillLineAbilityMap mSkillLineAbilityMap;
PetLevelupSpellMap mPetLevelupSpellMap;
PetDefaultSpellsMap mPetDefaultSpellsMap; // only spells not listed in related mPetLevelupSpellMap entry
diff --git a/src/server/scripts/Commands/cs_cheat.cpp b/src/server/scripts/Commands/cs_cheat.cpp
index 0adff61c9ec..af78eaf3a3b 100644
--- a/src/server/scripts/Commands/cs_cheat.cpp
+++ b/src/server/scripts/Commands/cs_cheat.cpp
@@ -246,7 +246,6 @@ public:
if (!*args)
return false;
- // std::int flag = (char*)args;
int flag = atoi((char*)args);
Player* chr = handler->getSelectedPlayer();
diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
index 3cf78b79f67..95082a4268a 100644
--- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
@@ -1023,7 +1023,6 @@ class npc_scarlet_miner_cart : public CreatureScript
{
npc_scarlet_miner_cartAI(Creature* creature) : PassiveAI(creature)
{
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
me->SetDisplayId(me->GetCreatureTemplate()->Modelid1); // Modelid2 is a horse.
}
diff --git a/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp b/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp
index 68391c65655..eb4db03e20a 100644
--- a/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp
+++ b/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp
@@ -98,7 +98,7 @@ class boss_archaedas : public CreatureScript
instance->SetData(0, 5); // respawn any dead minions
me->setFaction(35);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL);
+ me->SetControlled(true, UNIT_STATE_ROOT);
me->AddAura(SPELL_FREEZE_ANIM, me);
}
@@ -111,7 +111,7 @@ class boss_archaedas : public CreatureScript
DoCast(minion, SPELL_AWAKEN_VAULT_WALKER, flag);
minion->CastSpell(minion, SPELL_ARCHAEDAS_AWAKEN, true);
minion->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- minion->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL);
+ minion->SetControlled(false, UNIT_STATE_ROOT);
minion->setFaction(14);
minion->RemoveAura(SPELL_MINION_FREEZE_ANIM);
}
@@ -121,7 +121,7 @@ class boss_archaedas : public CreatureScript
{
me->setFaction(14);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL);
+ me->SetControlled(false, UNIT_STATE_ROOT);
}
void SpellHit(Unit* /*caster*/, const SpellInfo* spell) override
@@ -261,7 +261,7 @@ class npc_archaedas_minions : public CreatureScript
me->setFaction(35);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL);
+ me->SetControlled(true, UNIT_STATE_ROOT);
me->RemoveAllAuras();
me->AddAura(SPELL_MINION_FREEZE_ANIM, me);
}
@@ -270,8 +270,8 @@ class npc_archaedas_minions : public CreatureScript
{
me->setFaction (14);
me->RemoveAllAuras();
- me->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ me->SetControlled(false, UNIT_STATE_ROOT);
bAmIAwake = true;
}
@@ -350,7 +350,7 @@ class npc_stonekeepers : public CreatureScript
{
me->setFaction(35);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL);
+ me->SetControlled(true, UNIT_STATE_ROOT);
me->RemoveAllAuras();
me->AddAura(SPELL_MINION_FREEZE_ANIM, me);
}
@@ -359,7 +359,7 @@ class npc_stonekeepers : public CreatureScript
{
me->setFaction(14);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL);
+ me->SetControlled(false, UNIT_STATE_ROOT);
}
void UpdateAI(uint32 /*diff*/) override
diff --git a/src/server/scripts/EasternKingdoms/Uldaman/instance_uldaman.cpp b/src/server/scripts/EasternKingdoms/Uldaman/instance_uldaman.cpp
index 28a3a4eb4e0..604174a8935 100644
--- a/src/server/scripts/EasternKingdoms/Uldaman/instance_uldaman.cpp
+++ b/src/server/scripts/EasternKingdoms/Uldaman/instance_uldaman.cpp
@@ -147,7 +147,7 @@ class instance_uldaman : public InstanceMapScript
creature->setFaction(35);
creature->RemoveAllAuras();
creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL);
+ creature->SetControlled(true, UNIT_STATE_ROOT);
creature->AddAura(SPELL_MINION_FREEZE_ANIM, creature);
}
@@ -178,7 +178,7 @@ class instance_uldaman : public InstanceMapScript
Creature* target = instance->GetCreature(*i);
if (!target || !target->IsAlive())
continue;
- target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL);
+ target->SetControlled(false, UNIT_STATE_ROOT);
target->setFaction(14);
target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
target->RemoveAura(SPELL_MINION_FREEZE_ANIM);
@@ -202,7 +202,7 @@ class instance_uldaman : public InstanceMapScript
Creature* target = instance->GetCreature(*i);
if (!target || !target->IsAlive() || target->getFaction() == 14)
continue;
- target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL);
+ target->SetControlled(false, UNIT_STATE_ROOT);
target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
target->setFaction(14);
target->RemoveAura(SPELL_MINION_FREEZE_ANIM);
@@ -268,7 +268,7 @@ class instance_uldaman : public InstanceMapScript
return;
ironaya->setFaction(415);
- ironaya->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL);
+ ironaya->SetControlled(false, UNIT_STATE_ROOT);
ironaya->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
ironaya->GetMotionMaster()->Clear();
diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp
index 2df0fceab9c..95335393942 100644
--- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp
+++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp
@@ -156,7 +156,8 @@ public:
ImpaleTarget = impaleTarget->GetGUID();
impaleTarget->SetReactState(REACT_PASSIVE);
impaleTarget->SetDisplayId(DISPLAY_INVISIBLE);
- impaleTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL|UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
+ impaleTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
+ impaleTarget->SetControlled(true, UNIT_STATE_ROOT);
return impaleTarget;
}
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp
index b2283ec6fde..69a9e354660 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp
@@ -646,7 +646,7 @@ struct boss_jormungarAI : public BossAI
// if the worm was mobile before submerging, make him stationary now
if (WasMobile)
{
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL);
+ me->SetControlled(true, UNIT_STATE_ROOT);
SetCombatMovement(false);
me->SetDisplayId(ModelStationary);
me->CastSpell(me, SPELL_GROUND_VISUAL_1, true);
@@ -658,7 +658,7 @@ struct boss_jormungarAI : public BossAI
}
else
{
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL);
+ me->SetControlled(false, UNIT_STATE_ROOT);
SetCombatMovement(true);
me->GetMotionMaster()->MoveChase(me->GetVictim());
me->SetDisplayId(ModelMobile);
@@ -1023,7 +1023,8 @@ class boss_icehowl : public CreatureScript
me->SetTarget(_trampleTargetGUID);
_trampleCast = false;
SetCombatMovement(false);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_REMOVE_CLIENT_CONTROL);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ me->SetControlled(true, UNIT_STATE_ROOT);
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveIdle();
events.ScheduleEvent(EVENT_TRAMPLE, 4*IN_MILLISECONDS);
@@ -1107,7 +1108,8 @@ class boss_icehowl : public CreatureScript
Talk(EMOTE_TRAMPLE_FAIL);
}
_movementStarted = false;
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_REMOVE_CLIENT_CONTROL);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ me->SetControlled(false, UNIT_STATE_ROOT);
SetCombatMovement(true);
me->GetMotionMaster()->MovementExpired();
me->GetMotionMaster()->Clear();
diff --git a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp
index 94d1d93225c..e49f7044c0a 100644
--- a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp
@@ -144,7 +144,7 @@ class boss_devourer_of_souls : public CreatureScript
void Reset() override
{
_Reset();
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL);
+ me->SetControlled(false, UNIT_STATE_ROOT);
me->SetDisplayId(DISPLAY_ANGER);
me->SetReactState(REACT_AGGRESSIVE);
@@ -297,7 +297,7 @@ class boss_devourer_of_souls : public CreatureScript
me->SetTarget(ObjectGuid::Empty);
me->GetMotionMaster()->Clear();
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL);
+ me->SetControlled(true, UNIT_STATE_ROOT);
wailingSoulTick = 15;
events.DelayEvents(18000); // no other events during wailing souls
@@ -317,7 +317,7 @@ class boss_devourer_of_souls : public CreatureScript
{
me->SetReactState(REACT_AGGRESSIVE);
me->SetDisplayId(DISPLAY_ANGER);
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL);
+ me->SetControlled(false, UNIT_STATE_ROOT);
me->GetMotionMaster()->MoveChase(me->GetVictim());
events.ScheduleEvent(EVENT_WAILING_SOULS, urand(60000, 70000));
}
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp
index 42efdfbfe67..2452385b97c 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp
@@ -16,27 +16,19 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Boss_KelThuzad
-SD%Complete: 80%
-SDComment: VERIFY SCRIPT
-SDCategory: Naxxramas
-EndScriptData */
-
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "SpellScript.h"
#include "SpellAuraEffects.h"
#include "naxxramas.h"
-#include "Player.h"
+#include "PlayerAI.h"
enum Texts
{
SAY_AGGRO = 7,
SAY_SLAY = 8,
SAY_DEATH = 9,
- SAY_CHAIN = 10,
- SAY_FROST_BLAST = 11,
+ SAY_CHAINS = 10,
SAY_REQUEST_AID = 12, //start of phase 3
EMOTE_PHASE_TWO = 13,
SAY_SUMMON_MINIONS = 14, //start of phase 1
@@ -45,219 +37,165 @@ enum Texts
// The Lich King
SAY_ANSWER_REQUEST = 3,
- // Old World Trigger
- SAY_GUARDIAN_SPAWNED = 0
+ // Guardian of Icecrown
+ EMOTE_GUARDIAN_FLEE = 0,
+ EMOTE_GUARDIAN_APPEAR = 1
};
enum Events
{
- EVENT_NONE,
- EVENT_BOLT,
- EVENT_NOVA,
- EVENT_CHAIN,
- EVENT_CHAINED_SPELL,
- EVENT_DETONATE,
- EVENT_FISSURE,
- EVENT_BLAST,
-
- EVENT_WASTE,
- EVENT_ABOMIN,
- EVENT_WEAVER,
- EVENT_ICECROWN,
- EVENT_TRIGGER,
-
- EVENT_PHASE,
- EVENT_MORTAL_WOUND,
-
- EVENT_ANSWER_REQUEST,
- EVENT_SUMMON_GUARDIANS
+ // phase one
+ EVENT_SKELETON = 1,
+ EVENT_BANSHEE,
+ EVENT_ABOMINATION,
+ EVENT_DESPAWN_MINIONS,
+ EVENT_PHASE_TWO,
+
+ // phase two
+ EVENT_FROSTBOLT_VOLLEY,
+ EVENT_SHADOW_FISSURE,
+ EVENT_DETONATE_MANA,
+ EVENT_FROST_BLAST,
+ EVENT_CHAINS,
+
+ // phase three transition
+ EVENT_TRANSITION_REPLY,
+ EVENT_TRANSITION_SUMMON,
};
-enum Spells
+enum Actions
{
- SPELL_FROST_BOLT = 28478,
- SPELL_FROST_BOLT_AOE = 28479,
- SPELL_SHADOW_FISURE = 27810,
- SPELL_VOID_BLAST = 27812,
- SPELL_MANA_DETONATION = 27819,
- SPELL_MANA_DETONATION_DAMAGE = 27820,
- SPELL_FROST_BLAST = 27808,
- SPELL_CHAINS_OF_KELTHUZAD = 28410, //28408 script effect
- SPELL_KELTHUZAD_CHANNEL = 29423,
- SPELL_BERSERK = 28498,
-
- //spells for chained
- //warlock
- SPELL_CURSE_OF_AGONY = 47864,
- SPELL_SHADOW_BOLT = 47809,
- //shaman
- SPELL_EARTH_SHOCK = 49231,
- SPELL_HEALING_WAVE = 49273,
- //mage
- SPELL_FROST_FIREBOLT = 47610,
- SPELL_ARCANE_MISSILES = 42846,
- //rogue
- SPELL_HEMORRHAGE = 48660,
- SPELL_MUTILATE = 48666,
- //paladin
- SPELL_HOLY_SHOCK = 48825,
- SPELL_HAMMER_OF_JUSTICE = 10308,
- //priest
- SPELL_VAMPIRIC_TOUCH = 48160,
- SPELL_RENEW = 48068,
- //hunter
- SPELL_MULTI_SHOT = 49048,
- SPELL_VOLLEY = 58434,
- //warrior
- SPELL_BLADESTORM = 46924,
- SPELL_CLEAVE = 47520,
- //druid
- SPELL_MOONFIRE = 48463,
- SPELL_LIFEBLOOM = 48451,
- //death knight
- SPELL_PLAGUE_STRIKE = 49921,
- SPELL_HOWLING_BLAST = 51411,
-
- // Abomination spells
- SPELL_FRENZY = 28468,
- SPELL_MORTAL_WOUND = 28467
+ ACTION_BEGIN_ENCOUNTER,
+ ACTION_JUST_SUMMONED,
+ ACTION_ABOMINATION_DIED,
+ ACTION_KELTHUZAD_DIED
};
-enum Phases
+enum KTData
{
- PHASE_ONE = 1, // Players move in the circle and Kel'Thuzad spawns his minions.
- PHASE_TWO = 2, // Starts on a timer.
- PHASE_THREE = 3 // At 45% health.
+ DATA_MINION_POCKET_ID,
+ DATA_ABOMINATION_DEATH_COUNT
};
-enum Creatures
+enum Spells
{
- NPC_WASTE = 16427, // Soldiers of the Frozen Wastes
- NPC_ABOMINATION = 16428, // Unstoppable Abominations
- NPC_WEAVER = 16429, // Soul Weavers
- NPC_ICECROWN = 16441 // Guardians of Icecrown
+ // Kel'thuzad - Phase one
+ SPELL_VISUAL_CHANNEL = 29423, // channeled throughout phase one
+
+ // Kel'thuzad - Phase two
+ SPELL_FROSTBOLT_SINGLE = 28478,
+ SPELL_FROSTBOLT_VOLLEY = 28479,
+ SPELL_SHADOW_FISSURE = 27810,
+ SPELL_DETONATE_MANA = 27819,
+ SPELL_MANA_DETONATION_DAMAGE = 27820,
+ SPELL_FROST_BLAST = 27808,
+ SPELL_CHAINS = 28410,
+ SPELL_CHAINS_DUMMY = 28408, // this holds the category cooldown - the main chains spell can't have one as it is cast multiple times
+
+ SPELL_BERSERK = 28498,
+
+ // Unstoppable Abomination
+ SPELL_MORTAL_WOUND = 28467,
+
+ // Guardian of Icecrown
+ SPELL_BLOOD_TAP = 28470
};
-Position const Pos[12] =
+static const uint8 nGuardianSpawns = 4;
+static const uint8 nMinionGroups = 7;
+enum SummonGroups
{
- {3783.272705f, -5062.697266f, 143.711203f, 3.617599f}, //LEFT_FAR
- {3730.291260f, -5027.239258f, 143.956909f, 4.461900f}, //LEFT_MIDDLE
- {3757.6f, -5172.0f, 143.7f, 1.97f}, //WINDOW_PORTAL05
- {3759.355225f, -5174.128418f, 143.802383f, 2.170104f}, //RIGHT_FAR
- {3700.724365f, -5185.123047f, 143.928024f, 1.309310f}, //RIGHT_MIDDLE
- {3700.86f, -5181.29f, 143.928024f, 1.42f}, //WINDOW_PORTAL04
- {3754.431396f, -5080.727734f, 142.036316f, 3.736189f}, //LEFT_FAR
- {3724.396484f, -5061.330566f, 142.032700f, 4.564785f}, //LEFT_MIDDLE
- {3732.02f, -5028.53f, 143.92f, 4.49f}, //WINDOW_PORTAL02
- {3687.571777f, -5126.831055f, 142.017807f, 0.604023f}, //RIGHT_FAR
- {3707.990733f, -5151.450195f, 142.032562f, 1.376855f}, //RIGHT_MIDDLE
- {3782.76f, -5062.97f, 143.79f, 3.82f} //WINDOW_PORTAL03
+ SUMMON_GROUP_GUARDIAN_FIRST = 01 /*..04 */,
+ SUMMON_GROUP_MINION_FIRST = 05 /*..11 */
};
+static const std::initializer_list<Data64> portalList = { DATA_KELTHUZAD_PORTAL01, DATA_KELTHUZAD_PORTAL02, DATA_KELTHUZAD_PORTAL03, DATA_KELTHUZAD_PORTAL04 };
-//creatures in corners
-//Unstoppable Abominations
-#define MAX_ABOMINATIONS 21
-Position const PosAbominations[MAX_ABOMINATIONS] =
+enum Phases
{
- {3755.52f, -5155.22f, 143.480f, 2.0f},
- {3744.35f, -5164.03f, 143.590f, 2.00f},
- {3749.28f, -5159.04f, 143.190f, 2.0f},
- {3774.47f, -5076.28f, 143.528f, 2.15912f},
- {3765.94f, -5074.15f, 143.186f, 3.77233f},
- {3763.15f, -5063.36f, 143.694f, 3.77233f},
- {3737.81f, -5045.69f, 143.709f, 4.9033f},
- {3728.13f, -5045.01f, 143.355f, 1.45069f},
- {3721.56f, -5048.35f, 143.542f, 1.45069f},
- {3689.55f, -5049.66f, 143.637f, 5.2104f},
- {3681.71f, -5053.03f, 143.242f, 2.47957f},
- {3677.64f, -5061.44f, 143.358f, 2.47957f},
- {3654.2f, -5090.87f, 143.469f, 1.0313f},
- {3650.39f, -5097.45f, 143.496f, 2.5047f},
- {3658.7f, -5103.59f, 143.607f, 3.3278f},
- {3659.02f, -5133.97f, 143.624f, 3.84538f},
- {3666.33f, -5139.34f, 143.183f, 3.84538f},
- {3669.74f, -5149.63f, 143.678f, 0.528643f},
- {3695.53f, -5169.53f, 143.671f, 2.11908f},
- {3701.98f, -5166.51f, 143.395f, 1.24257f},
- {3709.62f, -5169.15f, 143.576f, 5.97695f}
+ PHASE_ONE = 1,
+ PHASE_TWO = 2 // "phase three" is not actually a phase in events, as timers from phase two carry over
};
-//Soldiers of the Frozen Wastes
-#define MAX_WASTES 49
-Position const PosWastes[MAX_WASTES] =
+enum Movements
{
- {3754.41f, -5147.24f, 143.204f, 2.0f},
- {3754.68f, -5156.17f, 143.418f, 2.0f},
- {3757.91f, -5160.12f, 143.503f, 2.0f},
- {3752.67f, -5164.6f, 143.395f, 2.0f},
- {3745.42f, -5164.47f, 143.565f, 2.74587f},
- {3741.2f, -5155.92f, 143.17f, 5.29134f},
- {3746.57f, -5148.82f, 143.176f, 5.07772f},
- {3778.14f, -5070.1f, 143.568f, 3.16208f},
- {3775.09f, -5078.97f, 143.65f, 2.81022f},
- {3773.54f, -5083.47f, 143.758f, 3.21549f},
- {3765, -5078.29f, 143.176f, 4.36688f},
- {3766.94f, -5072.63f, 143.184f, 5.27951f},
- {3762.68f, -5064.94f, 143.635f, 3.95297f},
- {3769.9f, -5059.94f, 143.74f, 3.36549f},
- {3736.33f, -5042.18f, 143.643f, 5.9471f},
- {3727.51f, -5040.58f, 143.502f, 0.871859f},
- {3719.89f, -5049.64f, 143.58f, 4.75172f},
- {3720.69f, -5044.43f, 143.662f, 1.87245f},
- {3725.69f, -5048.99f, 143.363f, 2.48271f},
- {3732.33f, -5054.01f, 143.44f, 3.59405f},
- {3738.09f, -5051.06f, 143.718f, 4.70931f},
- {3682.76f, -5063.5f, 143.175f, 0.636238f},
- {3686.7f, -5060.58f, 143.18f, 0.636238f},
- {3682.45f, -5057.21f, 143.184f, 5.61252f},
- {3677.57f, -5053.34f, 143.369f, 1.52531f},
- {3677.3f, -5062.26f, 143.369f, 2.73482f},
- {3691.21f, -5053.02f, 143.421f, 5.93218f},
- {3685.22f, -5053.34f, 143.314f, 4.70303f},
- {3652.11f, -5088.47f, 143.555f, 0.793317f},
- {3648.23f, -5093.21f, 143.311f, 1.18837f},
- {3648.14f, -5100.11f, 143.632f, 2.12221f},
- {3653.88f, -5099.7f, 143.558f, 3.04348f},
- {3661.23f, -5100.33f, 143.42f, 4.08335f},
- {3663.49f, -5092.77f, 143.346f, 4.47134f},
- {3661.85f, -5087.99f, 143.571f, 1.0148f},
- {3664.56f, -5149.01f, 143.532f, 0.0762528f},
- {3665.01f, -5142.04f, 143.201f, 1.72009f},
- {3671.15f, -5142.92f, 143.174f, 4.81535f},
- {3670.18f, -5134.38f, 143.177f, 5.37534f},
- {3664.33f, -5131.69f, 143.262f, 5.39576f},
- {3658.21f, -5133.63f, 143.662f, 1.3863f},
- {3659.7f, -5144.49f, 143.363f, 2.32328f},
- {3705.71f, -5179.63f, 143.746f, 1.06743f},
- {3696.77f, -5177.45f, 143.759f, 5.36748f},
- {3700.97f, -5173.13f, 143.52f, 3.26575f},
- {3708.53f, -5172.19f, 143.573f, 3.26575f},
- {3712.49f, -5167.62f, 143.657f, 5.63295f},
- {3704.89f, -5161.84f, 143.239f, 5.63295f},
- {3695.66f, -5164.63f, 143.674f, 1.54416f}
+ MOVEMENT_MINION_RANDOM = 1,
};
-//Soul Weavers
-#define MAX_WEAVERS 7
-Position const PosWeavers[MAX_WEAVERS] =
+enum Creatures
{
- {3752.45f, -5168.35f, 143.562f, 1.6094f},
- {3772.2f, -5070.04f, 143.329f, 1.93686f},
- {3732.28f, -5032.88f, 143.771f, 3.08355f},
- {3689.05f, -5055.7f, 143.172f, 6.09554f},
- {3649.45f, -5093.17f, 143.299f, 2.51805f},
- {3659.7f, -5144.49f, 143.363f, 4.08806f},
- {3704.71f, -5175.96f, 143.597f, 3.36549f}
+ NPC_SKELETON1 = 16427, // Soldiers of the Frozen Wastes
+ NPC_SKELETON2 = 23561,
+ NPC_ABOMINATION1 = 16428, // Unstoppable Abominations
+ NPC_ABOMINATION2 = 23562,
+ NPC_BANSHEE1 = 16429, // Soul Weavers
+ NPC_BANSHEE2 = 23563,
+ NPC_GUARDIAN = 16441 // Guardians of Icecrown
+};
+
+static const uint8 nMinionSpawnPoints = 7;
+static const Position minionSpawnPoints[nMinionSpawnPoints] = {
+ { 3768.40f, -5072.00f, 143.65f }, // summon group 5
+ { 3729.30f, -5044.10f, 143.65f }, // summon group 6
+ { 3683.00f, -5054.05f, 143.65f }, // summon group 7
+ { 3654.15f, -5093.48f, 143.65f }, // summon group 8
+ { 3664.55f, -5140.50f, 143.65f }, // summon group 9
+ { 3704.00f, -5170.00f, 143.65f }, // summon group 10
+ { 3751.95f, -5158.90f, 143.65f } // summon group 11
};
+static inline Position const& GetRandomMinionSpawnPoint()
+{
+ return minionSpawnPoints[urand(0, nMinionSpawnPoints - 1)];
+}
+
+// uniformly distribute on the circle
+static Position GetRandomPositionOnCircle(Position const& center, float radius)
+{
+ double angle = rand_norm() * M_2_PI;
+ double relDistance = rand_norm() + rand_norm();
+ if (relDistance > 1)
+ relDistance = 1 - relDistance;
+ return Position(center.GetPositionX() + std::sin(angle)*relDistance*radius, center.GetPositionY() + std::cos(angle)*relDistance*radius, center.GetPositionZ());
+}
-// predicate function to select not charmed target
-struct NotCharmedTargetSelector : public std::unary_function<Unit*, bool>
+class KelThuzadCharmedPlayerAI : public SimpleCharmedPlayerAI
{
- NotCharmedTargetSelector() { }
+ public:
+ KelThuzadCharmedPlayerAI(Player* player) : SimpleCharmedPlayerAI(player) { }
+
+ struct CharmedPlayerTargetSelectPred : public std::unary_function<Unit*, bool>
+ {
+ bool operator()(Unit const* target) const
+ {
+ Player const* pTarget = target->ToPlayer();
+ if (!pTarget)
+ return false;
+ if (pTarget->HasAura(SPELL_CHAINS))
+ return false;
+ if (pTarget->HasBreakableByDamageCrowdControlAura())
+ return false;
+ // We _really_ dislike healers. So we hit them in the face. Repeatedly. Exclusively.
+ return PlayerAI::IsPlayerHealer(pTarget);
+ }
+ };
+
+ Unit* SelectAttackTarget() const override
+ {
+ if (Creature* charmer = GetCharmer())
+ {
+ if (Unit* target = charmer->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, CharmedPlayerTargetSelectPred()))
+ return target;
+ if (Unit* target = charmer->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_CHAINS))
+ return target;
+ }
+ return nullptr;
+ }
+};
+struct ManaUserTargetSelector : public std::unary_function<Unit*, bool>
+{
bool operator()(Unit const* target) const
{
- return !target->IsCharmed();
+ return target->GetTypeId() == TYPEID_PLAYER && target->getPowerType() == POWER_MANA;
}
};
@@ -268,355 +206,362 @@ public:
struct boss_kelthuzadAI : public BossAI
{
- boss_kelthuzadAI(Creature* creature) : BossAI(creature, BOSS_KELTHUZAD), spawns(creature)
- {
- Initialize();
- uiFaction = me->getFaction();
- }
-
- void Initialize()
- {
- nGuardiansOfIcecrownCount = 0;
-
- nAbomination = 0;
- nWeaver = 0;
- }
-
- uint32 uiFaction;
-
- uint8 nGuardiansOfIcecrownCount;
- uint8 nAbomination;
- uint8 nWeaver;
-
- std::map<ObjectGuid, float> chained;
-
- SummonList spawns; // adds spawn by the trigger. kept in separated list (i.e. not in summons)
-
- void ResetPlayerScale()
- {
- std::map<ObjectGuid, float>::const_iterator itr;
- for (itr = chained.begin(); itr != chained.end(); ++itr)
+ public:
+ boss_kelthuzadAI(Creature* creature) : BossAI(creature, BOSS_KELTHUZAD), _skeletonCount(0), _bansheeCount(0), _abominationCount(0), _abominationDeathCount(0), _frostboltCooldown(0), _phaseThree(false), _guardianCount(0)
{
- if (Player* charmed = ObjectAccessor::GetPlayer(*me, itr->first))
- charmed->SetObjectScale(itr->second);
+ for (uint8 i = 0; i < nGuardianSpawns; ++i)
+ _guardianGroups[i] = SUMMON_GROUP_GUARDIAN_FIRST + i;
}
- chained.clear();
- }
-
- void Reset() override
- {
- _Reset();
-
- me->setFaction(35);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_NOT_SELECTABLE);
-
- ResetPlayerScale();
- spawns.DespawnAll();
-
- instance->SetData(DATA_ABOMINATION_KILLED, 0);
-
- if (GameObject* trigger = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_KELTHUZAD_TRIGGER)))
+ void Reset() override
{
- trigger->ResetDoorOrButton();
- trigger->SetPhaseMask(1, true);
+ if (!me->IsAlive())
+ return;
+ _Reset();
+ me->SetReactState(REACT_PASSIVE);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE);
+ _skeletonCount = 0;
+ _bansheeCount = 0;
+ _abominationCount = 0;
+ _abominationDeathCount = 0;
+ _phaseThree = false;
}
-
- for (uint8 i = 0; i <= 3; ++i)
+ void EnterEvadeMode(EvadeReason /*why*/) override
{
- if (GameObject* portal = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_KELTHUZAD_PORTAL01 + i)))
- if (!((portal->getLootState() == GO_READY) || (portal->getLootState() == GO_NOT_READY)))
- portal->ResetDoorOrButton();
- }
+ for (Data64 portalData : portalList)
+ if (GameObject* portal = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(portalData)))
+ portal->SetGoState(GO_STATE_READY);
- Initialize();
- }
+ Reset();
+ _DespawnAtEvade();
+ }
- void KilledUnit(Unit* /*victim*/) override
- {
- Talk(SAY_SLAY);
- }
+ void JustSummoned (Creature* summon) override
+ { // prevent DoZoneInCombat
+ summons.Summon(summon);
+ }
- void JustDied(Unit* /*killer*/) override
- {
- _JustDied();
- Talk(SAY_DEATH);
+ void KilledUnit(Unit* victim) override
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_SLAY);
+ }
- ResetPlayerScale();
- }
+ void JustDied(Unit* /*killer*/) override
+ {
+ SummonList::iterator it = summons.begin();
+ while (it != summons.end())
+ if (Creature* cSummon = ObjectAccessor::GetCreature(*me, *it))
+ {
+ if (cSummon->IsAlive() && cSummon->GetEntry() == NPC_GUARDIAN)
+ {
+ cSummon->AI()->DoAction(ACTION_KELTHUZAD_DIED);
+ it = summons.erase(it); // prevent them from being despawned by _JustDied
+ }
+ else
+ ++it;
+ }
- void EnterCombat(Unit* /*who*/) override
- {
- me->setFaction(uiFaction);
- _EnterCombat();
- for (uint8 i = 0; i <= 3; ++i)
+ _JustDied();
+ Talk(SAY_DEATH);
+ }
+
+ void DamageTaken(Unit* /*attacker*/, uint32& damage) override
{
- if (GameObject* portal = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_KELTHUZAD_PORTAL01 + i)))
- portal->ResetDoorOrButton();
+ if (events.IsInPhase(PHASE_ONE))
+ damage = 0;
}
- DoCast(me, SPELL_KELTHUZAD_CHANNEL, false);
- Talk(SAY_SUMMON_MINIONS);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_NOT_SELECTABLE);
- me->SetFloatValue(UNIT_FIELD_COMBATREACH, 4);
- me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 4);
- events.SetPhase(PHASE_ONE);
- events.ScheduleEvent(EVENT_TRIGGER, 5000);
- events.ScheduleEvent(EVENT_WASTE, 15000);
- events.ScheduleEvent(EVENT_ABOMIN, 30000);
- events.ScheduleEvent(EVENT_WEAVER, 50000);
- events.ScheduleEvent(EVENT_PHASE, 228000);
- }
- void DamageTaken(Unit* /*attacker*/, uint32& damage) override
- {
- if (events.IsInPhase(PHASE_TWO) && me->HealthBelowPctDamaged(45, damage))
+ void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
{
- Talk(SAY_REQUEST_AID);
- events.SetPhase(PHASE_THREE);
- events.ScheduleEvent(EVENT_ANSWER_REQUEST, 4000);
-
- for (uint8 i = 0; i <= 3; ++i)
+ if (spell->Id == SPELL_CHAINS_DUMMY)
{
- if (GameObject* portal = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_KELTHUZAD_PORTAL01 + i)))
- if (portal->getLootState() == GO_READY)
- portal->UseDoorOrButton();
+ Talk(SAY_CHAINS);
+ std::list<Unit*> targets;
+ SelectTargetList(targets, 3, SELECT_TARGET_RANDOM, 0.0f, true);
+ for (Unit* target : targets)
+ if (me->GetVictim() != target) // skip MT
+ DoCast(target, SPELL_CHAINS);
}
}
- }
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- events.Update(diff);
+ events.Update(diff);
- if (events.IsInPhase(PHASE_ONE))
- {
- while (uint32 eventId = events.ExecuteEvent())
+ if (_frostboltCooldown < diff)
+ _frostboltCooldown = 0;
+ else
+ _frostboltCooldown -= diff;
+
+ if (!events.IsInPhase(PHASE_ONE) && me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ if (!_phaseThree && HealthBelowPct(45))
{
- switch (eventId)
+ _phaseThree = true;
+ _guardianCount = 0;
+ Talk(SAY_REQUEST_AID);
+ events.ScheduleEvent(EVENT_TRANSITION_REPLY, Seconds(4), 0, PHASE_TWO);
+ events.ScheduleEvent(EVENT_TRANSITION_SUMMON, randtime(Seconds(7), Seconds(9)), 0, PHASE_TWO);
+ events.ScheduleEvent(EVENT_TRANSITION_SUMMON, randtime(Seconds(13), Seconds(15)), 0, PHASE_TWO);
+ if (Is25ManRaid())
{
- case EVENT_WASTE:
- DoSummon(NPC_WASTE, Pos[RAND(0, 3, 6, 9)]);
- events.Repeat(2000, 5000);
- break;
- case EVENT_ABOMIN:
- if (nAbomination < 8)
- {
- DoSummon(NPC_ABOMINATION, Pos[RAND(1, 4, 7, 10)]);
- nAbomination++;
- events.Repeat(20000);
- }
- break;
- case EVENT_WEAVER:
- if (nWeaver < 8)
- {
- DoSummon(NPC_WEAVER, Pos[RAND(0, 3, 6, 9)]);
- nWeaver++;
- events.Repeat(25000);
- }
- break;
- case EVENT_TRIGGER:
- if (GameObject* trigger = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_KELTHUZAD_TRIGGER)))
- trigger->SetPhaseMask(2, true);
- break;
- case EVENT_PHASE:
- events.Reset();
- Talk(SAY_AGGRO);
- Talk(EMOTE_PHASE_TWO);
- spawns.DespawnAll();
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_NOT_SELECTABLE);
- me->CastStop();
-
- DoStartMovement(me->GetVictim());
- events.ScheduleEvent(EVENT_BOLT, urand(5000, 10000));
- events.ScheduleEvent(EVENT_NOVA, 15000);
- events.ScheduleEvent(EVENT_DETONATE, urand(30000, 40000));
- events.ScheduleEvent(EVENT_FISSURE, urand(10000, 30000));
- events.ScheduleEvent(EVENT_BLAST, urand(60000, 120000));
- if (GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL)
- events.ScheduleEvent(EVENT_CHAIN, urand(30000, 60000));
- events.SetPhase(PHASE_TWO);
- break;
- default:
- break;
+ events.ScheduleEvent(EVENT_TRANSITION_SUMMON, randtime(Seconds(19), Seconds(21)), 0, PHASE_TWO);
+ events.ScheduleEvent(EVENT_TRANSITION_SUMMON, randtime(Seconds(25), Seconds(27)), 0, PHASE_TWO);
}
}
- }
- else
- {
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
- if (uint32 eventId = events.ExecuteEvent())
+ while (uint32 eventId = events.ExecuteEvent())
{
+ if (_frostboltCooldown <= 4 * IN_MILLISECONDS) // stop casting bolts for 4 seconds after doing another action
+ _frostboltCooldown = 4 * IN_MILLISECONDS;
switch (eventId)
{
- case EVENT_BOLT:
- DoCastVictim(SPELL_FROST_BOLT);
- events.Repeat(5000, 10000);
- break;
- case EVENT_NOVA:
- DoCastAOE(SPELL_FROST_BOLT_AOE);
- events.Repeat(15000, 30000);
- break;
- case EVENT_CHAIN:
+ case EVENT_SKELETON:
{
- uint32 count = urand(1, 3);
- for (uint8 i = 1; i <= count; i++)
+ ++_skeletonCount;
+ if (_skeletonCount == 1) // the first skeleton is actually one of the pre-existing ones - I'm not sure why, but that's what the sniffs say
{
- Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 200, true);
- if (target && !target->IsCharmed() && (chained.find(target->GetGUID()) == chained.end()))
- {
- DoCast(target, SPELL_CHAINS_OF_KELTHUZAD);
- float scale = target->GetObjectScale();
- chained.insert(std::make_pair(target->GetGUID(), scale));
- target->SetObjectScale(scale * 2);
- events.ScheduleEvent(EVENT_CHAINED_SPELL, 2000); //core has 2000ms to set unit flag charm
+ std::list<Creature*> skeletons;
+ me->GetCreatureListWithEntryInGrid(skeletons, NPC_SKELETON2, 200.0f);
+ if (skeletons.empty())
+ { // prevent UB
+ EnterEvadeMode(EVADE_REASON_OTHER);
+ return;
}
+ std::list<Creature*>::iterator it = skeletons.begin();
+ std::advance(it, urand(0, skeletons.size() - 1));
+ (*it)->SetReactState(REACT_AGGRESSIVE);
+ (*it)->AI()->DoZoneInCombat(); // will select a player on our threat list as we are the summoner
}
- if (!chained.empty())
- Talk(SAY_CHAIN);
- events.Repeat(100000, 180000);
- break;
- }
- case EVENT_CHAINED_SPELL:
- {
- std::map<ObjectGuid, float>::iterator itr;
- for (itr = chained.begin(); itr != chained.end();)
+ else
{
- if (Unit* player = ObjectAccessor::GetPlayer(*me, itr->first))
- {
- if (!player->IsCharmed())
- {
- player->SetObjectScale(itr->second);
- std::map<ObjectGuid, float>::iterator next = itr;
- ++next;
- chained.erase(itr);
- itr = next;
- continue;
- }
-
- if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0, NotCharmedTargetSelector()))
- {
- switch (player->getClass())
- {
- case CLASS_DRUID:
- if (urand(0, 1))
- player->CastSpell(target, SPELL_MOONFIRE, false);
- else
- player->CastSpell(me, SPELL_LIFEBLOOM, false);
- break;
- case CLASS_HUNTER:
- player->CastSpell(target, RAND(SPELL_MULTI_SHOT, SPELL_VOLLEY), false);
- break;
- case CLASS_MAGE:
- player->CastSpell(target, RAND(SPELL_FROST_FIREBOLT, SPELL_ARCANE_MISSILES), false);
- break;
- case CLASS_WARLOCK:
- player->CastSpell(target, RAND(SPELL_CURSE_OF_AGONY, SPELL_SHADOW_BOLT), true);
- break;
- case CLASS_WARRIOR:
- player->CastSpell(target, RAND(SPELL_BLADESTORM, SPELL_CLEAVE), false);
- break;
- case CLASS_PALADIN:
- if (urand(0, 1))
- player->CastSpell(target, SPELL_HAMMER_OF_JUSTICE, false);
- else
- player->CastSpell(me, SPELL_HOLY_SHOCK, false);
- break;
- case CLASS_PRIEST:
- if (urand(0, 1))
- player->CastSpell(target, SPELL_VAMPIRIC_TOUCH, false);
- else
- player->CastSpell(me, SPELL_RENEW, false);
- break;
- case CLASS_SHAMAN:
- if (urand(0, 1))
- player->CastSpell(target, SPELL_EARTH_SHOCK, false);
- else
- player->CastSpell(me, SPELL_HEALING_WAVE, false);
- break;
- case CLASS_ROGUE:
- player->CastSpell(target, RAND(SPELL_HEMORRHAGE, SPELL_MUTILATE), false);
- break;
- case CLASS_DEATH_KNIGHT:
- if (urand(0, 1))
- player->CastSpell(target, SPELL_PLAGUE_STRIKE, true);
- else
- player->CastSpell(target, SPELL_HOWLING_BLAST, true);
- break;
- }
- }
- }
- ++itr;
+ // retail uses server-side spell 28421 for this
+ Creature* summon = me->SummonCreature(NPC_SKELETON1, GetRandomMinionSpawnPoint(), TEMPSUMMON_CORPSE_TIMED_DESPAWN, 2 * IN_MILLISECONDS);
+ summon->AI()->DoZoneInCombat();
}
- if (!chained.empty())
- events.Repeat(5000);
+ uint8 nextTime = 0;
+ if (_skeletonCount < 10)
+ nextTime = 5;
+ else if (_skeletonCount < 19)
+ nextTime = 4;
+ else if (_skeletonCount < 31)
+ nextTime = 3;
+ else if (_skeletonCount == 31)
+ nextTime = 4;
+ else if (_skeletonCount < 72)
+ nextTime = 2;
+
+ if (nextTime)
+ events.ScheduleEvent(EVENT_SKELETON, Seconds(nextTime), 0, PHASE_ONE);
+ break;
+ }
+
+ case EVENT_BANSHEE:
+ {
+ ++_bansheeCount;
+ // retail uses server-side spell 28423 for this
+ Creature* summon = me->SummonCreature(NPC_BANSHEE1, GetRandomMinionSpawnPoint(), TEMPSUMMON_CORPSE_TIMED_DESPAWN, 2 * IN_MILLISECONDS);
+ summon->AI()->DoZoneInCombat();
+
+ uint8 nextTime = 0;
+ if (_bansheeCount < 3)
+ nextTime = 30;
+ else if (_bansheeCount < 7)
+ nextTime = 20;
+ else if (_bansheeCount < 9)
+ nextTime = 15;
+
+ if (nextTime)
+ events.ScheduleEvent(EVENT_BANSHEE, Seconds(nextTime), 0, PHASE_ONE);
+ break;
+ }
+ case EVENT_ABOMINATION:
+ {
+ ++_abominationCount;
+ // retail uses server-side spell 28422 for this
+ Creature* summon = me->SummonCreature(NPC_ABOMINATION1, GetRandomMinionSpawnPoint(), TEMPSUMMON_CORPSE_TIMED_DESPAWN, 2 * IN_MILLISECONDS);
+ summon->AI()->DoZoneInCombat();
+
+ uint8 nextTime = 0;
+ if (_abominationCount < 3)
+ nextTime = 30;
+ else if (_abominationCount < 7)
+ nextTime = 20;
+ else if (_abominationCount < 9)
+ nextTime = 15;
+
+ if (nextTime)
+ events.ScheduleEvent(EVENT_ABOMINATION, Seconds(nextTime), 0, PHASE_ONE);
break;
}
- case EVENT_DETONATE:
+
+ case EVENT_DESPAWN_MINIONS:
{
- std::vector<Unit*> unitList;
- ThreatContainer::StorageType const &threatList = me->getThreatManager().getThreatList();
- for (ThreatContainer::StorageType::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr)
- {
- Unit* const target = (*itr)->getTarget();
+ // we need a temp vector, as we can't modify summons while iterating (this would cause UB)
+ std::vector<Creature*> toDespawn;
+ toDespawn.reserve(summons.size());
+ for (ObjectGuid sGuid : summons)
+ if (Creature* summon = ObjectAccessor::GetCreature(*me, sGuid))
+ if (!summon->IsInCombat())
+ toDespawn.push_back(summon);
+ for (Creature* summon : toDespawn)
+ summon->DespawnOrUnsummon();
+ Talk(SAY_AGGRO);
+ break;
+ }
- if (target->GetTypeId() == TYPEID_PLAYER
- && target->getPowerType() == POWER_MANA
- && target->GetPower(POWER_MANA))
- {
- unitList.push_back(target);
- }
- }
+ case EVENT_PHASE_TWO:
+ me->CastStop();
+ events.SetPhase(PHASE_TWO);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC);
+ me->getThreatManager().resetAllAggro();
+ me->SetReactState(REACT_AGGRESSIVE);
+ Talk(EMOTE_PHASE_TWO);
- if (!unitList.empty())
- {
- std::vector<Unit*>::const_iterator itr = unitList.begin();
- advance(itr, rand32() % unitList.size());
- DoCast(*itr, SPELL_MANA_DETONATION);
- Talk(SAY_SPECIAL);
- }
+ _frostboltCooldown = 2 * IN_MILLISECONDS;
+ events.ScheduleEvent(EVENT_FROSTBOLT_VOLLEY, randtime(Seconds(24), Seconds(28)), 0, PHASE_TWO);
+ events.ScheduleEvent(EVENT_SHADOW_FISSURE, randtime(Seconds(6), Seconds(10)), 0, PHASE_TWO);
+ events.ScheduleEvent(EVENT_DETONATE_MANA, randtime(Seconds(27), Seconds(33)), 0, PHASE_TWO);
+ events.ScheduleEvent(EVENT_FROST_BLAST, randtime(Seconds(25), Seconds(45)), 0, PHASE_TWO);
+ if (Is25ManRaid())
+ events.ScheduleEvent(EVENT_CHAINS, randtime(Seconds(60), Seconds(80)), 0, PHASE_TWO);
+ break;
+
+ case EVENT_FROSTBOLT_VOLLEY:
+ DoCastAOE(SPELL_FROSTBOLT_VOLLEY);
+ events.Repeat(randtime(Seconds(16), Seconds(18)));
+ break;
- events.Repeat(20000, 50000);
+ case EVENT_SHADOW_FISSURE:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
+ DoCast(target, SPELL_SHADOW_FISSURE);
+ events.Repeat(randtime(Seconds(14), Seconds(17)));
break;
- }
- case EVENT_FISSURE:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- DoCast(target, SPELL_SHADOW_FISURE);
- events.Repeat(10000, 45000);
+
+ case EVENT_DETONATE_MANA:
+ {
+ ManaUserTargetSelector pred;
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, pred))
+ DoCast(target, SPELL_DETONATE_MANA);
+ events.Repeat(randtime(Seconds(30), Seconds(40)));
break;
- case EVENT_BLAST:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, RAID_MODE(1, 0), 0, true))
+ }
+
+ case EVENT_FROST_BLAST:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true))
DoCast(target, SPELL_FROST_BLAST);
- if (rand32() % 2)
- Talk(SAY_FROST_BLAST);
- events.Repeat(30000, 90000);
+ events.Repeat(randtime(Seconds(25), Seconds(45)));
break;
- case EVENT_ANSWER_REQUEST:
+
+ case EVENT_CHAINS:
+ {
+ DoCastAOE(SPELL_CHAINS_DUMMY);
+ events.Repeat(Minutes(1) + randtime(Seconds(0), Seconds(20)));
+ break;
+ }
+
+ case EVENT_TRANSITION_REPLY:
if (Creature* lichKing = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_LICH_KING)))
lichKing->AI()->Talk(SAY_ANSWER_REQUEST);
- events.ScheduleEvent(EVENT_SUMMON_GUARDIANS, 5000);
+ for (Data64 portalData : portalList)
+ if (GameObject* portal = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(portalData)))
+ portal->SetGoState(GO_STATE_ACTIVE);
break;
- case EVENT_SUMMON_GUARDIANS:
- if (Creature* guardian = DoSummon(NPC_ICECROWN, Pos[RAND(2, 5, 8, 11)]))
- guardian->SetFloatValue(UNIT_FIELD_COMBATREACH, 2);
- ++nGuardiansOfIcecrownCount;
- if (nGuardiansOfIcecrownCount < RAID_MODE(2, 4))
- events.ScheduleEvent(EVENT_SUMMON_GUARDIANS, 5000);
- break;
- default:
+
+ case EVENT_TRANSITION_SUMMON:
+ {
+ uint8 selected = urand(_guardianCount, nGuardianSpawns - 1);
+ if (selected != _guardianCount)
+ std::swap(_guardianGroups[selected], _guardianGroups[_guardianCount]);
+
+ std::list<TempSummon*> summoned;
+ // server-side spell 28454 is used on retail - no point replicating this in spell_dbc
+ me->SummonCreatureGroup(_guardianGroups[_guardianCount++], &summoned);
+ for (TempSummon* guardian : summoned)
+ guardian->AI()->DoAction(ACTION_JUST_SUMMONED);
break;
+ }
}
}
- DoMeleeAttackIfReady();
+ if (!_frostboltCooldown)
+ {
+ DoCastVictim(SPELL_FROSTBOLT_SINGLE);
+ _frostboltCooldown = 3 * IN_MILLISECONDS;
+ }
+ else
+ DoMeleeAttackIfReady();
}
- }
+
+ uint32 GetData(uint32 data) const override
+ {
+ if (data == DATA_ABOMINATION_DEATH_COUNT)
+ return _abominationDeathCount;
+ return 0;
+ }
+
+ void DoAction(int32 action) override
+ {
+ switch (action)
+ {
+ case ACTION_BEGIN_ENCOUNTER:
+ if (instance->GetBossState(BOSS_KELTHUZAD) != NOT_STARTED)
+ return;
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
+ instance->SetBossState(BOSS_KELTHUZAD, IN_PROGRESS);
+ events.SetPhase(PHASE_ONE);
+ DoZoneInCombat();
+ DoCastAOE(SPELL_VISUAL_CHANNEL);
+ Talk(SAY_SUMMON_MINIONS);
+
+ for (uint8 group = SUMMON_GROUP_MINION_FIRST; group < SUMMON_GROUP_MINION_FIRST + nMinionGroups; ++group)
+ {
+ std::list<TempSummon*> summoned;
+ me->SummonCreatureGroup(group, &summoned);
+ for (TempSummon* summon : summoned)
+ {
+ summon->SetReactState(REACT_PASSIVE);
+ summon->AI()->SetData(DATA_MINION_POCKET_ID, group);
+ }
+ }
+
+ events.ScheduleEvent(EVENT_SKELETON, Seconds(5), 0, PHASE_ONE);
+ events.ScheduleEvent(EVENT_BANSHEE, Seconds(30), 0, PHASE_ONE);
+ events.ScheduleEvent(EVENT_ABOMINATION, Seconds(30), 0, PHASE_ONE);
+ events.ScheduleEvent(EVENT_DESPAWN_MINIONS, Minutes(3) + Seconds(33), 0, PHASE_ONE);
+ events.ScheduleEvent(EVENT_PHASE_TWO, Minutes(3) + Seconds(48), 0, PHASE_ONE);
+ break;
+
+ case ACTION_ABOMINATION_DIED:
+ ++_abominationDeathCount;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ PlayerAI* GetAIForCharmedPlayer(Player* player) override
+ {
+ return new KelThuzadCharmedPlayerAI(player);
+ }
+
+ private:
+ uint8 _skeletonCount;
+ uint8 _bansheeCount;
+ uint8 _abominationCount;
+ uint8 _abominationDeathCount;
+ uint32 _frostboltCooldown;
+ bool _phaseThree;
+ uint32 _guardianCount;
+ std::array<uint32, nGuardianSpawns> _guardianGroups;
};
CreatureAI* GetAI(Creature* creature) const override
@@ -625,188 +570,427 @@ public:
}
};
-class at_kelthuzad_center : public AreaTriggerScript
+static const float MINION_AGGRO_DISTANCE = 20.0f;
+// @hack the entire _movementTimer logic only exists because RandomMovementGenerator gets really confused due to the unique map geography of KT's room (it's placed on top of a copy of Winterspring).
+// As of the time of writing, RMG sometimes selects positions on the "floor" below the room, causing Abominations to path wildly through the room.
+// This custom movement code prevents this by simply ignoring z coord calculation (the floor of the minion coves is flat anyway).
+// Dev from the future that is reading this, if RMG has been fixed on the current core revision, please get rid of this hack. Thank you!
+struct npc_kelthuzad_minionAI : public ScriptedAI
{
-public:
- at_kelthuzad_center() : AreaTriggerScript("at_kelthuzad_center") { }
-
- bool OnTrigger(Player* player, const AreaTriggerEntry* /*at*/) override
- {
- if (player->IsGameMaster())
- return false;
-
- InstanceScript* instance = player->GetInstanceScript();
- if (!instance || instance->IsEncounterInProgress() || instance->GetBossState(BOSS_KELTHUZAD) == DONE)
- return false;
-
- Creature* pKelthuzad = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_KELTHUZAD));
- if (!pKelthuzad)
- return false;
+ public:
+ npc_kelthuzad_minionAI(Creature* creature) : ScriptedAI(creature), instance(creature->GetInstanceScript()), _movementTimer(urandms(4,12)), _home(me->GetPosition()) { }
- boss_kelthuzad::boss_kelthuzadAI* pKelthuzadAI = CAST_AI(boss_kelthuzad::boss_kelthuzadAI, pKelthuzad->AI());
- if (!pKelthuzadAI)
- return false;
+ void Reset() override
+ {
+ }
- pKelthuzadAI->AttackStart(player);
- if (GameObject* trigger = ObjectAccessor::GetGameObject(*player, instance->GetGuidData(DATA_KELTHUZAD_TRIGGER)))
+ void EnterEvadeMode(EvadeReason why) override
{
- if (trigger->getLootState() == GO_READY)
- trigger->UseDoorOrButton();
+ ScriptedAI::EnterEvadeMode(why);
+ if (Creature* kelThuzad = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_KELTHUZAD)))
+ kelThuzad->AI()->EnterEvadeMode(EVADE_REASON_OTHER);
+ }
- // Note: summon must be done by trigger and not by KT.
- // Otherwise, they attack immediately as KT is in combat.
- for (uint8 i = 0; i < MAX_ABOMINATIONS; ++i)
+ void EnterCombat(Unit* who) override
+ {
+ _movementTimer = 0; // once it's zero, it'll never get checked again
+ if (!me->HasReactState(REACT_PASSIVE))
{
- if (Creature* sum = trigger->SummonCreature(NPC_ABOMINATION, PosAbominations[i]))
- {
- pKelthuzadAI->spawns.Summon(sum);
- sum->GetMotionMaster()->MoveRandom(9.0f);
- sum->SetReactState(REACT_DEFENSIVE);
- }
+ DoZoneInCombat();
+ return;
}
- for (uint8 i = 0; i < MAX_WASTES; ++i)
- {
- if (Creature* sum = trigger->SummonCreature(NPC_WASTE, PosWastes[i]))
+
+ std::list<Creature*> others;
+ me->GetCreatureListWithEntryInGrid(others, me->GetEntry(), 80.0f);
+ for (Creature* other : others)
+ if (other->AI()->GetData(DATA_MINION_POCKET_ID) == pocketId)
{
- pKelthuzadAI->spawns.Summon(sum);
- sum->GetMotionMaster()->MoveRandom(5.0f);
- sum->SetReactState(REACT_DEFENSIVE);
+ other->SetReactState(REACT_AGGRESSIVE);
+ other->AI()->AttackStart(who);
}
+ me->SetReactState(REACT_AGGRESSIVE);
+ AttackStart(who);
+ ScriptedAI::EnterCombat(who);
+ }
+
+ void AttackStart(Unit* who) override
+ {
+ ScriptedAI::AttackStart(who);
+ }
+
+ void MoveInLineOfSight(Unit* who) override
+ {
+ if (!me->HasReactState(REACT_PASSIVE))
+ {
+ ScriptedAI::MoveInLineOfSight(who);
+ return;
}
- for (uint8 i = 0; i < MAX_WEAVERS; ++i)
+
+ if (me->CanStartAttack(who, false) && me->GetDistance2d(who) <= MINION_AGGRO_DISTANCE)
+ EnterCombat(who);
+ }
+
+ void SetData(uint32 data, uint32 value) override
+ {
+ if (data == DATA_MINION_POCKET_ID)
+ pocketId = value;
+ }
+
+ uint32 GetData(uint32 data) const override
+ {
+ if (data == DATA_MINION_POCKET_ID)
+ return pocketId;
+ return 0;
+ }
+
+ void MovementInform(uint32 /*type*/, uint32 id) override
+ {
+ if (id == MOVEMENT_MINION_RANDOM)
+ _movementTimer = urandms(2, 10) + urandms(2, 10);
+ }
+
+ void UpdateRandomMovement(uint32 diff)
+ {
+ if (!_movementTimer)
+ return;
+
+ if (_movementTimer <= diff)
{
- if (Creature* sum = trigger->SummonCreature(NPC_WEAVER, PosWeavers[i]))
- {
- pKelthuzadAI->spawns.Summon(sum);
- sum->GetMotionMaster()->MoveRandom(9.0f);
- sum->SetReactState(REACT_DEFENSIVE);
- }
+ _movementTimer = 0;
+ me->GetMotionMaster()->MovePoint(MOVEMENT_MINION_RANDOM, GetRandomPositionOnCircle(_home, 3.0f));
}
+ else
+ _movementTimer -= diff;
}
- return true;
+ protected:
+ InstanceScript* const instance;
+ uint32 pocketId;
+
+ private:
+ uint32 _movementTimer;
+ Position const _home;
+};
+
+class npc_kelthuzad_skeleton : public CreatureScript
+{
+public:
+ npc_kelthuzad_skeleton() : CreatureScript("npc_kelthuzad_skeleton") { }
+
+ struct npc_kelthuzad_skeletonAI : public npc_kelthuzad_minionAI
+ {
+ npc_kelthuzad_skeletonAI(Creature* creature) : npc_kelthuzad_minionAI(creature) { }
+
+ void UpdateAI(uint32 diff) override
+ {
+ UpdateRandomMovement(diff);
+
+ if (!UpdateVictim())
+ return;
+
+ DoMeleeAttackIfReady();
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<npc_kelthuzad_skeletonAI>(creature);
+ }
+};
+
+class npc_kelthuzad_banshee : public CreatureScript
+{
+public:
+ npc_kelthuzad_banshee() : CreatureScript("npc_kelthuzad_banshee") { }
+
+ struct npc_kelthuzad_bansheeAI : public npc_kelthuzad_minionAI
+ {
+ npc_kelthuzad_bansheeAI(Creature* creature) : npc_kelthuzad_minionAI(creature) { }
+
+ void UpdateAI(uint32 diff) override
+ {
+ UpdateRandomMovement(diff);
+
+ if (!UpdateVictim())
+ return;
+
+ DoMeleeAttackIfReady();
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<npc_kelthuzad_bansheeAI>(creature);
}
};
class npc_kelthuzad_abomination : public CreatureScript
{
- public:
- npc_kelthuzad_abomination() : CreatureScript("npc_kelthuzad_abomination") { }
+public:
+ npc_kelthuzad_abomination() : CreatureScript("npc_kelthuzad_abomination") { }
+
+ struct npc_kelthuzad_abominationAI : public npc_kelthuzad_minionAI
+ {
+ npc_kelthuzad_abominationAI(Creature* creature) : npc_kelthuzad_minionAI(creature), _woundTimer(urandms(10, 20)) { }
- struct npc_kelthuzad_abominationAI : public ScriptedAI
+ void UpdateAI(uint32 diff) override
{
- npc_kelthuzad_abominationAI(Creature* creature) : ScriptedAI(creature)
+ UpdateRandomMovement(diff);
+
+ if (!UpdateVictim())
+ return;
+
+ if (_woundTimer <= diff)
{
- _instance = creature->GetInstanceScript();
+ _woundTimer = urandms(14, 18);
+ DoCastVictim(SPELL_MORTAL_WOUND);
+ }
+ else
+ _woundTimer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+
+ void JustDied(Unit* killer) override
+ {
+ if (Creature* kelThuzad = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_KELTHUZAD)))
+ kelThuzad->AI()->DoAction(ACTION_ABOMINATION_DIED);
+ npc_kelthuzad_minionAI::JustDied(killer);
+ }
+
+ uint32 _woundTimer;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<npc_kelthuzad_abominationAI>(creature);
+ }
+};
+
+class npc_kelthuzad_guardian : public CreatureScript
+{
+public:
+ npc_kelthuzad_guardian() : CreatureScript("npc_kelthuzad_guardian") { }
+
+ struct npc_kelthuzad_guardianAI : public ScriptedAI
+ {
+ public:
+ npc_kelthuzad_guardianAI(Creature* creature) : ScriptedAI(creature), instance(creature->GetInstanceScript()), _visibilityTimer(0), _bloodTapTimer(0) { }
+
+ void DoAction(int32 action) override
+ {
+ switch (action)
+ {
+ case ACTION_JUST_SUMMONED:
+ me->SetVisible(false);
+ me->SetHomePosition(me->GetPosition());
+ DoZoneInCombat();
+ me->SetCombatPulseDelay(5);
+ _visibilityTimer = 2 * IN_MILLISECONDS;
+ _bloodTapTimer = 25 * IN_MILLISECONDS;
+ break;
+ case ACTION_KELTHUZAD_DIED:
+ Talk(EMOTE_GUARDIAN_FLEE);
+ me->SetReactState(REACT_PASSIVE);
+ me->RemoveAllAuras();
+ me->CombatStop();
+ me->StopMoving();
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
+ me->DespawnOrUnsummon(30 * IN_MILLISECONDS); // just in case anything interrupts the movement
+ me->GetMotionMaster()->MoveTargetedHome();
+ default:
+ break;
+ }
+ }
+
+ void EnterEvadeMode(EvadeReason why) override
+ {
+ if (Creature* kelthuzad = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_KELTHUZAD)))
+ kelthuzad->AI()->EnterEvadeMode();
+ ScriptedAI::EnterEvadeMode(why);
+ }
+
+ void JustReachedHome() override
+ {
+ me->DespawnOrUnsummon();
}
void Reset() override
{
- _events.Reset();
- _events.ScheduleEvent(EVENT_MORTAL_WOUND, urand(2000, 5000));
- DoCast(me, SPELL_FRENZY, true);
+ me->SetCombatPulseDelay(0);
+ ScriptedAI::Reset();
}
void UpdateAI(uint32 diff) override
{
+ if (_visibilityTimer)
+ {
+ if (diff > _visibilityTimer)
+ _visibilityTimer -= diff;
+ else
+ {
+ me->SetVisible(true);
+ Talk(EMOTE_GUARDIAN_APPEAR);
+ _visibilityTimer = 0;
+ }
+ }
+
if (!UpdateVictim())
return;
- _events.Update(diff);
-
- while (uint32 eventId = _events.ExecuteEvent())
+ if (_bloodTapTimer <= diff)
{
- switch (eventId)
- {
- case EVENT_MORTAL_WOUND:
- DoCastVictim(SPELL_MORTAL_WOUND, true);
- _events.ScheduleEvent(EVENT_MORTAL_WOUND, urand(10000, 15000));
- break;
- default:
- break;
- }
+ DoCastVictim(SPELL_BLOOD_TAP);
+ _bloodTapTimer = urandms(18, 26);
}
- }
+ else
+ _bloodTapTimer -= diff;
- void JustDied(Unit* /*killer*/) override
- {
- _instance->SetData(DATA_ABOMINATION_KILLED, _instance->GetData(DATA_ABOMINATION_KILLED) + 1);
+ DoMeleeAttackIfReady();
}
private:
- InstanceScript* _instance;
- EventMap _events;
- };
+ InstanceScript* const instance;
+ uint32 _visibilityTimer;
+ uint32 _bloodTapTimer;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<npc_kelthuzad_guardianAI>(creature);
+ }
+};
+
+class spell_kelthuzad_chains : public SpellScriptLoader
+{
+public:
+ spell_kelthuzad_chains() : SpellScriptLoader("spell_kelthuzad_chains") { }
+
+ class spell_kelthuzad_chains_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_kelthuzad_chains_AuraScript);
+
+ void HandleApply(AuraEffect const* /*eff*/, AuraEffectHandleModes /*mode*/)
+ {
+ Unit* target = GetTarget();
+ float scale = target->GetObjectScale();
+ ApplyPercentModFloatVar(scale, 200.0f, true);
+ target->SetObjectScale(scale);
+ }
+
+ void HandleRemove(AuraEffect const* /*eff*/, AuraEffectHandleModes /*mode*/)
+ {
+ Unit* target = GetTarget();
+ float scale = target->GetObjectScale();
+ ApplyPercentModFloatVar(scale, 200.0f, false);
+ target->SetObjectScale(scale);
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ void Register() override
{
- return GetInstanceAI<npc_kelthuzad_abominationAI>(creature);
+ AfterEffectApply += AuraEffectApplyFn(spell_kelthuzad_chains_AuraScript::HandleApply, EFFECT_0, SPELL_AURA_AOE_CHARM, AURA_EFFECT_HANDLE_REAL);
+ AfterEffectRemove += AuraEffectApplyFn(spell_kelthuzad_chains_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_AOE_CHARM, AURA_EFFECT_HANDLE_REAL);
}
+ };
+
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_kelthuzad_chains_AuraScript();
+ }
};
class spell_kelthuzad_detonate_mana : public SpellScriptLoader
{
- public:
- spell_kelthuzad_detonate_mana() : SpellScriptLoader("spell_kelthuzad_detonate_mana") { }
-
- class spell_kelthuzad_detonate_mana_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_kelthuzad_detonate_mana_AuraScript);
+public:
+ spell_kelthuzad_detonate_mana() : SpellScriptLoader("spell_kelthuzad_detonate_mana") { }
- bool Validate(SpellInfo const* /*spell*/) override
- {
- if (!sSpellMgr->GetSpellInfo(SPELL_MANA_DETONATION_DAMAGE))
- return false;
- return true;
- }
+ class spell_kelthuzad_detonate_mana_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_kelthuzad_detonate_mana_AuraScript);
- void HandleScript(AuraEffect const* aurEff)
- {
- PreventDefaultAction();
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_MANA_DETONATION_DAMAGE))
+ return false;
+ return true;
+ }
- Unit* target = GetTarget();
- if (int32 mana = int32(target->GetMaxPower(POWER_MANA) / 10))
- {
- mana = target->ModifyPower(POWER_MANA, -mana);
- target->CastCustomSpell(SPELL_MANA_DETONATION_DAMAGE, SPELLVALUE_BASE_POINT0, -mana * 10, target, true, NULL, aurEff);
- }
- }
+ void HandleScript(AuraEffect const* aurEff)
+ {
+ PreventDefaultAction();
- void Register() override
+ Unit* target = GetTarget();
+ if (int32 mana = int32(target->GetMaxPower(POWER_MANA) / 10))
{
- OnEffectPeriodic += AuraEffectPeriodicFn(spell_kelthuzad_detonate_mana_AuraScript::HandleScript, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ mana = target->ModifyPower(POWER_MANA, -mana);
+ target->CastCustomSpell(SPELL_MANA_DETONATION_DAMAGE, SPELLVALUE_BASE_POINT0, -mana * 10, target, true, NULL, aurEff);
}
- };
+ }
- AuraScript* GetAuraScript() const override
+ void Register() override
{
- return new spell_kelthuzad_detonate_mana_AuraScript();
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_kelthuzad_detonate_mana_AuraScript::HandleScript, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
}
+ };
+
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_kelthuzad_detonate_mana_AuraScript();
+ }
+};
+
+class at_kelthuzad_center : public AreaTriggerScript
+{
+public:
+ at_kelthuzad_center() : AreaTriggerScript("at_kelthuzad_center") { }
+
+ bool OnTrigger(Player* player, const AreaTriggerEntry* /*at*/) override
+ {
+ InstanceScript* instance = player->GetInstanceScript();
+ if (!instance || instance->GetBossState(BOSS_KELTHUZAD) != NOT_STARTED)
+ return true;
+
+ if (player->IsGameMaster())
+ return true;
+
+ Creature* kelThuzad = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_KELTHUZAD));
+ if (!kelThuzad)
+ return true;
+
+ kelThuzad->AI()->DoAction(ACTION_BEGIN_ENCOUNTER);
+
+ return true;
+ }
};
class achievement_just_cant_get_enough : public AchievementCriteriaScript
{
public:
- achievement_just_cant_get_enough() : AchievementCriteriaScript("achievement_just_cant_get_enough") { }
+ achievement_just_cant_get_enough() : AchievementCriteriaScript("achievement_just_cant_get_enough") { }
- bool OnCheck(Player* /*player*/, Unit* target) override
- {
- if (!target)
- return false;
+ bool OnCheck(Player* /*player*/, Unit* target) override
+ {
+ if (!target)
+ return false;
- if (InstanceScript* instance = target->GetInstanceScript())
- if (instance->GetData(DATA_ABOMINATION_KILLED) >= 18)
- return true;
+ if (InstanceScript* instance = target->GetInstanceScript())
+ if (Creature* kelThuzad = ObjectAccessor::GetCreature(*target, instance->GetGuidData(DATA_KELTHUZAD)))
+ if (kelThuzad->AI()->GetData(DATA_ABOMINATION_DEATH_COUNT) >= 18)
+ return true;
- return false;
- }
+ return false;
+ }
};
void AddSC_boss_kelthuzad()
{
new boss_kelthuzad();
- new at_kelthuzad_center();
+ new npc_kelthuzad_skeleton();
+ new npc_kelthuzad_banshee();
new npc_kelthuzad_abomination();
+ new npc_kelthuzad_guardian();
+ new spell_kelthuzad_chains();
new spell_kelthuzad_detonate_mana();
+ new at_kelthuzad_center();
new achievement_just_cant_get_enough();
}
diff --git a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp
index 720549de0b2..aa043316088 100644
--- a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp
@@ -97,6 +97,7 @@ ObjectData const objectData[] =
{ GO_NAXX_PORTAL_CONSTRUCT, DATA_NAXX_PORTAL_CONSTRUCT },
{ GO_NAXX_PORTAL_PLAGUE, DATA_NAXX_PORTAL_PLAGUE },
{ GO_NAXX_PORTAL_MILITARY, DATA_NAXX_PORTAL_MILITARY },
+ { GO_KELTHUZAD_THRONE, DATA_KELTHUZAD_THRONE },
{ 0, 0, }
};
@@ -115,7 +116,6 @@ class instance_naxxramas : public InstanceMapScript
LoadDoorData(doorData);
LoadObjectData(nullptr, objectData);
- AbominationCount = 0;
hadAnubRekhanGreet = false;
hadFaerlinaGreet = false;
hadThaddiusGreet = false;
@@ -230,6 +230,10 @@ class instance_naxxramas : public InstanceMapScript
if (GetBossState(BOSS_HORSEMEN) == DONE)
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
break;
+ case GO_KELTHUZAD_THRONE:
+ if (GetBossState(BOSS_KELTHUZAD) == DONE)
+ go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
+ break;
case GO_BIRTH:
if (hadSapphironBirth || GetBossState(BOSS_SAPPHIRON) == DONE)
{
@@ -270,9 +274,6 @@ class instance_naxxramas : public InstanceMapScript
if (GameObject* gate = instance->GetGameObject(GothikGateGUID))
gate->SetGoState(GOState(value));
break;
- case DATA_ABOMINATION_KILLED:
- AbominationCount = value;
- break;
case DATA_HAD_ANUBREKHAN_GREET:
hadAnubRekhanGreet = (value == 1u);
break;
@@ -294,8 +295,6 @@ class instance_naxxramas : public InstanceMapScript
{
switch (id)
{
- case DATA_ABOMINATION_KILLED:
- return AbominationCount;
case DATA_HAD_ANUBREKHAN_GREET:
return hadAnubRekhanGreet ? 1u : 0u;
case DATA_HAD_FAERLINA_GREET:
@@ -418,6 +417,12 @@ class instance_naxxramas : public InstanceMapScript
case BOSS_SAPPHIRON:
if (state == DONE)
events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD, Seconds(6));
+ HandleGameObject(KelthuzadDoorGUID, false);
+ break;
+ case BOSS_KELTHUZAD:
+ if (state == DONE)
+ if (GameObject* throne = GetGameObject(DATA_KELTHUZAD_THRONE))
+ throne->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
break;
default:
break;
@@ -493,7 +498,6 @@ class instance_naxxramas : public InstanceMapScript
case EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD:
if (Creature* kelthuzad = instance->GetCreature(KelthuzadGUID))
kelthuzad->AI()->Talk(SAY_DIALOGUE_SAPPHIRON_KELTHUZAD);
- HandleGameObject(KelthuzadDoorGUID, false);
events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_LICHKING, Seconds(6));
break;
case EVENT_DIALOGUE_SAPPHIRON_LICHKING:
@@ -616,7 +620,6 @@ class instance_naxxramas : public InstanceMapScript
ObjectGuid PortalsGUID[4];
ObjectGuid KelthuzadDoorGUID;
ObjectGuid LichKingGUID;
- uint8 AbominationCount;
bool hadAnubRekhanGreet;
bool hadFaerlinaGreet;
bool hadThaddiusGreet;
diff --git a/src/server/scripts/Northrend/Naxxramas/naxxramas.h b/src/server/scripts/Northrend/Naxxramas/naxxramas.h
index 75e7314c5d0..b1f51172280 100644
--- a/src/server/scripts/Northrend/Naxxramas/naxxramas.h
+++ b/src/server/scripts/Northrend/Naxxramas/naxxramas.h
@@ -50,12 +50,12 @@ enum Data
DATA_HAD_SAPPHIRON_BIRTH,
DATA_HORSEMEN_CHECK_ACHIEVEMENT_CREDIT,
- DATA_ABOMINATION_KILLED,
DATA_NAXX_PORTAL_ARACHNID,
DATA_NAXX_PORTAL_CONSTRUCT,
DATA_NAXX_PORTAL_PLAGUE,
- DATA_NAXX_PORTAL_MILITARY
+ DATA_NAXX_PORTAL_MILITARY,
+ DATA_KELTHUZAD_THRONE
};
enum Data64
@@ -121,6 +121,7 @@ enum GameObjectsIds
GO_KELTHUZAD_PORTAL03 = 181404,
GO_KELTHUZAD_PORTAL04 = 181405,
GO_KELTHUZAD_TRIGGER = 181444,
+ GO_KELTHUZAD_THRONE = 181640,
GO_ROOM_ANUBREKHAN = 181126,
GO_PASSAGE_ANUBREKHAN = 181195,
GO_PASSAGE_FAERLINA = 194022,
@@ -138,14 +139,20 @@ enum GameObjectsIds
GO_ROOM_HORSEMEN = 181119,
GO_PASSAGE_SAPPHIRON = 181225,
GO_ROOM_KELTHUZAD = 181228,
+
+ // End of wing portals
GO_ARAC_PORTAL = 181575,
GO_PLAG_PORTAL = 181577,
GO_MILI_PORTAL = 181578,
GO_CONS_PORTAL = 181576,
+
+ // "Glow" effect on center-side portal
GO_ARAC_EYE_RAMP = 181212,
GO_PLAG_EYE_RAMP = 181211,
GO_MILI_EYE_RAMP = 181210,
GO_CONS_EYE_RAMP = 181213,
+
+ // "Glow" effect on boss-side portal
GO_ARAC_EYE_RAMP_BOSS = 181233,
GO_PLAG_EYE_RAMP_BOSS = 181231,
GO_MILI_EYE_RAMP_BOSS = 181230,
diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp
index 55295a534e1..5cfabb42797 100644
--- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp
+++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp
@@ -113,7 +113,8 @@ public:
Initialize();
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_REMOVE_CLIENT_CONTROL);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
+ me->SetControlled(false, UNIT_STATE_ROOT);
if (!me->IsVisible())
me->SetVisible(true);
@@ -152,7 +153,8 @@ public:
me->AttackStop();
me->SetVisible(false);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_REMOVE_CLIENT_CONTROL);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
+ me->SetControlled(true, UNIT_STATE_ROOT);
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveIdle();
@@ -236,7 +238,8 @@ public:
else if (lSparkList.empty())
{
me->SetVisible(true);
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_REMOVE_CLIENT_CONTROL);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
+ me->SetControlled(false, UNIT_STATE_ROOT);
DoCast(me, SPELL_SPARK_DESPAWN, false);
diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp
index f20de459b12..70c1c0221c4 100644
--- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp
+++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp
@@ -204,12 +204,15 @@ public:
}
}
- void JustReachedHome() override
+ void MovementInform(uint32 type, uint32 data) override
{
- if (m_uiSummonPhase == 2)
+ if (type == POINT_MOTION_TYPE && data == EVENT_FORGE_CAST)
{
- me->SetOrientation(2.29f);
- m_uiSummonPhase = 3;
+ if (m_uiSummonPhase == 2)
+ {
+ me->SetOrientation(2.29f);
+ m_uiSummonPhase = 3;
+ }
}
}
@@ -298,12 +301,12 @@ public:
case 1:
// 1 - Start run to Anvil
Talk(EMOTE_TO_ANVIL);
- me->GetMotionMaster()->MoveTargetedHome();
+ me->GetMotionMaster()->MovePoint(EVENT_FORGE_CAST, me->GetHomePosition());
m_uiSummonPhase = 2; // Set Next Phase
break;
case 2:
// 2 - Check if reached Anvil
- // This is handled in: void JustReachedHome() override
+ // This is handled in: void MovementInform(uint32, uint32) override
break;
case 3:
// 3 - Cast Temper on the Anvil
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp
index cbd24141bdf..21d42d57a5e 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp
@@ -415,7 +415,8 @@ class npc_saronite_vapors : public CreatureScript
if (damage >= me->GetHealth())
{
damage = 0;
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_REMOVE_CLIENT_CONTROL);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
+ me->SetControlled(true, UNIT_STATE_ROOT);
me->SetStandState(UNIT_STAND_STATE_DEAD);
me->SetHealth(me->GetMaxHealth());
me->RemoveAllAuras();
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp
index c03a1c6fbc1..d600eabd462 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp
@@ -186,7 +186,8 @@ class npc_flash_freeze : public CreatureScript
Initialize();
instance = me->GetInstanceScript();
me->SetDisplayId(me->GetCreatureTemplate()->Modelid2);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED);
+ me->SetControlled(true, UNIT_STATE_ROOT);
}
void Initialize()
@@ -261,7 +262,8 @@ class npc_ice_block : public CreatureScript
{
instance = me->GetInstanceScript();
me->SetDisplayId(me->GetCreatureTemplate()->Modelid2);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED);
+ me->SetControlled(true, UNIT_STATE_ROOT);
}
InstanceScript* instance;
@@ -271,7 +273,8 @@ class npc_ice_block : public CreatureScript
void IsSummonedBy(Unit* summoner) override
{
targetGUID = summoner->GetGUID();
- summoner->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED);
+ summoner->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED);
+ summoner->SetControlled(true, UNIT_STATE_ROOT);
me->SetInCombatWith(summoner);
me->AddThreat(summoner, 250.0f);
summoner->AddThreat(me, 250.0f);
@@ -287,7 +290,8 @@ class npc_ice_block : public CreatureScript
{
if (Creature* Helper = ObjectAccessor::GetCreature(*me, targetGUID))
{
- Helper->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED);
+ Helper->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED);
+ Helper->SetControlled(false, UNIT_STATE_ROOT);
if (Creature* Hodir = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_HODIR)))
{
@@ -390,7 +394,8 @@ class boss_hodir : public CreatureScript
me->RemoveAllAttackers();
me->AttackStop();
me->SetReactState(REACT_PASSIVE);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_REMOVE_CLIENT_CONTROL);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ me->SetControlled(true, UNIT_STATE_ROOT);
me->InterruptNonMeleeSpells(true);
me->StopMoving();
me->GetMotionMaster()->Clear();
@@ -547,7 +552,8 @@ class npc_icicle : public CreatureScript
{
Initialize();
me->SetDisplayId(me->GetCreatureTemplate()->Modelid1);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_PACIFIED | UNIT_FLAG_NOT_SELECTABLE);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_PACIFIED | UNIT_FLAG_NOT_SELECTABLE);
+ me->SetControlled(true, UNIT_STATE_ROOT);
me->SetReactState(REACT_PASSIVE);
}
@@ -601,7 +607,8 @@ class npc_snowpacked_icicle : public CreatureScript
{
Initialize();
me->SetDisplayId(me->GetCreatureTemplate()->Modelid2);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED);
+ me->SetControlled(true, UNIT_STATE_ROOT);
me->SetReactState(REACT_PASSIVE);
}
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp
index a50643c5deb..1a515e5d4a5 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp
@@ -178,7 +178,8 @@ class boss_ignis : public CreatureScript
{
summon->setFaction(16);
summon->SetReactState(REACT_AGGRESSIVE);
- summon->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED | UNIT_FLAG_STUNNED | UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_IMMUNE_TO_PC);
+ summon->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED | UNIT_FLAG_STUNNED | UNIT_FLAG_IMMUNE_TO_PC);
+ summon->SetControlled(false, UNIT_STATE_ROOT);
}
summon->AI()->AttackStart(me->GetVictim());
@@ -375,7 +376,8 @@ class npc_scorch_ground : public CreatureScript
npc_scorch_groundAI(Creature* creature) : ScriptedAI(creature)
{
Initialize();
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL |UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED);
+ me->SetControlled(true, UNIT_STATE_ROOT);
creature->SetDisplayId(16925); //model 2 in db cannot overwrite wdb fields
}
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp
index 45d4fa58a03..f4ea5a826c2 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp
@@ -104,7 +104,7 @@ class boss_kologarn : public CreatureScript
left(false), right(false)
{
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL);
+ me->SetControlled(true, UNIT_STATE_ROOT);
DoCast(SPELL_KOLOGARN_REDUCE_PARRY);
SetCombatMovement(false);
diff --git a/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp b/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp
index e7305e53808..c9d78441e5b 100644
--- a/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp
+++ b/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp
@@ -247,7 +247,8 @@ class npc_frozen_orb_stalker : public CreatureScript
npc_frozen_orb_stalkerAI(Creature* creature) : ScriptedAI(creature)
{
creature->SetVisible(false);
- creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_REMOVE_CLIENT_CONTROL);
+ creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
+ me->SetControlled(true, UNIT_STATE_ROOT);
creature->SetReactState(REACT_PASSIVE);
instance = creature->GetInstanceScript();
diff --git a/src/server/scripts/Northrend/zone_dalaran.cpp b/src/server/scripts/Northrend/zone_dalaran.cpp
index 03af1a6417f..ac05c421efb 100644
--- a/src/server/scripts/Northrend/zone_dalaran.cpp
+++ b/src/server/scripts/Northrend/zone_dalaran.cpp
@@ -115,7 +115,6 @@ public:
}
break;
}
- me->SetOrientation(me->GetHomePosition().GetOrientation());
return;
}
diff --git a/src/server/scripts/Northrend/zone_icecrown.cpp b/src/server/scripts/Northrend/zone_icecrown.cpp
index 3d801cc2fbb..a99803ee99a 100644
--- a/src/server/scripts/Northrend/zone_icecrown.cpp
+++ b/src/server/scripts/Northrend/zone_icecrown.cpp
@@ -215,17 +215,6 @@ class npc_tournament_training_dummy : public CreatureScript
me->SetControlled(true, UNIT_STATE_STUNNED);
Initialize();
- // Cast Defend spells to max stack size
- switch (me->GetEntry())
- {
- case NPC_CHARGE_TARGET:
- DoCast(SPELL_CHARGE_DEFEND);
- break;
- case NPC_RANGED_TARGET:
- me->CastCustomSpell(SPELL_RANGED_DEFEND, SPELLVALUE_AURA_STACK, 3, me);
- break;
- }
-
events.Reset();
events.ScheduleEvent(EVENT_DUMMY_RECAST_DEFEND, 5000);
}
@@ -286,14 +275,14 @@ class npc_tournament_training_dummy : public CreatureScript
case NPC_CHARGE_TARGET:
{
if (!me->HasAura(SPELL_CHARGE_DEFEND))
- DoCast(SPELL_CHARGE_DEFEND);
+ DoCast(me, SPELL_CHARGE_DEFEND, true);
break;
}
case NPC_RANGED_TARGET:
{
Aura* defend = me->GetAura(SPELL_RANGED_DEFEND);
if (!defend || defend->GetStackAmount() < 3 || defend->GetDuration() <= 8000)
- DoCast(SPELL_RANGED_DEFEND);
+ DoCast(me, SPELL_RANGED_DEFEND, true);
break;
}
}
diff --git a/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp b/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp
index 56d333b2dda..699dd578b8d 100644
--- a/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp
+++ b/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp
@@ -241,7 +241,6 @@ public:
boss_teron_gorefiendAI(Creature* creature) : BossAI(creature, DATA_TERON_GOREFIEND)
{
Initialize();
- instance = creature->GetInstanceScript();
}
void Initialize()
@@ -259,8 +258,6 @@ public:
Done = false;
}
- InstanceScript* instance;
-
uint32 IncinerateTimer;
uint32 SummonDoomBlossomTimer;
uint32 EnrageTimer;
diff --git a/src/server/scripts/Spells/spell_holiday.cpp b/src/server/scripts/Spells/spell_holiday.cpp
index bd36e3cb765..a7b58737374 100644
--- a/src/server/scripts/Spells/spell_holiday.cpp
+++ b/src/server/scripts/Spells/spell_holiday.cpp
@@ -846,6 +846,7 @@ enum RamBlaBla
{
SPELL_GIDDYUP = 42924,
SPELL_RENTAL_RACING_RAM = 43883,
+ SPELL_SWIFT_WORK_RAM = 43880,
SPELL_RENTAL_RACING_RAM_AURA = 42146,
SPELL_RAM_LEVEL_NEUTRAL = 43310,
SPELL_RAM_TROT = 42992,
@@ -853,6 +854,7 @@ enum RamBlaBla
SPELL_RAM_GALLOP = 42994,
SPELL_RAM_FATIGUE = 43052,
SPELL_EXHAUSTED_RAM = 43332,
+ SPELL_RELAY_RACE_TURN_IN = 44501,
// Quest
SPELL_BREWFEST_QUEST_SPEED_BUNNY_GREEN = 43345,
@@ -873,7 +875,7 @@ class spell_brewfest_giddyup : public SpellScriptLoader
void OnChange(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
Unit* target = GetTarget();
- if (!target->HasAura(SPELL_RENTAL_RACING_RAM))
+ if (!target->HasAura(SPELL_RENTAL_RACING_RAM) && !target->HasAura(SPELL_SWIFT_WORK_RAM))
{
target->RemoveAura(GetId());
return;
@@ -1110,6 +1112,38 @@ class spell_brewfest_relay_race_intro_force_player_to_throw : public SpellScript
}
};
+class spell_brewfest_relay_race_turn_in : public SpellScriptLoader
+{
+public:
+ spell_brewfest_relay_race_turn_in() : SpellScriptLoader("spell_brewfest_relay_race_turn_in") { }
+
+ class spell_brewfest_relay_race_turn_in_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_brewfest_relay_race_turn_in_SpellScript);
+
+ void HandleDummy(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+
+ if (Aura* aura = GetHitUnit()->GetAura(SPELL_SWIFT_WORK_RAM))
+ {
+ aura->SetDuration(aura->GetDuration() + 30 * IN_MILLISECONDS);
+ GetCaster()->CastSpell(GetHitUnit(), SPELL_RELAY_RACE_TURN_IN, TRIGGERED_FULL_MASK);
+ }
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_brewfest_relay_race_turn_in_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_brewfest_relay_race_turn_in_SpellScript();
+ }
+};
+
// 43876 - Dismount Ram
class spell_brewfest_dismount_ram : public SpellScriptLoader
{
@@ -1382,6 +1416,7 @@ void AddSC_holiday_spell_scripts()
new spell_brewfest_apple_trap();
new spell_brewfest_exhausted_ram();
new spell_brewfest_relay_race_intro_force_player_to_throw();
+ new spell_brewfest_relay_race_turn_in();
new spell_brewfest_dismount_ram();
new spell_brewfest_barker_bunny();
// Midsummer Fire Festival
diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp
index 715e4d4ed2d..bf0fc3d0565 100644
--- a/src/server/scripts/Spells/spell_quest.cpp
+++ b/src/server/scripts/Spells/spell_quest.cpp
@@ -1127,6 +1127,75 @@ class spell_q9452_cast_net: public SpellScriptLoader
}
};
+enum PoundDrumSpells
+{
+ SPELL_SUMMON_DEEP_JORMUNGAR = 66510,
+ SPELL_STORMFORGED_MOLE_MACHINE = 66492
+};
+
+class spell_q14076_14092_pound_drum : public SpellScriptLoader
+{
+ public:
+ spell_q14076_14092_pound_drum() : SpellScriptLoader("spell_q14076_14092_pound_drum") { }
+
+ class spell_q14076_14092_pound_drum_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_q14076_14092_pound_drum_SpellScript);
+
+ void HandleSummon()
+ {
+ Unit* caster = GetCaster();
+
+ if (roll_chance_i(80))
+ caster->CastSpell(caster, SPELL_SUMMON_DEEP_JORMUNGAR, true);
+ else
+ caster->CastSpell(caster, SPELL_STORMFORGED_MOLE_MACHINE, true);
+ }
+
+ void HandleActiveObject(SpellEffIndex /*effIndex*/)
+ {
+ GetHitGObj()->SetLootState(GO_JUST_DEACTIVATED);
+ }
+
+ void Register() override
+ {
+ OnCast += SpellCastFn(spell_q14076_14092_pound_drum_SpellScript::HandleSummon);
+ OnEffectHitTarget += SpellEffectFn(spell_q14076_14092_pound_drum_SpellScript::HandleActiveObject, EFFECT_0, SPELL_EFFECT_ACTIVATE_OBJECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_q14076_14092_pound_drum_SpellScript();
+ }
+};
+
+class spell_q12279_cast_net : public SpellScriptLoader
+{
+ public:
+ spell_q12279_cast_net() : SpellScriptLoader("spell_q12279_cast_net") { }
+
+ class spell_q12279_cast_net_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_q12279_cast_net_SpellScript);
+
+ void HandleActiveObject(SpellEffIndex /*effIndex*/)
+ {
+ GetHitGObj()->SetLootState(GO_JUST_DEACTIVATED);
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_q12279_cast_net_SpellScript::HandleActiveObject, EFFECT_1, SPELL_EFFECT_ACTIVATE_OBJECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_q12279_cast_net_SpellScript();
+ }
+};
+
enum HodirsHelm
{
SAY_1 = 1,
@@ -2523,6 +2592,8 @@ void AddSC_quest_spell_scripts()
new spell_q13280_13283_plant_battle_standard();
new spell_q14112_14145_chum_the_water();
new spell_q9452_cast_net();
+ new spell_q12279_cast_net();
+ new spell_q14076_14092_pound_drum();
new spell_q12987_read_pronouncement();
new spell_q12277_wintergarde_mine_explosion();
new spell_q12066_bunny_kill_credit();
diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp
index 5e6407e361e..c33d74d0faa 100644
--- a/src/server/scripts/World/npcs_special.cpp
+++ b/src/server/scripts/World/npcs_special.cpp
@@ -586,7 +586,7 @@ public:
events.Reset();
running = false;
}
-
+
void Reset() override
{
Initialize();
@@ -1660,25 +1660,25 @@ public:
# npc_wormhole
######*/
-#define GOSSIP_ENGINEERING1 "Borean Tundra"
-#define GOSSIP_ENGINEERING2 "Howling Fjord"
-#define GOSSIP_ENGINEERING3 "Sholazar Basin"
-#define GOSSIP_ENGINEERING4 "Icecrown"
-#define GOSSIP_ENGINEERING5 "Storm Peaks"
-#define GOSSIP_ENGINEERING6 "Underground..."
-
-enum WormholeSpells
+enum NPC_Wormhole
{
- SPELL_BOREAN_TUNDRA = 67834,
- SPELL_SHOLAZAR_BASIN = 67835,
- SPELL_ICECROWN = 67836,
- SPELL_STORM_PEAKS = 67837,
- SPELL_HOWLING_FJORD = 67838,
- SPELL_UNDERGROUND = 68081,
-
- TEXT_WORMHOLE = 907,
-
- DATA_SHOW_UNDERGROUND = 1,
+ DATA_SHOW_UNDERGROUND = 1, // -> Random 0 or 1
+
+ MENU_ID_WORMHOLE = 10668, // "This tear in the fabric of time and space looks ominous."
+ NPC_TEXT_WORMHOLE = 14785, // (not 907 "What brings you to this part of the world, $n?")
+ GOSSIP_OPTION_1 = 0, // "Borean Tundra"
+ GOSSIP_OPTION_2 = 1, // "Howling Fjord"
+ GOSSIP_OPTION_3 = 2, // "Sholazar Basin"
+ GOSSIP_OPTION_4 = 3, // "Icecrown"
+ GOSSIP_OPTION_5 = 4, // "Storm Peaks"
+ GOSSIP_OPTION_6 = 5, // "Underground..."
+
+ SPELL_BOREAN_TUNDRA = 67834, // 0
+ SPELL_HOWLING_FJORD = 67838, // 1
+ SPELL_SHOLAZAR_BASIN = 67835, // 2
+ SPELL_ICECROWN = 67836, // 3
+ SPELL_STORM_PEAKS = 67837, // 4
+ SPELL_UNDERGROUND = 68081 // 5
};
class npc_wormhole : public CreatureScript
@@ -1718,16 +1718,16 @@ class npc_wormhole : public CreatureScript
{
if (player == creature->ToTempSummon()->GetSummoner())
{
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ENGINEERING1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ENGINEERING2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ENGINEERING3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ENGINEERING4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ENGINEERING5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
+ player->ADD_GOSSIP_ITEM_DB(MENU_ID_WORMHOLE, GOSSIP_OPTION_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
+ player->ADD_GOSSIP_ITEM_DB(MENU_ID_WORMHOLE, GOSSIP_OPTION_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
+ player->ADD_GOSSIP_ITEM_DB(MENU_ID_WORMHOLE, GOSSIP_OPTION_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
+ player->ADD_GOSSIP_ITEM_DB(MENU_ID_WORMHOLE, GOSSIP_OPTION_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
+ player->ADD_GOSSIP_ITEM_DB(MENU_ID_WORMHOLE, GOSSIP_OPTION_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
if (creature->AI()->GetData(DATA_SHOW_UNDERGROUND))
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ENGINEERING6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6);
+ player->ADD_GOSSIP_ITEM_DB(MENU_ID_WORMHOLE, GOSSIP_OPTION_6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6);
- player->PlayerTalkClass->SendGossipMenu(TEXT_WORMHOLE, creature->GetGUID());
+ player->SEND_GOSSIP_MENU(NPC_TEXT_WORMHOLE, creature->GetGUID());
}
}
diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp
index fe0e3ffd13d..bf157a228dd 100644
--- a/src/tools/mmaps_generator/MapBuilder.cpp
+++ b/src/tools/mmaps_generator/MapBuilder.cpp
@@ -70,6 +70,10 @@ namespace MMAP
m_rcContext = new rcContext(false);
+ // percentageDone - Initializing
+ m_totalTiles = 0;
+ m_totalTilesBuilt = 0;
+
discoverTiles();
}
@@ -152,6 +156,9 @@ namespace MMAP
}
}
printf("found %u.\n\n", count);
+
+ // percentageDone - total tiles to process
+ m_totalTiles = count;
}
/**************************************************************************/
@@ -424,7 +431,8 @@ namespace MMAP
/**************************************************************************/
void MapBuilder::buildTile(uint32 mapID, uint32 tileX, uint32 tileY, dtNavMesh* navMesh)
{
- printf("[Map %03i] Building tile [%02u,%02u]\n", mapID, tileX, tileY);
+ // percentageDone - added, now it will show addional reference percentage done of the overall process
+ printf("%u%% [Map %03i] Building tile [%02u,%02u]\n", percentageDone(m_totalTiles, m_totalTilesBuilt), mapID, tileX, tileY);
MeshData meshData;
@@ -458,6 +466,9 @@ namespace MMAP
// build navmesh tile
buildMoveMapTile(mapID, tileX, tileY, meshData, bmin, bmax, navMesh);
+
+ // percentageDone - increment tiles built
+ m_totalTilesBuilt++;
}
/**************************************************************************/
@@ -1015,4 +1026,13 @@ namespace MMAP
return true;
}
+ /**************************************************************************/
+ uint32 MapBuilder::percentageDone(uint32 totalTiles, uint32 totalTilesBuilt)
+ {
+ if (totalTiles)
+ return totalTilesBuilt * 100 / totalTiles;
+
+ return 0;
+ }
+
}
diff --git a/src/tools/mmaps_generator/MapBuilder.h b/src/tools/mmaps_generator/MapBuilder.h
index d4b1bdf00fc..9c22a66ea87 100644
--- a/src/tools/mmaps_generator/MapBuilder.h
+++ b/src/tools/mmaps_generator/MapBuilder.h
@@ -123,6 +123,8 @@ namespace MMAP
bool shouldSkipMap(uint32 mapID);
bool isTransportMap(uint32 mapID);
bool shouldSkipTile(uint32 mapID, uint32 tileX, uint32 tileY);
+ // percentageDone - method to calculate percentage
+ uint32 percentageDone(uint32 totalTiles, uint32 totalTilesDone);
TerrainBuilder* m_terrainBuilder;
TileList m_tiles;
@@ -136,6 +138,9 @@ namespace MMAP
float m_maxWalkableAngle;
bool m_bigBaseUnit;
+ // percentageDone - variables to calculate percentage
+ uint32 m_totalTiles;
+ std::atomic<uint32> m_totalTilesBuilt;
// build performance - not really used for now
rcContext* m_rcContext;