aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2020-04-24 18:45:56 +0200
committerGitHub <noreply@github.com>2020-04-24 18:45:56 +0200
commit1a415147b9acc945163f6c8044e886983cbe8900 (patch)
treeae2d3709f586815853ef7519619e6f3c24dc8489
parentbbfbb7d4bfa869755e702b40b53dbd295f8c964d (diff)
parent72ffe65dacf9a6eb62f337c2a49d8fff2716febd (diff)
Merge pull request #24433 from funjoker/cherry-picks
-rw-r--r--sql/updates/world/master/2020_04_06_00_world_2017_01_15_02_world.sql48
-rw-r--r--sql/updates/world/master/2020_04_06_01_world_2017_01_15_03_world.sql72
-rw-r--r--sql/updates/world/master/2020_04_06_01_world_2017_01_15_04_world.sql75
-rw-r--r--sql/updates/world/master/2020_04_10_00_world_2017_01_15_05_world.sql32
-rw-r--r--sql/updates/world/master/2020_04_10_01_world_2017_01_15_06_world.sql37
-rw-r--r--sql/updates/world/master/2020_04_10_02_world_2017_01_15_07_world.sql34
-rw-r--r--sql/updates/world/master/2020_04_10_03_world_2017_01_15_08_world.sql28
-rw-r--r--sql/updates/world/master/2020_04_10_04_world_2017_01_15_09_world.sql36
-rw-r--r--sql/updates/world/master/2020_04_10_05_world_2017_01_15_10_world.sql125
-rw-r--r--sql/updates/world/master/2020_04_10_06_world_2017_01_16_00_world.sql143
-rw-r--r--sql/updates/world/master/2020_04_10_07_world_2017_01_16_01_world.sql41
-rw-r--r--sql/updates/world/master/2020_04_10_08_world_2017_01_16_02_world.sql42
-rw-r--r--sql/updates/world/master/2020_04_10_09_world_2017_01_16_03_world.sql28
-rw-r--r--sql/updates/world/master/2020_04_10_10_world_2017_01_16_04_world.sql98
-rw-r--r--sql/updates/world/master/2020_04_10_11_world_2017_01_16_05_world.sql35
-rw-r--r--sql/updates/world/master/2020_04_10_12_world_2017_01_16_06_world.sql60
-rw-r--r--sql/updates/world/master/2020_04_10_13_world_2017_01_17_00_world.sql279
-rw-r--r--sql/updates/world/master/2020_04_10_14_world_2017_01_20_02_world.sql91
-rw-r--r--sql/updates/world/master/2020_04_10_15_world_2017_01_20_03_world.sql168
-rw-r--r--sql/updates/world/master/2020_04_10_16_world_2017_01_20_04_world.sql224
-rw-r--r--sql/updates/world/master/2020_04_10_17_world_2017_01_20_05_world.sql142
-rw-r--r--sql/updates/world/master/2020_04_10_18_world_2017_01_22_07_world.sql6
-rw-r--r--sql/updates/world/master/2020_04_10_19_world_2017_01_22_08_world.sql40
-rw-r--r--sql/updates/world/master/2020_04_10_20_world_2017_01_22_09_world.sql131
-rw-r--r--sql/updates/world/master/2020_04_10_21_world_2017_01_22_12_world.sql148
-rw-r--r--sql/updates/world/master/2020_04_10_22_world_2017_01_23_03_world.sql7
-rw-r--r--sql/updates/world/master/2020_04_10_22_world_2017_01_24_01_world.sql77
-rw-r--r--sql/updates/world/master/2020_04_10_23_world_2017_01_25_01_world.sql4
-rw-r--r--sql/updates/world/master/2020_04_14_00_world_2017_03_03_00_world.sql2
-rw-r--r--sql/updates/world/master/2020_04_14_01_world_2017_03_16_02_world.sql5
-rw-r--r--sql/updates/world/master/2020_04_14_02_world_2017_03_17_02_world.sql12
-rw-r--r--sql/updates/world/master/2020_04_14_03_world_2017_03_17_03_world.sql23
-rw-r--r--sql/updates/world/master/2020_04_16_00_world_2017_03_24_00_world.sql14
-rw-r--r--sql/updates/world/master/2020_04_16_01_world_2017_03_25_01_world.sql1
-rw-r--r--sql/updates/world/master/2020_04_16_02_world_2017_03_26_00_world.sql2
-rw-r--r--sql/updates/world/master/2020_04_16_03_world_2017_03_26_01_world_335.sql6
-rw-r--r--sql/updates/world/master/2020_04_16_04_world_2017_03_26_02_world.sql11
-rw-r--r--sql/updates/world/master/2020_04_16_05_world_2017_03_26_03_world.sql43
-rw-r--r--sql/updates/world/master/2020_04_16_06_world_2017_03_27_00_world_335.sql11
-rw-r--r--sql/updates/world/master/2020_04_17_00_world_2017_03_27_01_world.sql23
-rw-r--r--sql/updates/world/master/2020_04_17_01_world_2017_03_30_01_world.sql19
-rw-r--r--sql/updates/world/master/2020_04_17_02_world_2017_03_31_00_world.sql23
-rw-r--r--src/common/Debugging/WheatyExceptionReport.cpp194
-rw-r--r--src/common/Debugging/WheatyExceptionReport.h19
-rw-r--r--src/common/Utilities/Util.h7
-rw-r--r--src/server/game/AI/CreatureAI.cpp16
-rw-r--r--src/server/game/AI/CreatureAI.h5
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp4
-rw-r--r--src/server/game/Achievements/AchievementMgr.cpp3
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp34
-rw-r--r--src/server/game/Entities/Creature/Creature.h2
-rw-r--r--src/server/game/Entities/Creature/CreatureData.h31
-rw-r--r--src/server/game/Entities/Creature/GossipDef.cpp8
-rw-r--r--src/server/game/Entities/Creature/TemporarySummon.h1
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp3
-rw-r--r--src/server/game/Entities/GameObject/GameObject.h4
-rw-r--r--src/server/game/Entities/Item/Item.cpp4
-rw-r--r--src/server/game/Entities/Item/Item.h1
-rw-r--r--src/server/game/Entities/Object/Object.cpp84
-rw-r--r--src/server/game/Entities/Object/Object.h6
-rw-r--r--src/server/game/Entities/Object/ObjectDefines.h10
-rw-r--r--src/server/game/Entities/Object/Position.cpp6
-rw-r--r--src/server/game/Entities/Object/Position.h5
-rw-r--r--src/server/game/Entities/Pet/Pet.cpp18
-rw-r--r--src/server/game/Entities/Player/Player.cpp471
-rw-r--r--src/server/game/Entities/Player/Player.h37
-rw-r--r--src/server/game/Entities/Player/SocialMgr.cpp5
-rw-r--r--src/server/game/Entities/Unit/StatSystem.cpp124
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp304
-rw-r--r--src/server/game/Entities/Unit/Unit.h142
-rw-r--r--src/server/game/Entities/Unit/UnitDefines.h1
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp411
-rw-r--r--src/server/game/Globals/ObjectMgr.h15
-rw-r--r--src/server/game/Grids/Cells/CellImpl.h2
-rw-r--r--src/server/game/Grids/Notifiers/GridNotifiers.h59
-rw-r--r--src/server/game/Handlers/SpellHandler.cpp1
-rw-r--r--src/server/game/Instances/InstanceScript.cpp2
-rw-r--r--src/server/game/Instances/InstanceScript.h2
-rw-r--r--src/server/game/Maps/AreaBoundary.cpp24
-rw-r--r--src/server/game/Maps/AreaBoundary.h83
-rw-r--r--src/server/game/Miscellaneous/Language.h2
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h8
-rw-r--r--src/server/game/Movement/MotionMaster.cpp45
-rw-r--r--src/server/game/Movement/MotionMaster.h23
-rw-r--r--src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp2
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp2
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp6
-rw-r--r--src/server/game/Quests/QuestDef.cpp219
-rw-r--r--src/server/game/Quests/QuestDef.h413
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp338
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.h1
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.cpp10
-rw-r--r--src/server/game/Spells/Spell.cpp37
-rw-r--r--src/server/game/Spells/SpellEffects.cpp24
-rw-r--r--src/server/game/Spells/SpellInfo.cpp29
-rw-r--r--src/server/game/Spells/SpellInfo.h1
-rw-r--r--src/server/game/Spells/SpellMgr.cpp22
-rw-r--r--src/server/scripts/Commands/cs_debug.cpp2
-rw-r--r--src/server/scripts/Commands/cs_group.cpp2
-rw-r--r--src/server/scripts/Commands/cs_misc.cpp5
-rw-r--r--src/server/scripts/Commands/cs_npc.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletEnclave/zone_the_scarlet_enclave.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/SunkenTemple/sunken_temple.h16
-rw-r--r--src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp2
-rw-r--r--src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp11
-rw-r--r--src/server/scripts/Northrend/DraktharonKeep/boss_king_dred.cpp2
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp6
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp316
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h4
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp18
-rw-r--r--src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp6
-rw-r--r--src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h12
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp2
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp8
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp11
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp30
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp8
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp38
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp2
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp40
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp77
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp58
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp44
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp323
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h2
-rw-r--r--src/server/scripts/Northrend/zone_zuldrak.cpp4
-rw-r--r--src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp8
-rw-r--r--src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/instance_magtheridons_lair.cpp4
-rw-r--r--src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/magtheridons_lair.h8
-rw-r--r--src/server/scripts/Outland/zone_shadowmoon_valley.cpp2
-rw-r--r--src/server/scripts/Spells/spell_generic.cpp37
-rw-r--r--src/server/scripts/Spells/spell_item.cpp41
-rw-r--r--src/server/scripts/Spells/spell_pet.cpp2
-rw-r--r--src/server/scripts/World/go_scripts.cpp2
-rw-r--r--src/server/scripts/World/item_scripts.cpp2
138 files changed, 4862 insertions, 2079 deletions
diff --git a/sql/updates/world/master/2020_04_06_00_world_2017_01_15_02_world.sql b/sql/updates/world/master/2020_04_06_00_world_2017_01_15_02_world.sql
new file mode 100644
index 00000000000..0a2e3a24e9b
--- /dev/null
+++ b/sql/updates/world/master/2020_04_06_00_world_2017_01_15_02_world.sql
@@ -0,0 +1,48 @@
+-- Nurse Judith -- http://wotlk.openwow.com/npc=19455
+UPDATE `creature_template_addon` SET `bytes1`=0 WHERE `entry`=19455;
+
+-- Nurse Judith SAI
+SET @ENTRY := 19455;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,25,0,100,0,0,0,0,0,53,0,19455,1,0,0,1,0,0,0,0,0,0,0,0,"Nurse Judith - On Reset - Start Waypoint"),
+(@ENTRY,0,1,0,64,0,100,0,0,0,0,0,54,180000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Nurse Judith - On Gossip Hello - Pause Waypoint"),
+(@ENTRY,0,2,3,40,0,100,0,2,19455,0,0,80,@ENTRY*100+00,2,0,0,0,0,1,0,0,0,0,0,0,0,"Nurse Judith - On Waypoint 2 Reached - Run Script"),
+(@ENTRY,0,3,0,61,0,100,0,2,19455,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,2.76273,"Nurse Judith - On Waypoint 2 Reached - Set Orientation 2,76273"),
+(@ENTRY,0,4,5,40,0,100,0,5,19455,0,0,80,@ENTRY*100+00,2,0,0,0,0,1,0,0,0,0,0,0,0,"Nurse Judith - On Waypoint 5 Reached - Run Script"),
+(@ENTRY,0,5,0,61,0,100,0,5,19455,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,4.1529,"Nurse Judith - On Waypoint 5 Reached - Set Orientation 4,1529"),
+(@ENTRY,0,5,6,40,0,100,0,7,19455,0,0,80,@ENTRY*100+00,2,0,0,0,0,1,0,0,0,0,0,0,0,"Nurse Judith - On Waypoint 7 Reached - Run Script"),
+(@ENTRY,0,6,0,61,0,100,0,7,19455,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,4.25502,"Nurse Judith - On Waypoint 7 Reached - Set Orientation 4.25502"),
+(@ENTRY,0,7,8,40,0,100,0,9,19455,0,0,80,@ENTRY*100+00,2,0,0,0,0,1,0,0,0,0,0,0,0,"Nurse Judith - On Waypoint 9 Reached - Run Script"),
+(@ENTRY,0,8,0,61,0,100,0,9,19455,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,2.969,"Nurse Judith - On Waypoint 9 Reached - Set Orientation 2.969"),
+(@ENTRY,0,9,10,40,0,100,0,12,19455,0,0,80,@ENTRY*100+00,2,0,0,0,0,1,0,0,0,0,0,0,0,"Nurse Judith - On Waypoint 12 Reached - Run Script"),
+(@ENTRY,0,10,0,61,0,100,0,12,19455,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,4.17224,"Nurse Judith - On Waypoint 12 Reached - Set Orientation 4.17224"),
+(@ENTRY,0,11,12,40,0,100,0,15,19455,0,0,80,@ENTRY*100+00,2,0,0,0,0,1,0,0,0,0,0,0,0,"Nurse Judith - On Waypoint 15 Reached - Run Script"),
+(@ENTRY,0,12,0,61,0,100,0,15,19455,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,4.1529,"Nurse Judith - On Waypoint 15 Reached - Set Orientation 2.41624");
+
+-- Actionlist SAI
+SET @ENTRY := 1945500;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,0,0,0,0,54,12000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Nurse Judith - On Script - Pause Waypoint"),
+(@ENTRY,9,1,0,0,0,100,0,4000,4000,0,0,90,8,0,0,0,0,0,1,0,0,0,0,0,0,0,"Nurse Judith - On Script - Set Flag Standstate Kneel"),
+(@ENTRY,9,2,0,0,0,100,0,6000,6000,0,0,91,8,0,0,0,0,0,1,0,0,0,0,0,0,0,"Nurse Judith - On Script - Remove Flag Standstate Kneel");
+
+DELETE FROM `waypoints` WHERE `entry`=19455;
+INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `point_comment`) VALUES
+(19455, 1, -365.789, 981.419, 54.195, 'Nurse Judith'),
+(19455, 2, -368.858, 982.56, 54.1727, 'Nurse Judith'),
+(19455, 3, -363.252, 980.47, 54.2127, 'Nurse Judith'),
+(19455, 4, -357.494, 978.322, 54.2425, 'Nurse Judith'),
+(19455, 5, -358.948, 975.922, 54.243, 'Nurse Judith'),
+(19455, 6, -357.512, 973.939, 54.2493, 'Nurse Judith'),
+(19455, 7, -360.045, 968.102, 54.2344, 'Nurse Judith'),
+(19455, 8, -358.571, 965.26, 54.2447, 'Nurse Judith'),
+(19455, 9, -362.99, 962.005, 54.2135, 'Nurse Judith'),
+(19455, 10, -352.415, 973.809, 54.2617, 'Nurse Judith'),
+(19455, 11, -349.296, 971.591, 54.2724, 'Nurse Judith'),
+(19455, 12, -349.964, 970.224, 54.2733, 'Nurse Judith'),
+(19455, 13, -350.597, 974.797, 54.2635, 'Nurse Judith'),
+(19455, 14, -362.665, 981.665, 54.2171, 'Nurse Judith'),
+(19455, 15, -364.29, 984.89, 54.2066, 'Nurse Judith');
diff --git a/sql/updates/world/master/2020_04_06_01_world_2017_01_15_03_world.sql b/sql/updates/world/master/2020_04_06_01_world_2017_01_15_03_world.sql
new file mode 100644
index 00000000000..fbb73cd39e8
--- /dev/null
+++ b/sql/updates/world/master/2020_04_06_01_world_2017_01_15_03_world.sql
@@ -0,0 +1,72 @@
+-- Consortium Nether Runner -- http://wotlk.openwow.com/npc=19667
+UPDATE `creature` SET `position_x`=-2057.45, `position_y`=8528.71, `position_z`=24.6556, `orientation`=2.05449, `spawntimesecs`=120 WHERE `guid`=70166;
+
+-- Consortium Nether Runner SAI
+SET @ENTRY := 19667;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,25,0,100,0,0,0,0,0,53,0,19667,0,0,0,1,1,0,0,0,0,0,0,0,"Consortium Nether Runner - On Reset - Start Waypoint"),
+(@ENTRY,0,1,0,64,0,100,0,0,0,0,0,54,180000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Consortium Nether Runner - On Gossip Hello - Pause Waypoint"),
+(@ENTRY,0,2,0,40,0,100,0,1,19667,0,0,80,@ENTRY*100+00,2,0,0,0,0,1,0,0,0,0,0,0,0,"Consortium Nether Runner - On Waypoint 1 Reached - Run Script"),
+(@ENTRY,0,3,0,40,0,100,0,5,19667,0,0,80,@ENTRY*100+01,2,0,0,0,0,1,0,0,0,0,0,0,0,"Consortium Nether Runner - On Waypoint 5 Reached - Run Script"),
+(@ENTRY,0,4,0,40,0,100,0,8,19667,0,0,80,@ENTRY*100+02,2,0,0,0,0,1,0,0,0,0,0,0,0,"Consortium Nether Runner - On Waypoint 8 Reached - Run Script");
+
+-- Actionlist SAI
+SET @ENTRY := 1966700;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,0,0,0,0,54,3000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Consortium Nether Runner - On Script - Pause Waypoint"),
+(@ENTRY,9,1,0,0,0,100,0,0,0,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,2.05449,"Consortium Nether Runner - On Script - Set Orientation 2.05449"),
+(@ENTRY,9,2,0,0,0,100,0,0,0,0,0,11,34427,0,0,0,0,0,1,0,0,0,0,0,0,0,"Consortium Nether Runner - On Script - Cast 'Ethereal Teleport'");
+
+-- Actionlist SAI
+SET @ENTRY := 1966701;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,0,0,0,0,54,11000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Consortium Nether Runner - On Script - Pause Waypoint"),
+(@ENTRY,9,1,0,0,0,100,0,0,0,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,3.57111,"Consortium Nether Runner - On Script - Set Orientation 3.57111"),
+(@ENTRY,9,2,0,0,0,100,0,1000,1000,0,0,1,0,6000,0,0,0,0,1,0,0,0,0,0,0,0,"Consortium Nether Runner - On Script - Say Line 0"),
+(@ENTRY,9,3,0,0,0,100,0,3000,3000,0,0,45,1,1,0,0,0,0,10,65554,18265,0,0,0,0,0,"Consortium Nether Runner - On Script - Set Data 1 1"),
+(@ENTRY,9,4,0,0,0,100,0,3000,3000,0,0,1,0,5000,0,0,0,0,10,65554,18265,0,0,0,0,0,"Consortium Nether Runner - On Script - Say Line 0"),
+(@ENTRY,9,5,0,0,0,100,0,5000,5000,0,0,1,1,6000,0,0,0,0,1,0,0,0,0,0,0,0,"Consortium Nether Runner - On Script - Say Line 1"),
+(@ENTRY,9,6,0,0,0,100,0,0,0,0,0,45,2,2,0,0,0,0,10,65554,18265,0,0,0,0,0,"Consortium Nether Runner - On Script - Set Data 1 1");
+
+-- Actionlist SAI
+SET @ENTRY := 1966702;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,0,0,0,0,54,3000,0,0,0,0,0,1,0,0,0,0,0,0,0,"On Script - Pause Waypoint"),
+(@ENTRY,9,1,0,0,0,100,0,0,0,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,0.573574,"On Script - Set Orientation 0,573574"),
+(@ENTRY,9,2,0,0,0,100,0,1000,1000,0,0,11,34427,0,0,0,0,0,1,0,0,0,0,0,0,0,"On Script - Cast 'Ethereal Teleport'"),
+(@ENTRY,9,3,0,0,0,100,0,2000,2000,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"On Script - Despawn Instant");
+
+-- Buddy AI
+-- Gezhe SAI
+SET @ENTRY := 18265;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,38,0,100,0,1,1,0,0,66,0,0,0,0,0,0,10,70166,19667,0,0,0,0,0,"Gezhe - On Data Set 1 1 - Set Orientation Closest Creature 'Consortium Nether Runner'"),
+(@ENTRY,0,1,0,38,0,100,0,2,2,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,2.513270,"Gezhe - On Data Set 2 2 - Set Orientation 2,513270");
+
+DELETE FROM `creature_text` WHERE `CreatureID` IN (19667, 18265);
+INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `comment`) VALUES
+-- Consortium Nether Runner
+(19667, 0, 0, 'Hail, Gezhe! Seventeen more orders have been placed in the Hara''samid Sector. The markets of heavy veldarite have all but collapsed, as you predicted.', 12, 0, 100, 0, 0, 0, 17184, 'Consortium Nether Runner'),
+(19667, 0, 1, 'Heraazi exports are on the rise, sir. We''ve already bribed the appropriate taxation officers and contraband will begin to arrive within days.', 12, 0, 100, 0, 0, 0, 17186, 'Consortium Nether Runner'),
+(19667, 1, 0, 'By your leave, sir.', 12, 0, 100, 0, 0, 0, 17185, 'Consortium Nether Runner'),
+-- Gezhe
+(18265, 0, 0, 'Nothing surprising there. Come back with some real news, will you?', 12, 0, 100, 0, 0, 0, 17191, 'Gezhe'),
+(18265, 0, 1, 'As expected. Very well, dismissed.', 12, 0, 100, 0, 0, 0, 17190, 'Gezhe');
+
+DELETE FROM `waypoints` WHERE `entry`=19667;
+INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `point_comment`) VALUES
+(19667, 1, -2057.45, 8528.71, 24.6556, 'Consortium Nether Runner'),
+(19667, 2, -2058.23, 8547.79, 24.0203, 'Consortium Nether Runner'),
+(19667, 3, -2064.09, 8554.57, 23.9054, 'Consortium Nether Runner'),
+(19667, 4, -2075.08, 8562.74, 22.9801, 'Consortium Nether Runner'),
+(19667, 5, -2083.14, 8565.28, 22.0791, 'Consortium Nether Runner'),
+(19667, 6, -2062.94, 8574.57, 23.1942, 'Consortium Nether Runner'),
+(19667, 7, -2056.25, 8597.59, 21.3663, 'Consortium Nether Runner'),
+(19667, 8, -2049.12, 8603.37, 22.7377, 'Consortium Nether Runner');
diff --git a/sql/updates/world/master/2020_04_06_01_world_2017_01_15_04_world.sql b/sql/updates/world/master/2020_04_06_01_world_2017_01_15_04_world.sql
new file mode 100644
index 00000000000..df5d193be2d
--- /dev/null
+++ b/sql/updates/world/master/2020_04_06_01_world_2017_01_15_04_world.sql
@@ -0,0 +1,75 @@
+-- Experimental Pilot -- http://wotlk.openwow.com/npc=19776
+
+-- Experimental Pilot SAI
+SET @ENTRY := 19776;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,25,0,100,0,0,0,0,0,53,0,19776,1,0,0,0,1,0,0,0,0,0,0,0,"Experimental Pilot - On Reset - Start Waypoint"),
+(@ENTRY,0,1,0,64,0,100,0,0,0,0,0,54,180000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Experimental Pilot - On Gossip Hello - Pause Waypoint"),
+(@ENTRY,0,2,0,40,0,100,0,8,19776,0,0,80,@ENTRY*100+00,2,0,0,0,0,1,0,0,0,0,0,0,0,"Experimental Pilot - On Waypoint 8 Reached - Run Script"),
+(@ENTRY,0,3,4,40,0,100,0,15,19776,0,0,54,300000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Experimental Pilot - On Waypoint 15 Reached - Pause Waypoint"),
+(@ENTRY,0,4,0,61,0,100,0,15,19776,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,5.0689,"Experimental Pilot - On Waypoint 15 Reached - Set Orientation 5,0689");
+
+-- Actionlist SAI
+SET @ENTRY := 1977600;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,0,0,0,0,54,140000,0,0,0,0,0,1,0,0,0,0,0,0,0,"On Script - Pause Waypoint"),
+(@ENTRY,9,1,0,0,0,100,0,0,0,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,2.111339,"On Script - Set Orientation 2.111339"),
+(@ENTRY,9,2,0,0,0,100,0,4000,4000,0,0,45,1,1,0,0,0,0,10,70614,19737,0,0,0,0,0,"On Script - Set Data 1 1"),
+(@ENTRY,9,3,0,0,0,100,0,1000,1000,0,0,1,0,15000,0,0,0,0,1,0,0,0,0,0,0,0,"On Script - Say Line 0"),
+(@ENTRY,9,4,0,0,0,100,0,15000,15000,0,0,1,0,20000,0,0,0,0,10,70614,19737,0,0,0,0,0,"On Script - Say Line 0"),
+(@ENTRY,9,5,0,0,0,100,0,20000,20000,0,0,1,1,20000,0,0,0,0,1,0,0,0,0,0,0,0,"On Script - Say Line 1"),
+(@ENTRY,9,6,0,0,0,100,0,0,0,0,0,5,6,0,0,0,0,0,1,0,0,0,0,0,0,0,"On Script - Play Emote 6"),
+(@ENTRY,9,7,0,0,0,100,0,20000,20000,0,0,1,1,15000,0,0,0,0,10,70614,19737,0,0,0,0,0,"On Script - Say Line 1"),
+(@ENTRY,9,8,0,0,0,100,0,15000,15000,0,0,5,6,0,0,0,0,0,1,0,0,0,0,0,0,0,"On Script - Play Emote 6"),
+(@ENTRY,9,9,0,0,0,100,0,0,0,0,0,1,2,15000,0,0,0,0,1,0,0,0,0,0,0,0,"On Script - Say Line 2"),
+(@ENTRY,9,10,0,0,0,100,0,15000,15000,0,0,1,2,10000,0,0,0,0,10,70614,19737,0,0,0,0,0,"On Script - Say Line 2"),
+(@ENTRY,9,11,0,0,0,100,0,10000,10000,0,0,1,3,15000,0,0,0,0,1,0,0,0,0,0,0,0,"On Script - Say Line 3"),
+(@ENTRY,9,12,0,0,0,100,0,0,0,0,0,5,6,0,0,0,0,0,1,0,0,0,0,0,0,0,"On Script - Play Emote 6"),
+(@ENTRY,9,13,0,0,0,100,0,15000,15000,0,0,1,3,10000,0,0,0,0,10,70614,19737,0,0,0,0,0,"On Script - Say Line 3"),
+(@ENTRY,9,14,0,0,0,100,0,10000,10000,0,0,1,4,15000,0,0,0,0,1,0,0,0,0,0,0,0,"On Script - Say Line 4"),
+(@ENTRY,9,15,0,0,0,100,0,15000,15000,0,0,1,4,0,0,0,0,0,10,70614,19737,0,0,0,0,0,"On Script - Say Line 4"),
+(@ENTRY,9,16,0,0,0,100,0,0,0,0,0,45,2,2,0,0,0,0,10,70614,19737,0,0,0,0,0,"On Script - Set Data 2 2");
+
+-- Buddy AI
+-- Engineering Crewmember SAI
+SET @GUID := -70614;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=19737;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@GUID 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
+(@GUID,0,0,0,38,0,100,0,1,1,0,0,66,0,0,0,0,0,0,10,70731,19776,0,0,0,0,0,"Engineering Crewmember - On Data Set 1 1 - Set Orientation Closest Creature 'Experimental Pilot'"),
+(@GUID,0,1,0,38,0,100,0,2,2,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,2.199120,"Engineering Crewmember - On Data Set 2 2 - Set Orientation 2,199120");
+
+DELETE FROM `creature_text` WHERE `CreatureID` IN (19737, 19776);
+INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `comment`) VALUES
+(19776, 0, 0, 'All my bags are packed, I''m ready to go.', 12, 0, 100, 0, 0, 0, 17413, 'Experimental Pilot'),
+(19776, 1, 0, 'You need to do what? All this science, I don''t understand... Look, this is just my job, five days a week.', 12, 0, 100, 0, 0, 0, 17416, 'Experimental Pilot'),
+(19776, 2, 0, 'I can''t. I''m not the man they think I am at home. Besides, I didn''t bring them out here.', 12, 0, 100, 0, 0, 0, 17419, 'Experimental Pilot'),
+(19776, 3, 0, 'This isn''t the kind of place to raise your kids. It''s cold, and there''d be no one to raise them.', 12, 0, 100, 0, 0, 0, 17421, 'Experimental Pilot'),
+(19776, 4, 0, 'Oh no, no, no... I''m a rocket man.', 12, 0, 100, 0, 0, 0, 17423, 'Experimental Pilot'),
+--
+(19737, 0, 0, 'The ship''s not ready yet. We still need to calibrate the fuse length to make sure that it doesn''t burn out and leave you up there alone.', 12, 0, 100, 0, 0, 0, 17414, 'Engineering Crewmember'),
+(19737, 1, 0, 'Essentially, it''s going to be a long, long time till we are ready to launch. Maybe you should just head back home to your family.', 12, 0, 100, 0, 0, 0, 17417, 'Engineering Crewmember'),
+(19737, 2, 0, 'Why not? A family can give you strength.', 12, 0, 100, 0, 0, 0, 17420, 'Engineering Crewmember'),
+(19737, 3, 0, 'Couldn''t you raise them?', 12, 0, 100, 0, 0, 0, 17422, 'Engineering Crewmember'),
+(19737, 4, 0, 'Well, it''s like I said; it''s going to be a while before we get this ship ready for flight. We''ll keep you informed.', 12, 0, 100, 0, 0, 0, 17424, 'Engineering Crewmember');
+
+DELETE FROM `waypoints` WHERE `entry`=19776;
+INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `point_comment`) VALUES
+(19776, 1, 2976.31, 3709.67, 142.398, 'Experimental Pilot'),
+(19776, 2, 2987.82, 3686.2, 142.681, 'Experimental Pilot'),
+(19776, 3, 2987.82, 3652.62, 143.244, 'Experimental Pilot'),
+(19776, 4, 2999.17, 3645.03, 143.849, 'Experimental Pilot'),
+(19776, 5, 3006.7, 3648.63, 143.771, 'Experimental Pilot'),
+(19776, 6, 3042.1, 3645.08, 142.808, 'Experimental Pilot'),
+(19776, 7, 3047.12, 3648.91, 142.832, 'Experimental Pilot'),
+(19776, 8, 3043.87, 3652.34, 142.88, 'Experimental Pilot'),
+(19776, 9, 3026.43, 3641.43, 143.507, 'Experimental Pilot'),
+(19776, 10, 2989.67, 3650.38, 143.486, 'Experimental Pilot'),
+(19776, 11, 2988.99, 3685.32, 142.73, 'Experimental Pilot'),
+(19776, 12, 2975.27, 3712.82, 142.309, 'Experimental Pilot'),
+(19776, 13, 2975.12, 3725.84, 142.688, 'Experimental Pilot'),
+(19776, 14, 2965.31, 3733.57, 143.503, 'Experimental Pilot'),
+(19776, 15, 2966.14, 3733, 143.472, 'Experimental Pilot');
diff --git a/sql/updates/world/master/2020_04_10_00_world_2017_01_15_05_world.sql b/sql/updates/world/master/2020_04_10_00_world_2017_01_15_05_world.sql
new file mode 100644
index 00000000000..84ec22473d4
--- /dev/null
+++ b/sql/updates/world/master/2020_04_10_00_world_2017_01_15_05_world.sql
@@ -0,0 +1,32 @@
+-- Levixus SAI
+SET @ENTRY := 19847;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,11,0,100,1,0,0,0,0,11,24313,0,0,0,0,0,1,0,0,0,0,0,0,0,"Levixus - On Respawn - Cast 'Shade' (No Repeat)"),
+(@ENTRY,0,1,0,0,0,100,0,3000,7000,13000,17000,11,11443,0,0,0,0,0,2,0,0,0,0,0,0,0,"Levixus - In Combat - Cast 'Cripple'"),
+(@ENTRY,0,2,0,0,0,100,0,9000,14000,13000,17000,11,7645,1,0,0,0,0,6,0,0,0,0,0,0,0,"Levixus - In Combat - Cast 'Dominate Mind'"),
+(@ENTRY,0,3,0,0,0,100,0,10000,13000,18000,22000,11,38939,1,0,0,0,0,2,0,0,0,0,0,0,0,"Levixus - In Combat - Cast 'Inferno'"),
+(@ENTRY,0,4,0,1,0,100,0,0,0,20000,20000,80,@ENTRY*100+00,2,0,0,0,0,1,0,0,0,0,0,0,0,"Levixus - Out of Combat - Run Script");
+
+-- Actionlist SAI
+SET @ENTRY := 1984700;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,1000,1000,0,0,1,0,1000,0,0,0,0,1,0,0,0,0,0,0,0,"Levixus - On Script - Say Line 0"),
+(@ENTRY,9,1,0,0,0,100,0,1000,1000,0,0,1,1,8000,0,0,0,0,1,0,0,0,0,0,0,0,"Levixus - On Script - Say Line 1"),
+(@ENTRY,9,2,0,0,0,100,0,8000,8000,0,0,1,0,1000,0,0,0,0,1,0,0,0,0,0,0,0,"Levixus - On Script - Say Line 0"),
+(@ENTRY,9,3,0,0,0,100,0,1000,1000,0,0,1,1,5000,0,0,0,0,1,0,0,0,0,0,0,0,"Levixus - On Script - Say Line 1");
+
+DELETE FROM `creature_text` WHERE `CreatureID`=19847;
+INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `comment`) VALUES
+(19847, 0, 0, '%s reads from the book of the dead.', 16, 0, 100, 0, 0, 0, 17446, 'Levixus'),
+--
+(19847, 1, 0, 'Shane Dabiri, Lee, Alex T., Rob F., J. A. B., A. Mayberry!', 12, 8, 100, 15, 0, 0, 17454, 'Levixus'),
+(19847, 1, 1, 'Jeffrey Kaplan! Tom Chilton! Rob Pardo!', 12, 8, 100, 15, 0, 0, 17447, 'Levixus'),
+(19847, 1, 2, 'Justin Thavirat! Roman Kenney! Our entire awesome art and animation team!', 12, 8, 100, 15, 0, 0, 17448, 'Levixus'),
+(19847, 1, 3, 'Kevin Jordan and Jonathan LeCraft!', 12, 8, 100, 15, 0, 0, 17453, 'Levixus'),
+(19847, 1, 4, 'CHRIS METZEN!', 12, 8, 100, 15, 0, 0, 17449, 'Levixus'),
+(19847, 1, 5, 'Pat Nagle! World design team! Cory Stockton, Paul C., Jim Chadwick, Staats, Ed Hanes, Morris, Gotcher, Jesse!, Sarah B., Victor C., Dave A.! All of our amazing exterior artists!', 12, 8, 100, 15, 0, 0, 17450, 'Levixus'),
+(19847, 1, 6, 'Scott Mercer! Geoff, Wyatt, Joe, Travis, Kris, Steven! Brazie!', 12, 8, 100, 15, 0, 0, 17451, 'Levixus'),
+(19847, 1, 7, 'Luis, Brianna and Eric! Blizzard QA team! Of course our fans!', 12, 8, 100, 15, 0, 0, 17452, 'Levixus');
diff --git a/sql/updates/world/master/2020_04_10_01_world_2017_01_15_06_world.sql b/sql/updates/world/master/2020_04_10_01_world_2017_01_15_06_world.sql
new file mode 100644
index 00000000000..230e6b1efe9
--- /dev/null
+++ b/sql/updates/world/master/2020_04_10_01_world_2017_01_15_06_world.sql
@@ -0,0 +1,37 @@
+-- Eye of the Citadel -- http://wotlk.openwow.com/npc=21134
+-- Warlord Morkh SAI
+SET @ENTRY := 16964;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,0,0,100,0,9000,9000,17000,17000,11,34080,1,0,0,0,0,1,0,0,0,0,0,0,0,"Warlord Morkh - In Combat - Cast 'Riposte Stance'"),
+(@ENTRY,0,1,0,0,0,100,0,7000,7000,8000,8000,11,11978,1,0,0,0,0,2,0,0,0,0,0,0,0,"Warlord Morkh - In Combat - Cast 'Kick'"),
+(@ENTRY,0,2,3,2,0,100,1,0,20,0,0,11,8599,1,0,0,0,0,1,0,0,0,0,0,0,0,"Warlord Morkh - Between 0-20% Health - Cast 'Enrage' (No Repeat)"),
+(@ENTRY,0,3,0,61,0,100,0,0,20,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warlord Morkh - Between 0-20% Health - Say Line 0 (No Repeat)"),
+(@ENTRY,0,4,5,6,0,100,0,0,0,0,0,64,1,0,0,0,0,0,7,0,0,0,0,0,0,0,"Warlord Morkh - On Just Died - Store Targetlist"),
+(@ENTRY,0,5,6,61,0,100,0,0,0,0,0,100,1,0,0,0,0,0,10,86039,21134,0,0,0,0,0,"Warlord Morkh - On Just Died - Send Target 1"),
+(@ENTRY,0,6,0,61,0,100,0,0,0,0,0,45,1,1,0,0,0,0,10,86039,21134,0,0,0,0,0,"Warlord Morkh - On Just Died - Set Data 1 1");
+
+-- Eye of the Citadel SAI
+SET @ENTRY := 21134;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,38,0,100,0,1,1,0,0,80,@ENTRY*100+00,2,0,0,0,0,1,0,0,0,0,0,0,0,"Eye of the Citadel - On Data Set 1 1 - Run Script"),
+(@ENTRY,0,1,0,25,0,100,0,0,0,0,0,47,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Eye of the Citadel - On Reset - Set Visibility Off");
+
+-- Actionlist SAI
+SET @ENTRY := 2113400;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,3000,3000,0,0,1,0,3000,0,0,0,0,1,0,0,0,0,0,0,0,"Eye of the Citadel - On Script - Say Line 0"),
+(@ENTRY,9,1,0,0,0,100,0,0,0,0,0,47,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Eye of the Citadel - On Script - Set Visibility On"),
+(@ENTRY,9,2,0,0,0,100,0,3000,3000,0,0,1,1,4000,0,0,0,0,12,1,0,0,0,0,0,0,"Eye of the Citadel - On Script - Say Line 1"),
+(@ENTRY,9,3,0,0,0,100,0,4000,4000,0,0,1,2,5000,0,0,0,0,1,0,0,0,0,0,0,0,"Eye of the Citadel - On Script - Say Line 2"),
+(@ENTRY,9,4,0,0,0,100,0,3000,3000,0,0,47,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Eye of the Citadel - On Script - Set Visibility Off");
+
+DELETE FROM `creature_text` WHERE `CreatureID`=21134;
+INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `comment`, `TextRange`) VALUES
+(21134, 0, 0, 'A deep, bone chilling voice echoes from the %s...', 16, 0, 100, 0, 0, 0, 18774, 'Eye of the Citadel', 0),
+(21134, 1, 0, 'How dare you trifle with my playthings, $n!', 12, 0, 100, 0, 0, 0, 18775, 'Eye of the Citadel', 0),
+(21134, 2, 0, 'The orcs in my citadel will drink your blood and dovour you!', 12, 0, 100, 0, 0, 0, 18776, 'Eye of the Citadel', 0);
diff --git a/sql/updates/world/master/2020_04_10_02_world_2017_01_15_07_world.sql b/sql/updates/world/master/2020_04_10_02_world_2017_01_15_07_world.sql
new file mode 100644
index 00000000000..0d688f4ac08
--- /dev/null
+++ b/sql/updates/world/master/2020_04_10_02_world_2017_01_15_07_world.sql
@@ -0,0 +1,34 @@
+-- Painmistress Gabrissa -- http://wotlk.openwow.com/npc=21309
+-- Painmistress Gabrissa SAI
+SET @ENTRY := 21309;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,0,0,100,0,5000,7000,20000,25000,11,38048,0,0,0,0,0,2,0,0,0,0,0,0,0,"Painmistress Gabrissa - In Combat - Cast 'Curse of Pain'"),
+(@ENTRY,0,1,0,0,0,100,0,6000,7000,17000,20000,11,38169,0,0,0,0,0,2,0,0,0,0,0,0,0,"Painmistress Gabrissa - In Combat - Cast 'Subservience'"),
+(@ENTRY,0,2,0,25,0,100,0,0,0,0,0,53,0,21309,1,0,0,2,0,0,0,0,0,0,0,0,"Painmistress Gabrissa - On Reset - Start Waypoint"),
+(@ENTRY,0,3,0,40,0,100,0,5,21309,0,0,80,@ENTRY*100+00,0,0,0,0,0,1,0,0,0,0,0,0,0,"Painmistress Gabrissa - On Waypoint 5 Reached - Run Script"),
+(@ENTRY,0,4,5,40,0,100,0,9,21309,0,0,54,20000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Painmistress Gabrissa - On Waypoint 9 Reached - Pause Waypoint"),
+(@ENTRY,0,5,0,61,0,100,0,9,21309,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,3.37533,"Painmistress Gabrissa - On Waypoint 9 Reached - Set Orientation 3.37533"),
+(@ENTRY,0,6,0,4,0,100,0,0,0,0,0,49,0,0,0,0,0,0,2,0,0,0,0,0,0,0,"Painmistress Gabrissa - On Aggro - Start Attacking");
+
+-- Actionlist SAI
+SET @ENTRY := 2130900;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,0,0,0,0,54,6000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Painmistress Gabrissa - On Script - Pause Waypoint"),
+(@ENTRY,9,1,0,0,0,100,0,0,0,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,3.60702,"Painmistress Gabrissa - On Script - Set Orientation 3,60702"),
+(@ENTRY,9,2,0,0,0,100,0,1000,1000,0,0,11,36578,0,0,0,0,0,10,74619,21310,0,0,0,0,0,"Painmistress Gabrissa - On Script - Cast 'Fool's Fortune'"),
+(@ENTRY,9,3,0,0,0,100,0,4000,4000,0,0,92,0,36578,1,0,0,0,1,0,0,0,0,0,0,0,"Painmistress Gabrissa - On Script - Interrupt Spell 'Fool's Fortune'");
+
+DELETE FROM `waypoints` WHERE `entry`=21309;
+INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `point_comment`) VALUES
+(21309, 1, -3697.1, 2669.77, 107.186, 'Painmistress Gabrissa'),
+(21309, 2, -3697.68, 2673.34, 108.569, 'Painmistress Gabrissa'),
+(21309, 3, -3692.22, 2678.74, 108.66, 'Painmistress Gabrissa'),
+(21309, 4, -3690.04, 2682.79, 108.752, 'Painmistress Gabrissa'),
+(21309, 5, -3692.89, 2684.18, 108.485, 'Painmistress Gabrissa'),
+(21309, 6, -3690.92, 2682.03, 108.744, 'Painmistress Gabrissa'),
+(21309, 7, -3694.07, 2677.51, 108.537, 'Painmistress Gabrissa'),
+(21309, 8, -3697.53, 2673.77, 108.581, 'Painmistress Gabrissa'),
+(21309, 9, -3693.46, 2668.44, 107.174, 'Painmistress Gabrissa');
diff --git a/sql/updates/world/master/2020_04_10_03_world_2017_01_15_08_world.sql b/sql/updates/world/master/2020_04_10_03_world_2017_01_15_08_world.sql
new file mode 100644
index 00000000000..eb7ba4dd25c
--- /dev/null
+++ b/sql/updates/world/master/2020_04_10_03_world_2017_01_15_08_world.sql
@@ -0,0 +1,28 @@
+-- Chancellor Bloodleaf -- http://wotlk.openwow.com/npc=22012
+-- Chancellor Bloodleaf SAI
+SET @ENTRY := 22012;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,1,0,100,0,15000,15000,130000,130000,80,@ENTRY*100+00,0,0,0,0,0,1,0,0,0,0,0,0,0,"Chancellor Bloodleaf - Out of Combat - Run Script"),
+(@ENTRY,0,1,0,0,0,100,0,5000,6000,5000,6000,11,34517,0,0,0,0,0,1,0,0,0,0,0,0,0,"Chancellor Bloodleaf - In Combat - Cast 'Arcane Explosion'");
+
+-- Actionlist SAI
+SET @ENTRY := 2201200;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,1000,1000,0,0,1,0,8000,0,0,0,0,1,0,0,0,0,0,0,0,"Chancellor Bloodleaf - On Script - Say Line 0"),
+(@ENTRY,9,1,0,0,0,100,0,1000,1000,0,0,5,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Chancellor Bloodleaf - On Script - Play Emote 1"),
+(@ENTRY,9,2,0,0,0,100,0,9000,9000,0,0,1,0,6000,0,0,0,0,10,77086,22011,0,0,0,0,0,"Chancellor Bloodleaf - On Script - Say Line 0"),
+(@ENTRY,9,3,0,0,0,100,0,6000,6000,0,0,1,1,7000,0,0,0,0,1,0,0,0,0,0,0,0,"Chancellor Bloodleaf - On Script - Say Line 1"),
+(@ENTRY,9,4,0,0,0,100,0,1000,1000,0,0,5,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Chancellor Bloodleaf - On Script - Play Emote 1"),
+(@ENTRY,9,5,0,0,0,100,0,6000,6000,0,0,1,2,6000,0,0,0,0,1,0,0,0,0,0,0,0,"Chancellor Bloodleaf - On Script - Say Line 2");
+
+DELETE FROM `creature_text` WHERE `CreatureID` IN (22011, 22012);
+INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `comment`) VALUES
+-- Corok the Mighty
+(22011, 0, 0, 'And... if we do not?', 12, 0, 100, 0, 0, 0, 19695, 'Corok the Mighty'),
+-- Chancellor Bloodleaf
+(22012, 0, 0, 'Lend us the strength of the giants of Shadowmoon, Corok. The master is a just ruler. He will be sure to take care of those that assisted in subduing the dissidents of this world.', 12, 0, 100, 0, 0, 0, 19693, 'Chancellor Bloodleaf'),
+(22012, 1, 0, 'Then you become enemies of my lord, Illidan. Enemies of Illidan are destroyed. Are your giants able to withstand an attack from the forces of Eclipse Point?', 12, 0, 100, 0, 0, 0, 19696, 'Chancellor Bloodleaf'),
+(22012, 2, 0, 'No... I did not think so...', 12, 0, 100, 0, 0, 0, 19697, 'Chancellor Bloodleaf');
diff --git a/sql/updates/world/master/2020_04_10_04_world_2017_01_15_09_world.sql b/sql/updates/world/master/2020_04_10_04_world_2017_01_15_09_world.sql
new file mode 100644
index 00000000000..e50d903be51
--- /dev/null
+++ b/sql/updates/world/master/2020_04_10_04_world_2017_01_15_09_world.sql
@@ -0,0 +1,36 @@
+-- Mordenai -- http://wotlk.openwow.com/npc=22113
+-- Mordenai SAI
+SET @ENTRY := 22113;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,25,0,100,0,0,0,0,0,53,0,22113,1,0,0,2,1,0,0,0,0,0,0,0,"Mordenai - On Reset - Start Waypoint"),
+(@ENTRY,0,1,0,64,0,100,0,0,0,0,0,54,180000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Mordenai - On Gossip Hello - Pause Waypoint"),
+(@ENTRY,0,2,3,40,0,100,0,1,22113,0,0,54,12000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Mordenai - On Waypoint 1 Reached - Pause Waypoint"),
+(@ENTRY,0,3,0,61,0,100,0,1,22113,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,4.59702,"Mordenai - On Waypoint 1 Reached - Set Orientation 4.59702"),
+(@ENTRY,0,4,0,40,0,100,0,2,22113,0,0,49,0,0,0,0,0,0,19,21478,80,0,0,0,0,0,"Mordenai - On Waypoint 2 Reached - Start Attacking"),
+(@ENTRY,0,5,0,40,0,100,0,12,22113,0,0,49,0,0,0,0,0,0,19,21478,80,0,0,0,0,0,"Mordenai - On Waypoint 12 Reached - Start Attacking"),
+(@ENTRY,0,6,0,0,0,100,0,0,0,2300,3900,11,41440,64,0,0,0,0,2,0,0,0,0,0,0,0,"Mordenai - In Combat - Cast 'Shoot'"),
+(@ENTRY,0,7,0,0,0,100,0,6000,9000,27000,28000,11,41448,0,0,0,0,0,2,0,0,0,0,0,0,0,"Mordenai - In Combat - Cast 'Multi-Shot'"),
+(@ENTRY,0,8,0,0,0,100,0,5000,5000,18000,18000,11,38370,0,0,0,0,0,2,0,0,0,0,0,0,0,"Mordenai - In Combat - Cast 'Aimed Shot'");
+
+DELETE FROM `waypoints` WHERE `entry`=22113;
+INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `point_comment`) VALUES
+(22113, 1, -4100.05, 969.276, 24.9571, 'Mordenai'),
+(22113, 2, -4104.06, 931.187, 18.8469, 'Mordenai'),
+(22113, 3, -4105.65, 911.224, 16.1353, 'Mordenai'),
+(22113, 4, -4106.05, 889.833, 14.4649, 'Mordenai'),
+(22113, 5, -4118.47, 857.928, 8.29486, 'Mordenai'),
+(22113, 6, -4122.4, 839.518, 10.4151, 'Mordenai'),
+(22113, 7, -4143.45, 803.2, 9.22043, 'Mordenai'),
+(22113, 8, -4150.96, 769.769, 6.31908, 'Mordenai'),
+(22113, 9, -4153.1, 760.191, 3.47747, 'Mordenai'),
+(22113, 10, -4155.08, 747.368, 1.8985, 'Mordenai'),
+(22113, 11, -4151.37, 769.929, 6.42453, 'Mordenai'),
+(22113, 12, -4132.84, 797.355, 8.16607, 'Mordenai'),
+(22113, 13, -4137.32, 823.672, 9.68296, 'Mordenai'),
+(22113, 14, -4119.16, 842.164, 9.89524, 'Mordenai'),
+(22113, 15, -4115.26, 851.276, 7.68533, 'Mordenai'),
+(22113, 16, -4109.66, 883.088, 13.8876, 'Mordenai'),
+(22113, 17, -4110.74, 914.769, 17.723, 'Mordenai'),
+(22113, 18, -4106.89, 948.026, 23.0078, 'Mordenai');
diff --git a/sql/updates/world/master/2020_04_10_05_world_2017_01_15_10_world.sql b/sql/updates/world/master/2020_04_10_05_world_2017_01_15_10_world.sql
new file mode 100644
index 00000000000..6d4923d8960
--- /dev/null
+++ b/sql/updates/world/master/2020_04_10_05_world_2017_01_15_10_world.sql
@@ -0,0 +1,125 @@
+-- Armorer Orkuruk --
+UPDATE `creature_addon` SET `path_id`=0 WHERE `guid`=125542;
+DELETE FROM `waypoint_data` WHERE `id`=1255420;
+UPDATE `creature` SET `MovementType`=0 WHERE `guid`=125542;
+
+-- Armorer Orkuruk SAI
+SET @ENTRY := 25274;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,25,0,100,0,0,0,0,0,53,0,25274,1,0,0,0,1,0,0,0,0,0,0,0,"Armorer Orkuruk - On Reset - Start Waypoint"),
+(@ENTRY,0,1,0,64,0,100,0,0,0,0,0,54,180000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Armorer Orkuruk - On Gossip Hello - Pause Waypoint"),
+(@ENTRY,0,2,3,40,0,100,0,17,25274,0,0,80,@ENTRY*100+00,0,0,0,0,0,1,0,0,0,0,0,0,0,"Armorer Orkuruk - On Waypoint 17 Reached - Run Script"),
+(@ENTRY,0,3,0,61,0,100,0,17,25274,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,3.38169,"Armorer Orkuruk - On Waypoint 17 Reached - Set Orientation 3,38169"),
+(@ENTRY,0,4,5,40,0,100,0,71,25274,0,0,80,@ENTRY*100+00,0,0,0,0,0,1,0,0,0,0,0,0,0,"Armorer Orkuruk - On Waypoint 71 Reached - Run Script"),
+(@ENTRY,0,5,0,61,0,100,0,71,25274,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,2.88465,"Armorer Orkuruk - On Waypoint 71 Reached - Set Orientation 2,88465");
+
+-- Actionlist SAI
+SET @ENTRY := 2527400;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,0,0,0,0,54,15000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Armorer Orkuruk - On Script - Pause Waypoint"),
+(@ENTRY,9,1,0,0,0,100,0,2000,2000,0,0,5,5,0,0,0,0,0,1,0,0,0,0,0,0,0,"Armorer Orkuruk - On Script - Play Emote 5"),
+(@ENTRY,9,2,0,0,0,100,0,3000,3000,0,0,1,0,10000,0,0,0,0,1,0,0,0,0,0,0,0,"Armorer Orkuruk - On Script - Say Line 0");
+
+DELETE FROM `creature_text` WHERE `CreatureID`=25274;
+INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `comment`) VALUES
+(25274, 0, 0, 'Keep ''em hot you big dummy!', 12, 1, 100, 0, 0, 0, 25133, 'Armorer Orkuruk'),
+(25274, 0, 1, 'Those weapons ain''t gonna build themselves! Faster!', 12, 1, 100, 0, 0, 0, 25134, 'Armorer Orkuruk'),
+(25274, 0, 2, 'You call that a hammer strike? What kind of amateurs am I workin'' with here?', 12, 1, 100, 0, 0, 0, 25135, 'Armorer Orkuruk'),
+(25274, 0, 3, 'You keep that garbage up and I''ll ship you back to your momma in a box with a note strapped to your chest that reads: FAILURE.', 12, 1, 100, 0, 0, 0, 25136, 'Armorer Orkuruk'),
+(25274, 0, 4, 'And WHAT are our soldiers supposed to do with that shoddy piece of junk?', 12, 1, 100, 0, 0, 0, 25137, 'Armorer Orkuruk'),
+(25274, 0, 5, 'You''re an embarassment to this entire operation! Pack up your stuff and get out!', 12, 1, 100, 0, 0, 0, 25138, 'Armorer Orkuruk');
+
+DELETE FROM `waypoints` WHERE `entry`=25274;
+INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `point_comment`) VALUES
+(25274, 1, 2761.85, 6187.82, 83.448, 'Armorer Orkuruk'),
+(25274, 2, 2763.1, 6203.83, 83.4409, 'Armorer Orkuruk'),
+(25274, 3, 2765.37, 6209.65, 83.4451, 'Armorer Orkuruk'),
+(25274, 4, 2772.92, 6217.22, 83.4475, 'Armorer Orkuruk'),
+(25274, 5, 2766.39, 6211.48, 83.437, 'Armorer Orkuruk'),
+(25274, 6, 2762.96, 6202.62, 83.4409, 'Armorer Orkuruk'),
+(25274, 7, 2762.31, 6187.53, 83.4546, 'Armorer Orkuruk'),
+(25274, 8, 2765.22, 6178.21, 83.4565, 'Armorer Orkuruk'),
+(25274, 9, 2762.24, 6188.36, 83.4575, 'Armorer Orkuruk'),
+(25274, 10, 2763.33, 6204.33, 83.4432, 'Armorer Orkuruk'),
+(25274, 11, 2766.61, 6211.59, 83.4381, 'Armorer Orkuruk'),
+(25274, 12, 2773.5, 6217.87, 83.4484, 'Armorer Orkuruk'),
+(25274, 13, 2765.7, 6210.09, 83.4438, 'Armorer Orkuruk'),
+(25274, 14, 2762.77, 6202.1, 83.4395, 'Armorer Orkuruk'),
+(25274, 15, 2762.54, 6187.41, 83.4578, 'Armorer Orkuruk'),
+(25274, 16, 2765.46, 6178.01, 83.4598, 'Armorer Orkuruk'),
+(25274, 17, 2764.09, 6182.25, 83.4576, 'Armorer Orkuruk'),
+(25274, 18, 2762.03, 6188.66, 83.4549, 'Armorer Orkuruk'),
+(25274, 19, 2763.21, 6203.82, 83.4422, 'Armorer Orkuruk'),
+(25274, 20, 2766.87, 6211.5, 83.4422, 'Armorer Orkuruk'),
+(25274, 21, 2773.88, 6218.09, 83.4497, 'Armorer Orkuruk'),
+(25274, 22, 2765.7, 6210.09, 83.4438, 'Armorer Orkuruk'),
+(25274, 23, 2762.77, 6202.1, 83.4395, 'Armorer Orkuruk'),
+(25274, 24, 2762.54, 6187.41, 83.4578, 'Armorer Orkuruk'),
+(25274, 25, 2765.46, 6178.01, 83.4598, 'Armorer Orkuruk'),
+(25274, 26, 2762.24, 6188.36, 83.4575, 'Armorer Orkuruk'),
+(25274, 27, 2763.33, 6204.33, 83.4432, 'Armorer Orkuruk'),
+(25274, 28, 2766.61, 6211.59, 83.4381, 'Armorer Orkuruk'),
+(25274, 29, 2773.5, 6217.87, 83.4484, 'Armorer Orkuruk'),
+(25274, 30, 2765.7, 6210.09, 83.4438, 'Armorer Orkuruk'),
+(25274, 31, 2762.77, 6202.1, 83.4395, 'Armorer Orkuruk'),
+(25274, 32, 2762.54, 6187.41, 83.4578, 'Armorer Orkuruk'),
+(25274, 33, 2765.46, 6178.01, 83.4598, 'Armorer Orkuruk'),
+(25274, 34, 2762.24, 6188.36, 83.4575, 'Armorer Orkuruk'),
+(25274, 35, 2763.33, 6204.33, 83.4432, 'Armorer Orkuruk'),
+(25274, 36, 2766.61, 6211.59, 83.4381, 'Armorer Orkuruk'),
+(25274, 37, 2773.5, 6217.87, 83.4484, 'Armorer Orkuruk'),
+(25274, 38, 2765.7, 6210.09, 83.4438, 'Armorer Orkuruk'),
+(25274, 39, 2762.77, 6202.1, 83.4395, 'Armorer Orkuruk'),
+(25274, 40, 2762.54, 6187.41, 83.4578, 'Armorer Orkuruk'),
+(25274, 41, 2765.46, 6178.01, 83.4598, 'Armorer Orkuruk'),
+(25274, 42, 2762.24, 6188.36, 83.4575, 'Armorer Orkuruk'),
+(25274, 43, 2763.33, 6204.33, 83.4432, 'Armorer Orkuruk'),
+(25274, 44, 2766.61, 6211.59, 83.4381, 'Armorer Orkuruk'),
+(25274, 45, 2773.5, 6217.87, 83.4484, 'Armorer Orkuruk'),
+(25274, 46, 2765.7, 6210.09, 83.4438, 'Armorer Orkuruk'),
+(25274, 47, 2762.77, 6202.1, 83.4395, 'Armorer Orkuruk'),
+(25274, 48, 2762.54, 6187.41, 83.4578, 'Armorer Orkuruk'),
+(25274, 49, 2765.46, 6178.01, 83.4598, 'Armorer Orkuruk'),
+(25274, 50, 2762.24, 6188.36, 83.4575, 'Armorer Orkuruk'),
+(25274, 51, 2763.33, 6204.33, 83.4432, 'Armorer Orkuruk'),
+(25274, 52, 2766.61, 6211.59, 83.4381, 'Armorer Orkuruk'),
+(25274, 53, 2773.5, 6217.87, 83.4484, 'Armorer Orkuruk'),
+(25274, 54, 2765.7, 6210.09, 83.4438, 'Armorer Orkuruk'),
+(25274, 55, 2762.77, 6202.1, 83.4395, 'Armorer Orkuruk'),
+(25274, 56, 2762.54, 6187.41, 83.4578, 'Armorer Orkuruk'),
+(25274, 57, 2765.46, 6178.01, 83.4598, 'Armorer Orkuruk'),
+(25274, 58, 2762.24, 6188.36, 83.4575, 'Armorer Orkuruk'),
+(25274, 59, 2763.33, 6204.33, 83.4432, 'Armorer Orkuruk'),
+(25274, 60, 2766.61, 6211.59, 83.4381, 'Armorer Orkuruk'),
+(25274, 61, 2773.5, 6217.87, 83.4484, 'Armorer Orkuruk'),
+(25274, 62, 2765.7, 6210.09, 83.4438, 'Armorer Orkuruk'),
+(25274, 63, 2762.77, 6202.1, 83.4395, 'Armorer Orkuruk'),
+(25274, 64, 2762.54, 6187.41, 83.4578, 'Armorer Orkuruk'),
+(25274, 65, 2765.46, 6178.01, 83.4598, 'Armorer Orkuruk'),
+(25274, 66, 2762.24, 6188.36, 83.4575, 'Armorer Orkuruk'),
+(25274, 67, 2763.33, 6204.33, 83.4432, 'Armorer Orkuruk'),
+(25274, 68, 2766.61, 6211.59, 83.4381, 'Armorer Orkuruk'),
+(25274, 69, 2773.5, 6217.87, 83.4484, 'Armorer Orkuruk'),
+(25274, 70, 2766.07, 6210.93, 83.4391, 'Armorer Orkuruk'),
+(25274, 71, 2762.53, 6207.16, 83.4206, 'Armorer Orkuruk'),
+(25274, 72, 2762.16, 6187.79, 83.4531, 'Armorer Orkuruk'),
+(25274, 73, 2765.46, 6178.01, 83.4598, 'Armorer Orkuruk'),
+(25274, 74, 2761.85, 6187.82, 83.448, 'Armorer Orkuruk'),
+(25274, 75, 2763.1, 6203.83, 83.4409, 'Armorer Orkuruk'),
+(25274, 76, 2765.37, 6209.65, 83.4451, 'Armorer Orkuruk'),
+(25274, 77, 2772.92, 6217.22, 83.4475, 'Armorer Orkuruk'),
+(25274, 78, 2766.39, 6211.48, 83.437, 'Armorer Orkuruk'),
+(25274, 79, 2762.96, 6202.62, 83.4409, 'Armorer Orkuruk'),
+(25274, 80, 2762.31, 6187.53, 83.4546, 'Armorer Orkuruk'),
+(25274, 81, 2765.22, 6178.21, 83.4565, 'Armorer Orkuruk'),
+(25274, 82, 2762.24, 6188.36, 83.4575, 'Armorer Orkuruk'),
+(25274, 83, 2763.33, 6204.33, 83.4432, 'Armorer Orkuruk'),
+(25274, 84, 2766.61, 6211.59, 83.4381, 'Armorer Orkuruk'),
+(25274, 85, 2773.5, 6217.87, 83.4484, 'Armorer Orkuruk'),
+(25274, 86, 2765.7, 6210.09, 83.4438, 'Armorer Orkuruk'),
+(25274, 87, 2762.77, 6202.1, 83.4395, 'Armorer Orkuruk'),
+(25274, 88, 2762.54, 6187.41, 83.4578, 'Armorer Orkuruk'),
+(25274, 89, 2765.46, 6178.01, 83.4598, 'Armorer Orkuruk');
diff --git a/sql/updates/world/master/2020_04_10_06_world_2017_01_16_00_world.sql b/sql/updates/world/master/2020_04_10_06_world_2017_01_16_00_world.sql
new file mode 100644
index 00000000000..8bae4281411
--- /dev/null
+++ b/sql/updates/world/master/2020_04_10_06_world_2017_01_16_00_world.sql
@@ -0,0 +1,143 @@
+-- Wind Master To'bor & Warsong Wind Rider Script -- http://wotlk.openwow.com/npc=25289
+-- Warsong Wind Rider SAI
+SET @ENTRY := 25286;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,25,0,100,0,0,0,0,0,60,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warsong Wind Rider - On Reset - Set Fly Off");
+UPDATE `creature_template` SET `InhabitType`=4 WHERE `entry`=25286;
+
+-- Warsong Wind Rider SAI
+SET @GUID := -125578;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=25286;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@GUID 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
+(@GUID,0,0,0,25,0,100,0,0,0,0,0,60,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warsong Wind Rider - On Reset - Set Fly Off"),
+(@GUID,0,1,0,38,0,100,0,1,1,0,0,80,12557800,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warsong Wind Rider - On Data Set 1 1 - Run Script"),
+(@GUID,0,2,3,40,0,100,0,9,125578,0,0,60,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warsong Wind Rider - On Waypoint 9 Reached - Set Fly On"),
+(@GUID,0,3,0,61,0,100,0,9,125578,0,0,59,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warsong Wind Rider - On Waypoint 9 Reached - Set Run On"),
+(@GUID,0,4,0,40,0,100,0,1,125578,0,0,54,5000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warsong Wind Rider - On Waypoint 1 Reached - Pause Waypoint"),
+(@GUID,0,5,6,40,0,100,0,42,125578,0,0,59,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warsong Wind Rider - On Waypoint 42 Reached - Set Run Off"),
+(@GUID,0,6,0,61,0,100,0,42,125578,0,0,60,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warsong Wind Rider - On Waypoint 42 Reached - Set Fly Off"),
+(@GUID,0,7,8,40,0,100,0,46,125578,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,2.19912,"Warsong Wind Rider - On Waypoint 46 Reached - Set Orientation 2,19912"),
+(@GUID,0,8,0,61,0,100,0,46,125578,0,0,48,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warsong Wind Rider - On Waypoint 46 Reached - Set Active Off");
+
+-- Actionlist SAI
+SET @ENTRY := 12557800;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,0,0,0,0,48,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warsong Wind Rider - On Script - Set Active On"),
+(@ENTRY,9,1,0,0,0,100,0,0,0,0,0,1,0,5000,0,0,0,0,1,0,0,0,0,0,0,0,"Warsong Wind Rider - On Script - Say Line 0"),
+(@ENTRY,9,2,0,0,0,100,0,2000,2000,0,0,53,0,125578,0,0,0,1,1,0,0,0,0,0,0,0,"Warsong Wind Rider - On Script - Start Waypoint");
+
+UPDATE `creature` SET `MovementType`=0 WHERE `guid`=125584;
+DELETE FROM `waypoint_data` WHERE `id`=1255840;
+UPDATE `creature_addon` SET `path_id`=0 WHERE `guid`=125584;
+
+-- Wind Master To'bor SAI
+SET @ENTRY := 25289;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,25,0,100,0,0,0,0,0,53,0,25289,1,0,0,1,1,0,0,0,0,0,0,0,"Wind Master To'bor - On Reset - Start Waypoint"),
+(@ENTRY,0,1,0,64,0,100,0,0,0,0,0,54,180000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Wind Master To'bor - On Gossip Hello - Pause Waypoint"),
+(@ENTRY,0,2,0,40,0,100,0,9,25289,0,0,80,@ENTRY*100+00,0,0,0,0,0,1,0,0,0,0,0,0,0,"Wind Master To'bor - On Waypoint 9 Reached - Run Script");
+
+-- Actionlist SAI
+SET @ENTRY := 2528900;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,0,0,0,0,54,12000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Wind Master To'bor - On Script - Pause Waypoint"),
+(@ENTRY,9,1,0,0,0,100,0,0,0,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,5.14906,"Wind Master To'bor - On Script - Set Orientation 5,14906"),
+(@ENTRY,9,2,0,0,0,100,0,0,0,0,0,48,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Wind Master To'bor - On Script - Set Active On"),
+(@ENTRY,9,3,0,0,0,100,0,3000,3000,0,0,1,0,3000,0,0,0,0,1,0,0,0,0,0,0,0,"Wind Master To'bor - On Script - Say Line 0"),
+(@ENTRY,9,4,0,0,0,100,0,3000,3000,0,0,45,1,1,0,0,0,0,10,125578,25286,0,0,0,0,0,"Wind Master To'bor - On Script - Set Data 1 1"),
+(@ENTRY,9,5,0,0,0,100,0,0,0,0,0,48,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Wind Master To'bor - On Script - Set Active Off");
+
+DELETE FROM `creature_text` WHERE `CreatureID` IN (25289, 25286);
+INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `comment`) VALUES
+(25289, 0, 0, 'Aye, solja! Lift off time!', 12, 1, 100, 1, 0, 0, 24521, 'Wind Master To''bor'),
+(25286, 0, 0, 'Yes sir!', 12, 1, 100, 0, 0, 0, 24522, 'Warsong Wind Rider');
+
+DELETE FROM `waypoints` WHERE `entry`=25289;
+INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `point_comment`) VALUES
+(25289, 1, 2802.31, 6147.69, 208.197, 'Wind Master To''bor'),
+(25289, 2, 2760.18, 6107.54, 208.576, 'Wind Master To''bor'),
+(25289, 3, 2802.31, 6147.69, 208.197, 'Wind Master To''bor'),
+(25289, 4, 2760.18, 6107.54, 208.576, 'Wind Master To''bor'),
+(25289, 5, 2802.31, 6147.69, 208.197, 'Wind Master To''bor'),
+(25289, 6, 2760.18, 6107.54, 208.576, 'Wind Master To''bor'),
+(25289, 7, 2802.31, 6147.69, 208.197, 'Wind Master To''bor'),
+(25289, 8, 2760.18, 6107.54, 208.576, 'Wind Master To''bor'),
+(25289, 9, 2767.55, 6112.47, 208.234, 'Wind Master To''bor'),
+(25289, 10, 2802.31, 6147.69, 208.197, 'Wind Master To''bor'),
+(25289, 11, 2760.18, 6107.54, 208.576, 'Wind Master To''bor'),
+(25289, 12, 2802.31, 6147.69, 208.197, 'Wind Master To''bor'),
+(25289, 13, 2760.18, 6107.54, 208.576, 'Wind Master To''bor'),
+(25289, 14, 2802.31, 6147.69, 208.197, 'Wind Master To''bor'),
+(25289, 15, 2760.18, 6107.54, 208.576, 'Wind Master To''bor'),
+(25289, 16, 2802.31, 6147.69, 208.197, 'Wind Master To''bor'),
+(25289, 17, 2760.18, 6107.54, 208.576, 'Wind Master To''bor'),
+(25289, 18, 2802.31, 6147.69, 208.197, 'Wind Master To''bor'),
+(25289, 19, 2760.18, 6107.54, 208.576, 'Wind Master To''bor'),
+(25289, 20, 2802.31, 6147.69, 208.197, 'Wind Master To''bor'),
+(25289, 21, 2760.18, 6107.54, 208.576, 'Wind Master To''bor'),
+(25289, 22, 2802.31, 6147.69, 208.197, 'Wind Master To''bor'),
+(25289, 23, 2760.18, 6107.54, 208.576, 'Wind Master To''bor'),
+(25289, 24, 2802.31, 6147.69, 208.197, 'Wind Master To''bor'),
+(25289, 25, 2760.18, 6107.54, 208.576, 'Wind Master To''bor'),
+(25289, 26, 2802.31, 6147.69, 208.197, 'Wind Master To''bor'),
+(25289, 27, 2760.18, 6107.54, 208.576, 'Wind Master To''bor'),
+(25289, 28, 2802.31, 6147.69, 208.197, 'Wind Master To''bor'),
+(25289, 29, 2760.18, 6107.54, 208.576, 'Wind Master To''bor'),
+(25289, 30, 2802.31, 6147.69, 208.197, 'Wind Master To''bor'),
+(25289, 31, 2760.18, 6107.54, 208.576, 'Wind Master To''bor');
+
+DELETE FROM `waypoints` WHERE `entry`=125578;
+INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `point_comment`) VALUES
+(125578, 1, 2772.24, 6103.7, 209.008, 'Warsong Wind Rider'),
+(125578, 2, 2766.12, 6109.4, 208.372, 'Warsong Wind Rider'),
+(125578, 3, 2763.93, 6113.74, 208.298, 'Warsong Wind Rider'),
+(125578, 4, 2769.51, 6121.43, 208.123, 'Warsong Wind Rider'),
+(125578, 5, 2793.61, 6143.72, 208.129, 'Warsong Wind Rider'),
+(125578, 6, 2801.04, 6151.28, 208.13, 'Warsong Wind Rider'),
+(125578, 7, 2801.21, 6154.14, 208.287, 'Warsong Wind Rider'),
+(125578, 8, 2797.93, 6153.58, 208.192, 'Warsong Wind Rider'),
+(125578, 9, 2785.39, 6137.84, 208.123, 'Warsong Wind Rider'),
+(125578, 10, 2775.29, 6128.2, 208.123, 'Warsong Wind Rider'),
+(125578, 11, 2765.01, 6118.83, 216.447, 'Warsong Wind Rider'),
+(125578, 12, 2746.45, 6098.37, 238.299, 'Warsong Wind Rider'),
+(125578, 13, 2724.52, 6069.8, 238.299, 'Warsong Wind Rider'),
+(125578, 14, 2707, 6047.38, 238.299, 'Warsong Wind Rider'),
+(125578, 15, 2680.77, 6017.05, 238.299, 'Warsong Wind Rider'),
+(125578, 16, 2643.17, 5992.25, 216.577, 'Warsong Wind Rider'),
+(125578, 17, 2617.43, 5969.46, 190.605, 'Warsong Wind Rider'),
+(125578, 18, 2594.97, 5950.58, 168.994, 'Warsong Wind Rider'),
+(125578, 19, 2577.94, 5924.14, 149.911, 'Warsong Wind Rider'),
+(125578, 20, 2550.24, 5897.53, 149.911, 'Warsong Wind Rider'),
+(125578, 21, 2562.29, 5866.69, 149.911, 'Warsong Wind Rider'),
+(125578, 22, 2596.48, 5847.32, 149.911, 'Warsong Wind Rider'),
+(125578, 23, 2626.64, 5851.95, 149.911, 'Warsong Wind Rider'),
+(125578, 24, 2647.13, 5873.16, 149.911, 'Warsong Wind Rider'),
+(125578, 25, 2645.8, 5899.81, 149.911, 'Warsong Wind Rider'),
+(125578, 26, 2640.92, 5934.65, 149.911, 'Warsong Wind Rider'),
+(125578, 27, 2627.54, 5981.53, 138.022, 'Warsong Wind Rider'),
+(125578, 28, 2646.58, 6020.77, 125.022, 'Warsong Wind Rider'),
+(125578, 29, 2650.72, 6063.53, 100.244, 'Warsong Wind Rider'),
+(125578, 30, 2658.58, 6107.69, 80.8551, 'Warsong Wind Rider'),
+(125578, 31, 2650.11, 6144.21, 80.8551, 'Warsong Wind Rider'),
+(125578, 32, 2644.45, 6182.45, 80.8551, 'Warsong Wind Rider'),
+(125578, 33, 2657.69, 6217.98, 91.7996, 'Warsong Wind Rider'),
+(125578, 34, 2675, 6225.02, 121.827, 'Warsong Wind Rider'),
+(125578, 35, 2699.94, 6246.2, 121.827, 'Warsong Wind Rider'),
+(125578, 36, 2721.17, 6228.85, 152.188, 'Warsong Wind Rider'),
+(125578, 37, 2731.05, 6205.52, 168.188, 'Warsong Wind Rider'),
+(125578, 38, 2752.55, 6184.18, 181.438, 'Warsong Wind Rider'),
+(125578, 39, 2764.62, 6189.2, 199.411, 'Warsong Wind Rider'),
+(125578, 40, 2779.31, 6168.48, 221.641, 'Warsong Wind Rider'),
+(125578, 41, 2792.78, 6160.51, 219.669, 'Warsong Wind Rider'),
+(125578, 42, 2797.35, 6154.19, 209.197, 'Warsong Wind Rider'),
+(125578, 43, 2790.22, 6145.23, 208.123, 'Warsong Wind Rider'),
+(125578, 44, 2778.24, 6132.59, 208.123, 'Warsong Wind Rider'),
+(125578, 45, 2764.71, 6113.99, 208.27, 'Warsong Wind Rider'),
+(125578, 46, 2772.627197, 6102.89990, 209.02432, 'Warsong Wind Rider');
diff --git a/sql/updates/world/master/2020_04_10_07_world_2017_01_16_01_world.sql b/sql/updates/world/master/2020_04_10_07_world_2017_01_16_01_world.sql
new file mode 100644
index 00000000000..4f5d31b9e73
--- /dev/null
+++ b/sql/updates/world/master/2020_04_10_07_world_2017_01_16_01_world.sql
@@ -0,0 +1,41 @@
+-- Karen I Don't Caribou the Culler SAI
+SET @ENTRY := 25803;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,0,0,100,0,8000,10000,10000,15000,11,42724,0,0,0,0,0,2,0,0,0,0,0,0,0,"Karen I Don't Caribou the Culler - In Combat - Cast 'Cleave'"),
+(@ENTRY,0,1,0,0,0,100,0,4000,4000,15000,21000,11,48280,0,0,0,0,0,1,0,0,0,0,0,0,0,"Karen I Don't Caribou the Culler - In Combat - Cast 'Whirlwind'"),
+(@ENTRY,0,2,0,9,0,100,0,8,25,10000,10000,11,27577,0,0,0,0,0,2,0,0,0,0,0,0,0,"Karen I Don't Caribou the Culler - Within 8-25 Range - Cast 'Intercept'"),
+(@ENTRY,0,3,0,25,0,100,0,0,0,0,0,53,0,25803,1,0,0,2,1,0,0,0,0,0,0,0,"Karen I Don't Caribou the Culler - On Reset - Start Waypoint"),
+(@ENTRY,0,4,5,40,0,100,0,15,25803,0,0,54,26000,0,0,0,0,0,0,0,0,0,0,0,0,0,"Karen I Don't Caribou the Culler - On Waypoint 15 Reached - Pause Waypoint"),
+(@ENTRY,0,5,6,61,0,100,0,15,25803,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,0.698295,"Karen I Don't Caribou the Culler - On Waypoint 15 Reached - Set Orientation 0.698295"),
+(@ENTRY,0,6,0,61,0,100,0,15,25803,0,0,11,46147,0,0,0,0,0,1,0,0,0,0,0,0,0,"Karen I Don't Caribou the Culler - On Waypoint 15 Reached - Cast 'Karen Eats'");
+
+DELETE FROM `waypoints` WHERE `entry`=25803;
+INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `point_comment`) VALUES
+(25803, 1, 2732.85, 5267, 70.526, 'Karen I Don''t Caribou the Cullerr'),
+(25803, 2, 2726.15, 5264.63, 71.5126, 'Karen I Don''t Caribou the Cullerr'),
+(25803, 3, 2721.45, 5267.05, 71.632, 'Karen I Don''t Caribou the Cullerr'),
+(25803, 4, 2721.44, 5276.07, 70.8437, 'Karen I Don''t Caribou the Cullerr'),
+(25803, 5, 2729.39, 5276.17, 71.4764, 'Karen I Don''t Caribou the Cullerr'),
+(25803, 6, 2732.85, 5267, 70.526, 'Karen I Don''t Caribou the Cullerr'),
+(25803, 7, 2726.15, 5264.63, 71.5126, 'Karen I Don''t Caribou the Cullerr'),
+(25803, 8, 2721.45, 5267.05, 71.632, 'Karen I Don''t Caribou the Cullerr'),
+(25803, 9, 2721.44, 5276.07, 70.8437, 'Karen I Don''t Caribou the Cullerr'),
+(25803, 10, 2729.39, 5276.17, 71.4764, 'Karen I Don''t Caribou the Cullerr'),
+(25803, 11, 2732.85, 5267, 70.526, 'Karen I Don''t Caribou the Cullerr'),
+(25803, 12, 2726.15, 5264.63, 71.5126, 'Karen I Don''t Caribou the Cullerr'),
+(25803, 13, 2721.45, 5267.05, 71.632, 'Karen I Don''t Caribou the Cullerr'),
+(25803, 14, 2721.44, 5276.07, 70.8437, 'Karen I Don''t Caribou the Cullerr'),
+(25803, 15, 2728.34, 5281.66, 71.0141, 'Karen I Don''t Caribou the Cullerr'),
+(25803, 16, 2729.39, 5276.17, 71.4764, 'Karen I Don''t Caribou the Cullerr'),
+(25803, 17, 2732.85, 5267, 70.526, 'Karen I Don''t Caribou the Cullerr'),
+(25803, 18, 2726.15, 5264.63, 71.5126, 'Karen I Don''t Caribou the Cullerr'),
+(25803, 19, 2721.45, 5267.05, 71.632, 'Karen I Don''t Caribou the Cullerr'),
+(25803, 20, 2721.44, 5276.07, 70.8437, 'Karen I Don''t Caribou the Cullerr'),
+(25803, 21, 2729.39, 5276.17, 71.4764, 'Karen I Don''t Caribou the Cullerr'),
+(25803, 22, 2732.85, 5267, 70.526, 'Karen I Don''t Caribou the Cullerr'),
+(25803, 23, 2726.15, 5264.63, 71.5126, 'Karen I Don''t Caribou the Cullerr'),
+(25803, 24, 2721.45, 5267.05, 71.632, 'Karen I Don''t Caribou the Cullerr'),
+(25803, 25, 2721.44, 5276.07, 70.8437, 'Karen I Don''t Caribou the Cullerr'),
+(25803, 26, 2729.39, 5276.17, 71.4764, 'Karen I Don''t Caribou the Cullerr');
diff --git a/sql/updates/world/master/2020_04_10_08_world_2017_01_16_02_world.sql b/sql/updates/world/master/2020_04_10_08_world_2017_01_16_02_world.sql
new file mode 100644
index 00000000000..3287e8a0f5e
--- /dev/null
+++ b/sql/updates/world/master/2020_04_10_08_world_2017_01_16_02_world.sql
@@ -0,0 +1,42 @@
+-- Fruits of Our Labor - http://wotlk.openwow.com/quest=11904
+-- Cart Release SAI
+SET @ENTRY := 188104;
+UPDATE `gameobject_template` SET `AIName`="SmartGameObjectAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=1;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,1,0,0,70,0,100,0,2,0,0,0,45,1,1,0,0,0,0,19,25986,20,0,0,0,0,0,"Cart Release - On Gameobject State Changed - Set Data 1 1");
+
+DELETE FROM `creature_text` WHERE `CreatureID`=25986;
+INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `comment`) VALUES
+(25986, 0, 0, 'The Ore Cart squeaks against the rails as it is released.', 16, 0, 100, 0, 0, 0, 25416, 'Ore Cart');
+
+UPDATE `creature` SET `spawntimesecs`=1 WHERE `guid`=132773;
+
+-- Ore Cart SAI
+SET @ENTRY := 25986;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,1,38,0,100,1,1,1,0,0,48,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Ore Cart - On Data Set 1 1 - Set Active On (No Repeat)"),
+(@ENTRY,0,1,3,61,0,100,0,1,1,0,0,53,0,25986,0,0,0,0,1,0,0,0,0,0,0,0,"Ore Cart - On Data Set 1 1 - Start Waypoint (No Repeat)"),
+(@ENTRY,0,2,4,40,0,100,0,15,25986,0,0,41,100,0,0,0,0,0,1,0,0,0,0,0,0,0,"Ore Cart - On Waypoint 15 Reached - Despawn In 100 ms"),
+(@ENTRY,0,3,0,61,0,100,0,1,1,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Ore Cart - On Data Set 1 1 - Say Line 0 (No Repeat)"),
+(@ENTRY,0,4,0,61,0,100,0,15,25986,0,0,48,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Ore Cart - On Waypoint 15 Reached - Set Active Off");
+
+DELETE FROM `waypoints` WHERE `entry`=25986;
+INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `point_comment`) VALUES
+(25986,1,2797.49,5277.37,22.0435, 'Ore Cart'),
+(25986,2,2794.32,5281.92,22.4205, 'Ore Cart'),
+(25986,3,2790.66,5285.51,21.9443, 'Ore Cart'),
+(25986,4,2783.22,5291.11,22.7502, 'Ore Cart'),
+(25986,5,2776.37,5297,24.6788, 'Ore Cart'),
+(25986,6,2772.41,5299.31,25.5129, 'Ore Cart'),
+(25986,7,2767.82,5300.13,26.1103, 'Ore Cart'),
+(25986,8,2764.16,5299.4,26.2145, 'Ore Cart'),
+(25986,9,2760.57,5297.91,26.187, 'Ore Cart'),
+(25986,10,2757.37,5295.31,25.8549, 'Ore Cart'),
+(25986,11,2755.49,5291.84,25.142, 'Ore Cart'),
+(25986,12,2752.95,5288.89,24.7977, 'Ore Cart'),
+(25986,13,2748.91,5286.94,24.7359, 'Ore Cart'),
+(25986,14,2746.13,5285.9,24.8515, 'Ore Cart'),
+(25986,15,2733.06,5284.92,27.2962, 'Ore Cart');
diff --git a/sql/updates/world/master/2020_04_10_09_world_2017_01_16_03_world.sql b/sql/updates/world/master/2020_04_10_09_world_2017_01_16_03_world.sql
new file mode 100644
index 00000000000..459a6a5fe6f
--- /dev/null
+++ b/sql/updates/world/master/2020_04_10_09_world_2017_01_16_03_world.sql
@@ -0,0 +1,28 @@
+-- Librarian Hamilton -- http://www.wowhead.com/npc=27141/librarian-hamilton
+-- Librarian Hamilton SAI
+SET @ENTRY := 27141;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,25,0,100,0,0,0,0,0,53,0,27141,1,0,0,1,1,0,0,0,0,0,0,0,"Librarian Hamilton - On Reset - Start Waypoint"),
+(@ENTRY,0,1,0,64,0,100,0,0,0,0,0,54,180000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Librarian Hamilton - On Gossip Hello - Pause Waypoint"),
+(@ENTRY,0,2,0,40,0,100,0,1,27141,0,0,54,60000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Librarian Hamilton - On Waypoint 1 Reached - Pause Waypoint"),
+(@ENTRY,0,3,0,40,0,100,0,2,27141,0,0,80,@ENTRY*100+00,0,0,0,0,0,1,0,0,0,0,0,0,0,"Librarian Hamilton - On Waypoint 2 Reached - Run Script"),
+(@ENTRY,0,4,0,40,0,100,0,3,27141,0,0,54,60000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Librarian Hamilton - On Waypoint 3 Reached - Pause Waypoint"),
+(@ENTRY,0,5,6,40,0,100,0,4,27141,0,0,80,@ENTRY*100+00,0,0,0,0,0,1,0,0,0,0,0,0,0,"Librarian Hamilton - On Waypoint 4 Reached - Run Script"),
+(@ENTRY,0,6,0,61,0,100,0,4,27141,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,3.15815,"Librarian Hamilton - On Waypoint 4 Reached - Set Orientation 3,15815");
+
+-- Actionlist SAI
+SET @ENTRY := 2714100;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,0,0,0,0,54,17000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Librarian Hamilton - On Script - Pause Waypoint"),
+(@ENTRY,9,1,0,0,0,100,0,3000,3000,0,0,90,8,0,0,0,0,0,1,0,0,0,0,0,0,0,"Librarian Hamilton - On Script - Set Flag Standstate Kneel"),
+(@ENTRY,9,2,0,0,0,100,0,11000,11000,0,0,91,8,0,0,0,0,0,1,0,0,0,0,0,0,0,"Librarian Hamilton - On Script - Remove Flag Standstate Kneel");
+
+DELETE FROM `waypoints` WHERE `entry`=27141;
+INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `point_comment`) VALUES
+(27141, 1, 3595.1, 5959.01, 136.328, 'Librarian Hamilton'),
+(27141, 2, 3590.25, 5953.57, 136.203, 'Librarian Hamilton'),
+(27141, 3, 3595.1, 5959.01, 136.328, 'Librarian Hamilton'),
+(27141, 4, 3593.01, 5963.17, 136.328, 'Librarian Hamilton');
diff --git a/sql/updates/world/master/2020_04_10_10_world_2017_01_16_04_world.sql b/sql/updates/world/master/2020_04_10_10_world_2017_01_16_04_world.sql
new file mode 100644
index 00000000000..3b30a8c1743
--- /dev/null
+++ b/sql/updates/world/master/2020_04_10_10_world_2017_01_16_04_world.sql
@@ -0,0 +1,98 @@
+-- Initiate Vernon SAI
+SET @ENTRY := 27300;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,1,38,0,100,0,1,1,0,0,103,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Initiate Vernon - On Data Set 1 1 - Set Rooted On"),
+(@ENTRY,0,1,0,61,0,100,0,1,1,0,0,17,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Initiate Vernon - On Data Set 1 1 - Set Emote State 0"),
+(@ENTRY,0,2,0,38,0,100,0,2,2,0,0,66,0,0,0,0,0,0,10,111281,27299,0,0,0,0,0,"Initiate Vernon - On Data Set 2 2 - Set Orientation Closest Creature 'Initiate Greer'"),
+(@ENTRY,0,3,0,38,0,100,0,3,3,0,0,11,48254,0,0,0,0,0,1,0,0,0,0,0,0,0,"Initiate Vernon - On Data Set 3 3 - Cast 'Prototype Neural Needle Impact'"),
+(@ENTRY,0,4,0,38,0,100,0,4,4,0,0,103,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Initiate Vernon - On Data Set 4 4 - Set Rooted Off");
+
+SET @MAXGUID := 915;
+SET @SCRIPTID := 11130700;
+DELETE FROM `waypoint_scripts` WHERE `id` IN (@SCRIPTID+0);
+INSERT INTO `waypoint_scripts` (`id`, `delay`, `command`, `datalong`, `datalong2`, `dataint`, `x`, `y`, `z`, `o`, `guid`) VALUES
+(@SCRIPTID+0, 2, 1, 69, 1, 0, 0, 0, 0, 0, (@MAXGUID := @MAXGUID + 1)),
+(@SCRIPTID+0, 17, 1, 0, 1, 0, 0, 0, 0, 0, (@MAXGUID := @MAXGUID + 1));
+
+SET @NPC := 111307;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `spawndist`=0,`MovementType`=2 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`, `delay`, `action`, `orientation`) VALUES
+(@PATH, 1, 3647.87, 5909.61, 174.578, 21000, @SCRIPTID, 1.26067),
+(@PATH, 2, 3640.9, 5911.28, 174.579, 21000, @SCRIPTID, 1.26067);
+
+UPDATE `waypoint_data` SET `action_chance`=100 WHERE `action` IN (@SCRIPTID);
+
+-- Initiate Greer SAI
+SET @ENTRY := 27299;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,25,0,100,0,0,0,0,0,53,0,27299,1,0,0,1,1,0,0,0,0,0,0,0,"Initiate Greer - On Reset - Start Waypoint"),
+(@ENTRY,0,1,0,64,0,100,0,0,0,0,0,54,180000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Initiate Greer - On Gossip Hello - Pause Waypoint"),
+(@ENTRY,0,2,3,40,0,100,0,5,27299,0,0,80,@ENTRY*100+00,0,0,0,0,0,1,0,0,0,0,0,0,0,"Initiate Greer - On Waypoint 5 Reached - Run Script"),
+(@ENTRY,0,3,0,61,0,100,0,5,27299,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,2.76692,"Initiate Greer - On Waypoint 5 Reached - Set Orientation 2,76692"),
+(@ENTRY,0,4,5,40,0,100,0,11,27299,0,0,80,@ENTRY*100+01,0,0,0,0,0,1,0,0,0,0,0,0,0,"Initiate Greer - On Waypoint 11 Reached - Run Script"),
+(@ENTRY,0,5,0,61,0,100,0,11,27299,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,5.84897,"Initiate Greer - On Waypoint 11 Reached - Set Orientation 5,84897");
+
+-- Actionlist SAI
+SET @ENTRY := 2729900;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,0,0,0,0,54,55000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Initiate Greer - On Script - Pause Waypoint"),
+(@ENTRY,9,1,0,0,0,100,0,0,0,0,0,48,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Initiate Greer - On Script - Set Active On"),
+(@ENTRY,9,2,0,0,0,100,0,3000,3000,0,0,17,133,0,0,0,0,0,1,0,0,0,0,0,0,0,"Initiate Greer - On Script - Set Emote State 133"),
+(@ENTRY,9,3,0,0,0,100,0,10000,10000,0,0,17,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Initiate Greer - On Script - Set Emote State 0"),
+(@ENTRY,9,4,0,0,0,100,0,3000,3000,0,0,1,0,6000,0,0,0,0,1,0,0,0,0,0,0,0,"Initiate Greer - On Script - Say Line 0"),
+(@ENTRY,9,5,0,0,0,100,0,5000,5000,0,0,45,3,3,0,0,0,0,10,111307,27300,0,0,0,0,0,"Initiate Greer - On Script - Set Data 3 3"),
+(@ENTRY,9,6,0,0,0,100,0,1000,1000,0,0,45,1,1,0,0,0,0,10,111307,27300,0,0,0,0,0,"Initiate Greer - On Script - Set Data 1 1"),
+(@ENTRY,9,7,0,0,0,100,0,6000,6000,0,0,1,1,6000,0,0,0,0,1,0,0,0,0,0,0,0,"Initiate Greer - On Script - Say Line 1"),
+(@ENTRY,9,8,0,0,0,100,0,4000,4000,0,0,45,2,2,0,0,0,0,10,111307,27300,0,0,0,0,0,"Initiate Greer - On Script - Set Data 2 2"),
+(@ENTRY,9,9,0,0,0,100,0,2000,2000,0,0,1,0,6000,0,0,0,0,10,111307,27300,0,0,0,0,0,"Initiate Greer - On Script - Say Line 0"),
+(@ENTRY,9,10,0,0,0,100,0,14000,14000,0,0,1,2,6000,0,0,0,0,1,0,0,0,0,0,0,0,"Initiate Greer - On Script - Say Line 2"),
+(@ENTRY,9,11,0,0,0,100,0,0,0,0,0,45,4,4,0,0,0,0,10,111307,27300,0,0,0,0,0,"Initiate Greer - On Script - Set Data 4 4"),
+(@ENTRY,9,12,0,0,0,100,0,2000,2000,0,0,48,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Initiate Greer - On Script - Set Active Off");
+
+-- Actionlist SAI
+SET @ENTRY := 2729901;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,0,0,0,0,54,70000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Initiate Greer - On Script - Pause Waypoint"),
+(@ENTRY,9,1,0,0,0,100,0,0,0,0,0,48,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Initiate Greer - On Script - Set Active On"),
+(@ENTRY,9,2,0,0,0,100,0,3000,3000,0,0,17,133,0,0,0,0,0,1,0,0,0,0,0,0,0,"Initiate Greer - On Script - Set Emote State 133"),
+(@ENTRY,9,3,0,0,0,100,0,64000,64000,0,0,17,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Initiate Greer - On Script - Set Emote State 0"),
+(@ENTRY,9,4,0,0,0,100,0,0,0,0,0,48,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Initiate Greer - On Script - Set Active Off");
+
+DELETE FROM `creature_text` WHERE `CreatureID` IN (27299, 27300);
+INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `comment`) VALUES
+(27299, 0, 0, 'Tell me if this hurts.', 12, 0, 100, 0, 0, 0, 26296, 'Initiate Greer'),
+(27299, 0, 1, 'Let''s try this one out...', 12, 0, 100, 0, 0, 0, 26298, 'Initiate Greer'),
+(27299, 0, 2, 'I think I''ve got it this time..', 12, 0, 100, 0, 0, 0, 26297, 'Initiate Greer'),
+(27299, 1, 0, 'How''d that feel?', 12, 0, 100, 0, 0, 0, 26299, 'Initiate Greer'),
+(27299, 1, 1, 'Was that potent enough?', 12, 0, 100, 0, 0, 0, 26302, 'Initiate Greer'),
+(27299, 1, 2, 'Do you think that will get some answers?', 12, 0, 100, 0, 0, 0, 26300, 'Initiate Greer'),
+(27299, 2, 0, 'Hmm...', 12, 0, 100, 0, 0, 0, 26304, 'Initiate Greer'),
+(27299, 2, 1, 'True, our enemies would show us no mercy.', 12, 0, 100, 0, 0, 0, 26320, 'Initiate Greer'),
+(27299, 2, 2, 'True, but how far should we push? At what point are we no better than our enemies?', 12, 0, 100, 0, 0, 0, 26319, 'Initiate Greer'),
+(27300, 0, 0, 'You need more bite. Do not show our enemies any mercy.', 12, 0, 100, 0, 0, 0, 26305, 'Initiate Vernon'),
+(27300, 0, 1, 'The more pain we can inflict, the quicker we can get our answers.', 12, 0, 100, 0, 0, 0, 26306, 'Initiate Vernon');
+
+UPDATE `creature` SET `spawndist`=0, `MovementType`=0 WHERE `guid`=111281;
+DELETE FROM `waypoints` WHERE `entry`=27299;
+INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `point_comment`) VALUES
+(27299, 1, 3640.38, 5908, 174.576, 'Initiate Greer'),
+(27299, 2, 3642.54, 5905.63, 174.572, 'Initiate Greer'),
+(27299, 3, 3645.93, 5904.91, 174.571, 'Initiate Greer'),
+(27299, 4, 3647.52, 5906.78, 174.576, 'Initiate Greer'),
+(27299, 5, 3646.7, 5907.29, 174.578, 'Initiate Greer'),
+(27299, 6, 3647.49, 5906.69, 174.578, 'Initiate Greer'),
+(27299, 7, 3646.49, 5905.07, 174.576, 'Initiate Greer'),
+(27299, 8, 3643.7, 5905.04, 174.568, 'Initiate Greer'),
+(27299, 9, 3641.21, 5906.38, 174.577, 'Initiate Greer'),
+(27299, 10, 3640.11, 5908.16, 174.577, 'Initiate Greer'),
+(27299, 11, 3641.55, 5908.3, 174.577, 'Initiate Greer');
diff --git a/sql/updates/world/master/2020_04_10_11_world_2017_01_16_05_world.sql b/sql/updates/world/master/2020_04_10_11_world_2017_01_16_05_world.sql
new file mode 100644
index 00000000000..b4351d0c775
--- /dev/null
+++ b/sql/updates/world/master/2020_04_10_11_world_2017_01_16_05_world.sql
@@ -0,0 +1,35 @@
+-- Apprentice Trotter -- http://www.wowhead.com/npc=27301
+-- Apprentice Trotter SAI
+SET @ENTRY := 27301;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,25,0,100,0,0,0,0,0,53,0,27301,1,0,0,1,1,0,0,0,0,0,0,0,"Apprentice Trotter - On Reset - Start Waypoint"),
+(@ENTRY,0,1,0,64,0,100,0,0,0,0,0,54,180000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Apprentice Trotter - On Gossip Hello - Pause Waypoint"),
+(@ENTRY,0,2,3,40,0,100,0,3,27301,0,0,80,@ENTRY*100+00,0,0,0,0,0,1,0,0,0,0,0,0,0,"Apprentice Trotter - On Waypoint 3 Reached - Run Script"),
+(@ENTRY,0,3,0,61,0,100,0,3,27301,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,5.20907,"Apprentice Trotter - On Waypoint 3 Reached - Set Orientation 5,20907"),
+(@ENTRY,0,4,5,40,0,100,0,5,27301,0,0,80,@ENTRY*100+00,0,0,0,0,0,1,0,0,0,0,0,0,0,"Apprentice Trotter - On Waypoint 5 Reached - Run Script"),
+(@ENTRY,0,5,0,61,0,100,0,5,27301,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,6.1162,"Apprentice Trotter - On Waypoint 5 Reached - Set Orientation 6,1162"),
+(@ENTRY,0,6,7,40,0,100,0,8,27301,0,0,80,@ENTRY*100+00,0,0,0,0,0,1,0,0,0,0,0,0,0,"Apprentice Trotter - On Waypoint 8 Reached - Run Script"),
+(@ENTRY,0,7,0,61,0,100,0,8,27301,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,6.10835,"Apprentice Trotter - On Waypoint 8 Reached - Set Orientation 6,10835");
+
+-- Actionlist SAI
+SET @ENTRY := 2730100;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,0,0,0,0,54,16000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Apprentice Trotter - On Script - Pause Waypoint"),
+(@ENTRY,9,1,0,0,0,100,0,3000,3000,0,0,17,133,0,0,0,0,0,1,0,0,0,0,0,0,0,"Apprentice Trotter - On Script - Set Emote State 133"),
+(@ENTRY,9,2,0,0,0,100,0,8000,8000,0,0,17,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Apprentice Trotter - On Script - Set Emote State 0");
+
+UPDATE `creature` SET `spawndist`=0, `MovementType`=0 WHERE `guid`=111400;
+DELETE FROM `waypoints` WHERE `entry`=27301;
+INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `point_comment`) VALUES
+(27301, 1, 3655.39, 5880.89, 174.576, 'Apprentice Trotter'),
+(27301, 2, 3648.21, 5875.72, 174.554, 'Apprentice Trotter'),
+(27301, 3, 3649.17, 5874.43, 174.578, 'Apprentice Trotter'),
+(27301, 4, 3656.08, 5881.3, 174.577, 'Apprentice Trotter'),
+(27301, 5, 3659.29, 5880.93, 174.577, 'Apprentice Trotter'),
+(27301, 6, 3658.57, 5882.95, 174.577, 'Apprentice Trotter'),
+(27301, 7, 3659.6, 5887.87, 174.577, 'Apprentice Trotter'),
+(27301, 8, 3661.47, 5888.53, 174.577, 'Apprentice Trotter'),
+(27301, 9, 3659.61, 5887.48, 174.576, 'Apprentice Trotter');
diff --git a/sql/updates/world/master/2020_04_10_12_world_2017_01_16_06_world.sql b/sql/updates/world/master/2020_04_10_12_world_2017_01_16_06_world.sql
new file mode 100644
index 00000000000..c781ef0e9d3
--- /dev/null
+++ b/sql/updates/world/master/2020_04_10_12_world_2017_01_16_06_world.sql
@@ -0,0 +1,60 @@
+-- Warden Nork Bloodfrenzy SAI
+SET @ENTRY := 25379;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0 AND `id`=4;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,0,4,0,1,0,100,0,10000,10000,470000,470000,80,@ENTRY*100+00,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warden Nork Bloodfrenzy - Out of Combat - Run Script");
+
+-- Actionlist SAI
+SET @ENTRY := 2537900;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,0,0,0,0,48,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warden Nork Bloodfrenzy - On Script - Set Active On"),
+(@ENTRY,9,1,0,0,0,100,0,2000,2000,0,0,1,1,3000,0,0,0,0,1,0,0,0,0,0,0,0,"Warden Nork Bloodfrenzy - On Script - Say Line 1"),
+(@ENTRY,9,2,0,0,0,100,0,3000,3000,0,0,1,0,10000,0,0,0,0,10,125421,25426,0,0,0,0,0,"Warden Nork Bloodfrenzy - On Script - Say Line 0"),
+(@ENTRY,9,3,0,0,0,100,0,8000,8000,0,0,5,11,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warden Nork Bloodfrenzy - On Script - Play Emote 11"),
+(@ENTRY,9,4,0,0,0,100,0,2000,2000,0,0,1,2,1000,0,0,0,0,1,0,0,0,0,0,0,0,"Warden Nork Bloodfrenzy - On Script - Say Line 2"),
+(@ENTRY,9,5,0,0,0,100,0,1000,1000,0,0,1,3,5000,0,0,0,0,1,0,0,0,0,0,0,0,"Warden Nork Bloodfrenzy - On Script - Say Line 3"),
+(@ENTRY,9,6,0,0,0,100,0,5000,5000,0,0,1,1,6000,0,0,0,0,10,125421,25426,0,0,0,0,0,"Warden Nork Bloodfrenzy - On Script - Say Line 1"),
+(@ENTRY,9,7,0,0,0,100,0,6000,6000,0,0,1,4,3000,0,0,0,0,1,0,0,0,0,0,0,0,"Warden Nork Bloodfrenzy - On Script - Say Line 4"),
+(@ENTRY,9,8,0,0,0,100,0,3000,3000,0,0,1,5,10000,0,0,0,0,1,0,0,0,0,0,0,0,"Warden Nork Bloodfrenzy - On Script - Say Line 5"),
+(@ENTRY,9,9,0,0,0,100,0,5000,5000,0,0,5,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warden Nork Bloodfrenzy - On Script - Play Emote 1"),
+(@ENTRY,9,10,0,0,0,100,0,5000,5000,0,0,1,2,8000,0,0,0,0,10,125421,25426,0,0,0,0,0,"Warden Nork Bloodfrenzy - On Script - Say Line 2"),
+(@ENTRY,9,11,0,0,0,100,0,8000,8000,0,0,1,6,9000,0,0,0,0,1,0,0,0,0,0,0,0,"Warden Nork Bloodfrenzy - On Script - Say Line 6"),
+(@ENTRY,9,12,0,0,0,100,0,5000,5000,0,0,5,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warden Nork Bloodfrenzy - On Script - Play Emote 1"),
+(@ENTRY,9,13,0,0,0,100,0,4000,4000,0,0,1,7,5000,0,0,0,0,1,0,0,0,0,0,0,0,"Warden Nork Bloodfrenzy - On Script - Say Line 7"),
+(@ENTRY,9,14,0,0,0,100,0,5000,5000,0,0,1,8,7000,0,0,0,0,1,0,0,0,0,0,0,0,"Warden Nork Bloodfrenzy - On Script - Say Line 8"),
+(@ENTRY,9,15,0,0,0,100,0,7000,7000,0,0,1,3,3000,0,0,0,0,10,125421,25426,0,0,0,0,0,"Warden Nork Bloodfrenzy - On Script - Say Line 3"),
+(@ENTRY,9,16,0,0,0,100,0,3000,3000,0,0,1,4,5000,0,0,0,0,10,125421,25426,0,0,0,0,0,"Warden Nork Bloodfrenzy - On Script - Say Line 4"),
+(@ENTRY,9,17,0,0,0,100,0,5000,5000,0,0,1,5,3000,0,0,0,0,10,125421,25426,0,0,0,0,0,"Warden Nork Bloodfrenzy - On Script - Say Line 5"),
+(@ENTRY,9,18,0,0,0,100,0,3000,3000,0,0,1,6,5000,0,0,0,0,10,125421,25426,0,0,0,0,0,"Warden Nork Bloodfrenzy - On Script - Say Line 6"),
+(@ENTRY,9,19,0,0,0,100,0,5000,5000,0,0,1,9,2000,0,0,0,0,1,0,0,0,0,0,0,0,"Warden Nork Bloodfrenzy - On Script - Say Line 9"),
+(@ENTRY,9,20,0,0,0,100,0,2000,2000,0,0,1,10,7000,0,0,0,0,1,0,0,0,0,0,0,0,"Warden Nork Bloodfrenzy - On Script - Say Line 10"),
+(@ENTRY,9,21,0,0,0,100,0,4000,4000,0,0,5,15,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warden Nork Bloodfrenzy - On Script - Play Emote 15"),
+(@ENTRY,9,22,0,0,0,100,0,3000,3000,0,0,1,11,6000,0,0,0,0,1,0,0,0,0,0,0,0,"Warden Nork Bloodfrenzy - On Script - Say Line 11"),
+(@ENTRY,9,23,0,0,0,100,0,3000,3000,0,0,5,5,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warden Nork Bloodfrenzy - On Script - Play Emote 5"),
+(@ENTRY,9,24,0,0,0,100,0,2000,2000,0,0,48,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Warden Nork Bloodfrenzy - On Script - Set Active Off");
+
+DELETE FROM `creature_text` WHERE `CreatureID`=25379 AND `GroupID` >=1;
+DELETE FROM `creature_text` WHERE `CreatureID`=25426;
+INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `comment`) VALUES
+-- Warden Nork Bloodfrenzy
+(25379, 1, 0, 'Look at \'em, Ug. You know what those are?', 12, 1, 100, 25, 0, 0, 24631, 'Warden Nork Bloodfrenzy'),
+(25379, 2, 0, 'Those...', 12, 1, 100, 25, 0, 0, 24633, 'Warden Nork Bloodfrenzy'),
+(25379, 3, 0, 'Those are cowards.', 12, 1, 100, 1, 0, 0, 24634, 'Warden Nork Bloodfrenzy'),
+(25379, 4, 0, '%s shakes his head.', 16, 1, 100, 274, 0, 0, 24636, 'Warden Nork Bloodfrenzy'),
+(25379, 5, 0, 'No, blood of my blood, they are soldiers of the Alliance. Our sworn enemies.', 12, 1, 100, 1, 0, 0, 24637, 'Warden Nork Bloodfrenzy'),
+(25379, 6, 0, 'They are here because they do not wish to defend their homes... their families...', 12, 1, 100, 1, 0, 0, 24639, 'Warden Nork Bloodfrenzy'),
+(25379, 7, 0, 'They have given up and surrendered - willingly - to us.', 12, 1, 100, 1, 0, 0, 24640, 'Warden Nork Bloodfrenzy'),
+(25379, 8, 0, 'Ug\'thor, they are afraid to die.', 12, 1, 100, 1, 0, 0, 24641, 'Warden Nork Bloodfrenzy'),
+(25379, 9, 0, '%s laughs.', 16, 1, 100, 11, 0, 0, 24646, 'Warden Nork Bloodfrenzy'),
+(25379, 10, 0, 'That\'s right, Ug. Victory or death!', 12, 1, 100, 273, 0, 0, 24647, 'Warden Nork Bloodfrenzy'),
+(25379, 11, 0, '[In Broken Common] Hear boy, cowards? Boy die! Boy die for freedom!', 12, 0, 100, 273, 0, 0, 24648, 'Warden Nork Bloodfrenzy'),
+-- Ug''thor Bloodfrenzy
+(25426, 0, 0, 'No, popo. They look kind of like the pigs. Are they pigs?', 12, 1, 100, 1, 0, 0, 24632, 'Ug''thor Bloodfrenzy'),
+(25426, 1, 0, 'Are they cowardly pigs, popo?', 12, 1, 100, 1, 0, 0, 24635, 'Ug''thor Bloodfrenzy'),
+(25426, 2, 0, 'But popo, what are they afraid of? Why are they here?', 12, 1, 100, 1, 0, 0, 24638, 'Ug''thor Bloodfrenzy'),
+(25426, 3, 0, '%s scratches his head.', 16, 1, 100, 0, 0, 0, 24642, 'Ug''thor Bloodfrenzy'),
+(25426, 4, 0, 'I... I don\'t understand, popo.', 12, 1, 100, 1, 0, 0, 24643, 'Ug''thor Bloodfrenzy'),
+(25426, 5, 0, '%s puffs out his chest and stands on his tip-toes.', 16, 1, 100, 0, 0, 0, 24644, 'Ug''thor Bloodfrenzy'),
+(25426, 6, 0, 'Lok\'tar ogar, popo!', 12, 1, 100, 1, 0, 0, 24645, 'Ug''thor Bloodfrenzy');
diff --git a/sql/updates/world/master/2020_04_10_13_world_2017_01_17_00_world.sql b/sql/updates/world/master/2020_04_10_13_world_2017_01_17_00_world.sql
new file mode 100644
index 00000000000..f8e9d1b95a6
--- /dev/null
+++ b/sql/updates/world/master/2020_04_10_13_world_2017_01_17_00_world.sql
@@ -0,0 +1,279 @@
+-- Instructor Razuvious - Event with Acherus Necromancer and Death Knight Initiate -- http://wow.gamepedia.com/Death_Knight_Initiate
+-- Instructor Razuvious
+SET @NPC := 129307;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `spawndist`=0,`MovementType`=2 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`, `orientation`, `delay`) VALUES
+(@PATH, 1, 2481.1, -5560.54, 420.493, 5.58015, 0),
+(@PATH, 2, 2491.86, -5571.77, 420.459, 5.3508, 0),
+(@PATH, 3, 2497.91, -5588.32, 420.462, 4.9212, 0),
+(@PATH, 4, 2494.03, -5612.09, 420.491, 1.24868, 0),
+(@PATH, 5, 2498.68, -5591.69, 420.494, 1.78118, 0),
+(@PATH, 6, 2492.94, -5573.05, 420.475, 2.14717, 0),
+(@PATH, 7, 2475.93, -5558.57, 420.485, 2.79199, 0),
+(@PATH, 8, 2455.66, -5554.78, 420.508, 0.040735, 0),
+(@PATH, 9, 2472.56, -5558.04, 420.453, 6.06788, 0),
+(@PATH, 10, 2481.1, -5560.54, 420.493, 5.58015, 0),
+(@PATH, 11, 2491.86, -5571.77, 420.459, 5.3508, 0),
+(@PATH, 12, 2497.91, -5588.32, 420.462, 4.9212, 0),
+(@PATH, 13, 2494.03, -5612.09, 420.491, 1.24868, 0),
+(@PATH, 14, 2498.68, -5591.69, 420.494, 1.78118, 0),
+(@PATH, 15, 2492.94, -5573.05, 420.475, 2.14717, 0),
+(@PATH, 16, 2475.93, -5558.57, 420.485, 2.79199, 0),
+(@PATH, 17, 2455.66, -5554.78, 420.508, 0.040735, 0),
+(@PATH, 18, 2472.56, -5558.04, 420.453, 6.06788, 0),
+(@PATH, 19, 2481.1, -5560.54, 420.493, 5.58, 0),
+(@PATH, 20, 2482.32, -5552.39, 420.641, 1.51, 70000),
+(@PATH, 21, 2491.86, -5571.77, 420.459, 5.351, 0),
+(@PATH, 22, 2497.91, -5588.32, 420.462, 4.9212, 0),
+(@PATH, 23, 2494.03, -5612.09, 420.491, 1.24868, 0),
+(@PATH, 24, 2498.68, -5591.69, 420.494, 1.78118, 0),
+(@PATH, 25, 2492.94, -5573.05, 420.475, 2.14717, 0),
+(@PATH, 26, 2475.93, -5558.57, 420.485, 2.79199, 0),
+(@PATH, 27, 2455.66, -5554.78, 420.508, 0.040735, 0),
+(@PATH, 28, 2472.56, -5558.04, 420.453, 6.06788, 0),
+(@PATH, 29, 2481.1, -5560.54, 420.493, 5.58015, 0),
+(@PATH, 30, 2491.86, -5571.77, 420.459, 5.3508, 0),
+(@PATH, 31, 2497.91, -5588.32, 420.462, 4.9212, 0),
+(@PATH, 32, 2494.03, -5612.09, 420.491, 1.24868, 0),
+(@PATH, 33, 2498.68, -5591.69, 420.494, 1.78118, 0),
+(@PATH, 34, 2492.94, -5573.05, 420.475, 2.14717, 0),
+(@PATH, 35, 2475.93, -5558.57, 420.485, 2.79199, 0),
+(@PATH, 36, 2455.66, -5554.78, 420.508, 0.040735, 0),
+(@PATH, 37, 2472.56, -5558.04, 420.453, 6.06788, 0),
+(@PATH, 38, 2481.1, -5560.54, 420.493, 5.58015, 0),
+(@PATH, 39, 2491.86, -5571.77, 420.459, 5.3508, 0),
+(@PATH, 40, 2497.91, -5588.32, 420.462, 4.9212, 0),
+(@PATH, 41, 2494.03, -5612.09, 420.491, 1.24868, 0),
+(@PATH, 42, 2498.68, -5591.69, 420.494, 1.78118, 0),
+(@PATH, 43, 2510.38, -5592.75, 420.643, 6.19, 75000),
+(@PATH, 44, 2492.94, -5573.05, 420.475, 2.147, 0),
+(@PATH, 45, 2475.93, -5558.57, 420.485, 2.79, 0),
+(@PATH, 46, 2455.66, -5554.78, 420.508, 0.040735, 0),
+(@PATH, 47, 2472.56, -5558.04, 420.453, 6.06788, 0);
+
+-- Instructor Razuvious SAI
+SET @ENTRY := 28357;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,34,0,100,0,2,19,0,0,80,@ENTRY*100+00,0,0,0,0,0,1,0,0,0,0,0,0,0,"Instructor Razuvious - On Reached Point 19 - Run Script"),
+(@ENTRY,0,1,0,34,0,100,0,2,42,0,0,80,@ENTRY*100+01,0,0,0,0,0,1,0,0,0,0,0,0,0,"Instructor Razuvious - On Reached Point 42 - Run Script"),
+(@ENTRY,0,2,0,38,0,100,0,1,1,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,2.78367,"Instructor Razuvious - On Data Set 1 1 - Set Orientation 2.78367"),
+(@ENTRY,0,3,0,38,0,100,0,2,2,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,1.50472,"Instructor Razuvious - On Data Set 2 2 - Set Orientation 1.50472"),
+(@ENTRY,0,4,0,38,0,100,0,3,3,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,1.26755,"Instructor Razuvious - On Data Set 3 3 - Set Orientation 1.26755"),
+(@ENTRY,0,5,0,38,0,100,0,4,4,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,6.19669,"Instructor Razuvious - On Data Set 4 4 - Set Orientation 6,19669");
+
+-- Actionlist SAI
+SET @ENTRY := 2835700;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,0,0,0,0,48,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"On Script - Set Active On"),
+(@ENTRY,9,1,0,0,0,100,0,1000,1000,0,0,1,0,5000,0,0,0,0,1,0,0,0,0,0,0,0,"On Script - Say Line 0"),
+(@ENTRY,9,2,0,0,0,100,0,1000,1000,0,0,45,1,1,0,0,0,0,10,129391,28383,0,0,0,0,0,"On Script - Set Data 1 1");
+
+-- Actionlist SAI
+SET @ENTRY := 2835701;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,0,0,0,0,48,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"On Script - Set Active On"),
+(@ENTRY,9,1,0,0,0,100,0,1000,1000,0,0,1,0,5000,0,0,0,0,1,0,0,0,0,0,0,0,"On Script - Say Line 0"),
+(@ENTRY,9,2,0,0,0,100,0,1000,1000,0,0,45,1,1,0,0,0,0,10,129390,28383,0,0,0,0,0,"On Script - Set Data 1 1");
+
+-- Acherus Necromancer SAI
+SET @GUID := -129391;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=28383;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@GUID 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
+(@GUID,0,0,1,38,0,100,0,1,1,0,0,80,12939100,0,0,0,0,0,1,0,0,0,0,0,0,0,"Acherus Necromancer - On Data Set 1 1 - Run Script"),
+(@GUID,0,1,0,61,0,100,0,1,1,0,0,48,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Acherus Necromancer - On Data Set 1 1 - Set Active On");
+
+UPDATE `creature` SET `id`=28391, `spawntimesecs`=1, `modelid`=25361 WHERE `guid` IN (130292);
+UPDATE `creature` SET `position_x`=2477.361328, `position_y`=-5538.785156, `position_z`=420.645264, `orientation`=4.889500 WHERE `guid`=129458;
+DELETE FROM `creature` WHERE `guid`=129452;
+UPDATE `creature` SET `spawntimesecs`=1 WHERE `guid`=129459;
+
+-- Actionlist SAI
+SET @ENTRY := 12939100;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,3000,3000,0,0,11,51516,0,0,0,0,0,1,0,0,0,0,0,0,0,"Acherus Necromancer - On Script - Cast 'Raise Dead'"),
+(@ENTRY,9,1,0,0,0,100,0,4000,4000,0,0,86,51517,0,10,130292,28391,0,1,0,0,0,0,0,0,0,"Acherus Necromancer - On Script - Cross Cast 'Raise Dead'"),
+(@ENTRY,9,2,0,0,0,100,0,1000,1000,0,0,28,29266,0,0,0,0,0,10,130292,28391,0,0,0,0,0,"Acherus Necromancer - On Script - Remove Aura 'Permanent Feign Death'"),
+(@ENTRY,9,3,0,0,0,100,0,0,0,0,0,96,32,0,0,0,0,0,10,130292,28391,0,0,0,0,0,"Acherus Necromancer - On Script - Remove Dynamic Flag Dead"),
+(@ENTRY,9,4,0,0,0,100,0,0,0,0,0,19,537165824,0,0,0,0,0,10,130292,28391,0,0,0,0,0,"Acherus Necromancer - On Script - Remove Flag Stunned"),
+(@ENTRY,9,5,0,0,0,100,0,0,0,0,0,19,1,1,0,0,0,0,10,130292,28391,0,0,0,0,0,"Acherus Necromancer - On Script - Remove Flag Server Controlled"),
+(@ENTRY,9,6,0,0,0,100,0,0,0,0,0,91,7,0,0,0,0,0,10,130292,28391,0,0,0,0,0,"Acherus Necromancer - On Script - Remove Flag Standstate Dead"),
+(@ENTRY,9,7,0,0,0,100,0,0,0,0,0,91,257,0,0,0,0,0,10,130292,28391,0,0,0,0,0,"Acherus Necromancer - On Script - Remove Flag <Unknown bytes1 (UnitStandStateType)>"),
+(@ENTRY,9,8,0,0,0,100,0,2000,2000,0,0,2,1770,0,0,0,0,0,10,130292,28391,0,0,0,0,0,"Acherus Necromancer - On Script - Set Faction 1770"),
+(@ENTRY,9,9,0,0,0,100,0,1000,1000,0,0,45,1,1,0,0,0,0,10,130292,28391,0,0,0,0,0,"Acherus Necromancer - On Script - Set Data 1 1"),
+(@ENTRY,9,10,0,0,0,100,0,0,0,0,0,90,8,0,0,0,0,0,10,130292,28391,0,0,0,0,0,"Acherus Necromancer - On Script - Set Flag Standstate Kneel"),
+(@ENTRY,9,11,0,0,0,100,0,4000,4000,0,0,1,0,5000,0,0,0,0,26,28391,50,0,0,0,0,0,"Acherus Necromancer - On Script - Say Line 0"),
+(@ENTRY,9,12,0,0,0,100,0,5000,5000,0,0,1,1,5000,0,0,0,0,10,129307,28357,0,0,0,0,0,"Acherus Necromancer - On Script - Say Line 1"),
+(@ENTRY,9,13,0,0,0,100,0,5000,5000,0,0,45,1,1,0,0,0,0,10,129307,28357,0,0,0,0,0,"Acherus Necromancer - On Script - Set Data 1 1"),
+(@ENTRY,9,14,0,0,0,100,0,3000,3000,0,0,1,2,5000,0,0,0,0,10,129307,28357,0,0,0,0,0,"Acherus Necromancer - On Script - Say Line 2"),
+(@ENTRY,9,15,0,0,0,100,0,3000,3000,0,0,45,2,2,0,0,0,0,10,129307,28357,0,0,0,0,0,"Acherus Necromancer - On Script - Set Data 2 2"),
+(@ENTRY,9,16,0,0,0,100,0,0,0,0,0,1,0,5000,0,0,0,0,1,0,0,0,0,0,0,0,"Acherus Necromancer - On Script - Say Line 0"),
+(@ENTRY,9,17,0,0,0,100,0,4000,4000,0,0,59,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Acherus Necromancer - On Script - Set Run Off"),
+(@ENTRY,9,18,0,0,0,100,0,0,0,0,0,69,0,0,0,0,0,0,8,0,0,0,2482.23,-5546.44,420.644,0.761266,"Acherus Necromancer - On Script - Move To Position"),
+(@ENTRY,9,19,0,0,0,100,0,4000,4000,0,0,17,133,0,0,0,0,0,1,0,0,0,0,0,0,0,"Acherus Necromancer - On Script - Set Emote State 133"),
+(@ENTRY,9,20,0,0,0,100,0,5000,5000,0,0,17,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Acherus Necromancer - On Script - Set Emote State 0"),
+(@ENTRY,9,21,0,0,0,100,0,0,0,0,0,86,51537,0,10,130292,28391,0,1,0,0,0,0,0,0,0,"Acherus Necromancer - On Script - Cross Cast 'Death Knight Initiate (Female, Dwarf)'"),
+(@ENTRY,9,22,0,0,0,100,0,0,0,0,0,3,0,25406,0,0,0,0,10,130292,28391,0,0,0,0,0,"Acherus Necromancer - On Script - Morph To Model 25406"),
+(@ENTRY,9,23,0,0,0,100,0,2000,2000,0,0,86,51519,0,10,130292,28391,0,1,0,0,0,0,0,0,0,"Acherus Necromancer - On Script - Cross Cast 'Death Knight Initiate Visual'"),
+(@ENTRY,9,24,0,0,0,100,0,2000,2000,0,0,91,8,0,0,0,0,0,10,130292,28391,0,0,0,0,0,"Acherus Necromancer - On Script - Remove Flag Standstate Kneel"),
+(@ENTRY,9,25,0,0,0,100,0,2000,2000,0,0,69,0,0,0,0,0,0,8,0,0,0,2477.37,-5551,420.647,0.77,"Acherus Necromancer - On Script - Move To Position"),
+(@ENTRY,9,26,0,0,0,100,0,4000,4000,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,0.746414,"Acherus Necromancer - On Script - Set Orientation 0.746414"),
+(@ENTRY,9,27,0,0,0,100,0,1000,1000,0,0,1,3,5000,0,0,0,0,10,129307,28357,0,0,0,0,0,"Acherus Necromancer - On Script - Say Line 3"),
+(@ENTRY,9,28,0,0,0,100,0,5000,5000,0,0,1,1,5000,0,0,0,0,10,130292,28391,0,0,0,0,0,"Acherus Necromancer - On Script - Say Line 1"),
+(@ENTRY,9,29,0,0,0,100,0,1000,1000,0,0,48,1,0,0,0,0,0,10,130292,28391,0,0,0,0,0,"Acherus Necromancer - On Script - Set Active On"),
+(@ENTRY,9,30,0,0,0,100,0,0,0,0,0,45,2,2,0,0,0,0,10,130292,28391,0,0,0,0,0,"Acherus Necromancer - On Script - Set Data 2 2"),
+(@ENTRY,9,31,0,0,0,100,0,1000,1000,0,0,48,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Acherus Necromancer - On Script - Set Active Off");
+
+-- Acherus Necromancer SAI
+SET @GUID := -129390;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=28383;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@GUID 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
+(@GUID,0,0,1,38,0,100,0,1,1,0,0,80,12939000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Acherus Necromancer - On Data Set 1 1 - Run Script"),
+(@GUID,0,1,0,61,0,100,0,1,1,0,0,48,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Acherus Necromancer - On Data Set 1 1 - Set Active On");
+
+-- Actionlist SAI
+SET @ENTRY := 12939000;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,3000,3000,0,0,11,51516,0,1,0,0,0,1,0,0,0,0,0,0,0,"Acherus Necromancer - On Script - Cross Cast 'Raise Dead'"),
+(@ENTRY,9,1,0,0,0,100,0,4000,4000,0,0,86,51517,0,10,129459,28394,0,1,0,0,0,0,0,0,0,"Acherus Necromancer - On Script - Cross Cast 'Raise Dead'"),
+(@ENTRY,9,2,0,0,0,100,0,1000,1000,0,0,28,29266,0,0,0,0,0,10,129459,28394,0,0,0,0,0,"Acherus Necromancer - On Script - Remove Aura 'Permanent Feign Death'"),
+(@ENTRY,9,3,0,0,0,100,0,0,0,0,0,96,32,0,0,0,0,0,10,129459,28394,0,0,0,0,0,"Acherus Necromancer - On Script - Remove Dynamic Flag Dead"),
+(@ENTRY,9,4,0,0,0,100,0,0,0,0,0,19,537165824,0,0,0,0,0,10,129459,28394,0,0,0,0,0,"Acherus Necromancer - On Script - Remove Flag Stunned"),
+(@ENTRY,9,5,0,0,0,100,0,0,0,0,0,19,1,1,0,0,0,0,10,129459,28394,0,0,0,0,0,"Acherus Necromancer - On Script - Remove Flag Server Controlled"),
+(@ENTRY,9,6,0,0,0,100,0,0,0,0,0,91,7,0,0,0,0,0,10,129459,28394,0,0,0,0,0,"Acherus Necromancer - On Script - Remove Flag Standstate Dead"),
+(@ENTRY,9,7,0,0,0,100,0,0,0,0,0,91,257,0,0,0,0,0,10,129459,28394,0,0,0,0,0,"Acherus Necromancer - On Script - Remove Flag Dead"),
+(@ENTRY,9,8,0,0,0,100,0,2000,2000,0,0,2,1770,0,0,0,0,0,10,129459,28394,0,0,0,0,0,"Acherus Necromancer - On Script - Set Faction 1770"),
+(@ENTRY,9,9,0,0,0,100,0,1000,1000,0,0,45,1,1,0,0,0,0,10,129459,28394,0,0,0,0,0,"Acherus Necromancer - On Script - Set Data 1 1"),
+(@ENTRY,9,10,0,0,0,100,0,0,0,0,0,90,8,0,0,0,0,0,10,129459,28394,0,0,0,0,0,"Acherus Necromancer - On Script - Set Flag Standstate Kneel"),
+(@ENTRY,9,11,0,0,0,100,0,4000,4000,0,0,1,0,5000,0,0,0,0,10,129459,28394,0,0,0,0,0,"Acherus Necromancer - On Script - Say Line 0"),
+(@ENTRY,9,12,0,0,0,100,0,5000,5000,0,0,1,4,5000,0,0,0,0,10,129307,28357,0,0,0,0,0,"Acherus Necromancer - On Script - Say Line 4"),
+(@ENTRY,9,13,0,0,0,100,0,6000,6000,0,0,1,5,6000,0,0,0,0,10,129307,28357,0,0,0,0,0,"Acherus Necromancer - On Script - Say Line 5"),
+(@ENTRY,9,14,0,0,0,100,0,5000,5000,0,0,45,3,3,0,0,0,0,10,129307,28357,0,0,0,0,0,"Acherus Necromancer - On Script - Set Data 3 3"),
+(@ENTRY,9,15,0,0,0,100,0,4000,4000,0,0,1,6,6000,0,0,0,0,10,129307,28357,0,0,0,0,0,"Acherus Necromancer - On Script - Say Line 6"),
+(@ENTRY,9,16,0,0,0,100,0,6000,6000,0,0,45,4,4,0,0,0,0,10,129307,28357,0,0,0,0,0,"Acherus Necromancer - On Script - Set Data 4 4"),
+(@ENTRY,9,17,0,0,0,100,0,0,0,0,0,1,0,5000,0,0,0,0,1,0,0,0,0,0,0,0,"Acherus Necromancer - On Script - Say Line 0"),
+(@ENTRY,9,18,0,0,0,100,0,5000,5000,0,0,1,1,5000,0,0,0,0,1,0,0,0,0,0,0,0,"Acherus Necromancer - On Script - Say Line 1"),
+(@ENTRY,9,19,0,0,0,100,0,4000,4000,0,0,12,28405,3,19000,0,0,0,8,0,0,0,2520.44,-5593.01,420.727,3.4383,"Acherus Necromancer - On Script - Summon Creature 'Acherus Ghoul'"),
+(@ENTRY,9,20,0,0,0,100,0,0,0,0,0,12,28405,3,19000,0,0,0,8,0,0,0,2516.65,-5596.68,420.727,1.39626,"Acherus Necromancer - On Script - Summon Creature 'Acherus Ghoul'"),
+(@ENTRY,9,21,0,0,0,100,0,0,0,0,0,12,28405,3,19000,0,0,0,8,0,0,0,2515.93,-5589.89,420.727,4.92183,"Acherus Necromancer - On Script - Summon Creature 'Acherus Ghoul'"),
+(@ENTRY,9,22,0,0,0,100,0,20000,20000,0,0,48,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Acherus Necromancer - On Script - Set Active Off");
+
+DELETE FROM `creature_text` WHERE `CreatureID` IN (28357, 28383, 28391, 28394);
+INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `comment`) VALUES
+-- Instructor Razuvious
+(28357, 0, 0, 'This one...', 12, 0, 100, 25, 0, 0, 27876, 'Instructor Razuvious'),
+(28357, 1, 0, 'The Lich King will be pleased with this initiate.', 12, 0, 100, 5, 0, 0, 27869, 'Instructor Razuvious'),
+(28357, 1, 1, 'Amidst the wretch, a champion has been found.', 12, 0, 100, 5, 0, 0, 27870, 'Instructor Razuvious'),
+(28357, 1, 2, 'CHAOS! DOOM! DESTRUCTION! This one will claim them all!', 12, 0, 100, 5, 0, 0, 27871, 'Instructor Razuvious'),
+(28357, 1, 3, 'Marvel at its tenacity and vigor! A champion has been found!', 12, 0, 100, 5, 0, 0, 27868, 'Instructor Razuvious'),
+(28357, 1, 4, 'A harbinger of death is reborn...', 12, 0, 100, 5, 0, 0, 27872, 'Instructor Razuvious'),
+(28357, 2, 0, 'Place upon it the trappings befitting a herald of Arthas.', 12, 0, 100, 1, 0, 0, 27873, 'Instructor Razuvious'),
+(28357, 3, 0, 'Stand and be measured! Rise, for your master awaits your arrival. Go now!', 12, 0, 100, 5, 0, 0, 27883, 'Instructor Razuvious'),
+(28357, 3, 1, 'Listen, death knight... Listen for the voice of your master. He calls to you now.', 12, 0, 100, 5, 0, 0, 27884, 'Instructor Razuvious'),
+(28357, 4, 0, 'Pathetic...', 12, 0, 100, 1, 0, 0, 27865, 'Instructor Razuvious'),
+(28357, 4, 1, 'Useless...', 12, 0, 100, 1, 0, 0, 27862, 'Instructor Razuvious'),
+(28357, 4, 2, 'Another failure...', 12, 0, 100, 1, 0, 0, 27861, 'Instructor Razuvious'),
+(28357, 4, 3, 'This one has awoken too soon. It retains emotion and memory...', 12, 0, 100, 1, 0, 0, 27864, 'Instructor Razuvious'),
+(28357, 5, 0, 'You have been measured and found wanting...', 12, 0, 100, 25, 0, 0, 27866, 'Instructor Razuvious'),
+(28357, 6, 0, 'Dispose of it...', 12, 0, 100, 1, 0, 0, 27867, 'Instructor Razuvious'),
+-- Acherus Necromancer
+(28383, 0, 0, 'Yes, instructor.', 12, 0, 100, 1, 0, 0, 27874, 'Acherus Necromancer'),
+(28383, 0, 1, 'Right away, instructor.', 12, 0, 100, 1, 0, 0, 27881, 'Acherus Necromancer'),
+(28383, 1, 0, 'Rise, minions. Rise and feast upon the weak!', 12, 0, 100, 22, 0, 0, 27875, 'Acherus Necromancer'),
+-- Death Knight Initiate 1
+(28391, 0, 0, 'I return from the grave to do my master\'s bidding.', 12, 0, 100, 0, 0, 0, 27880, 'Death Knight Initiate'),
+(28391, 0, 1, 'The voice... such splendor... Arthas... My king....', 12, 0, 100, 0, 0, 0, 27879, 'Death Knight Initiate'),
+(28391, 0, 2, 'Reborn, I shall become an instrument of doom...', 12, 0, 100, 0, 0, 0, 27878, 'Death Knight Initiate'),
+(28391, 0, 3, 'Dark energy courses through me... Such power! I hunger for more!', 12, 0, 100, 0, 0, 0, 27877, 'Death Knight Initiate'),
+(28391, 1, 0, 'Death to all that oppose us!', 12, 0, 100, 66, 0, 0, 27888, 'Death Knight Initiate'),
+(28391, 1, 1, 'Victory to the Scourge!', 12, 0, 100, 66, 0, 0, 27887, 'Death Knight Initiate'),
+(28391, 1, 2, 'I live only to serve the Lich King!', 12, 0, 100, 66, 0, 0, 27886, 'Death Knight Initiate'),
+(28391, 1, 3, 'As you command, instructor!', 12, 0, 100, 66, 0, 0, 27885, 'Death Knight Initiate'),
+(28391, 2, 0, 'Woe unto those that dare oppose the Scourge!', 12, 0, 100, 66, 0, 0, 30176, 'Death Knight Initiate'),
+(28391, 2, 1, 'I am reborn, my king, only to serve you.', 12, 0, 100, 66, 0, 0, 30179, 'Death Knight Initiate'),
+(28391, 2, 2, 'I am an instrument of your destruction, my king! Command me!', 12, 0, 100, 66, 0, 0, 30175, 'Death Knight Initiate'),
+(28391, 2, 3, 'Our enemies will be annihilated!', 12, 0, 100, 66, 0, 0, 30177, 'Death Knight Initiate'),
+(28391, 2, 4, 'A thousand-thousand lives I will sacrifice for you, my lord.', 12, 0, 100, 66, 0, 0, 30172, 'Death Knight Initiate'),
+(28391, 2, 5, 'I am yours to command, my king!', 12, 0, 100, 66, 0, 0, 30173, 'Death Knight Initiate'),
+(28391, 2, 6, 'There will be no survivors, my lord.', 12, 0, 100, 66, 0, 0, 30180, 'Death Knight Initiate'),
+(28391, 2, 7, 'My king, the world will tremble in reverence...', 12, 0, 100, 66, 0, 0, 30174, 'Death Knight Initiate'),
+-- Death Knight Initiate 2
+(28394, 0, 0, 'Where am I? What is this place?', 12, 0, 100, 0, 0, 0, 27856, 'Death Knight Initiate'),
+(28394, 0, 1, 'Who... who are you? Who... what am I?', 12, 0, 100, 0, 0, 0, 27858, 'Death Knight Initiate'),
+(28394, 0, 2, 'I hurt... suffering unbearable... end my pain... I beg of you!', 12, 0, 100, 0, 0, 0, 27859, 'Death Knight Initiate'),
+(28394, 0, 3, 'I... I have awoken to a nightmare?', 12, 0, 100, 0, 0, 0, 27857, 'Death Knight Initiate');
+
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceGroup`=1 AND `SourceEntry` IN (51516);
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(13, 1, 51516, 0, 0, 31, 0, 3, 28394, 0, 0, 0, 0, '', 'Rise dead only targets Death Knight Initiate'),
+(13, 1, 51516, 0, 1, 31, 0, 3, 28391, 0, 0, 0, 0, '', 'Rise dead only targets Death Knight Initiate');
+
+-- Death Knight Initiate SAI
+SET @ENTRY := 28391;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,38,0,100,0,1,1,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,4.16204,"Death Knight Initiate - On Data Set 1 1 - Set Orientation 4.16204"),
+(@ENTRY,0,1,6,38,0,100,0,2,2,0,0,53,1,28391,0,0,0,0,1,0,0,0,0,0,0,0,"Death Knight Initiate - On Data Set 2 2 - Start Waypoint"),
+(@ENTRY,0,2,3,40,0,100,0,7,28391,0,0,54,11000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Death Knight Initiate - On Waypoint 7 Reached - Pause Waypoint"),
+(@ENTRY,0,3,0,61,0,100,0,7,28391,0,0,80,@ENTRY*100+00,0,0,0,0,0,1,0,0,0,0,0,0,0,"Death Knight Initiate - On Waypoint 7 Reached - Run Script"),
+(@ENTRY,0,4,0,40,0,100,0,9,28391,0,0,41,2000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Death Knight Initiate - On Waypoint 9 Reached - Despawn In 2000 ms"),
+(@ENTRY,0,5,0,25,0,100,0,0,0,0,0,18,295170,0,0,0,0,0,1,0,0,0,0,0,0,0,"Death Knight Initiate - On Reset - Set Flags Not Attackable & Immune To Players & Stunned"),
+(@ENTRY,0,6,0,61,0,100,0,2,2,0,0,48,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Death Knight Initiate - On Data Set 2 2 - Set Active On");
+
+-- Actionlist SAI
+SET @ENTRY := 2839100;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,1000,1000,0,0,5,66,0,0,0,0,0,1,0,0,0,0,0,0,0,"Death Knight Initiate - On Script - Play Emote 66"),
+(@ENTRY,9,1,0,0,0,100,0,2000,2000,0,0,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0,"Death Knight Initiate - On Script - Say Line 2"),
+(@ENTRY,9,2,0,0,0,100,0,6000,6000,0,0,5,2,0,0,0,0,0,1,0,0,0,0,0,0,0,"Death Knight Initiate - On Script - Play Emote 2");
+
+DELETE FROM `waypoints` WHERE `entry`=28391;
+INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `point_comment`) VALUES
+(28391,1,2453.87,-5545.37,420.643,'Death Knight Initiate'),
+(28391,2,2423.38,-5574.52,420.631,'Death Knight Initiate'),
+(28391,3,2423.38,-5610.59,420.6,'Death Knight Initiate'),
+(28391,4,2410.19,-5626.02,420.654,'Death Knight Initiate'),
+(28391,5,2381.18,-5637.17,420.858,'Death Knight Initiate'),
+(28391,6,2372.68,-5645.34,426.017,'Death Knight Initiate'),
+(28391,7,2348.248,-5666.514,426.029,'Death Knight Initiate'),
+(28391,8,2373.07,-5652.69,426.126,'Death Knight Initiate'),
+(28391,9,2382.63,-5645.56,421.512,'Death Knight Initiate');
+
+-- Death Knight Initiate SAI
+SET @ENTRY := 28394;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,38,0,100,0,1,1,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,3.07005,"Death Knight Initiate - On Data Set 1 1 - Set Orientation 3.07005"),
+(@ENTRY,0,1,0,25,0,100,0,0,0,0,0,18,295170,0,0,0,0,0,1,0,0,0,0,0,0,0,"Death Knight Initiate - On Reset - Set Flags Not Attackable & Immune To Players & Stunned");
+
+-- Acherus Ghoul SAI
+SET @ENTRY := 28405;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,63,0,100,0,0,0,0,0,80,@ENTRY*100+00,2,0,0,0,0,1,0,0,0,0,0,0,0,"Acherus Ghoul - On Just Created - Run Script");
+
+-- Actionlist SAI
+SET @ENTRY := 2840500;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,0,0,0,0,17,373,0,0,0,0,0,1,0,0,0,0,0,0,0,"Acherus Ghoul - On Script - Set Emote State 373"),
+(@ENTRY,9,1,0,0,0,100,0,1000,1000,0,0,11,26047,0,0,0,0,0,1,0,0,0,0,0,0,0,"Acherus Ghoul - On Script - Cast 'Birth'"),
+(@ENTRY,9,2,0,0,0,100,0,2000,2000,0,0,17,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Acherus Ghoul - On Script - Set Emote State 0"),
+(@ENTRY,9,3,0,0,0,100,0,1000,1000,0,0,2,2093,0,0,0,0,0,1,0,0,0,0,0,0,0,"Acherus Ghoul - On Script - Set Faction 2093"),
+(@ENTRY,9,4,0,0,0,100,0,0,0,0,0,19,514,0,0,0,0,0,10,129459,28394,0,0,0,0,0,"Acherus Ghoul - On Script - Remove Flags Not Attackable & Immune To NPC's"),
+(@ENTRY,9,5,0,0,0,100,0,0,0,0,0,49,0,0,0,0,0,0,10,129459,28394,0,0,0,0,0,"Acherus Ghoul - On Script - Start Attacking");
diff --git a/sql/updates/world/master/2020_04_10_14_world_2017_01_20_02_world.sql b/sql/updates/world/master/2020_04_10_14_world_2017_01_20_02_world.sql
new file mode 100644
index 00000000000..a5cde613775
--- /dev/null
+++ b/sql/updates/world/master/2020_04_10_14_world_2017_01_20_02_world.sql
@@ -0,0 +1,91 @@
+-- Lord Thorval - Rework Textevent
+SET @NPC := 128506;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `spawndist`=0,`MovementType`=2 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`, `orientation`, `delay`) VALUES
+(@PATH, 1, 2527.73, -5549.21, 377.036, 3.735, 30000),
+(@PATH, 2, 2524.61, -5545.03, 377.027, 2.21325, 0),
+(@PATH, 3, 2524.61, -5545.03, 377.027, 4.06051, 15000),
+(@PATH, 4, 2530.44, -5554.25, 377.056, 5.26204, 0),
+(@PATH, 5, 2530.44, -5554.25, 377.056, 3.50275, 15000),
+(@PATH, 6, 2524.61, -5545.03, 377.027, 2.21325, 0),
+(@PATH, 7, 2524.61, -5545.03, 377.027, 4.06051, 15000),
+(@PATH, 8, 2530.44, -5554.25, 377.056, 5.26204, 1000),
+(@PATH, 9, 2524.61, -5545.03, 377.027, 2.21325, 1000),
+(@PATH, 10, 2530.44, -5554.25, 377.056, 5.26204, 1000),
+(@PATH, 11, 2524.61, -5545.03, 377.027, 2.21325, 0),
+(@PATH, 12, 2524.61, -5545.03, 377.027, 4.06051, 15000),
+(@PATH, 13, 2527.73, -5549.21, 377.036, 2.18866, 0),
+(@PATH, 14, 2527.73, -5549.21, 377.036, 3.735, 330000);
+
+-- Lord Thorval SAI
+SET @ENTRY := 28472;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,34,0,100,0,2,2,0,0,80,@ENTRY*100+00,0,0,0,0,0,1,0,0,0,0,0,0,0,"Lord Thorval - On Reached Point 2 - Run Script"),
+(@ENTRY,0,1,0,34,0,100,0,2,4,0,0,80,@ENTRY*100+01,0,0,0,0,0,1,0,0,0,0,0,0,0,"Lord Thorval - On Reached Point 4 - Run Script"),
+(@ENTRY,0,2,0,34,0,100,0,2,6,0,0,80,@ENTRY*100+02,0,0,0,0,0,1,0,0,0,0,0,0,0,"Lord Thorval - On Reached Point 6 - Run Script"),
+(@ENTRY,0,3,0,34,0,100,0,2,7,0,0,80,@ENTRY*100+03,0,0,0,0,0,1,0,0,0,0,0,0,0,"Lord Thorval - On Reached Point 7 - Run Script"),
+(@ENTRY,0,4,0,34,0,100,0,2,8,0,0,80,@ENTRY*100+04,0,0,0,0,0,1,0,0,0,0,0,0,0,"Lord Thorval - On Reached Point 8 - Run Script"),
+(@ENTRY,0,5,0,34,0,100,0,2,9,0,0,80,@ENTRY*100+05,0,0,0,0,0,1,0,0,0,0,0,0,0,"Lord Thorval - On Reached Point 9 - Run Script"),
+(@ENTRY,0,6,0,34,0,100,0,2,11,0,0,80,@ENTRY*100+06,0,0,0,0,0,1,0,0,0,0,0,0,0,"Lord Thorval - On Reached Point 11 - Run Script");
+
+-- Actionlist SAI
+SET @ENTRY := 2847200;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,1000,1000,0,0,1,0,5000,0,0,0,0,1,0,0,0,0,0,0,0,"Lord Thorval - On Script - Say Line 0");
+
+-- Actionlist SAI
+SET @ENTRY := 2847201;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,1000,1000,0,0,1,1,5000,0,0,0,0,1,0,0,0,0,0,0,0,"Lord Thorval - On Script - Say Line 1"),
+(@ENTRY,9,1,0,0,0,100,0,9000,9000,0,0,1,2,5000,0,0,0,0,1,0,0,0,0,0,0,0,"Lord Thorval - On Script - Say Line 2");
+
+-- Actionlist SAI
+SET @ENTRY := 2847202;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,1000,1000,0,0,1,3,9000,0,0,0,0,1,0,0,0,0,0,0,0,"Lord Thorval - On Script - Say Line 3"),
+(@ENTRY,9,1,0,0,0,100,0,9000,9000,0,0,1,4,5000,0,0,0,0,1,0,0,0,0,0,0,0,"Lord Thorval - On Script - Say Line 4");
+
+-- Actionlist SAI
+SET @ENTRY := 2847203;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,1000,1000,0,0,1,5,5000,0,0,0,0,1,0,0,0,0,0,0,0,"Lord Thorval - On Script - Say Line 5");
+
+-- Actionlist SAI
+SET @ENTRY := 2847204;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,1000,1000,0,0,1,6,6000,0,0,0,0,1,0,0,0,0,0,0,0,"Lord Thorval - On Script - Say Line 6");
+
+-- Actionlist SAI
+SET @ENTRY := 2847205;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,1000,1000,0,0,1,7,6000,0,0,0,0,1,0,0,0,0,0,0,0,"Lord Thorval - On Script - Say Line 7");
+
+-- Actionlist SAI
+SET @ENTRY := 2847206;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,1000,1000,0,0,1,8,6000,0,0,0,0,1,0,0,0,0,0,0,0,"Lord Thorval - On Script - Say Line 8");
+
+DELETE FROM `creature_text` WHERE `CreatureID`=@ENTRY;
+INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `comment`, `BroadcastTextId`) VALUES
+(@ENTRY, 0, 0, 'As disciples of blood, you strive to master the very lifeforce of your enemies.', 12, 0, 100, 1, 0, 0, 'Lord Thorval', 29867),
+(@ENTRY, 1, 0, 'Be it by blade or incantation, blood feeds our attacks and weakens our foes.', 12, 0, 100, 1, 0, 0, 'Lord Thorval', 29868),
+(@ENTRY, 2, 0, 'True masters learn to make blood serve more than just their strength in battle.', 12, 0, 100, 1, 0, 0, 'Lord Thorval', 29869),
+(@ENTRY, 3, 0, 'Stripping energy from our foes, both fighting and fallen, allows us to persevere where lesser beigns falls exhausted.', 12, 0, 100, 1, 0, 0, 'Lord Thorval', 29870),
+(@ENTRY, 4, 0, 'And every foe that falls, energy sapped and stolen, only further fuels our assault.', 12, 0, 100, 1, 0, 0, 'Lord Thorval', 29871),
+(@ENTRY, 5, 0, 'As masters of blood, we know battle without end...', 12, 0, 100, 1, 0, 0, 'Lord Thorval', 29872),
+(@ENTRY, 6, 0, 'We know hunger never to be quenched...', 12, 0, 100, 1, 0, 0, 'Lord Thorval', 29873),
+(@ENTRY, 7, 0, 'We know power never to be overcome...', 12, 0, 100, 1, 0, 0, 'Lord Thorval', 29874),
+(@ENTRY, 8, 0, 'As masters of blood, we are masters of life and death itself. Agains us, even hope falls drained and lifeless.', 12, 0, 100, 1, 0, 0, 'Lord Thorval', 29875);
diff --git a/sql/updates/world/master/2020_04_10_15_world_2017_01_20_03_world.sql b/sql/updates/world/master/2020_04_10_15_world_2017_01_20_03_world.sql
new file mode 100644
index 00000000000..8c668e9ec4b
--- /dev/null
+++ b/sql/updates/world/master/2020_04_10_15_world_2017_01_20_03_world.sql
@@ -0,0 +1,168 @@
+-- Gothik the Harvester
+UPDATE `creature_template` SET `Speed_Walk` = 1.6, `Speed_Run` = 1.714286 WHERE `entry` = 28890;
+UPDATE `creature` SET `position_x` = 2107.563721, `position_y` = -5742.198730, `position_z` = 99.855499, `orientation` = 1.374185 WHERE `guid` = 130121;
+SET @NPC := 130121;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `spawndist`=0,`MovementType`=2 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`, `orientation`, `delay`) VALUES
+(@PATH, 1, 2109.85, -5727.25, 100.257, 0.413397, 0),
+(@PATH, 2, 2156.03, -5712.91, 102.291, 6.15937, 0),
+(@PATH, 3, 2177.85, -5738.68, 101.921, 5.56012, 0),
+(@PATH, 4, 2188.7, -5759.94, 101.649, 5.14936, 10000),
+(@PATH, 5, 2225.29, -5781.82, 101.775, 5.67557, 0),
+(@PATH, 6, 2252.21, -5806.7, 100.959, 5.36848, 0),
+(@PATH, 7, 2265.43, -5827.23, 100.945, 5.03548, 0),
+(@PATH, 8, 2267.51, -5839.93, 100.944, 5.03941, 0),
+(@PATH, 9, 2284.81, -5845.79, 100.935, 5.98189, 10000),
+(@PATH, 10, 2259.68, -5866.16, 101.605, 3.82989, 0),
+(@PATH, 11, 2241.44, -5886.94, 100.764, 4.04195, 0),
+(@PATH, 12, 2228.81, -5899.27, 100.89, 3.64925, 0),
+(@PATH, 13, 2201.1, -5902.2, 100.88, 3.12696, 0),
+(@PATH, 14, 2179.59, -5890.74, 101.109, 2.15307, 0),
+(@PATH, 15, 2181.51, -5888.24, 100.93, 0.693798, 10000),
+(@PATH, 16, 2165.13, -5866.72, 101.331, 2.28265, 0),
+(@PATH, 17, 2143.17, -5825.25, 101.125, 1.94886, 0),
+(@PATH, 18, 2130.2, -5789.78, 98.9462, 1.48547, 10000),
+(@PATH, 19, 2115.31, -5769.12, 98.1968, 1.93551, 0),
+(@PATH, 20, 2107.57, -5742.3, 99.8496, 1.70931, 0);
+
+DELETE FROM `creature_text` WHERE `CreatureID`=28890;
+INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `comment`) VALUES
+(28890, 0, 0, 'Rise, minion. Rise and fly for the Scourge!', 12, 0, 100, 5, 0, 0, 29045, 'Gothik the Harvester'),
+(28890, 0, 1, 'You will fly again, beast...', 12, 0, 100, 5, 0, 0, 29043, 'Gothik the Harvester'),
+(28890, 1, 0, 'Surprise, surprise! Another ghoul!', 12, 0, 100, 5, 0, 0, 29038, 'Gothik the Harvester'),
+(28890, 1, 1, 'Is Gothik the Harvester going to have to choke a geist?', 12, 0, 100, 5, 0, 0, 29037, 'Gothik the Harvester'),
+(28890, 2, 0, 'Death is the only escape!', 12, 0, 100, 5, 0, 0, 29039, 'Gothik the Harvester');
+
+-- Gothik the Harvester SAI
+SET @ENTRY := 28890;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,34,0,100,0,2,3,0,0,80,@ENTRY*100+00,2,0,0,0,0,1,0,0,0,0,0,0,0,"Gothik the Harvester - On Reached Point 3 - Run Script"),
+(@ENTRY,0,1,0,34,0,100,0,2,8,0,0,80,@ENTRY*100+01,2,0,0,0,0,1,0,0,0,0,0,0,0,"Gothik the Harvester - On Reached Point 8 - Run Script"),
+(@ENTRY,0,2,0,34,0,100,0,2,14,0,0,80,@ENTRY*100+02,2,0,0,0,0,1,0,0,0,0,0,0,0,"Gothik the Harvester - On Reached Point 14 - Run Script"),
+(@ENTRY,0,3,0,34,0,100,0,2,17,0,0,80,@ENTRY*100+03,2,0,0,0,0,1,0,0,0,0,0,0,0,"Gothik the Harvester - On Reached Point 17 - Run Script"),
+(@ENTRY,0,4,0,25,0,100,1,0,0,0,0,48,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Gothik the Harvester - On Reset - Set Active On (No Repeat)");
+
+-- Actionlist SAI
+SET @ENTRY := 2889000;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,2000,2000,0,0,1,0,6000,0,0,0,0,1,0,0,0,0,0,0,0,"On Script - Say Line 0"),
+(@ENTRY,9,1,0,0,0,100,0,2000,2000,0,0,11,52685,0,0,0,0,0,1,0,0,0,0,0,0,0,"On Script - Cast 'Scourge Gryphon'"),
+(@ENTRY,9,2,0,0,0,100,0,0,0,0,0,41,1,0,0,0,0,0,19,28893,10,0,0,0,0,0,"Gothik the Harvester - On Script - Despawn Instant"),
+(@ENTRY,9,3,0,0,0,100,0,3000,3000,0,0,45,1,1,0,0,0,0,19,28906,20,0,0,0,0,0,"On Script - Set Data 1 1");
+
+-- Actionlist SAI
+SET @ENTRY := 2889001;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,2000,2000,0,0,1,0,6000,0,0,0,0,1,0,0,0,0,0,0,0,"On Script - Say Line 0"),
+(@ENTRY,9,1,0,0,0,100,0,2000,2000,0,0,11,52685,0,0,0,0,0,1,0,0,0,0,0,0,0,"On Script - Cast 'Scourge Gryphon'"),
+(@ENTRY,9,2,0,0,0,100,0,0,0,0,0,41,1,0,0,0,0,0,19,28893,10,0,0,0,0,0,"Gothik the Harvester - On Script - Despawn Instant"),
+(@ENTRY,9,3,0,0,0,100,0,3000,3000,0,0,45,2,2,0,0,0,0,19,28906,20,0,0,0,0,0,"On Script - Set Data 2 2");
+
+-- Actionlist SAI
+SET @ENTRY := 2889002;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,2000,2000,0,0,1,1,6000,0,0,0,0,1,0,0,0,0,0,0,0,"Gothik the Harvester - On Script - Say Line 1"),
+(@ENTRY,9,1,0,0,0,100,0,2000,2000,0,0,11,52683,0,0,0,0,0,1,0,0,0,0,0,0,0,"Gothik the Harvester - On Script - Cast 'Scarlet Ghoul'"),
+(@ENTRY,9,2,0,0,0,100,0,0,0,0,0,41,1,0,0,0,0,0,19,28896,10,0,0,0,0,0,"Gothik the Harvester - On Script - Despawn Instant"),
+(@ENTRY,9,3,0,0,0,100,0,3000,3000,0,0,45,1,1,0,0,0,0,19,28897,20,0,0,0,0,0,"Gothik the Harvester - On Script - Set Data 1 1");
+
+-- Actionlist SAI
+SET @ENTRY := 2889003;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,2000,2000,0,0,1,1,6000,0,0,0,0,1,0,0,0,0,0,0,0,"Gothik the Harvester - On Script - Say Line 1"),
+(@ENTRY,9,1,0,0,0,100,0,2000,2000,0,0,11,52683,0,0,0,0,0,1,0,0,0,0,0,0,0,"Gothik the Harvester - On Script - Cast 'Scarlet Ghoul'"),
+(@ENTRY,9,2,0,0,0,100,0,1000,1000,0,0,41,0,0,0,0,0,0,19,28898,10,0,0,0,0,0,"Gothik the Harvester - On Script - Despawn Instant"),
+(@ENTRY,9,3,0,0,0,100,0,0,0,0,0,11,52672,0,0,0,0,0,10,130312,28905,0,0,0,0,0,"Gothik the Harvester - On Script - Cast 'Ghoulplosion'"),
+(@ENTRY,9,4,0,0,0,100,0,0,0,0,0,1,2,3000,0,0,0,0,1,0,0,0,0,0,0,0,"Gothik the Harvester - On Script - Say Line 2"),
+(@ENTRY,9,5,0,0,0,100,0,3000,3000,0,0,45,1,1,0,0,0,0,19,28897,20,0,0,0,0,0,"Gothik the Harvester - On Script - Set Data 1 1");
+
+
+-- Scourge Gryphon
+UPDATE `creature_template` SET `MovementType` = 0, `InhabitType` = 4, `Speed_Walk` = 2.4, `Speed_Run` = 2.57143 WHERE `entry` = 28906;
+
+-- Scarlet Gryphon SAI
+SET @ENTRY := 28893;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,8,0,100,0,52685,0,0,0,41,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Scarlet Gryphon - On Spellhit 'Scourge Gryphon' - Despawn Instant");
+
+-- Scourge Gryphon SAI
+SET @ENTRY := 28906;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,1,38,0,100,0,1,1,0,0,48,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Scourge Gryphon - On Data Set 1 1 - Set Active On"),
+(@ENTRY,0,1,0,61,0,100,0,1,1,0,0,69,1,0,0,0,0,0,8,0,0,0,1781.18,-5818.34,114.383,0,"Scourge Gryphon - On Data Set 1 1 - Move To Position"),
+(@ENTRY,0,2,0,34,0,100,0,8,1,0,0,49,0,0,0,0,0,0,19,28610,100,0,0,0,0,0,"Scourge Gryphon - On Reached Point 1 - Start Attacking"),
+(@ENTRY,0,3,4,38,0,100,0,2,2,0,0,48,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Scourge Gryphon - On Data Set 2 2 - Set Active On"),
+(@ENTRY,0,4,0,61,0,100,0,2,2,0,0,69,2,0,0,0,0,0,8,0,0,0,1818.18,-5930.02,113.669,0,"Scourge Gryphon - On Data Set 2 2 - Move To Position"),
+(@ENTRY,0,5,0,34,0,100,0,8,2,0,0,49,0,0,0,0,0,0,19,28610,100,0,0,0,0,0,"Scourge Gryphon - On Reached Point 2 - Start Attacking"),
+(@ENTRY,0,6,0,63,0,100,0,0,0,0,0,41,300000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Scourge Gryphon - On Just Created - Despawn In 300000 ms");
+
+-- Scarlet Infantryman SAI
+SET @ENTRY := 28896;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,8,0,100,0,52683,0,0,0,41,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Scarlet Infantryman - On Spellhit 'Scarlet Ghoul' - Despawn Instant");
+
+-- Scarlet Captain SAI
+SET @ENTRY := 28898;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,8,0,100,0,52683,0,0,0,41,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Scarlet Captain - On Spellhit 'Scarlet Ghoul' - Despawn Instant");
+
+-- Scarlet Ghoul SAI
+SET @ENTRY := 28897;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,1,38,0,100,0,1,1,0,0,48,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Scarlet Ghoul - On Data Set 1 1 - Set Active On"),
+(@ENTRY,0,1,0,61,0,100,0,1,1,0,0,53,1,28897,0,0,0,2,8,0,0,0,1783.51,-5818.18,113.877,3.19587,"Scarlet Ghoul - On Data Set 1 1 - Start Waypoint"),
+(@ENTRY,0,2,3,63,0,100,0,0,0,0,0,41,300000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Scarlet Ghoul - On Just Created - Despawn In 300000 ms"),
+(@ENTRY,0,3,0,61,0,100,0,0,0,0,0,1,0,5000,0,0,0,0,1,0,0,0,0,0,0,0,"Scarlet Ghoul - On Just Created - Say Line 0");
+
+DELETE FROM `creature_text` WHERE `CreatureID`=28897;
+INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `comment`) VALUES
+(28897, 0, 0, 'So hungry...', 12, 0, 100, 0, 0, 0, 28955, 'Scarlet Ghoul'),
+(28897, 0, 1, 'Must feed...', 12, 0, 100, 0, 0, 0, 28956, 'Scarlet Ghoul'),
+(28897, 0, 2, 'Smell flesh... close...', 12, 0, 100, 0, 0, 0, 28958, 'Scarlet Ghoul');
+
+UPDATE `creature_template` SET `MovementType` = 0, `InhabitType` = 3 WHERE `entry` = 28897;
+DELETE FROM `waypoints` WHERE `entry`=28897;
+INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `point_comment`) VALUES
+(28897, 1, 2143.13, -5845.46, 101.335, 'Scarlet Ghoul'),
+(28897, 2, 2112.23, -5869.67, 102.671, 'Scarlet Ghoul'),
+(28897, 3, 2075.06, -5888.31, 104.169, 'Scarlet Ghoul'),
+(28897, 4, 2047.48, -5901.68, 105.289, 'Scarlet Ghoul'),
+(28897, 5, 2017.32, -5907.23, 104.617, 'Scarlet Ghoul'),
+(28897, 6, 1962.61, -5905.59, 102.366, 'Scarlet Ghoul'),
+(28897, 7, 1925.94, -5911, 101.514, 'Scarlet Ghoul'),
+(28897, 8, 1884.37, -5910.29, 103.345, 'Scarlet Ghoul'),
+(28897, 9, 1858.9, -5916.94, 104.525, 'Scarlet Ghoul'),
+(28897, 10, 1840.21, -5923.29, 107.843, 'Scarlet Ghoul'),
+(28897, 11, 1819.53, -5930.31, 113.439, 'Scarlet Ghoul'),
+(28897, 12, 1800.91, -5936.87, 115.947, 'Scarlet Ghoul');
+
+UPDATE `creature` SET `spawntimesecs`=30 WHERE `id` IN (28893, 28896, 28898);
+UPDATE `creature` SET `spawntimesecs`=30 WHERE `guid`=130312;
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceGroup`=1 AND `SourceEntry` IN (52685, 52683);
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(13, 1, 52685, 0, 0, 31, 0, 3, 28893, 0, 0, 0, 0, '', 'Scourge Gryphon only targets Scarlet Gryphon'),
+(13, 1, 52683, 0, 0, 31, 0, 3, 28896, 0, 0, 0, 0, '', 'Scarlet Ghoul only targets Scarlet Infantryman'),
+(13, 1, 52683, 0, 1, 31, 0, 3, 28898, 0, 0, 0, 0, '', 'Scarlet Ghoul only targets Scarlet Captain'),
+(13, 1, 52683, 0, 2, 31, 0, 3, 28892, 0, 0, 0, 0, '', 'Scarlet Ghoul only targets Scarlet Peasant'),
+(13, 1, 52683, 0, 3, 31, 0, 3, 28897, 0, 0, 0, 0, '', 'Scarlet Ghoul only targets Scarlet Ghoul'),
+(13, 1, 52683, 0, 4, 31, 0, 3, 28886, 0, 0, 0, 0, '', 'Scarlet Ghoul only targets Scarlet Fleet Defender');
diff --git a/sql/updates/world/master/2020_04_10_16_world_2017_01_20_04_world.sql b/sql/updates/world/master/2020_04_10_16_world_2017_01_20_04_world.sql
new file mode 100644
index 00000000000..fedd7e5c7c9
--- /dev/null
+++ b/sql/updates/world/master/2020_04_10_16_world_2017_01_20_04_world.sql
@@ -0,0 +1,224 @@
+-- Gothik the Harvester Entry 2 event
+-- Scarlet Deserter
+UPDATE `creature` SET `spawndist` = 0, `MovementType` = 0 WHERE `guid` IN (130402,130403,130404,130405);
+UPDATE `creature` SET `position_x` = 2817.77, `position_y` = -5453.906, `position_z` = 159.4021, `orientation` = 1.937315 WHERE `guid` = 130405;
+
+-- Scarlet Deserter SAI
+SET @GUID := -130405;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=29193;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@GUID 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
+(@GUID,0,0,0,25,0,100,0,0,0,0,0,60,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Scarlet Deserter - On Reset - Set Fly On");
+
+-- Gothik the Harvester SAI
+SET @ENTRY := 29112;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,1,0,100,0,2000,2000,640000,640000,80,@ENTRY*100+00,2,0,0,0,0,1,0,0,0,0,0,0,0,"Gothik the Harvester - Out of Combat - Run Script");
+
+-- Actionlist SAI
+SET @ENTRY := 2911200;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,0,0,0,0,48,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Gothik the Harvester - On Script - Set Active On"),
+(@ENTRY,9,1,0,0,0,100,0,3000,3000,0,0,1,0,4000,0,0,0,0,10,130405,29193,0,0,0,0,0,"Gothik the Harvester - On Script - Say Line 0"),
+(@ENTRY,9,2,0,0,0,100,0,4000,4000,0,0,1,0,30000,0,0,0,0,1,0,0,0,0,0,0,0,"Gothik the Harvester - On Script - Say Line 0"),
+(@ENTRY,9,3,0,0,0,100,0,63000,63000,0,0,1,1,4000,0,0,0,0,10,130405,29193,0,0,0,0,0,"Gothik the Harvester - On Script - Say Line 1"),
+(@ENTRY,9,4,0,0,0,100,0,4000,4000,0,0,1,1,30000,0,0,0,0,1,0,0,0,0,0,0,0,"Gothik the Harvester - On Script - Say Line 1"),
+(@ENTRY,9,5,0,0,0,100,0,73000,73000,0,0,1,2,4000,0,0,0,0,10,130405,29193,0,0,0,0,0,"Gothik the Harvester - On Script - Say Line 2"),
+(@ENTRY,9,6,0,0,0,100,0,4000,4000,0,0,1,2,30000,0,0,0,0,1,0,0,0,0,0,0,0,"Gothik the Harvester - On Script - Say Line 2"),
+(@ENTRY,9,7,0,0,0,100,0,68000,68000,0,0,1,3,4000,0,0,0,0,10,130405,29193,0,0,0,0,0,"Gothik the Harvester - On Script - Say Line 3"),
+(@ENTRY,9,8,0,0,0,100,0,4000,4000,0,0,1,3,30000,0,0,0,0,1,0,0,0,0,0,0,0,"Gothik the Harvester - On Script - Say Line 3"),
+(@ENTRY,9,9,0,0,0,100,0,78000,78000,0,0,1,4,4000,0,0,0,0,10,130405,29193,0,0,0,0,0,"Gothik the Harvester - On Script - Say Line 4"),
+(@ENTRY,9,10,0,0,0,100,0,4000,4000,0,0,1,4,30000,0,0,0,0,1,0,0,0,0,0,0,0,"Gothik the Harvester - On Script - Say Line 4"),
+(@ENTRY,9,11,0,0,0,100,0,73000,73000,0,0,1,5,4000,0,0,0,0,10,130405,29193,0,0,0,0,0,"Gothik the Harvester - On Script - Say Line 5"),
+(@ENTRY,9,12,0,0,0,100,0,4000,4000,0,0,1,5,30000,0,0,0,0,1,0,0,0,0,0,0,0,"Gothik the Harvester - On Script - Say Line 5"),
+(@ENTRY,9,13,0,0,0,100,0,53000,53000,0,0,1,6,30000,0,0,0,0,10,130405,29193,0,0,0,0,0,"Gothik the Harvester - On Script - Say Line 6"),
+(@ENTRY,9,14,0,0,0,100,0,0,0,0,0,48,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Gothik the Harvester - On Script - Set Active Off");
+
+DELETE FROM `creature_text` WHERE `CreatureID` IN (29193, 29112);
+INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `comment`) VALUES
+-- Scarlet Deserter
+(29193, 0, 0, 'You\'re a monster!', 12, 0, 100, 0, 0, 0, 29644, 'Scarlet Deserter'),
+(29193, 1, 0, 'Please! Spare me! I...', 12, 0, 100, 0, 0, 0, 29645, 'Scarlet Deserter'),
+(29193, 2, 0, 'Wi... Will it hurt?', 12, 0, 100, 0, 0, 0, 29641, 'Scarlet Deserter'),
+(29193, 3, 0, 'It tingles...', 12, 0, 100, 0, 0, 0, 29642, 'Scarlet Deserter'),
+(29193, 4, 0, 'Why don\'t you Just Kill me Already', 12, 0, 100, 0, 0, 0, 0, 'Scarlet Deserter'),
+(29193, 5, 0, 'Is it too late to change my mind? How about you just kill me instead?', 12, 0, 100, 0, 0, 0, 29643, 'Scarlet Deserter'),
+(29193, 6, 0, 'The horror! THE HORROR!', 12, 0, 100, 0, 0, 0, 29646, 'Scarlet Deserter'),
+-- Gothik the Harvester
+(29112, 0, 0, 'Flattery will get you nowhere.', 12, 0, 100, 1, 0, 0, 29650, 'Gothik the Harvester'),
+(29112, 1, 0, 'Don\'t be ridiculous. Where would you even go if I did spare you? We just finished eradicating your civilization, remember?', 12, 0, 100, 1, 0, 0, 29651, 'Gothik the Harvester'),
+(29112, 2, 0, 'Oh yes. Immensely. The pain will propably render you unconcious - hence the vat of slime you\'re floating in!', 12, 0, 100, 1, 0, 0, 0, 'Gothik the Harvester'),
+(29112, 3, 0, 'That\'s how you know it\'s working.', 12, 0, 100, 1, 0, 0, 29648, 'Gothik the Harvester'),
+(29112, 4, 0, 'You idiot! That\'s What I\'m Doing Right Now!', 12, 0, 100, 5, 0, 0, 0, 'Gothik the Harvester'),
+(29112, 5, 0, 'I AM going to kill you. What\'s the rush?', 12, 0, 100, 6, 0, 0, 29649, 'Gothik the Harvester');
+
+-- The Noxious Glade
+-- Noth the Plaguebringer SAI
+SET @ENTRY := 29113;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,1,0,100,0,60000,60000,60000,60000,1,0,20000,0,0,0,0,1,0,0,0,0,0,0,0,"Noth the Plaguebringer - Out of Combat - Say Line 0");
+
+DELETE FROM `creature_text` WHERE `CreatureID`=29113;
+INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `comment`) VALUES
+(29113, 0, 0, 'We need more flesh!', 14, 0, 100, 5, 0, 0, 29634, 'Noth the Plaguebringer'),
+(29113, 0, 1, 'Double your efforts! The final assault draws near!', 14, 0, 100, 5, 0, 0, 29639, 'Noth the Plaguebringer');
+
+-- Howling Geist
+UPDATE `creature` SET `position_x` = 2597.903076, `position_y` = -5549.420410, `position_z` = 159.772934, `spawndist` = 20, `MovementType` = 1 WHERE `guid` = 130387;
+UPDATE `creature` SET `position_x` = 2622.867432, `position_y` = -5481.481934, `position_z` = 156.948212, `spawndist` = 20, `MovementType` = 1 WHERE `guid` = 130386;
+UPDATE `creature` SET `position_x` = 2659.806885, `position_y` = -5537.375000, `position_z` = 163.303589, `spawndist` = 20, `MovementType` = 1 WHERE `guid` = 130385;
+UPDATE `creature` SET `position_x` = 2697.650391, `position_y` = -5469.664063, `position_z` = 156.943970, `spawndist` = 20, `MovementType` = 1 WHERE `guid` = 130383;
+UPDATE `creature` SET `position_x` = 2735.920410, `position_y` = -5363.948730, `position_z` = 157.715302, `spawndist` = 20, `MovementType` = 1 WHERE `guid` = 130381;
+
+-- Rampaging Abomination
+UPDATE `creature` SET `position_x` = 2770.925049, `position_y` = -5536.027344, `position_z` = 161.735718, `orientation` = 2.301208, `spawndist` = 10, `MovementType` = 1 WHERE guid = 130378;
+UPDATE `creature` SET `spawndist` = 0, `MovementType` = 2, `spawntimesecs` = 10 WHERE `guid` IN (130376,130379);
+
+SET @NPC := 130376;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `spawndist`=0,`MovementType`=2 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '53624');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`, `delay`) VALUES
+(@PATH, 1, 2723.56, -5356.07, 159.613,0),
+(@PATH, 2, 2704.62, -5360.77, 159.398,0),
+(@PATH, 3, 2691.18, -5349.93, 158.621,0),
+(@PATH, 4, 2683.39, -5323.99, 155.334,0),
+(@PATH, 5, 2675.71, -5304.56, 153.114,0),
+(@PATH, 6, 2663.78, -5284.98, 148.258,0),
+(@PATH, 7, 2658.59, -5275.23, 142.105,0),
+(@PATH, 8, 2644.61, -5255.16, 121.631,0),
+(@PATH, 9, 2631.96, -5238.4, 107.608,0),
+(@PATH, 10, 2613.31, -5216.83, 93.161,0),
+(@PATH, 11, 2598.7, -5201.75, 82.8146,0),
+(@PATH, 12, 2582.36, -5187.09, 75.8517,0),
+(@PATH, 13, 2569.27, -5176.85, 73.7495,0),
+(@PATH, 14, 2558.21, -5168.27, 74.6465,0),
+(@PATH, 15, 2538.28, -5155.75, 74.2881,0),
+(@PATH, 16, 2521.03, -5147.47, 73.6583,0),
+(@PATH, 17, 2502.8, -5138.25, 75.7383,0),
+(@PATH, 18, 2483.53, -5131.73, 75.9083, 2000);
+
+UPDATE `waypoint_data` SET `move_type`=1 WHERE `id`=@PATH;
+UPDATE `waypoint_data` SET `action`=1188, `action_chance`=100 WHERE `id`=@PATH AND `point`=18;
+
+SET @NPC := 130379;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `spawndist`=0,`MovementType`=2 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '53624');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`, `delay`) VALUES
+(@PATH, 1, 2726.07, -5498.8, 162.02,0),
+(@PATH, 2, 2727.57, -5481.48, 161.561,0),
+(@PATH, 3, 2732.97, -5468.64, 157.569,0),
+(@PATH, 4, 2750.98, -5458.35, 156.968,0),
+(@PATH, 5, 2772.88, -5441.7, 159.903,0),
+(@PATH, 6, 2774.75, -5416.45, 160.25,0),
+(@PATH, 7, 2771.21, -5396.04, 158.102,0),
+(@PATH, 8, 2750.66, -5381.1, 156.956,0),
+(@PATH, 9, 2727.84, -5372.87, 157.819,0),
+(@PATH, 10, 2707.88, -5366.33, 158.707,0),
+(@PATH, 11, 2693.81, -5354.31, 158.877,0),
+(@PATH, 12, 2687.94, -5338.24, 156.999,0),
+(@PATH, 13, 2681.92, -5317.73, 154.846,0),
+(@PATH, 14, 2675.34, -5305.38, 153.191,0),
+(@PATH, 15, 2659.58, -5278.96, 144.64,0),
+(@PATH, 16, 2651.18, -5266.35, 132.35,0),
+(@PATH, 17, 2636.53, -5246.73, 112.628,0),
+(@PATH, 18, 2619.36, -5225.24, 97.7497,0),
+(@PATH, 19, 2605.23, -5209.7, 86.9899,0),
+(@PATH, 20, 2591.1, -5194.16, 79.6859,0),
+(@PATH, 21, 2573.87, -5176.1, 73.9424,0),
+(@PATH, 22, 2558.81, -5161.48, 74.598,0),
+(@PATH, 23, 2540.44, -5148.6, 74.2861,0),
+(@PATH, 24, 2525.34, -5139.75, 73.6435,0),
+(@PATH, 25, 2505.64, -5127.77, 74.8511,0),
+(@PATH, 26, 2480.14, -5116.4, 79.0267, 2000);
+
+UPDATE `waypoint_data` SET `move_type`=1 WHERE `id`=@PATH;
+UPDATE `waypoint_data` SET `action`=1188, `action_chance`=100 WHERE `id`=@PATH AND `point`=26;
+
+-- Volatile Ghoul
+UPDATE `creature` SET `spawntimesecs` = 10 WHERE `guid` IN (130363,130373,130362);
+
+SET @MAXGUID := 917;
+SET @SCRIPTID := 13036300;
+DELETE FROM `waypoint_scripts` WHERE `id` IN (@SCRIPTID+0);
+INSERT INTO `waypoint_scripts` (`id`, `delay`, `command`, `datalong`, `datalong2`, `dataint`, `x`, `y`, `z`, `o`, `guid`) VALUES
+(@SCRIPTID+0, 1, 15, 26047, 1, 0, 0, 0, 0, 0, (@MAXGUID := @MAXGUID + 1)),
+(@SCRIPTID+0, 4, 1, 0, 1, 0, 0, 0, 0, 0, (@MAXGUID := @MAXGUID + 1));
+
+SET @NPC := 130363;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `spawndist`=0,`MovementType`=2 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,67108864,1,0, '53624');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`, `delay`, `action`, `action_chance`) VALUES
+(@PATH, 1, 2676.73, -5314.65, 154.792, 5000, @SCRIPTID, 100),
+(@PATH, 2, 2684.4, -5306.35, 154.941, 0, 0, 0),
+(@PATH, 3, 2670.25, -5284.02, 150.153, 0, 0, 0),
+(@PATH, 4, 2662.09, -5274.22, 142.412, 0, 0, 0),
+(@PATH, 5, 2644.94, -5255.23, 121.88, 0, 0, 0),
+(@PATH, 6, 2620.75, -5225.3, 98.1054, 0, 0, 0),
+(@PATH, 7, 2592.76, -5198.52, 80.7613, 0, 0, 0),
+(@PATH, 8, 2574.95, -5181.7, 74.3096, 0, 0, 0),
+(@PATH, 9, 2522.32, -5148.41, 73.6604, 0, 0, 0),
+(@PATH, 10, 2475.21, -5122.23, 77.9418, 2000, 1188, 100);
+
+UPDATE `waypoint_data` SET `move_type`=1 WHERE `id`=@PATH;
+
+SET @NPC := 130373;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `spawndist`=0,`MovementType`=2 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,67108864,1,0, '53624');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`, `delay`, `action`, `action_chance`) VALUES
+(@PATH, 1, 2632.02, -5394.72, 168.397, 5000, @SCRIPTID, 100),
+(@PATH, 2, 2651.32, -5405.91, 159.224, 0, 0, 0),
+(@PATH, 3, 2684.38, -5384.49, 157.184, 0, 0, 0),
+(@PATH, 4, 2687.79, -5330.18, 156.083, 0, 0, 0),
+(@PATH, 5, 2684.96, -5314.39, 154.96, 0, 0, 0),
+(@PATH, 6, 2679.3, -5303.38, 153.638, 0, 0, 0),
+(@PATH, 7, 2672.93, -5295.8, 151.813, 0, 0, 0),
+(@PATH, 8, 2664.86, -5285.81, 148.772, 0, 0, 0),
+(@PATH, 9, 2655.93, -5274.74, 141.215, 0, 0, 0),
+(@PATH, 10, 2639.53, -5252.05, 116.733, 0, 0, 0),
+(@PATH, 11, 2621.55, -5230.63, 100.908, 0, 0, 0),
+(@PATH, 12, 2606.08, -5211.66, 88.0324, 0, 0, 0),
+(@PATH, 13, 2582.86, -5185.51, 75.8192, 0, 0, 0),
+(@PATH, 14, 2564.62, -5169.25, 74.5214, 0, 0, 0),
+(@PATH, 15, 2536.72, -5149.97, 74.2893, 0, 0, 0),
+(@PATH, 16, 2516.32, -5145.46, 74.148, 0, 0, 0),
+(@PATH, 17, 2491.97, -5142.91, 76.1721, 0, 0, 0),
+(@PATH, 18, 2467.02, -5137.46, 77.5501, 2000, 1188, 100);
+
+UPDATE `waypoint_data` SET `move_type`=1 WHERE `id`=@PATH;
+
+SET @NPC := 130362;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `spawndist`=0,`MovementType`=2 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,67108864,1,0, '53624');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`, `delay`, `action`, `action_chance`) VALUES
+(@PATH, 1, 2567.76, -5185.66, 74.8526, 5000, @SCRIPTID, 100),
+(@PATH, 2, 2521.28, -5146.41, 73.6638, 0, 0, 0),
+(@PATH, 3, 2483.25, -5139.37, 76.3581, 0, 0, 0),
+(@PATH, 4, 2464.89, -5154.73, 78.0666, 2000, 1188, 100);
+
+UPDATE `waypoint_data` SET `move_type`=1 WHERE `id`=@PATH;
+
+-- Volatile Ghoul
+UPDATE `creature` SET `spawndist` = 0, `MovementType` = 2, `spawntimesecs` = 10 WHERE `guid` IN (130363,130373,130362);
+
+-- Scourge Commander Thalanor
+UPDATE `creature` SET `spawndist` = 10, `MovementType` = 1 WHERE `guid` = 130467;
diff --git a/sql/updates/world/master/2020_04_10_17_world_2017_01_20_05_world.sql b/sql/updates/world/master/2020_04_10_17_world_2017_01_20_05_world.sql
new file mode 100644
index 00000000000..d6fca0ef35c
--- /dev/null
+++ b/sql/updates/world/master/2020_04_10_17_world_2017_01_20_05_world.sql
@@ -0,0 +1,142 @@
+-- Zalduun <Priest Trainer>
+SET @NPC := 57213;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `spawndist`=0,`MovementType`=2 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`, `orientation`, `delay`) VALUES
+(@PATH, 1, -4113.68, -13762, 73.5694, 5.80705, 0),
+(@PATH, 2, -4110.51, -13765.2, 73.6102, 5.19209, 0),
+(@PATH, 3, -4107.71, -13772.5, 74.6982, 5.80705, 0),
+(@PATH, 4, -4102.51, -13772.3, 74.7185, 0.511104, 0),
+(@PATH, 5, -4099.89, -13768, 74.7256, 1.36954, 0),
+(@PATH, 6, -4102.44, -13763.8, 74.5717, 2.63796, 0),
+(@PATH, 7, -4125.6, -13762, 74.1406, 3.4807, 0),
+(@PATH, 8, -4129.88, -13764.2, 74.5865, 3.28513, 0),
+(@PATH, 9, -4135.57, -13762.7, 74.657, 2.14081, 0),
+(@PATH, 10, -4137.16, -13760, 74.6108, 1.35698, 0),
+(@PATH, 11, -4135.66, -13756.6, 74.5907, 0.545662, 0),
+(@PATH, 12, -4131.3, -13754.6, 74.6109, 6.14319, 0),
+(@PATH, 13, -4127.9, -13756.6, 74.2825, 5.30675, 0),
+(@PATH, 14, -4127.08, -13760.8, 74.2562, 5.74265, 0),
+(@PATH, 15, -4121.58, -13761.4, 73.5881, 0.0354084, 0),
+(@PATH, 16, -4113.68, -13762, 73.5694, 5.80705, 0),
+(@PATH, 17, -4110.51, -13765.2, 73.6102, 5.19209, 0),
+(@PATH, 18, -4107.71, -13772.5, 74.6982, 5.80705, 0),
+(@PATH, 19, -4102.51, -13772.3, 74.7185, 0.511104, 0),
+(@PATH, 20, -4099.89, -13768, 74.7256, 1.36954, 0),
+(@PATH, 21, -4102.44, -13763.8, 74.5717, 2.63796, 12000),
+(@PATH, 22, -4125.6, -13762, 74.1406, 3.4807, 0),
+(@PATH, 23, -4129.88, -13764.2, 74.5865, 3.28513, 0),
+(@PATH, 24, -4135.57, -13762.7, 74.657, 2.14081, 0),
+(@PATH, 25, -4137.16, -13760, 74.6108, 1.35698, 0),
+(@PATH, 26, -4135.66, -13756.6, 74.5907, 0.545662, 0),
+(@PATH, 27, -4131.3, -13754.6, 74.6109, 6.14319, 0),
+(@PATH, 28, -4127.9, -13756.6, 74.2825, 5.30675, 0),
+(@PATH, 29, -4127.08, -13760.8, 74.2562, 5.74265, 0),
+(@PATH, 30, -4121.58, -13761.4, 73.5881, 0.0354084, 0),
+(@PATH, 31, -4113.68, -13762, 73.5694, 5.80705, 0),
+(@PATH, 32, -4110.51, -13765.2, 73.6102, 5.19209, 0),
+(@PATH, 33, -4107.71, -13772.5, 74.6982, 5.80705, 0),
+(@PATH, 34, -4102.51, -13772.3, 74.7185, 0.511104, 0),
+(@PATH, 35, -4099.89, -13768, 74.7256, 1.36954, 0),
+(@PATH, 36, -4102.44, -13763.8, 74.5717, 2.63796, 0),
+(@PATH, 37, -4125.6, -13762, 74.1406, 3.4807, 0),
+(@PATH, 38, -4129.88, -13764.2, 74.5865, 3.28513, 0),
+(@PATH, 39, -4135.57, -13762.7, 74.657, 2.14081, 0),
+(@PATH, 40, -4137.16, -13760, 74.6108, 1.35698, 0),
+(@PATH, 41, -4135.66, -13756.6, 74.5907, 0.545662, 0),
+(@PATH, 42, -4131.3, -13754.6, 74.6109, 6.14319, 0),
+(@PATH, 43, -4127.9, -13756.6, 74.2825, 5.30675, 0),
+(@PATH, 44, -4127.08, -13760.8, 74.2562, 5.74265, 0),
+(@PATH, 45, -4121.58, -13761.4, 73.5881, 0.0354084, 0),
+(@PATH, 46, -4113.68, -13762, 73.5694, 5.80705, 0),
+(@PATH, 47, -4110.51, -13765.2, 73.6102, 5.19209, 0),
+(@PATH, 48, -4107.71, -13772.5, 74.6982, 5.80705, 0),
+(@PATH, 49, -4102.51, -13772.3, 74.7185, 0.511104, 0),
+(@PATH, 50, -4099.89, -13768, 74.7256, 1.36954, 0),
+(@PATH, 51, -4102.44, -13763.8, 74.5717, 2.63796, 0),
+(@PATH, 52, -4125.6, -13762, 74.1406, 3.4807, 0),
+(@PATH, 53, -4129.88, -13764.2, 74.5865, 3.28513, 0),
+(@PATH, 54, -4135.57, -13762.7, 74.657, 2.14081, 0),
+(@PATH, 55, -4137.16, -13760, 74.6108, 1.35698, 0),
+(@PATH, 56, -4135.66, -13756.6, 74.5907, 0.545662, 0),
+(@PATH, 57, -4131.3, -13754.6, 74.6109, 6.14319, 0),
+(@PATH, 58, -4127.9, -13756.6, 74.2825, 5.30675, 0),
+(@PATH, 59, -4127.08, -13760.8, 74.2562, 5.74265, 0),
+(@PATH, 60, -4121.58, -13761.4, 73.5881, 0.0354084, 0),
+(@PATH, 61, -4113.68, -13762, 73.5694, 5.80705, 0),
+(@PATH, 62, -4110.51, -13765.2, 73.6102, 5.19209, 0),
+(@PATH, 63, -4107.71, -13772.5, 74.6982, 5.80705, 0),
+(@PATH, 64, -4102.51, -13772.3, 74.7185, 0.511104, 0),
+(@PATH, 65, -4099.89, -13768, 74.7256, 1.36954, 0),
+(@PATH, 66, -4102.44, -13763.8, 74.5717, 2.63796, 0),
+(@PATH, 67, -4125.6, -13762, 74.1406, 3.4807, 0),
+(@PATH, 68, -4129.88, -13764.2, 74.5865, 3.28513, 12000),
+(@PATH, 69, -4135.57, -13762.7, 74.657, 2.14081, 0),
+(@PATH, 70, -4137.16, -13760, 74.6108, 1.35698, 0),
+(@PATH, 71, -4135.66, -13756.6, 74.5907, 0.545662, 0),
+(@PATH, 72, -4131.3, -13754.6, 74.6109, 6.14319, 0),
+(@PATH, 73, -4127.9, -13756.6, 74.2825, 5.30675, 0),
+(@PATH, 74, -4127.08, -13760.8, 74.2562, 5.74265, 0),
+(@PATH, 75, -4121.58, -13761.4, 73.5881, 0.0354084, 0),
+(@PATH, 76, -4113.68, -13762, 73.5694, 5.80705, 0),
+(@PATH, 77, -4110.51, -13765.2, 73.6102, 5.19209, 0),
+(@PATH, 78, -4107.71, -13772.5, 74.6982, 5.80705, 0),
+(@PATH, 79, -4102.51, -13772.3, 74.7185, 0.511104, 0),
+(@PATH, 80, -4099.89, -13768, 74.7256, 1.36954, 0),
+(@PATH, 81, -4102.44, -13763.8, 74.5717, 2.63796, 0),
+(@PATH, 82, -4125.6, -13762, 74.1406, 3.4807, 0),
+(@PATH, 83, -4129.88, -13764.2, 74.5865, 3.28513, 0),
+(@PATH, 84, -4135.57, -13762.7, 74.657, 2.14081, 0),
+(@PATH, 85, -4137.16, -13760, 74.6108, 1.35698, 0),
+(@PATH, 86, -4135.66, -13756.6, 74.5907, 0.545662, 0),
+(@PATH, 87, -4131.3, -13754.6, 74.6109, 6.14319, 0),
+(@PATH, 88, -4127.9, -13756.6, 74.2825, 5.30675, 0),
+(@PATH, 89, -4127.08, -13760.8, 74.2562, 5.74265, 0),
+(@PATH, 90, -4121.58, -13761.4, 73.5881, 0.0354084, 0),
+(@PATH, 91, -4113.68, -13762, 73.5694, 5.80705, 0),
+(@PATH, 92, -4110.51, -13765.2, 73.6102, 5.19209, 0),
+(@PATH, 93, -4107.71, -13772.5, 74.6982, 5.80705, 0),
+(@PATH, 94, -4102.51, -13772.3, 74.7185, 0.511104, 0),
+(@PATH, 95, -4099.89, -13768, 74.7256, 1.36954, 0),
+(@PATH, 96, -4102.44, -13763.8, 74.5717, 2.63796, 0),
+(@PATH, 97, -4125.6, -13762, 74.1406, 3.4807, 0),
+(@PATH, 98, -4129.88, -13764.2, 74.5865, 3.28513, 0),
+(@PATH, 99, -4135.57, -13762.7, 74.657, 2.14081, 0),
+(@PATH, 100, -4137.16, -13760, 74.6108, 1.35698, 0),
+(@PATH, 101, -4135.66, -13756.6, 74.5907, 0.545662, 0),
+(@PATH, 102, -4131.3, -13754.6, 74.6109, 6.14319, 0),
+(@PATH, 103, -4127.9, -13756.6, 74.2825, 5.30675, 0),
+(@PATH, 104, -4127.08, -13760.8, 74.2562, 5.74265, 0),
+(@PATH, 105, -4121.58, -13761.4, 73.5881, 0.0354084, 0);
+
+-- Zalduun SAI
+SET @ENTRY := 16502;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,74,0,100,0,0,40,120000,120000,11,29170,0,0,0,0,0,9,0,0,0,0,0,0,0,"Zalduun - On Friendly Between 0-40% Health - Cast 'Lesser Heal'"),
+(@ENTRY,0,1,0,34,0,100,0,2,20,0,0,80,@ENTRY*100+00,0,0,0,0,0,1,0,0,0,0,0,0,0,"Zalduun - On Reached Point 20 - Run Script"),
+(@ENTRY,0,2,0,34,0,100,0,2,67,0,0,80,@ENTRY*100+01,0,0,0,0,0,1,0,0,0,0,0,0,0,"Zalduun - On Reached Point 67 - Run Script");
+
+-- Actionlist SAI
+SET @ENTRY := 1650200;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,0,0,0,0,1,0,5000,0,0,0,0,1,0,0,0,0,0,0,0,"Zalduun - On Script - Say Line 0"),
+(@ENTRY,9,1,0,0,0,100,0,2000,2000,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,4.31173,"Zalduun - On Script - Set Orientation 4.31173"),
+(@ENTRY,9,2,0,0,0,100,0,2000,2000,0,0,11,29170,0,0,0,0,0,10,59238,16971,0,0,0,0,0,"Zalduun - On Script - Cast 'Lesser Heal'");
+
+-- Actionlist SAI
+SET @ENTRY := 1650201;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,0,0,0,0,1,0,5000,0,0,0,0,1,0,0,0,0,0,0,0,"Zalduun - On Script - Say Line 0"),
+(@ENTRY,9,1,0,0,0,100,0,2000,2000,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,0.157151,"Zalduun - On Script - Set Orientation 0.157151"),
+(@ENTRY,9,2,0,0,0,100,0,2000,2000,0,0,11,29170,0,0,0,0,0,10,59240,16971,0,0,0,0,0,"Zalduun - On Script - Cast 'Lesser Heal'");
+
+DELETE FROM `creature_text` WHERE `CreatureID`=16502;
+INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `comment`) VALUES
+(16502, 0, 0, 'Oh no! I\'m losing this one!', 12, 7, 100, 0, 0, 0, 13113, 'Zalduun');
diff --git a/sql/updates/world/master/2020_04_10_18_world_2017_01_22_07_world.sql b/sql/updates/world/master/2020_04_10_18_world_2017_01_22_07_world.sql
new file mode 100644
index 00000000000..bf0072004e7
--- /dev/null
+++ b/sql/updates/world/master/2020_04_10_18_world_2017_01_22_07_world.sql
@@ -0,0 +1,6 @@
+-- Torseg the Exiled SAI
+SET @ENTRY := 29350;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0 AND `id`>=2;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,0,2,0,25,0,100,0,0,0,0,0,90,3,0,0,0,0,0,1,0,0,0,0,0,0,0,"Torseg the Exiled - On Reset - Set Flag Standstate Sleep"),
+(@ENTRY,0,3,0,4,0,100,0,0,0,0,0,91,3,0,0,0,0,0,1,0,0,0,0,0,0,0,"Torseg the Exiled - On Aggro - Remove Flag Standstate Sleep");
diff --git a/sql/updates/world/master/2020_04_10_19_world_2017_01_22_08_world.sql b/sql/updates/world/master/2020_04_10_19_world_2017_01_22_08_world.sql
new file mode 100644
index 00000000000..d8751725a89
--- /dev/null
+++ b/sql/updates/world/master/2020_04_10_19_world_2017_01_22_08_world.sql
@@ -0,0 +1,40 @@
+-- Reduce respawntime for landmine
+UPDATE `gameobject` SET `spawntimesecs`=10 WHERE `id`=191502;
+
+-- add fake death emote for Savage Hill Scavengers
+UPDATE `creature` SET `spawndist`=0, `MovementType`=0, `unit_flags`=`unit_flags`|536870912|33554432|32770, `dynamicflags`=32 WHERE `guid` IN (116957, 116956, 116958, 116959);
+DELETE FROM `creature_addon` WHERE `guid` IN (116957, 116956, 116958, 116959);
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES
+(116957,0,0,7,1,0, '29266'),
+(116956,0,0,7,1,0, '29266'),
+(116958,0,0,7,1,0, '29266'),
+(116959,0,0,7,1,0, '29266');
+
+-- add textevent for Janks
+-- Janks SAI
+SET @ENTRY := 29429;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,25,0,100,0,0,0,0,0,90,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Janks - On Reset - Set Flag Standstate Sit Down"),
+(@ENTRY,0,1,0,10,0,100,0,1,10,55000,55000,80,@ENTRY*100+00,0,0,0,0,0,1,0,0,0,0,0,0,0,"Janks - Within 0-10 Range Out of Combat LoS - Run Script");
+
+-- Actionlist SAI
+SET @ENTRY := 2942900;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,0,0,0,0,48,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Janks - On Script - Set Active On"),
+(@ENTRY,9,1,0,0,0,100,0,0,0,0,0,91,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Janks - On Script - Remove Flag Standstate Sit Down"),
+(@ENTRY,9,2,0,0,0,100,0,0,0,0,0,1,0,5000,0,0,0,0,1,0,0,0,0,0,0,0,"Janks - On Script - Say Line 0"),
+(@ENTRY,9,3,0,0,0,100,0,5000,5000,0,0,1,1,5000,0,0,0,0,1,0,0,0,0,0,0,0,"Janks - On Script - Say Line 1"),
+(@ENTRY,9,4,0,0,0,100,0,5000,5000,0,0,1,2,5000,0,0,0,0,1,0,0,0,0,0,0,0,"Janks - On Script - Say Line 2"),
+(@ENTRY,9,5,0,0,0,100,0,5000,5000,0,0,1,3,5000,0,0,0,0,1,0,0,0,0,0,0,0,"Janks - On Script - Say Line 3"),
+(@ENTRY,9,6,0,0,0,100,0,3000,3000,0,0,90,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Janks - On Script - Set Flag Standstate Sit Down"),
+(@ENTRY,9,7,0,0,0,100,0,0,0,0,0,48,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Janks - On Script - Set Active Off");
+
+DELETE FROM `creature_text` WHERE `CreatureID`=29429;
+INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `comment`) VALUES
+(29429, 0, 0, 'Is it true?! Has someone finally come to get me out of this place?', 12, 0, 100, 0, 0, 0, 30198, 'Janks'),
+(29429, 1, 0, 'No... no... that''s not it, is it? That heartless lout probably sent you after the tools, didn''t he?', 12, 0, 100, 0, 0, 0, 30199, 'Janks'),
+(29429, 2, 0, 'Well... I guess I''ll just keep an eye on the turrets... or something.', 12, 0, 100, 0, 0, 0, 30200, 'Janks'),
+(29429, 3, 0, '%s sighs.', 16, 0, 100, 0, 0, 0, 30201, 'Janks');
diff --git a/sql/updates/world/master/2020_04_10_20_world_2017_01_22_09_world.sql b/sql/updates/world/master/2020_04_10_20_world_2017_01_22_09_world.sql
new file mode 100644
index 00000000000..01f6f5787fa
--- /dev/null
+++ b/sql/updates/world/master/2020_04_10_20_world_2017_01_22_09_world.sql
@@ -0,0 +1,131 @@
+-- Bailey + Bellinger Event
+UPDATE `creature` SET `spawndist`=0, `MovementType`=0 WHERE `guid` IN (114937, 114958);
+DELETE FROM `creature_formations` WHERE `leaderGUID`=114937;
+INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES
+(114937, 114937, 0, 0, 4, 0, 0),
+(114937, 114958, 2, 270, 4, 0, 0);
+
+-- Bailey SAI
+SET @ENTRY := 29643;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,1,0,100,0,1000,1000,900000,900000,80,@ENTRY*100+00,0,0,0,0,0,1,0,0,0,0,0,0,0,"Bailey - Out of Combat - Run Script"),
+(@ENTRY,0,1,0,40,0,100,0,4,29643,0,0,80,@ENTRY*100+01,0,0,0,0,0,1,0,0,0,0,0,0,0,"Bailey - On Waypoint 4 Reached - Run Script"),
+(@ENTRY,0,2,0,40,0,100,0,8,29643,0,0,80,@ENTRY*100+02,0,0,0,0,0,1,0,0,0,0,0,0,0,"Bailey - On Waypoint 8 Reached - Run Script"),
+(@ENTRY,0,3,0,40,0,100,0,15,29643,0,0,80,@ENTRY*100+03,0,0,0,0,0,1,0,0,0,0,0,0,0,"Bailey - On Waypoint 15 Reached - Run Script");
+
+-- Actionlist SAI
+SET @ENTRY := 2964300;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,0,0,0,0,1,0,6000,0,0,0,0,1,0,0,0,0,0,0,0,"Bailey - On Script - Say Line 0"),
+(@ENTRY,9,1,0,0,0,100,0,6000,6000,0,0,1,0,6000,0,0,0,0,10,114958,29644,0,0,0,0,0,"Bailey - On Script - Say Line 0"),
+(@ENTRY,9,2,0,0,0,100,0,6000,6000,0,0,1,1,6000,0,0,0,0,1,0,0,0,0,0,0,0,"Bailey - On Script - Say Line 1"),
+(@ENTRY,9,3,0,0,0,100,0,6000,6000,0,0,1,1,6000,0,0,0,0,10,114958,29644,0,0,0,0,0,"Bailey - On Script - Say Line 1"),
+(@ENTRY,9,4,0,0,0,100,0,6000,6000,0,0,1,2,6000,0,0,0,0,1,0,0,0,0,0,0,0,"Bailey - On Script - Say Line 2"),
+(@ENTRY,9,5,0,0,0,100,0,6000,6000,0,0,1,2,0,0,0,0,0,10,114958,29644,0,0,0,0,0,"Bailey - On Script - Say Line 2"),
+(@ENTRY,9,6,0,0,0,100,0,0,0,0,0,66,0,0,0,0,0,0,10,114958,29644,0,0,0,0,0,"Bailey - On Script - Set Orientation Closest Creature 'Bellinger'"),
+(@ENTRY,9,7,0,0,0,100,0,6000,6000,0,0,1,3,6000,0,0,0,0,1,0,0,0,0,0,0,0,"Bailey - On Script - Say Line 3"),
+(@ENTRY,9,8,0,0,0,100,0,3000,3000,0,0,5,60,0,0,0,0,0,1,0,0,0,0,0,0,0,"Bailey - On Script - Play Emote 60"),
+(@ENTRY,9,9,0,0,0,100,0,0,0,0,0,86,54899,0,10,114958,29644,0,1,0,0,0,0,0,0,0,"Bailey - On Script - Cross Cast 'Knockback 15'"),
+(@ENTRY,9,10,0,0,0,100,0,5000,5000,0,0,1,3,5000,0,0,0,0,10,114958,29644,0,0,0,0,0,"Bailey - On Script - Say Line 3"),
+(@ENTRY,9,11,0,0,0,100,0,0,0,0,0,45,4,4,0,0,0,0,10,114958,29644,0,0,0,0,0,"Bailey - On Script - Set Data 4 4"),
+(@ENTRY,9,12,0,0,0,100,0,0,0,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,1.58825,"Bailey - On Script - Set Orientation 1.58825"),
+(@ENTRY,9,13,0,0,0,100,0,3000,3000,0,0,1,4,3000,0,0,0,0,10,114958,29644,0,0,0,0,0,"Bailey - On Script - Say Line 4"),
+(@ENTRY,9,14,0,0,0,100,0,5000,5000,0,0,45,1,1,0,0,0,0,10,114958,29644,0,0,0,0,0,"Bailey - On Script - Set Data 1 1"),
+(@ENTRY,9,15,0,0,0,100,0,300000,300000,0,0,1,5,6000,0,0,0,0,10,114958,29644,0,0,0,0,0,"Bailey - On Script - Say Line 5"), -- 5min
+(@ENTRY,9,16,0,0,0,100,0,6000,6000,0,0,1,4,6000,0,0,0,0,1,0,0,0,0,0,0,0,"Bailey - On Script - Say Line 4"),
+(@ENTRY,9,17,0,0,0,100,0,6000,6000,0,0,1,6,6000,0,0,0,0,10,114958,29644,0,0,0,0,0,"Bailey - On Script - Say Line 6"),
+(@ENTRY,9,18,0,0,0,100,0,6000,6000,0,0,1,7,6000,0,0,0,0,10,114958,29644,0,0,0,0,0,"Bailey - On Script - Say Line 7"),
+(@ENTRY,9,19,0,0,0,100,0,6000,6000,0,0,1,8,6000,0,0,0,0,10,114958,29644,0,0,0,0,0,"Bailey - On Script - Say Line 8"),
+(@ENTRY,9,20,0,0,0,100,0,6000,6000,0,0,1,5,6000,0,0,0,0,1,0,0,0,0,0,0,0,"Bailey - On Script - Say Line 5"),
+(@ENTRY,9,21,0,0,0,100,0,6000,6000,0,0,1,6,6000,0,0,0,0,1,0,0,0,0,0,0,0,"Bailey - On Script - Say Line 6"),
+(@ENTRY,9,22,0,0,0,100,0,300000,300000,0,0,53,0,29643,0,0,0,1,1,0,0,0,0,0,0,0,"Bailey - On Script - Start Waypoint"); -- 5min 300000
+
+-- Actionlist SAI
+SET @ENTRY := 2964301;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,0,0,0,0,54,13000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Bailey - On Script - Pause Waypoint"),
+(@ENTRY,9,1,0,0,0,100,0,1000,1000,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,2.085985,"Bailey - On Script - Set Orientation 2,085985"),
+(@ENTRY,9,2,0,0,0,100,0,1000,1000,0,0,45,2,2,0,0,0,0,10,114958,29644,0,0,0,0,0,"Bailey - On Script - Set Data 2 2"),
+(@ENTRY,9,3,0,0,0,100,0,1000,1000,0,0,1,7,6000,0,0,0,0,1,0,0,0,0,0,0,0,"Bailey - On Script - Say Line 7"),
+(@ENTRY,9,4,0,0,0,100,0,6000,6000,0,0,1,9,5000,0,0,0,0,10,114958,29644,0,0,0,0,0,"Bailey - On Script - Say Line 9");
+
+-- Actionlist SAI
+SET @ENTRY := 2964302;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,0,0,0,0,54,33000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Bailey - On Script - Pause Waypoint"),
+(@ENTRY,9,1,0,0,0,100,0,1000,1000,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,2.50084,"Bailey - On Script - Set Orientation 2.50084"),
+(@ENTRY,9,2,0,0,0,100,0,1000,1000,0,0,45,3,3,0,0,0,0,10,114958,29644,0,0,0,0,0,"Bailey - On Script - Set Data 3 3"),
+(@ENTRY,9,3,0,0,0,100,0,3000,3000,0,0,1,8,6000,0,0,0,0,1,0,0,0,0,0,0,0,"Bailey - On Script - Say Line 8"),
+(@ENTRY,9,4,0,0,0,100,0,6000,6000,0,0,1,10,6000,0,0,0,0,10,114958,29644,0,0,0,0,0,"Bailey - On Script - Say Line 10"),
+(@ENTRY,9,5,0,0,0,100,0,6000,6000,0,0,1,9,6000,0,0,0,0,1,0,0,0,0,0,0,0,"Bailey - On Script - Say Line 9"),
+(@ENTRY,9,6,0,0,0,100,0,6000,6000,0,0,1,11,6000,0,0,0,0,10,114958,29644,0,0,0,0,0,"Bailey - On Script - Say Line 11"),
+(@ENTRY,9,7,0,0,0,100,0,6000,6000,0,0,1,10,6000,0,0,0,0,1,0,0,0,0,0,0,0,"Bailey - On Script - Say Line 10");
+
+-- Actionlist SAI
+SET @ENTRY := 2964303;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,4000,4000,0,0,45,5,5,0,0,0,0,10,114958,29644,0,0,0,0,0,"Bailey - On Script - Set Data 5 5"),
+(@ENTRY,9,1,0,0,0,100,0,1000,1000,0,0,48,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Bailey - On Script - Set Active Off");
+
+-- Bellinger SAI
+SET @ENTRY := 29644;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,38,0,100,0,1,1,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,1.50098,"Bellinger - On Data Set 1 1 - Set Orientation 1.50098"),
+(@ENTRY,0,1,0,38,0,100,0,2,2,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,2.08598,"Bellinger - On Data Set 2 2 - Set Orientation 2.08598"),
+(@ENTRY,0,2,0,38,0,100,0,3,3,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,2.50084,"Bellinger - On Data Set 3 3 - Set Orientation 2.50084"),
+(@ENTRY,0,3,0,38,0,100,0,4,4,0,0,69,0,0,0,0,0,0,8,0,0,0,6034.820,-750.8344,369.8008,1.4146,"Bellinger - On Data Set 4 4 - Move To Position"),
+(@ENTRY,0,4,0,38,0,100,0,5,5,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,1.269333,"Bellinger - On Data Set 3 3 - Set Orientation 1.269333");
+
+DELETE FROM `creature_text` WHERE `CreatureID` IN (29643, 29644);
+INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `comment`) VALUES
+-- Bailey
+(29643, 0, 0, 'This doesn''t look pretty, lad.', 12, 0, 100, 1, 0, 0, 30286, 'Bailey'),
+(29643, 1, 0, 'That right? Well why don''t you go prance your merry little self over and grab them, eh?', 12, 0, 100, 6, 0, 0, 30289, 'Bailey'),
+(29643, 2, 0, 'That''s strange... for a moment there, I could have swore you called me short.', 12, 0, 100, 1, 0, 0, 30288, 'Bailey'),
+(29643, 3, 0, 'Toss me?! Okay, that''s it punk.', 12, 0, 100, 5, 0, 0, 30290, 'Bailey'),
+(29643, 4, 0, 'Keep it to yourself.', 12, 0, 100, 1, 0, 0, 30291, 'Bailey'),
+(29643, 5, 0, 'You better hope they don''t survive it, lad.', 12, 0, 100, 1, 0, 0, 30292, 'Bailey'),
+(29643, 6, 0, 'Cause I''m just going to watch and laugh as they toss you in.', 12, 0, 100, 1, 0, 0, 30293, 'Bailey'),
+(29643, 7, 0, 'There''s got to be a way in somewhere.', 12, 0, 100, 1, 0, 0, 30294, 'Bailey'),
+(29643, 8, 0, 'How''d the goblin leave his tools there then?', 12, 0, 100, 1, 0, 0, 30295, 'Bailey'),
+(29643, 9, 0, 'That''s it, lad! It looks totally safe. Go for it, I''ll be right behind ya!', 12, 0, 100, 5, 0, 0, 30296, 'Bailey'),
+(29643, 10, 0, 'Pansy.', 12, 0, 100, 5, 0, 0, 30312, 'Bailey'),
+-- Bellinger
+(29644, 0, 0, 'I don''t know, Bailey... it''s not so bad. We could throw a rock at the tools from here.', 12, 0, 100, 1, 0, 0, 30287, 'Bellinger'),
+(29644, 1, 0, 'Well... I was just thinking... you''re a bit smaller, so you''re less likely to set off any of those mines.', 12, 0, 100, 1, 0, 0, 30297, 'Bellinger'),
+(29644, 2, 0, 'No, no, no! Not short... it''s just... well... maybe I could toss you across most of it?', 12, 0, 100, 1, 0, 0, 30298, 'Bellinger'),
+(29644, 3, 0, 'Ahhh!', 12, 0, 100, 0, 0, 0, 30306, 'Bellinger'),
+(29644, 4, 0, 'That was close! You scared me.', 12, 0, 100, 5, 0, 0, 30311, 'Bellinger'),
+(29644, 5, 0, 'I''ve got an idea, Bailey...', 12, 0, 100, 5, 0, 0, 30299, 'Bellinger'),
+(29644, 6, 0, 'No, no - this might work!', 12, 0, 100, 5, 0, 0, 30300, 'Bellinger'),
+(29644, 7, 0, 'There''s a path right there... only a few mines at the end in between us and the tools.', 12, 0, 100, 1, 0, 0, 30301, 'Bellinger'),
+(29644, 8, 0, 'We wait for the next adventurer to come through and we tell him that''s the way to go... then after they set off the mines, we just walk in and grab the tools!', 12, 0, 100, 1, 0, 0, 30302, 'Bellinger'),
+(29644, 9, 0, 'It really doesn''t look like it, Bailey.', 12, 0, 100, 1, 0, 0, 30303, 'Bellinger'),
+(29644, 10, 0, 'Oh... good point. How about right there? That looks clear... kind of.', 12, 0, 100, 1, 0, 0, 30304, 'Bellinger'),
+(29644, 11, 0, 'Uh... that''s okay. It still kind of hurts from last time.', 12, 0, 100, 1, 0, 0, 30305, 'Bellinger');
+
+DELETE FROM `waypoints` WHERE `entry`=29643;
+INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `point_comment`) VALUES
+(29643, 1, 6043.27, -752.358, 371.289, 'Bailey'),
+(29643, 2, 6057.13, -750.684, 374.297, 'Bailey'),
+(29643, 3, 6075.11, -746.512, 378.785, 'Bailey'),
+(29643, 4, 6074.88, -746.098, 378.744, 'Bailey'),
+(29643, 5, 6082.66, -744.527, 380.612, 'Bailey'),
+(29643, 6, 6094.52, -739.821, 383.156, 'Bailey'),
+(29643, 7, 6108.06, -728.91, 385.165, 'Bailey'),
+(29643, 8, 6106.12, -727.415, 384.716, 'Bailey'),
+(29643, 9, 6103.38, -731.758, 384.439, 'Bailey'),
+(29643, 10, 6094.78, -740.08, 383.232, 'Bailey'),
+(29643, 11, 6081.35, -743.988, 380.304, 'Bailey'),
+(29643, 12, 6064.46, -748.543, 376.139, 'Bailey'),
+(29643, 13, 6047.42, -752.5, 372.131, 'Bailey'),
+(29643, 14, 6036.15, -753.071, 369.981, 'Bailey'),
+(29643, 15, 6036.69, -751.232, 370.083, 'Bailey');
diff --git a/sql/updates/world/master/2020_04_10_21_world_2017_01_22_12_world.sql b/sql/updates/world/master/2020_04_10_21_world_2017_01_22_12_world.sql
new file mode 100644
index 00000000000..cf5e82f626e
--- /dev/null
+++ b/sql/updates/world/master/2020_04_10_21_world_2017_01_22_12_world.sql
@@ -0,0 +1,148 @@
+-- Footman Rob + Footman Chuck + Footman George + Footman Mitch - Path and Textevent
+
+-- Footman Rob SAI
+SET @ENTRY := 25258;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,34,0,100,1,2,5,0,0,80,@ENTRY*100+00,0,0,0,0,0,1,0,0,0,0,0,0,0,"Footman Rob - On Reached Point 5 - Run Script (No Repeat)"),
+(@ENTRY,0,1,0,34,0,100,0,2,9,0,0,80,@ENTRY*100+01,0,0,0,0,0,1,0,0,0,0,0,0,0,"Footman Rob - On Reached Point 9 - Run Script"),
+(@ENTRY,0,2,0,34,0,100,0,2,10,0,0,80,@ENTRY*100+02,0,0,0,0,0,1,0,0,0,0,0,0,0,"Footman Rob - On Reached Point 10 - Run Script"),
+(@ENTRY,0,3,0,34,0,100,1,2,15,0,0,12,25260,3,180000,0,0,0,8,0,0,0,2255.77,5186.26,11.4391,1.47479,"Footman Rob - On Reached Point 15 - Summon Creature 'Footman Mitch' (No Repeat)"),
+(@ENTRY,0,4,0,34,0,100,0,2,17,0,0,80,@ENTRY*100+03,0,0,0,0,0,1,0,0,0,0,0,0,0,"Footman Rob - On Reached Point 17 - Run Script"),
+(@ENTRY,0,5,0,17,0,100,0,25260,0,0,0,64,1,0,0,0,0,0,7,0,0,0,0,0,0,0,"Footman Rob - On Summoned Unit - Store Targetlist"),
+(@ENTRY,0,6,0,1,0,100,1,100,100,0,0,71,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Footman Rob - Out of Combat - Change Equipment (No Repeat)"),
+(@ENTRY,0,7,0,1,0,100,1,100,100,0,0,71,0,0,0,0,0,0,10,85222,25259,0,0,0,0,0,"Footman Rob - Out of Combat - Change Equipment (No Repeat)"),
+(@ENTRY,0,8,0,1,0,100,1,100,100,0,0,71,0,0,0,0,0,0,10,85226,25261,0,0,0,0,0,"Footman Rob - Out of Combat - Change Equipment (No Repeat)");
+
+-- Actionlist SAI -- Stop in Front of house
+SET @ENTRY := 2525800;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,3000,3000,0,0,1,0,6000,0,0,0,0,1,0,0,0,0,0,0,0,"Footman Rob - On Script - Say Line 0"),
+(@ENTRY,9,1,0,0,0,100,0,6000,6000,0,0,1,0,0,0,0,0,0,10,85222,25259,0,0,0,0,0,"Footman Rob - On Script - Say Line 0");
+
+-- Actionlist SAI - stop in front of barkeeper
+SET @ENTRY := 2525801;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,4000,4000,0,0,1,1,6000,0,0,0,0,1,0,0,0,0,0,0,0,"Footman Rob - On Script - Say Line 1"),
+(@ENTRY,9,1,0,0,0,100,0,6000,6000,0,0,1,0,6000,0,0,0,0,10,110613,25245,0,0,0,0,0,"Footman Rob - On Script - Say Line 0"),
+(@ENTRY,9,2,0,0,0,100,0,6000,6000,0,0,1,2,6000,0,0,0,0,1,0,0,0,0,0,0,0,"Footman Rob - On Script - Say Line 2"),
+(@ENTRY,9,3,0,0,0,100,0,6000,6000,0,0,1,1,6000,0,0,0,0,10,110613,25245,0,0,0,0,0,"Footman Rob - On Script - Say Line 1"),
+(@ENTRY,9,4,0,0,0,100,0,3000,3000,0,0,5,397,0,0,0,0,0,10,110613,25245,0,0,0,0,0,"Footman Rob - On Script - Play Emote 397"),
+(@ENTRY,9,5,0,0,0,100,0,7000,7000,0,0,17,423,0,0,0,0,0,1,0,0,0,0,0,0,0,"Footman Rob - On Script - Set Emote State 423"),
+(@ENTRY,9,6,0,0,0,100,0,0,0,0,0,71,1,0,2703,0,0,0,1,0,0,0,0,0,0,0,"Footman Rob - On Script - Change Equipment"),
+(@ENTRY,9,7,0,0,0,100,0,0,0,0,0,71,1,0,2703,0,0,0,10,85222,25259,0,0,0,0,0,"Footman Rob - On Script - Change Equipment"),
+(@ENTRY,9,8,0,0,0,100,0,0,0,0,0,71,1,0,2703,0,0,0,10,85226,25261,0,0,0,0,0,"Footman Rob - On Script - Change Equipment"),
+(@ENTRY,9,9,0,0,0,100,0,5000,5000,0,0,17,423,0,0,0,0,0,10,85222,25259,0,0,0,0,0,"Footman Rob - On Script - Set Emote State 423"),
+(@ENTRY,9,10,0,0,0,100,0,0,0,0,0,17,423,0,0,0,0,0,10,85226,25261,0,0,0,0,0,"Footman Rob - On Script - Set Emote State 423"),
+(@ENTRY,9,11,0,0,0,100,0,22000,22000,0,0,17,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Footman Rob - On Script - Set Emote State 0"),
+(@ENTRY,9,12,0,0,0,100,0,0,0,0,0,17,0,0,0,0,0,0,10,85222,25259,0,0,0,0,0,"Footman Rob - On Script - Set Emote State 0"),
+(@ENTRY,9,13,0,0,0,100,0,0,0,0,0,17,0,0,0,0,0,0,10,85226,25261,0,0,0,0,0,"Footman Rob - On Script - Set Emote State 0"),
+(@ENTRY,9,14,0,0,0,100,0,0,0,0,0,71,1,0,2703,0,0,0,1,0,0,0,0,0,0,0,"Footman Rob - On Script - Change Equipment"),
+(@ENTRY,9,15,0,0,0,100,0,0,0,0,0,71,1,0,2703,0,0,0,10,85222,25259,0,0,0,0,0,"Footman Rob - On Script - Change Equipment"),
+(@ENTRY,9,16,0,0,0,100,0,0,0,0,0,71,1,0,2703,0,0,0,10,85226,25261,0,0,0,0,0,"Footman Rob - On Script - Change Equipment"),
+(@ENTRY,9,17,0,0,0,100,0,0,0,0,0,71,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Footman Rob - On Script - Change Equipment"),
+(@ENTRY,9,18,0,0,0,100,0,0,0,0,0,71,0,0,0,0,0,0,10,85222,25259,0,0,0,0,0,"Footman Rob - On Script - Change Equipment"),
+(@ENTRY,9,19,0,0,0,100,0,0,0,0,0,71,0,0,0,0,0,0,10,85226,25261,0,0,0,0,0,"Footman Rob - On Script - Change Equipment");
+
+-- Actionlist SAI - prepare leave building
+SET @ENTRY := 2525802;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,1000,1000,0,0,1,3,6000,0,0,0,0,1,0,0,0,0,0,0,0,"Footman Rob - On Script - Say Line 3"),
+(@ENTRY,9,1,0,0,0,100,0,3000,3000,0,0,45,1,1,0,0,0,0,10,85222,25259,0,0,0,0,0,"Footman Rob - On Script - Set Data 1 1"),
+(@ENTRY,9,2,0,0,0,100,0,0,0,0,0,45,1,1,0,0,0,0,10,85226,25261,0,0,0,0,0,"Footman Rob - On Script - Set Data 1 1"),
+(@ENTRY,9,3,0,0,0,100,0,3000,3000,0,0,1,0,6000,0,0,0,0,10,85226,25261,0,0,0,0,0,"Footman Rob - On Script - Say Line 0"),
+(@ENTRY,9,4,0,0,0,100,0,6000,6000,0,0,5,11,0,0,0,0,0,1,0,0,0,0,0,0,0,"Footman Rob - On Script - Play Emote 11"),
+(@ENTRY,9,5,0,0,0,100,0,0,0,0,0,5,11,0,0,0,0,0,10,85222,25259,0,0,0,0,0,"Footman Rob - On Script - Play Emote 11"),
+(@ENTRY,9,6,0,0,0,100,0,0,0,0,0,5,11,0,0,0,0,0,10,85226,25261,0,0,0,0,0,"Footman Rob - On Script - Play Emote 11"),
+(@ENTRY,9,7,0,0,0,100,0,1000,1000,0,0,5,274,0,0,0,0,0,1,0,0,0,0,0,0,0,"Footman Rob - On Script - Play Emote 274"),
+(@ENTRY,9,8,0,0,0,100,0,0,0,0,0,5,274,0,0,0,0,0,10,85222,25259,0,0,0,0,0,"Footman Rob - On Script - Play Emote 274"),
+(@ENTRY,9,9,0,0,0,100,0,0,0,0,0,5,274,0,0,0,0,0,10,85226,25261,0,0,0,0,0,"Footman Rob - On Script - Play Emote 274");
+
+-- Actionlist SAI - despawn all member
+SET @ENTRY := 2525803;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,0,0,0,0,41,1,0,0,0,0,0,10,85222,25259,0,0,0,0,0,"Footman Rob - On Script - Despawn Instant"),
+(@ENTRY,9,1,0,0,0,100,0,0,0,0,0,41,1,0,0,0,0,0,10,85226,25261,0,0,0,0,0,"Footman Rob - On Script - Despawn Instant"),
+(@ENTRY,9,2,0,0,0,100,0,0,0,0,0,41,1,0,0,0,0,0,12,1,0,0,0,0,0,0,"Footman Rob - On Script - Despawn Instant"),
+(@ENTRY,9,3,0,0,0,100,0,100,100,0,0,41,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Footman Rob - On Script - Despawn Instant");
+UPDATE `creature_template` SET `flags_extra`=2, `InhabitType`=3 WHERE `entry` IN (25259, 25258, 25261);
+
+-- Footman George SAI
+SET @ENTRY := 25259;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,38,0,100,0,1,1,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,4.282578,"Footman George - On Data Set 1 1 - Set Orientation 4,282578");
+
+-- Footman Chuck SAI
+SET @ENTRY := 25261;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,38,0,100,0,1,1,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,4.28258,"Footman Chuck - On Data Set 1 1 - Set Orientation 4.28258");
+
+-- Footman Mitch SAI
+SET @ENTRY := 25260;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,1,63,0,100,0,0,0,0,0,1,0,6000,0,0,0,0,1,0,0,0,0,0,0,0,"Footman Mitch - On Just Created - Say Line 0"),
+(@ENTRY,0,1,2,61,0,100,0,0,0,0,0,59,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Footman Mitch - On Just Created - Set Run Off"),
+(@ENTRY,0,2,0,61,0,100,0,0,0,0,0,69,0,0,0,0,0,0,8,0,0,0,2264.93652,5221.9863,11.2882,4.3713,"Footman Mitch - On Just Created - Move To Position");
+
+-- texts
+DELETE FROM `creature_text` WHERE `CreatureID` IN (25259, 25258, 25261, 25260, 25245);
+INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `comment`) VALUES
+-- Footman Rob
+(25258, 0, 0, 'One last drink before we head to the front?', 12, 7, 100, 1, 0, 0, 24475, 'Footman Rob'),
+(25258, 1, 0, 'Barkeep! Bring out your strongest ale. We''re off to the front.', 12, 7, 100, 1, 0, 0, 24478, 'Footman Rob'),
+(25258, 2, 0, 'You''ll surely make an exception for us, eh? We might not come back.', 12, 7, 100, 1, 0, 0, 24479, 'Footman Rob'),
+(25258, 3, 0, 'I guess that''s it then. Off we go.', 12, 7, 100, 1, 0, 0, 24482, 'Footman Rob'),
+-- Footman George
+(25259, 0, 0, 'Sure, why not?', 12, 7, 100, 6, 0, 0, 24476, 'Footman George'),
+-- Footman Chuck
+(25261, 0, 0, 'That was the worst beer I''ve ever had.', 12, 7, 100, 0, 0, 0, 24483, 'Footman Chuck'),
+-- Footman Mitch
+(25260, 0, 0, 'Hey, guys! Wait up!', 12, 7, 100, 0, 0, 0, 24761, 'Footman Mitch'),
+-- James Deacon
+(25245, 0, 0, 'You lads know the drill. No alcohol to servicemen on duty. You want the general to kill me himself?', 12, 7, 100, 274, 0, 0, 24744, 'James Deacon'),
+(25245, 1, 0, 'All right, all right... but you didn''t get these from me!', 12, 7, 100, 6, 0, 0, 24745, 'James Deacon');
+
+-- Formation
+DELETE FROM `creature_formations` WHERE `leaderGUID`= 85221;
+INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES
+(85221, 85221, 0, 0, 4, 0, 0), -- Rob
+(85221, 85222, 2, 305, 4, 0, 0), -- George
+(85221, 85226, 2, 55, 4, 0, 0); -- Chuck
+
+-- Waypoints for Rob
+SET @NPC := 85221;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `spawndist`=0,`MovementType`=2 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES
+(@PATH, 1, 2277.23, 5177.21, 11.34, 0, 0, 0, 0, 100, 0),
+(@PATH, 2, 2268.97, 5175.55, 11.1665, 0, 0, 0, 0, 100, 0),
+(@PATH, 3, 2254.59, 5188.89, 11.384, 0, 0, 0, 0, 100, 0),
+(@PATH, 4, 2254.27, 5196.42, 11.3837, 0, 0, 0, 0, 100, 0),
+(@PATH, 5, 2260.67, 5200.36, 11.3711, 0, 0, 0, 0, 100, 0),
+(@PATH, 6, 2264.38, 5199.09, 11.3676, 0, 13000, 0, 0, 100, 0), -- stop in front
+(@PATH, 7, 2270.18, 5196.94, 12.4959, 0, 0, 0, 0, 100, 0),
+(@PATH, 8, 2275.23, 5194.94, 12.49, 0, 0, 0, 0, 100, 0),
+(@PATH, 9, 2276.23, 5197.58, 12.4896, 0, 0, 0, 0, 100, 0),
+(@PATH, 10, 2279.08, 5206.5, 12.494, 0, 60000, 0, 0, 100, 0), -- stop beer
+(@PATH, 11, 2278.6, 5205.3, 12.4926, 0, 16000, 0, 0, 100, 0), -- stop go
+(@PATH, 12, 2275.55, 5197.84, 12.4897, 0, 0, 0, 0, 100, 0),
+(@PATH, 13, 2275.60, 5194.96, 12.489, 0, 0, 0, 0, 100, 0),
+(@PATH, 14, 2265.21, 5198.54, 11.3533, 0, 0, 0, 0, 100, 0),
+(@PATH, 15, 2258.23, 5201.82, 11.3182, 0, 0, 0, 0, 100, 0),
+(@PATH, 16, 2258.98, 5205.83, 11.322, 0, 0, 0, 0, 100, 0), -- summon friend
+(@PATH, 17, 2261, 5212.02, 11.2373, 0, 0, 0, 0, 100, 0),
+(@PATH, 18, 2268.17, 5226.07, 11.2421, 0, 5000, 0, 0, 100, 0); -- despawn
diff --git a/sql/updates/world/master/2020_04_10_22_world_2017_01_23_03_world.sql b/sql/updates/world/master/2020_04_10_22_world_2017_01_23_03_world.sql
new file mode 100644
index 00000000000..32eac33787a
--- /dev/null
+++ b/sql/updates/world/master/2020_04_10_22_world_2017_01_23_03_world.sql
@@ -0,0 +1,7 @@
+DELETE FROM `spell_proc` WHERE `SpellId`=13234;
+INSERT INTO `spell_proc` (`SpellId`, `SchoolMask`, `SpellFamilyName`, `SpellFamilyMask0`, `SpellFamilyMask1`, `SpellFamilyMask2`, `ProcFlags`, `SpellTypeMask`, `SpellPhaseMask`, `HitMask`, `AttributesMask`, `ProcsPerMinute`, `Chance`, `Cooldown`, `Charges`) VALUES
+(13234, 0, 0, 0x00000000, 0x00000000, 0x00000000, 0, 0x1, 0x0, 0x403, 0x2, 0, 0, 0, 0);
+
+DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_item_harm_prevention_belt';
+INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
+(13234, 'spell_item_harm_prevention_belt');
diff --git a/sql/updates/world/master/2020_04_10_22_world_2017_01_24_01_world.sql b/sql/updates/world/master/2020_04_10_22_world_2017_01_24_01_world.sql
new file mode 100644
index 00000000000..a06b67e94e1
--- /dev/null
+++ b/sql/updates/world/master/2020_04_10_22_world_2017_01_24_01_world.sql
@@ -0,0 +1,77 @@
+-- [NPC][WotlK] Savage Hill Brute/Mystic/Scavenger, missing spawn loc and emote
+SET @CGUID := 73938; -- SET BY TC TEAM
+DELETE FROM `creature` WHERE `guid` BETWEEN @CGUID+0 AND @CGUID+7;
+INSERT INTO `creature` (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnDifficulties`, `PhaseId`, `modelid`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `spawndist`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `VerifiedBuild`) VALUES
+(@CGUID+0, 29404, 571, 0, 0, '0', 0, 0, 1, 6089.3, -359.966, 455.223, 2.41823, 300, 6, 0, 11379, 0, 1, 0, 0, 0, 0),
+(@CGUID+1, 29404, 571, 0, 0, '0', 0, 0, 1, 6104.57, -380.103, 431.085, 1.31082, 300, 6, 0, 11379, 0, 1, 0, 0, 0, 0),
+(@CGUID+2, 29622, 571, 0, 0, '0', 0, 0, 1, 6106.41, -307.385, 445.287, 5.63439, 300, 0, 0, 9416, 8459, 0, 0, 0, 0, 0),
+(@CGUID+3, 29622, 571, 0, 0, '0', 0, 0, 1, 6151.58, -333.755, 436.37, 4.16491, 300, 0, 0, 9103, 8313, 0, 0, 0, 0, 0),
+(@CGUID+4, 29622, 571, 0, 0, '0', 0, 0, 1, 6131.09, -340.995, 436.336, 5.1412, 300, 0, 0, 9416, 8459, 0, 0, 0, 0, 0),
+(@CGUID+5, 29622, 571, 0, 0, '0', 0, 0, 1, 6119.04, -350.294, 436.988, 5.33912, 300, 0, 0, 9103, 8313, 0, 0, 0, 0, 0),
+(@CGUID+6, 29622, 571, 0, 0, '0', 0, 0, 1, 6158.21, -359.72, 435.302, 3.23503, 300, 0, 0, 9416, 8459, 0, 0, 0, 0, 0),
+(@CGUID+7, 29623, 571, 0, 0, '0', 0, 0, 1, 6135.28, -362.313, 433.083, 2.42607, 300, 6, 0, 11770, 0, 1, 0, 0, 0, 0);
+
+DELETE FROM `creature_addon` WHERE `guid` IN (117085, 113242, 113314, 113327);
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES
+(117085,0,0,3,1,0, ''),
+(113242,0,0,3,1,0, ''),
+(113314,0,0,3,1,0, ''),
+(113327,0,0,3,1,0, '');
+
+-- Savage Hill Scavenger SAI
+SET @ENTRY := 29404;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0 AND `id`=1;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,0,1,0,4,0,100,0,0,0,0,0,91,3,0,0,0,0,0,1,0,0,0,0,0,0,0,"Savage Hill Scavenger - On Aggro - Remove Flag Standstate Sleep");
+
+-- Savage Hill Mystic SAI
+SET @ENTRY := 29622;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0 AND `id`=2;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,0,2,0,4,0,100,0,0,0,0,0,91,3,0,0,0,0,0,1,0,0,0,0,0,0,0,"Savage Hill Mystic - On Aggro - Remove Flag Standstate Sleep");
+
+-- Savage Hill Brute SAI
+SET @ENTRY := 29623;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0 AND `id`= 1;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,0,1,0,4,0,100,0,0,0,0,0,91,3,0,0,0,0,0,1,0,0,0,0,0,0,0,"Savage Hill Brute - On Aggro - Remove Flag Standstate Sleep");
+
+SET @NPC := 113241;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `spawndist`=0,`MovementType`=2 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES
+(@PATH, 1, 6276.32, -648.906, 418.674, 0, 0, 0, 0, 100, 0),
+(@PATH, 2, 6269.54, -647.148, 418.458, 0, 10000, 0, 0, 100, 0),
+(@PATH, 3, 6259.28, -644.926, 417.527, 0, 0, 0, 0, 100, 0),
+(@PATH, 4, 6249.04, -642.598, 416.282, 0, 0, 0, 0, 100, 0),
+(@PATH, 5, 6235.14, -639.409, 414.451, 0, 10000, 0, 0, 100, 0),
+(@PATH, 6, 6238.54, -640.251, 414.906, 0, 0, 0, 0, 100, 0),
+(@PATH, 7, 6252.14, -643.517, 416.649, 0, 0, 0, 0, 100, 0),
+(@PATH, 8, 6262.42, -645.655, 417.845, 0, 0, 0, 0, 100, 0);
+
+SET @NPC := 113325;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `spawndist`=0,`MovementType`=2 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES
+(@PATH, 1, 6133.69, -454.762, 410.059, 0, 0, 0, 0, 100, 0),
+(@PATH, 2, 6123.02, -443.385, 411.551, 0, 0, 0, 0, 100, 0),
+(@PATH, 3, 6107.9, -429.985, 414.557, 0, 0, 0, 0, 100, 0),
+(@PATH, 4, 6121.41, -441.725, 411.852, 0, 0, 0, 0, 100, 0);
+
+SET @NPC := 113326;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `spawndist`=0,`MovementType`=2 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES
+(@PATH, 1, 6161.12, -428.764, 414.44, 0, 0, 0, 0, 100, 0),
+(@PATH, 2, 6143.3, -443.667, 412.639, 0, 0, 0, 0, 100, 0),
+(@PATH, 3, 6155.79, -433.246, 414.151, 0, 0, 0, 0, 100, 0),
+(@PATH, 4, 6177.02, -412.869, 415.473, 0, 0, 0, 0, 100, 0);
diff --git a/sql/updates/world/master/2020_04_10_23_world_2017_01_25_01_world.sql b/sql/updates/world/master/2020_04_10_23_world_2017_01_25_01_world.sql
new file mode 100644
index 00000000000..7af38f38e91
--- /dev/null
+++ b/sql/updates/world/master/2020_04_10_23_world_2017_01_25_01_world.sql
@@ -0,0 +1,4 @@
+-- Recently Bandaged
+DELETE FROM `spell_custom_attr` WHERE `entry` = 11196;
+INSERT INTO `spell_custom_attr` (`entry`, `attributes`) VALUES
+(11196, 0x40);
diff --git a/sql/updates/world/master/2020_04_14_00_world_2017_03_03_00_world.sql b/sql/updates/world/master/2020_04_14_00_world_2017_03_03_00_world.sql
new file mode 100644
index 00000000000..c4f9cacf76d
--- /dev/null
+++ b/sql/updates/world/master/2020_04_14_00_world_2017_03_03_00_world.sql
@@ -0,0 +1,2 @@
+--
+UPDATE `creature_text`SET `CreatureID`=28472 WHERE `CreatureID` IN(2847206);
diff --git a/sql/updates/world/master/2020_04_14_01_world_2017_03_16_02_world.sql b/sql/updates/world/master/2020_04_14_01_world_2017_03_16_02_world.sql
new file mode 100644
index 00000000000..08df52bf003
--- /dev/null
+++ b/sql/updates/world/master/2020_04_14_01_world_2017_03_16_02_world.sql
@@ -0,0 +1,5 @@
+UPDATE `quest_template_addon` SET `NextQuestID`='12225' WHERE `ID` IN (12222, 12223);
+UPDATE `quest_template_addon` SET `NextQuestID`='0' WHERE `ID`=8554;
+UPDATE `quest_template_addon` SET `NextQuestID`='0' WHERE `ID`=618;
+UPDATE `quest_template_addon` SET `NextQuestID`='0' WHERE `ID`=415;
+ALTER TABLE `quest_template_addon` CHANGE `NextQuestID` `NextQuestID` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT 0;
diff --git a/sql/updates/world/master/2020_04_14_02_world_2017_03_17_02_world.sql b/sql/updates/world/master/2020_04_14_02_world_2017_03_17_02_world.sql
new file mode 100644
index 00000000000..c026bbfe6da
--- /dev/null
+++ b/sql/updates/world/master/2020_04_14_02_world_2017_03_17_02_world.sql
@@ -0,0 +1,12 @@
+--
+SET @CGUID := 146562;
+SET @OGUID := 9743;
+
+
+DELETE FROM `game_event_creature` WHERE `guid` BETWEEN @CGUID+0 AND @CGUID+62 AND `eventEntry`=8;
+INSERT INTO `game_event_creature` SELECT 8, creature.guid FROM `creature` WHERE creature.guid BETWEEN @CGUID+0 AND @CGUID+62;
+
+DELETE FROM `game_event_gameobject` WHERE `guid` BETWEEN @CGUID+0 AND @CGUID+94 AND `eventEntry`=8;
+DELETE FROM `game_event_gameobject` WHERE `guid` BETWEEN @OGUID+0 AND @OGUID+94 AND `eventEntry`=8;
+INSERT INTO `game_event_gameobject` SELECT 8, gameobject.guid FROM `gameobject` WHERE gameobject.guid BETWEEN @OGUID+0 AND @OGUID+94;
+--
diff --git a/sql/updates/world/master/2020_04_14_03_world_2017_03_17_03_world.sql b/sql/updates/world/master/2020_04_14_03_world_2017_03_17_03_world.sql
new file mode 100644
index 00000000000..eaf7db21608
--- /dev/null
+++ b/sql/updates/world/master/2020_04_14_03_world_2017_03_17_03_world.sql
@@ -0,0 +1,23 @@
+--
+DELETE FROM conditions WHERE SourceTypeOrReferenceId=13 AND SourceEntry=45872;
+INSERT INTO conditions (SourceTypeOrReferenceId, SourceGroup, SourceEntry, SourceId, ElseGroup, ConditionTypeOrReference, ConditionTarget, ConditionValue1, ConditionValue2, ConditionValue3, NegativeCondition, ErrorType, ErrorTextId, ScriptName, COMMENT) VALUES
+(13, 1, 45872, 0, 0, 31, 0, 3, 23837, 0, 0, 0, 0, '', 'Defibrillate');
+
+SET @ENTRY := 25678;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,0,0,0,4,0,100,0,0,0,0,0,1,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Doctor Razorgin - On Aggro - Say Line 0 (random)'),
+(@ENTRY,0,1,2,1,0,100,0,3000,3000,30000,30000,11,45872,0,0,0,0,0,1,0,0,0,0,0,0,0,'Doctor Razorgin - OOC - Cast Defibrillate'),
+(@ENTRY,0,2,0,61,0,100,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Doctor Razorgin - Ooc - Say Line 1 (random)');
+
+DELETE FROM `creature_text` WHERE `CreatureID`=@ENTRY;
+INSERT INTO `creature_text` (`CreatureID`,`GroupID`,`ID`,`Text`,`Type`,`Language`,`Probability`,`Emote`,`Duration`,`Sound`,`comment`,`BroadcastTextId`) VALUES
+(@ENTRY,0,0,'Ah, good... more parts!',14,0,100,0,0,0,'Part of the Doctor Razorgin on aggro lines',24872),
+(@ENTRY,0,1,'Fresh meat!',14,0,100,0,0,0,'Part of the Doctor Razorgin on aggro lines',24871),
+(@ENTRY,0,2,'The doctor is in!',14,0,100,0,0,0,'Part of the Doctor Razorgin on aggro lines',24870),
+(@ENTRY,0,3,'I recommened evisceration!',14,0,100,0,0,0,'Part of the Doctor Razorgin on aggro lines',24873),
+(@ENTRY,1,0,'Clear!',14,0,100,0,0,0,'Part of the Doctor Razorgin ooc lines',24867),
+(@ENTRY,1,1,'It''s no good... you need more work first.',14,0,100,0,0,0,'Part of the Doctor Razorgin ooc lines',24869),
+(@ENTRY,1,2,'Live, damn you!',14,0,100,0,0,0,'Part of the Doctor Razorgin ooc lines',24868);
+
+UPDATE `creature` SET `position_x`=4402.431152, `position_y`=4554.557129, `position_z`=88.743332, `orientation`=0.395920, `MovementType`=0, `spawndist`=0 WHERE `id`=@ENTRY;
diff --git a/sql/updates/world/master/2020_04_16_00_world_2017_03_24_00_world.sql b/sql/updates/world/master/2020_04_16_00_world_2017_03_24_00_world.sql
new file mode 100644
index 00000000000..84277ee86c2
--- /dev/null
+++ b/sql/updates/world/master/2020_04_16_00_world_2017_03_24_00_world.sql
@@ -0,0 +1,14 @@
+-- Correct speed for Wicked Spirits and Spirit Bombs
+UPDATE `creature_template` SET `speed_walk`=1.2, `speed_run`=0.428571 WHERE `entry` IN(39189,39190,39287,39288,39289);
+UPDATE `creature_template` SET `InhabitType`=4, `HoverHeight`=4 WHERE `entry` IN(36609,39120,39121,39122);
+
+DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_the_lich_king_harvest_souls_teleport';
+INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
+(73655,'spell_the_lich_king_harvest_souls_teleport');
+
+DELETE FROM `spell_custom_attr` WHERE `entry` IN(69409,73797,73798,73799);
+INSERT INTO `spell_custom_attr` (`entry`,`attributes`) VALUES
+(69409,32768),
+(73797,32768),
+(73798,32768),
+(73799,32768);
diff --git a/sql/updates/world/master/2020_04_16_01_world_2017_03_25_01_world.sql b/sql/updates/world/master/2020_04_16_01_world_2017_03_25_01_world.sql
new file mode 100644
index 00000000000..1e678704466
--- /dev/null
+++ b/sql/updates/world/master/2020_04_16_01_world_2017_03_25_01_world.sql
@@ -0,0 +1 @@
+DELETE FROM `trinity_string` WHERE `entry`=530;
diff --git a/sql/updates/world/master/2020_04_16_02_world_2017_03_26_00_world.sql b/sql/updates/world/master/2020_04_16_02_world_2017_03_26_00_world.sql
new file mode 100644
index 00000000000..b8cae8584ea
--- /dev/null
+++ b/sql/updates/world/master/2020_04_16_02_world_2017_03_26_00_world.sql
@@ -0,0 +1,2 @@
+--
+UPDATE `creature_text` SET `Text`= "%s flees after seeing Kel'Thuzad fall!" WHERE `CreatureID`= 16441 AND `GroupID`= 0;
diff --git a/sql/updates/world/master/2020_04_16_03_world_2017_03_26_01_world_335.sql b/sql/updates/world/master/2020_04_16_03_world_2017_03_26_01_world_335.sql
new file mode 100644
index 00000000000..106556ff7e2
--- /dev/null
+++ b/sql/updates/world/master/2020_04_16_03_world_2017_03_26_01_world_335.sql
@@ -0,0 +1,6 @@
+-- Verifonix <The Surveyor>
+UPDATE `creature_template` SET `faction`=47 WHERE `entry`=14492;
+
+DELETE FROM `creature_onkill_reputation` WHERE `creature_id`=14492;
+INSERT INTO `creature_onkill_reputation` (`creature_id`,`RewOnKillRepFaction1`,`RewOnKillRepFaction2`,`MaxStanding1`,`IsTeamAward1`,`RewOnKillRepValue1`,`MaxStanding2`,`IsTeamAward2`,`RewOnKillRepValue2`,`TeamDependent`) VALUES
+(14492, 21, 0, 5, 0, 5, 0, 0, 0, 0);
diff --git a/sql/updates/world/master/2020_04_16_04_world_2017_03_26_02_world.sql b/sql/updates/world/master/2020_04_16_04_world_2017_03_26_02_world.sql
new file mode 100644
index 00000000000..6795f016af9
--- /dev/null
+++ b/sql/updates/world/master/2020_04_16_04_world_2017_03_26_02_world.sql
@@ -0,0 +1,11 @@
+-- Improved Land Mine SAI
+SET @ENTRY := 29475;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,25,0,100,0,0,0,0,0,89,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Improved Land Mine - On Reset - Start Random Movement"),
+(@ENTRY,0,1,2,60,0,100,0,0,0,1000,1000,11,54537,0,0,0,0,0,1,0,0,0,0,0,0,0,"Improved Land Mine - On Update - Cast 'Detonation'"),
+(@ENTRY,0,2,0,61,0,100,0,0,0,1000,1000,41,500,0,0,0,0,0,1,0,0,0,0,0,0,0,"Improved Land Mine - On Update - Despawn In 500 ms"),
+(@ENTRY,0,3,0,5,0,100,0,0,0,0,29618,33,29618,0,0,0,0,0,21,50,0,0,0,0,0,0,"Improved Land Mine - On Killed Unit - Update Quest Kill Credit for 'A Delicate Touch' or 'Overstock'"),
+(@ENTRY,0,4,0,5,0,100,0,0,0,0,29619,33,29618,0,0,0,0,0,21,50,0,0,0,0,0,0,"Improved Land Mine - On Killed Unit - Update Quest Kill Credit for 'A Delicate Touch' or 'Overstock'");
+--
diff --git a/sql/updates/world/master/2020_04_16_05_world_2017_03_26_03_world.sql b/sql/updates/world/master/2020_04_16_05_world_2017_03_26_03_world.sql
new file mode 100644
index 00000000000..ce76a657cd4
--- /dev/null
+++ b/sql/updates/world/master/2020_04_16_05_world_2017_03_26_03_world.sql
@@ -0,0 +1,43 @@
+-- Quest 27418, Challenge Overlord Mok'Morokk
+
+SET @OMM := 4500; -- Overlord Mok'Morokk
+
+UPDATE `quest_template_addon` SET `SpecialFlags`=2 WHERE `ID`=1173;
+
+DELETE FROM `creature_text` WHERE `CreatureID`= @OMM;
+INSERT INTO `creature_text` (`CreatureID`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`BroadcastTextId`,`TextRange`,`comment`) VALUES
+(@OMM, 0,0,'Puny $r wanna fight Overlord Mok''Morokk? Me beat you! Me boss here!',12,0,100,0,0,0,1515,0,'Overlord Mok''Morokk - on Quest Accept'),
+(@OMM, 1,0,'Me scared! Me run now!', 14,0,100,0,0,0,1523,0,'Overlord Mok''Morokk - on Health 0%-25%');
+
+DELETE FROM `waypoints` WHERE `entry` = @OMM;
+INSERT INTO `waypoints` (`entry`,`pointid`,`position_x`,`position_y`,`position_z`,`point_comment`) VALUES
+(@OMM, 1, -3138.49, -2864.64, 34.76, 'Overlord Mok''Morokk'),
+(@OMM, 2, -3128.08, -2847.37, 34.72, 'Overlord Mok''Morokk'),
+(@OMM, 3, -3108.94, -2839.60, 34.28, 'Overlord Mok''Morokk');
+
+UPDATE `creature_template` SET `AIName` = "SmartAI", `ScriptName` = '' WHERE `entry` = @OMM;
+DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@OMM, @OMM*100, @OMM*100+1);
+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
+(@OMM, 0, 0,0, 0,0,100,0, 1000,3000,7000,10000, 11, 6749, 2, 0,0,0,0, 2, 0,0,0,0,0,0,0,'Overlord Mok''Morokk - In Combat Update - cast ''Wide Swipe'''),
+(@OMM, 0, 1,2, 19,0,100,1, 1173, 0, 0, 0, 64, 1, 0, 0,0,0,0, 16, 0,0,0,0,0,0,0,'Overlord Mok''Morokk - on Quest Accept - Store players (No repeat)'),
+(@OMM, 0, 2,0, 61,0,100,0, 0, 0, 0, 0, 80, @OMM*100, 0, 0,0,0,0, 1, 0,0,0,0,0,0,0,'Overlord Mok''Morokk - on Quest Accept - Run Actionlist 450000'),
+(@OMM*100, 9, 0,0, 0,0,100,0, 3000,3000, 0, 0, 1, 0, 0, 0,0,0,0, 12, 1,0,0,0,0,0,0,'Overlord Mok''Morokk - Actionlist - Say text 0'),
+(@OMM*100, 9, 1,0, 0,0,100,0, 0, 0, 0, 0, 2, 16, 0, 0,0,0,0, 1, 0,0,0,0,0,0,0,'Overlord Mok''Morokk - Actionlist - Set faction (Monster)'),
+(@OMM*100, 9, 2,0, 0,0,100,0, 0, 0, 0, 0, 83, 2, 0, 0,0,0,0, 1, 0,0,0,0,0,0,0,'Overlord Mok''Morokk - Actionlist - Remove npcflag Quest Giver'),
+(@OMM*100, 9, 3,0, 0,0,100,0, 0, 0, 0, 0, 19, 768, 0, 0,0,0,0, 1, 0,0,0,0,0,0,0,'Overlord Mok''Morokk - Actionlist - Remove Unit Flags immune to NPC & immune to PC'),
+(@OMM*100, 9, 4,0, 0,0,100,0, 0, 0, 0, 0, 49, 0, 0, 0,0,0,0, 12, 1,0,0,0,0,0,0,'Overlord Mok''Morokk - Actionlist - Attack stored player'),
+(@OMM, 0, 3,0, 2,0,100,1, 0, 25, 0, 0, 80,@OMM*100+1, 2, 0,0,0,0, 1, 0,0,0,0,0,0,0,'Overlord Mok''Morokk - on Health 0%-25% - Run Actionlist 450001 (No repeat)'),
+(@OMM, 0, 4,0, 0,0,100,1, 0, 0, 0, 0, 42, 0, 1, 0,0,0,0, 1, 0,0,0,0,0,0,0,'Overlord Mok''Morokk - In Combat - Set invincibility hp level (No repeat)'),
+(@OMM*100+1,9, 0,0, 0,0,100,0, 0, 0, 0, 0, 18, 768, 0, 0,0,0,0, 1, 0,0,0,0,0,0,0,'Overlord Mok''Morokk - Actionlist - Set Unit Flags immune to NPC & immune to PC'),
+(@OMM*100+1,9, 1,0, 0,0,100,0, 0, 0, 0, 0, 28, 0, 0, 0,0,0,0, 1, 0,0,0,0,0,0,0,'Overlord Mok''Morokk - Actionlist - Remove all auras'),
+(@OMM*100+1,9, 2,0, 0,0,100,0, 0, 0, 0, 0, 2, 29, 0, 0,0,0,0, 1, 0,0,0,0,0,0,0,'Overlord Mok''Morokk - Actionlist - Set faction (Orgrimmar)'),
+(@OMM*100+1,9, 3,0, 0,0,100,0, 0, 0, 0, 0, 24, 0, 0, 0,0,0,0, 1, 0,0,0,0,0,0,0,'Overlord Mok''Morokk - Actionlist - Evade'),
+(@OMM*100+1,9, 4,0, 0,0,100,0, 0, 0, 0, 0, 15, 1173, 0, 0,0,0,0, 12, 1,0,0,0,0,0,0,'Overlord Mok''Morokk - Actionlist - Credit Quest ''Challenge Overlord Mok''Morokk'''),
+(@OMM*100+1,9, 5,0, 0,0,100,0, 500, 500, 0, 0, 1, 1, 0, 0,0,0,0, 12, 1,0,0,0,0,0,0,'Overlord Mok''Morokk - Actionlist - Say text 1'),
+(@OMM*100+1,9, 6,0, 0,0,100,0, 0, 0, 0, 0, 53, 1,@OMM, 0,0,0,0, 1, 0,0,0,0,0,0,0,'Overlord Mok''Morokk - Actionlist - Start Waypoint'),
+(@OMM, 0, 5,0, 58,0,100,0, 0,@OMM, 0, 0, 41, 0, 0, 0,0,0,0, 1, 0,0,0,0,0,0,0,'Overlord Mok''Morokk - on WP End - Despawn'),
+(@OMM, 0, 6,7, 25,0,100,0, 0, 0, 0, 0, 18, 768, 0, 0,0,0,0, 1, 0,0,0,0,0,0,0,'Overlord Mok''Morokk - on Reset - Set Unit Flags immune to NPC & immune to PC'),
+(@OMM, 0, 7,8, 61,0,100,0, 0, 0, 0, 0, 82, 2, 0, 0,0,0,0, 1, 0,0,0,0,0,0,0,'Overlord Mok''Morokk - on Reset - Remove all auras'),
+(@OMM, 0, 8,0, 61,0,100,0, 0, 0, 0, 0, 2, 29, 0, 0,0,0,0, 1, 0,0,0,0,0,0,0,'Overlord Mok''Morokk - on Reset - Set faction (Orgrimmar)'),
+(@OMM, 0, 9,0, 11,0,100,0, 0, 0, 0, 0, 42, 1, 0, 0,0,0,0, 1, 0,0,0,0,0,0,0,'Overlord Mok''Morokk - on Spawn - Set Invincibility at 1 HP');
+--
diff --git a/sql/updates/world/master/2020_04_16_06_world_2017_03_27_00_world_335.sql b/sql/updates/world/master/2020_04_16_06_world_2017_03_27_00_world_335.sql
new file mode 100644
index 00000000000..ebcafe18e14
--- /dev/null
+++ b/sql/updates/world/master/2020_04_16_06_world_2017_03_27_00_world_335.sql
@@ -0,0 +1,11 @@
+
+-- Franclorn Forgewright
+-- SET @ENTRY := 8888;
+-- UPDATE `creature_template` SET `flags_extra`=`flags_extra`|0x400 WHERE `entry`=@ENTRY;
+
+-- Gaeriyan
+-- SET @ENTRY := 9299;
+-- UPDATE `creature_template` SET `flags_extra`=`flags_extra`|0x400 WHERE `entry`=@ENTRY;
+
+-- Shroud of Death Spell
+DELETE FROM `spell_script_names` WHERE spell_id=10848;
diff --git a/sql/updates/world/master/2020_04_17_00_world_2017_03_27_01_world.sql b/sql/updates/world/master/2020_04_17_00_world_2017_03_27_01_world.sql
new file mode 100644
index 00000000000..fe640c4da90
--- /dev/null
+++ b/sql/updates/world/master/2020_04_17_00_world_2017_03_27_01_world.sql
@@ -0,0 +1,23 @@
+--
+UPDATE `smart_scripts` SET `action_type`=11, `action_param1`=54693, `action_param2`=1 WHERE `entryorguid` IN(29475) AND `id` IN (3,4) AND `source_type`=0;
+-- UPDATE `smart_scripts` SET `event_flags`=1 WHERE `entryorguid` IN (15069) AND `source_type`=0 AND `id`=1;
+UPDATE `smart_scripts` SET `event_flags`=1 WHERE `entryorguid` IN (15146) AND `source_type`=0 AND `id`=3;
+UPDATE `smart_scripts` SET `event_flags`=1 WHERE `entryorguid` IN (15281) AND `source_type`=0 AND `id` IN (0,5);
+UPDATE `smart_scripts` SET `event_flags`=1 WHERE `entryorguid` IN (15401) AND `source_type`=0 AND `id` IN (0,5);
+UPDATE `smart_scripts` SET `event_flags`=1 WHERE `entryorguid` IN (15405) AND `source_type`=0 AND `id` IN (0,5,12);
+-- UPDATE `smart_scripts` SET `event_flags`=1 WHERE `entryorguid` IN (15416) AND `source_type`=0 AND `id` IN (4);
+UPDATE `smart_scripts` SET `event_flags`=1 WHERE `entryorguid` IN (15417) AND `source_type`=0 AND `id` IN (0,5);
+UPDATE `smart_scripts` SET `event_flags`=1 WHERE `entryorguid` IN (15418) AND `source_type`=0 AND `id` IN (0,5,12);
+UPDATE `smart_scripts` SET `event_flags`=1 WHERE `entryorguid` IN (15641) AND `source_type`=0 AND `id`=0;
+UPDATE `smart_scripts` SET `event_param3`=2000, `event_param4`=2000 WHERE `entryorguid`=15641 AND `source_type`=0 AND `id` IN (6,8,11);
+UPDATE `smart_scripts` SET `event_param3`=2000, `event_param4`=2000 WHERE `entryorguid` IN (15970,15971) AND `source_type`=0 AND `id` IN (0,5);
+UPDATE `smart_scripts` SET `event_type`=25 WHERE `entryorguid` IN (16017) AND `source_type`=0 AND `id`=0;
+UPDATE `smart_scripts` SET `event_param3`=1000, `event_param4`=1000 WHERE `entryorguid`=16024 AND `source_type`=0 AND `id` IN (0);
+UPDATE `smart_scripts` SET `event_flags`=1 WHERE `entryorguid` IN (16204) AND `source_type`=0 AND `id` IN (0,5);
+UPDATE `smart_scripts` SET `event_flags`=1 WHERE `entryorguid` IN (16249) AND `source_type`=0 AND `id` IN (0,5);
+UPDATE `smart_scripts` SET `event_param3`=2000, `event_param4`=2000 WHERE `entryorguid` IN (16294) AND `source_type`=0 AND `id` IN (4,11);
+UPDATE `smart_scripts` SET `event_param3`=2000, `event_param4`=2000 WHERE `entryorguid` IN (16307) AND `source_type`=0 AND `id` IN (0,5);
+UPDATE `smart_scripts` SET `event_param3`=2000, `event_param4`=2000 WHERE `entryorguid` IN (16308) AND `source_type`=0 AND `id` IN (0,5);
+UPDATE `smart_scripts` SET `event_param3`=2000, `event_param4`=2000 WHERE `entryorguid` IN (16311) AND `source_type`=0 AND `id` IN (0,5);
+UPDATE `smart_scripts` SET `event_param3`=2000, `event_param4`=2000 WHERE `entryorguid` IN (16318) AND `source_type`=0 AND `id` IN (0,5);
+UPDATE `smart_scripts` SET `event_param3`=2000, `event_param4`=2000 WHERE `entryorguid` IN (16329) AND `source_type`=0 AND `id` IN (0,5);
diff --git a/sql/updates/world/master/2020_04_17_01_world_2017_03_30_01_world.sql b/sql/updates/world/master/2020_04_17_01_world_2017_03_30_01_world.sql
new file mode 100644
index 00000000000..2be7fb71ab0
--- /dev/null
+++ b/sql/updates/world/master/2020_04_17_01_world_2017_03_30_01_world.sql
@@ -0,0 +1,19 @@
+--
+DELETE FROM `smart_scripts` WHERE `entryorguid`=17101 AND `source_type`=0 AND `id`=2;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=17215 AND `source_type`=0 AND `id` IN (2, 3, 4);
+DELETE FROM `smart_scripts` WHERE `entryorguid`=17214 AND `source_type`=0 AND `id`=1;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=17242 AND `source_type`=0 AND `id` IN (1, 2, 3);
+DELETE FROM `smart_scripts` WHERE `entryorguid`=17117 AND `source_type`=0 AND `id` IN (2, 3);
+DELETE FROM `smart_scripts` WHERE `entryorguid`=17241 AND `source_type`=0 AND `id`=1;
+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
+(17101, 0, 2, 0, 20, 0, 100, 0, 9452, 0, 0, 0, 5, 24, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Diktynna - On Quest 'Red Snapper - Very Tasty!' Rewarded - Play Emote 24"),
+(17215, 0, 2, 0, 38, 0, 100, 512, 1, 1, 0, 0, 81, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Daedal - On Data Set 1 1- Set NPC Flags"),
+(17215, 0, 3, 0, 38, 0, 100, 512, 2, 2, 0, 0, 81, 83, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Daedal - On Data Set 2 2- Set NPC Flags"),
+(17215, 0, 4, 0, 20, 0, 100, 512, 9473, 2, 0, 0, 80, 1721500, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Daedal - On Quest 'An Alternative Alternative' Rewarded - Run Script"),
+(17214, 0, 1, 0, 20, 0, 100, 512, 9463, 2, 0, 0, 80, 1721400, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Anchorite Fateema - On Quest 'Medicinal Purposes' Rewarded - Run Script"),
+(17242, 0, 1, 0, 38, 0, 100, 512, 1, 1, 0, 0, 53, 0, 1724200, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Archaeologist Adamant Ironheart - On Data Set 1 1- Start WP (Path 1)"),
+(17242, 0, 2, 0, 38, 0, 100, 512, 2, 2, 0, 0, 53, 0, 1724201, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Archaeologist Adamant Ironheart - On Data Set 2 2- Start WP (Path 2)"),
+(17242, 0, 3, 0, 40, 0, 100, 512, 1, 1724201, 0, 0, 66, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 6.26573, "Archaeologist Adamant Ironheart - On Reached WP1 (Path 2) - Set Orientation"),
+(17117, 0, 2, 0, 38, 0, 100, 512, 1, 1, 0, 0, 91, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Injured Night Elf Priestess - On Data Set 1 1 - Set Bytes 1"),
+(17117, 0, 3, 0, 38, 0, 100, 512, 2, 2, 0, 0, 90, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Injured Night Elf Priestess - On Data Set 2 2 - Set Bytes 1"),
+(17241, 0, 1, 0, 20, 0, 100, 512, 9514, 0, 0, 0, 80, 1724100, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Priestess Kyleen Il'dinare - On Quest 'Rune Covered Tablet' Rewarded - Run Script");
diff --git a/sql/updates/world/master/2020_04_17_02_world_2017_03_31_00_world.sql b/sql/updates/world/master/2020_04_17_02_world_2017_03_31_00_world.sql
new file mode 100644
index 00000000000..52ae3f95909
--- /dev/null
+++ b/sql/updates/world/master/2020_04_17_02_world_2017_03_31_00_world.sql
@@ -0,0 +1,23 @@
+UPDATE `creature_template` SET `RegenHealth`=0 WHERE `entry` IN (
+/* Wintergrasp */
+27881, -- Wintergrasp Catapult
+28094, -- Wintergrasp Demolisher
+28312, -- Wintergrasp Siege Engine
+28366, -- Wintergrasp Tower Cannon
+32627, -- Wintergrasp Siege Engine
+
+/* Strand of the Ancients */
+27894, 32795, -- Antipersonnel Cannon
+28781, 32796, -- Battleground Demolisher
+
+/* Isle of Conquest*/
+34775, 35415, -- Demolisher
+34776, 35431, -- Siege Engine
+34793, 35413, -- Catapult
+34802, 35419, -- Glaive Thrower
+34929, 35410, -- Alliance Gunship Cannon
+34935, 35427, -- Horde Gunship Cannon
+34944, 35429, -- Keep Cannon
+35069, 35433, -- Siege Engine
+35273, 35421 -- Glaive Thrower
+);
diff --git a/src/common/Debugging/WheatyExceptionReport.cpp b/src/common/Debugging/WheatyExceptionReport.cpp
index 6e98bf23c5f..836ae7b0837 100644
--- a/src/common/Debugging/WheatyExceptionReport.cpp
+++ b/src/common/Debugging/WheatyExceptionReport.cpp
@@ -420,18 +420,18 @@ void WheatyExceptionReport::PrintSystemInfo()
MemoryStatus.dwLength = sizeof (MEMORYSTATUS);
::GlobalMemoryStatus(&MemoryStatus);
TCHAR sString[1024];
- _tprintf(_T("//=====================================================\r\n"));
+ Log(_T("//=====================================================\r\n"));
if (_GetProcessorName(sString, countof(sString)))
- _tprintf(_T("*** Hardware ***\r\nProcessor: %s\r\nNumber Of Processors: %d\r\nPhysical Memory: %d KB (Available: %d KB)\r\nCommit Charge Limit: %d KB\r\n"),
+ Log(_T("*** Hardware ***\r\nProcessor: %s\r\nNumber Of Processors: %d\r\nPhysical Memory: %d KB (Available: %d KB)\r\nCommit Charge Limit: %d KB\r\n"),
sString, SystemInfo.dwNumberOfProcessors, MemoryStatus.dwTotalPhys/0x400, MemoryStatus.dwAvailPhys/0x400, MemoryStatus.dwTotalPageFile/0x400);
else
- _tprintf(_T("*** Hardware ***\r\nProcessor: <unknown>\r\nNumber Of Processors: %d\r\nPhysical Memory: %d KB (Available: %d KB)\r\nCommit Charge Limit: %d KB\r\n"),
+ Log(_T("*** Hardware ***\r\nProcessor: <unknown>\r\nNumber Of Processors: %d\r\nPhysical Memory: %d KB (Available: %d KB)\r\nCommit Charge Limit: %d KB\r\n"),
SystemInfo.dwNumberOfProcessors, MemoryStatus.dwTotalPhys/0x400, MemoryStatus.dwAvailPhys/0x400, MemoryStatus.dwTotalPageFile/0x400);
if (_GetWindowsVersion(sString, countof(sString)))
- _tprintf(_T("\r\n*** Operation System ***\r\n%s\r\n"), sString);
+ Log(_T("\r\n*** Operation System ***\r\n%s\r\n"), sString);
else
- _tprintf(_T("\r\n*** Operation System:\r\n<unknown>\r\n"));
+ Log(_T("\r\n*** Operation System:\r\n<unknown>\r\n"));
}
//===========================================================================
@@ -494,14 +494,14 @@ PEXCEPTION_POINTERS pExceptionInfo)
GetLocalTime(&systime);
// Start out with a banner
- _tprintf(_T("Revision: %s\r\n"), GitRevision::GetFullVersion());
- _tprintf(_T("Date %u:%u:%u. Time %u:%u \r\n"), systime.wDay, systime.wMonth, systime.wYear, systime.wHour, systime.wMinute);
+ Log(_T("Revision: %s\r\n"), GitRevision::GetFullVersion());
+ Log(_T("Date %u:%u:%u. Time %u:%u \r\n"), systime.wDay, systime.wMonth, systime.wYear, systime.wHour, systime.wMinute);
PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
PrintSystemInfo();
// First print information about the type of fault
- _tprintf(_T("\r\n//=====================================================\r\n"));
- _tprintf(_T("Exception code: %08X %s\r\n"),
+ Log(_T("\r\n//=====================================================\r\n"));
+ Log(_T("Exception code: %08X %s\r\n"),
pExceptionRecord->ExceptionCode,
GetExceptionString(pExceptionRecord->ExceptionCode));
@@ -515,12 +515,12 @@ PEXCEPTION_POINTERS pExceptionInfo)
section, offset);
#ifdef _M_IX86
- _tprintf(_T("Fault address: %08X %02X:%08X %s\r\n"),
+ Log(_T("Fault address: %08X %02X:%08X %s\r\n"),
pExceptionRecord->ExceptionAddress,
section, offset, szFaultingModule);
#endif
#ifdef _M_X64
- _tprintf(_T("Fault address: %016I64X %02X:%016I64X %s\r\n"),
+ Log(_T("Fault address: %016I64X %02X:%016I64X %s\r\n"),
pExceptionRecord->ExceptionAddress,
section, offset, szFaultingModule);
#endif
@@ -529,32 +529,32 @@ PEXCEPTION_POINTERS pExceptionInfo)
// Show the registers
#ifdef _M_IX86 // X86 Only!
- _tprintf(_T("\r\nRegisters:\r\n"));
+ Log(_T("\r\nRegisters:\r\n"));
- _tprintf(_T("EAX:%08X\r\nEBX:%08X\r\nECX:%08X\r\nEDX:%08X\r\nESI:%08X\r\nEDI:%08X\r\n")
+ Log(_T("EAX:%08X\r\nEBX:%08X\r\nECX:%08X\r\nEDX:%08X\r\nESI:%08X\r\nEDI:%08X\r\n")
, pCtx->Eax, pCtx->Ebx, pCtx->Ecx, pCtx->Edx,
pCtx->Esi, pCtx->Edi);
- _tprintf(_T("CS:EIP:%04X:%08X\r\n"), pCtx->SegCs, pCtx->Eip);
- _tprintf(_T("SS:ESP:%04X:%08X EBP:%08X\r\n"),
+ Log(_T("CS:EIP:%04X:%08X\r\n"), pCtx->SegCs, pCtx->Eip);
+ Log(_T("SS:ESP:%04X:%08X EBP:%08X\r\n"),
pCtx->SegSs, pCtx->Esp, pCtx->Ebp);
- _tprintf(_T("DS:%04X ES:%04X FS:%04X GS:%04X\r\n"),
+ Log(_T("DS:%04X ES:%04X FS:%04X GS:%04X\r\n"),
pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs);
- _tprintf(_T("Flags:%08X\r\n"), pCtx->EFlags);
+ Log(_T("Flags:%08X\r\n"), pCtx->EFlags);
#endif
#ifdef _M_X64
- _tprintf(_T("\r\nRegisters:\r\n"));
- _tprintf(_T("RAX:%016I64X\r\nRBX:%016I64X\r\nRCX:%016I64X\r\nRDX:%016I64X\r\nRSI:%016I64X\r\nRDI:%016I64X\r\n")
+ Log(_T("\r\nRegisters:\r\n"));
+ Log(_T("RAX:%016I64X\r\nRBX:%016I64X\r\nRCX:%016I64X\r\nRDX:%016I64X\r\nRSI:%016I64X\r\nRDI:%016I64X\r\n")
_T("R8: %016I64X\r\nR9: %016I64X\r\nR10:%016I64X\r\nR11:%016I64X\r\nR12:%016I64X\r\nR13:%016I64X\r\nR14:%016I64X\r\nR15:%016I64X\r\n")
, pCtx->Rax, pCtx->Rbx, pCtx->Rcx, pCtx->Rdx,
pCtx->Rsi, pCtx->Rdi, pCtx->R9, pCtx->R10, pCtx->R11, pCtx->R12, pCtx->R13, pCtx->R14, pCtx->R15);
- _tprintf(_T("CS:RIP:%04X:%016I64X\r\n"), pCtx->SegCs, pCtx->Rip);
- _tprintf(_T("SS:RSP:%04X:%016X RBP:%08X\r\n"),
+ Log(_T("CS:RIP:%04X:%016I64X\r\n"), pCtx->SegCs, pCtx->Rip);
+ Log(_T("SS:RSP:%04X:%016X RBP:%08X\r\n"),
pCtx->SegSs, pCtx->Rsp, pCtx->Rbp);
- _tprintf(_T("DS:%04X ES:%04X FS:%04X GS:%04X\r\n"),
+ Log(_T("DS:%04X ES:%04X FS:%04X GS:%04X\r\n"),
pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs);
- _tprintf(_T("Flags:%08X\r\n"), pCtx->EFlags);
+ Log(_T("Flags:%08X\r\n"), pCtx->EFlags);
#endif
SymSetOptions(SYMOPT_DEFERRED_LOADS);
@@ -562,7 +562,7 @@ PEXCEPTION_POINTERS pExceptionInfo)
// Initialize DbgHelp
if (!SymInitialize(GetCurrentProcess(), 0, TRUE))
{
- _tprintf(_T("\n\rCRITICAL ERROR.\n\r Couldn't initialize the symbol handler for process.\n\rError [%s].\n\r\n\r"),
+ Log(_T("\n\rCRITICAL ERROR.\n\r Couldn't initialize the symbol handler for process.\n\rError [%s].\n\r\n\r"),
ErrorMessage(GetLastError()));
}
@@ -573,28 +573,20 @@ PEXCEPTION_POINTERS pExceptionInfo)
// #ifdef _M_IX86 // X86 Only!
- _tprintf(_T("========================\r\n"));
- _tprintf(_T("Local Variables And Parameters\r\n"));
+ Log(_T("========================\r\n"));
+ Log(_T("Local Variables And Parameters\r\n"));
trashableContext = *pCtx;
WriteStackDetails(&trashableContext, true, NULL);
printTracesForAllThreads(true);
- /*_tprintf(_T("========================\r\n"));
- _tprintf(_T("Global Variables\r\n"));
-
- SymEnumSymbols(GetCurrentProcess(),
- (UINT_PTR)GetModuleHandle(szFaultingModule),
- 0, EnumerateSymbolsCallback, 0);*/
- // #endif // X86 Only!
-
SymCleanup(GetCurrentProcess());
- _tprintf(_T("\r\n"));
+ Log(_T("\r\n"));
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
- _tprintf(_T("Error writing the crash log\r\n"));
+ Log(_T("Error writing the crash log\r\n"));
}
}
@@ -720,9 +712,9 @@ void WheatyExceptionReport::WriteStackDetails(
PCONTEXT pContext,
bool bWriteVariables, HANDLE pThreadHandle) // true if local/params should be output
{
- _tprintf(_T("\r\nCall stack:\r\n"));
+ Log(_T("\r\nCall stack:\r\n"));
- _tprintf(_T("Address Frame Function SourceFile\r\n"));
+ Log(_T("Address Frame Function SourceFile\r\n"));
DWORD dwMachineType = 0;
// Could use SymSetOptions here to add the SYMOPT_DEFERRED_LOADS flag
@@ -769,10 +761,10 @@ bool bWriteVariables, HANDLE pThreadHandle)
if (0 == sf.AddrFrame.Offset) // Basic sanity check to make sure
break; // the frame is OK. Bail if not.
#ifdef _M_IX86
- _tprintf(_T("%08X %08X "), sf.AddrPC.Offset, sf.AddrFrame.Offset);
+ Log(_T("%08X %08X "), sf.AddrPC.Offset, sf.AddrFrame.Offset);
#endif
#ifdef _M_X64
- _tprintf(_T("%016I64X %016I64X "), sf.AddrPC.Offset, sf.AddrFrame.Offset);
+ Log(_T("%016I64X %016I64X "), sf.AddrPC.Offset, sf.AddrFrame.Offset);
#endif
DWORD64 symDisplacement = 0; // Displacement of the input address,
@@ -786,7 +778,7 @@ bool bWriteVariables, HANDLE pThreadHandle)
&symDisplacement, // Address of the variable that will receive the displacement
&sip.si)) // Address of the SYMBOL_INFO structure (inside "sip" object)
{
- _tprintf(_T("%hs+%I64X"), sip.si.Name, symDisplacement);
+ Log(_T("%hs+%I64X"), sip.si.Name, symDisplacement);
}
else // No symbol found. Print out the logical address instead.
@@ -798,10 +790,10 @@ bool bWriteVariables, HANDLE pThreadHandle)
GetLogicalAddress((PVOID)sf.AddrPC.Offset,
szModule, sizeof(szModule), section, offset);
#ifdef _M_IX86
- _tprintf(_T("%04X:%08X %s"), section, offset, szModule);
+ Log(_T("%04X:%08X %s"), section, offset, szModule);
#endif
#ifdef _M_X64
- _tprintf(_T("%04X:%016I64X %s"), section, offset, szModule);
+ Log(_T("%04X:%016I64X %s"), section, offset, szModule);
#endif
}
@@ -811,10 +803,10 @@ bool bWriteVariables, HANDLE pThreadHandle)
if (SymGetLineFromAddr64(m_hProcess, sf.AddrPC.Offset,
&dwLineDisplacement, &lineInfo))
{
- _tprintf(_T(" %s line %u"), lineInfo.FileName, lineInfo.LineNumber);
+ Log(_T(" %s line %u"), lineInfo.FileName, lineInfo.LineNumber);
}
- _tprintf(_T("\r\n"));
+ Log(_T("\r\n"));
// Write out the variables, if desired
if (bWriteVariables)
@@ -827,7 +819,7 @@ bool bWriteVariables, HANDLE pThreadHandle)
// Enumerate the locals/parameters
SymEnumSymbols(m_hProcess, 0, 0, EnumerateSymbolsCallback, &sf);
- _tprintf(_T("\r\n"));
+ Log(_T("\r\n"));
}
}
@@ -843,22 +835,15 @@ PSYMBOL_INFO pSymInfo,
ULONG /*SymbolSize*/,
PVOID UserContext)
{
-
- char szBuffer[WER_LARGE_BUFFER_SIZE];
- memset(szBuffer, 0, sizeof(szBuffer));
-
__try
{
ClearSymbols();
- if (FormatSymbolValue(pSymInfo, (STACKFRAME64*)UserContext,
- szBuffer, sizeof(szBuffer)))
- _tprintf(_T("%s"), szBuffer);
+ FormatSymbolValue(pSymInfo, (STACKFRAME64*)UserContext);
+
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
- _tprintf(_T("punting on symbol %s, partial output:\r\n"), pSymInfo->Name);
- if (szBuffer[0] != '\0')
- _tprintf(_T("%s"), szBuffer);
+ Log(_T("punting on symbol %s, partial output:\r\n"), pSymInfo->Name);
}
return TRUE;
@@ -871,12 +856,8 @@ PVOID UserContext)
//////////////////////////////////////////////////////////////////////////////
bool WheatyExceptionReport::FormatSymbolValue(
PSYMBOL_INFO pSym,
-STACKFRAME64 * sf,
-char * pszBuffer,
-unsigned /*cbBuffer*/)
+STACKFRAME64 * sf)
{
- char * pszCurrBuffer = pszBuffer;
-
// If it's a function, don't do anything.
if (pSym->Tag == SymTagFunction) // SymTagFunction from CVCONST.H from the DIA SDK
return false;
@@ -904,7 +885,7 @@ unsigned /*cbBuffer*/)
pVariable = (DWORD_PTR)pSym->Address; // It must be a global variable
}
- pszCurrBuffer = PushSymbolDetail(pszCurrBuffer);
+ PushSymbolDetail();
// Indicate if the variable is a local or parameter
if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_PARAMETER)
@@ -915,8 +896,7 @@ unsigned /*cbBuffer*/)
// Determine if the variable is a user defined type (UDT). IF so, bHandled
// will return true.
bool bHandled;
- pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, pSym->ModBase, pSym->TypeIndex,
- pVariable, bHandled, pSym->Name, "", false, true);
+ DumpTypeIndex(pSym->ModBase, pSym->TypeIndex, pVariable, bHandled, pSym->Name, "", false, true);
if (!bHandled)
{
@@ -936,7 +916,7 @@ unsigned /*cbBuffer*/)
symbolDetails.top().Value = buffer;
}
- pszCurrBuffer = PopSymbolDetail(pszCurrBuffer);
+ PopSymbolDetail();
return true;
}
@@ -945,8 +925,7 @@ unsigned /*cbBuffer*/)
// at fundamental types. When he hit fundamental types, return
// bHandled = false, so that FormatSymbolValue() will format them.
//////////////////////////////////////////////////////////////////////////////
-char * WheatyExceptionReport::DumpTypeIndex(
-char * pszCurrBuffer,
+void WheatyExceptionReport::DumpTypeIndex(
DWORD64 modBase,
DWORD dwTypeIndex,
DWORD_PTR offset,
@@ -959,11 +938,11 @@ bool logChildren)
bHandled = false;
if (newSymbol)
- pszCurrBuffer = PushSymbolDetail(pszCurrBuffer);
+ PushSymbolDetail();
DWORD typeTag;
if (!SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_SYMTAG, &typeTag))
- return pszCurrBuffer;
+ return;
// Get the name of the symbol. This will either be a Type name (if a UDT),
// or the structure member name.
@@ -982,12 +961,12 @@ bool logChildren)
if (Name != NULL && Name[0] != '\0')
symbolDetails.top().Name = Name;
bHandled = true;
- return pszCurrBuffer;
+ return;
}
- char buffer[200];
+ char buffer[WER_SMALL_BUFFER_SIZE];
wcstombs(buffer, pwszTypeName, sizeof(buffer));
- buffer[199] = '\0';
+ buffer[WER_SMALL_BUFFER_SIZE - 1] = '\0';
if (Name != NULL && Name[0] != '\0')
{
symbolDetails.top().Type = buffer;
@@ -1006,7 +985,7 @@ bool logChildren)
// Skip printing address and base class if it has been printed already
if (typeTag == SymTagBaseClass)
bHandled = true;
- return pszCurrBuffer;
+ return;
}
DWORD innerTypeID;
@@ -1032,7 +1011,7 @@ bool logChildren)
// Try to dereference the pointer in a try/except block since it might be invalid
DWORD_PTR address = DereferenceUnsafePointer(offset);
- char buffer[50];
+ char buffer[WER_SMALL_BUFFER_SIZE];
FormatOutputValue(buffer, btVoid, sizeof(PVOID), (PVOID)offset, sizeof(buffer));
symbolDetails.top().Value = buffer;
@@ -1043,8 +1022,7 @@ bool logChildren)
if (address == NULL || address == DWORD_PTR(-1))
logChildren = false;
- pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, modBase, innerTypeID,
- address, bHandled, Name, addressStr, false, logChildren);
+ DumpTypeIndex(modBase, innerTypeID, address, bHandled, Name, addressStr, false, logChildren);
if (!bHandled)
{
@@ -1066,7 +1044,7 @@ bool logChildren)
symbolDetails.top().Value = buffer2;
}
bHandled = true;
- return pszCurrBuffer;
+ return;
}
else if (address == NULL)
symbolDetails.top().Value = "NULL";
@@ -1074,7 +1052,7 @@ bool logChildren)
{
symbolDetails.top().Value = "<Unable to read memory>";
bHandled = true;
- return pszCurrBuffer;
+ return;
}
}
break;
@@ -1090,17 +1068,17 @@ bool logChildren)
case SymTagUDT:
if (symbolDetails.size() >= WER_MAX_NESTING_LEVEL)
logChildren = false;
- pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, modBase, innerTypeID,
+ DumpTypeIndex(modBase, innerTypeID,
offset, bHandled, symbolDetails.top().Name.c_str(), "", false, logChildren);
break;
case SymTagPointerType:
if (Name != NULL && Name[0] != '\0')
symbolDetails.top().Name = Name;
- pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, modBase, innerTypeID,
+ DumpTypeIndex(modBase, innerTypeID,
offset, bHandled, symbolDetails.top().Name.c_str(), "", false, logChildren);
break;
case SymTagArrayType:
- pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, modBase, innerTypeID,
+ DumpTypeIndex(modBase, innerTypeID,
offset, bHandled, symbolDetails.top().Name.c_str(), "", false, logChildren);
break;
default:
@@ -1114,7 +1092,7 @@ bool logChildren)
symbolDetails.top().HasChildren = true;
BasicType basicType = btNoType;
- pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, modBase, innerTypeID,
+ DumpTypeIndex(modBase, innerTypeID,
offset, bHandled, Name, "", false, false);
// Set Value back to an empty string since the Array object itself has no value, only its elements have
@@ -1149,22 +1127,22 @@ bool logChildren)
default:
for (DWORD index = 0; index < elementsCount && index < WER_MAX_ARRAY_ELEMENTS_COUNT; index++)
{
- pszCurrBuffer = PushSymbolDetail(pszCurrBuffer);
+ PushSymbolDetail();
symbolDetails.top().Suffix += "[" + std::to_string(index) + "]";
FormatOutputValue(buffer, basicType, length, (PVOID)(offset + length * index), sizeof(buffer));
symbolDetails.top().Value = buffer;
- pszCurrBuffer = PopSymbolDetail(pszCurrBuffer);
+ PopSymbolDetail();
}
break;
}
- return pszCurrBuffer;
+ return;
}
break;
case SymTagBaseType:
break;
case SymTagEnum:
- return pszCurrBuffer;
+ return;
default:
break;
}
@@ -1174,7 +1152,7 @@ bool logChildren)
SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_CHILDRENCOUNT, &dwChildrenCount);
if (!dwChildrenCount) // If no children, we're done
- return pszCurrBuffer;
+ return;
// Prepare to get an array of "TypeIds", representing each of the children.
// SymGetTypeInfo(TI_FINDCHILDREN) expects more memory than just a
@@ -1192,7 +1170,7 @@ bool logChildren)
if (!SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_FINDCHILDREN,
&children))
{
- return pszCurrBuffer;
+ return;
}
// Iterate through each of the children
@@ -1220,7 +1198,7 @@ bool logChildren)
if (!logChildren)
{
bHandled = false;
- return pszCurrBuffer;
+ return;
}
// Recurse for each of the child types
@@ -1235,7 +1213,7 @@ bool logChildren)
// Calculate the address of the member
DWORD_PTR dwFinalOffset = offset + dwMemberOffset;
- pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, modBase,
+ DumpTypeIndex(modBase,
children.ChildId[i],
dwFinalOffset, bHandled2, ""/*Name */, "", true, true);
@@ -1260,11 +1238,11 @@ bool logChildren)
symbolDetails.top().Value = buffer;
}
- pszCurrBuffer = PopSymbolDetail(pszCurrBuffer);
+ PopSymbolDetail();
}
bHandled = true;
- return pszCurrBuffer;
+ return;
}
void WheatyExceptionReport::FormatOutputValue(char * pszCurrBuffer,
@@ -1386,26 +1364,26 @@ DWORD_PTR WheatyExceptionReport::DereferenceUnsafePointer(DWORD_PTR address)
// Helper function that writes to the report file, and allows the user to use
// printf style formating
//============================================================================
-int __cdecl WheatyExceptionReport::_tprintf(const TCHAR * format, ...)
+int __cdecl WheatyExceptionReport::Log(const TCHAR * format, ...)
{
int retValue;
va_list argptr;
va_start(argptr, format);
if (stackOverflowException)
{
- retValue = heapprintf(format, argptr);
+ retValue = HeapLog(format, argptr);
va_end(argptr);
}
else
{
- retValue = stackprintf(format, argptr);
+ retValue = StackLog(format, argptr);
va_end(argptr);
}
return retValue;
}
-int __cdecl WheatyExceptionReport::stackprintf(const TCHAR * format, va_list argptr)
+int __cdecl WheatyExceptionReport::StackLog(const TCHAR * format, va_list argptr)
{
int retValue;
DWORD cbWritten;
@@ -1417,7 +1395,7 @@ int __cdecl WheatyExceptionReport::stackprintf(const TCHAR * format, va_list arg
return retValue;
}
-int __cdecl WheatyExceptionReport::heapprintf(const TCHAR * format, va_list argptr)
+int __cdecl WheatyExceptionReport::HeapLog(const TCHAR * format, va_list argptr)
{
int retValue = 0;
DWORD cbWritten;
@@ -1444,37 +1422,35 @@ void WheatyExceptionReport::ClearSymbols()
symbolDetails.pop();
}
-char* WheatyExceptionReport::PushSymbolDetail(char* pszCurrBuffer)
+void WheatyExceptionReport::PushSymbolDetail()
{
// Log current symbol and then add another to the stack to keep the hierarchy format
- pszCurrBuffer = PrintSymbolDetail(pszCurrBuffer);
+ PrintSymbolDetail();
symbolDetails.emplace();
- return pszCurrBuffer;
}
-char* WheatyExceptionReport::PopSymbolDetail(char* pszCurrBuffer)
+void WheatyExceptionReport::PopSymbolDetail()
{
- pszCurrBuffer = PrintSymbolDetail(pszCurrBuffer);
+ PrintSymbolDetail();
symbolDetails.pop();
- return pszCurrBuffer;
}
-char* WheatyExceptionReport::PrintSymbolDetail(char* pszCurrBuffer)
+void WheatyExceptionReport::PrintSymbolDetail()
{
if (symbolDetails.empty())
- return pszCurrBuffer;
+ return;
// Don't log anything if has been logged already or if it's empty
if (symbolDetails.top().Logged || symbolDetails.top().empty())
- return pszCurrBuffer;
+ return;
// Add appropriate indentation level (since this routine is recursive)
for (size_t i = 0; i < symbolDetails.size(); i++)
- pszCurrBuffer += sprintf(pszCurrBuffer, "\t");
+ Log(_T("\t"));
- pszCurrBuffer += sprintf(pszCurrBuffer, "%s\r\n", symbolDetails.top().ToString().c_str());
+ Log(_T("%s\r\n"), symbolDetails.top().ToString().c_str());
- return pszCurrBuffer;
+ return;
}
#endif // _WIN32
diff --git a/src/common/Debugging/WheatyExceptionReport.h b/src/common/Debugging/WheatyExceptionReport.h
index 7d7ae3feb4e..42d4d3e0a2a 100644
--- a/src/common/Debugging/WheatyExceptionReport.h
+++ b/src/common/Debugging/WheatyExceptionReport.h
@@ -14,7 +14,8 @@
#define WER_MAX_ARRAY_ELEMENTS_COUNT 10
#define WER_MAX_NESTING_LEVEL 4
-#define WER_LARGE_BUFFER_SIZE 1024 * 128
+#define WER_SMALL_BUFFER_SIZE 1024
+#define WER_LARGE_BUFFER_SIZE WER_SMALL_BUFFER_SIZE * 16
enum BasicType // Stolen from CVCONST.H in the DIA 2.0 SDK
{
@@ -173,18 +174,18 @@ class WheatyExceptionReport
static BOOL CALLBACK EnumerateSymbolsCallback(PSYMBOL_INFO, ULONG, PVOID);
- static bool FormatSymbolValue(PSYMBOL_INFO, STACKFRAME64 *, char * pszBuffer, unsigned cbBuffer);
+ static bool FormatSymbolValue(PSYMBOL_INFO, STACKFRAME64 *);
- static char * DumpTypeIndex(char *, DWORD64, DWORD, DWORD_PTR, bool &, const char*, char*, bool, bool);
+ static void DumpTypeIndex(DWORD64, DWORD, DWORD_PTR, bool &, const char*, char*, bool, bool);
static void FormatOutputValue(char * pszCurrBuffer, BasicType basicType, DWORD64 length, PVOID pAddress, size_t bufferSize, size_t countOverride = 0);
static BasicType GetBasicType(DWORD typeIndex, DWORD64 modBase);
static DWORD_PTR DereferenceUnsafePointer(DWORD_PTR address);
- static int __cdecl _tprintf(const TCHAR * format, ...);
- static int __cdecl stackprintf(const TCHAR * format, va_list argptr);
- static int __cdecl heapprintf(const TCHAR * format, va_list argptr);
+ static int __cdecl Log(const TCHAR * format, ...);
+ static int __cdecl StackLog(const TCHAR * format, va_list argptr);
+ static int __cdecl HeapLog(const TCHAR * format, va_list argptr);
static bool StoreSymbol(DWORD type , DWORD_PTR offset);
static void ClearSymbols();
@@ -205,9 +206,9 @@ class WheatyExceptionReport
typedef NTSTATUS(NTAPI* pRtlGetVersion)(PRTL_OSVERSIONINFOW lpVersionInformation);
static pRtlGetVersion RtlGetVersion;
- static char* PushSymbolDetail(char* pszCurrBuffer);
- static char* PopSymbolDetail(char* pszCurrBuffer);
- static char* PrintSymbolDetail(char* pszCurrBuffer);
+ static void PushSymbolDetail();
+ static void PopSymbolDetail();
+ static void PrintSymbolDetail();
};
diff --git a/src/common/Utilities/Util.h b/src/common/Utilities/Util.h
index 20520cb2068..a18fd16ad15 100644
--- a/src/common/Utilities/Util.h
+++ b/src/common/Utilities/Util.h
@@ -63,13 +63,6 @@ TC_COMMON_API std::string secsToTimeString(uint64 timeInSecs, bool shortText = f
TC_COMMON_API uint32 TimeStringToSecs(const std::string& timestring);
TC_COMMON_API std::string TimeToTimestampStr(time_t t);
-inline void ApplyPercentModFloatVar(float& var, float val, bool apply)
-{
- if (val == -100.0f) // prevent set var to zero
- val = -99.99f;
- var *= (apply ? (100.0f + val) / 100.0f : 100.0f / (100.0f + val));
-}
-
// Percentage calculation
template <class T, class U>
inline T CalculatePct(T base, U pct)
diff --git a/src/server/game/AI/CreatureAI.cpp b/src/server/game/AI/CreatureAI.cpp
index 7fbc8ed2ed5..b9d052cb528 100644
--- a/src/server/game/AI/CreatureAI.cpp
+++ b/src/server/game/AI/CreatureAI.cpp
@@ -368,13 +368,25 @@ bool CreatureAI::CheckBoundary(Position const* who) const
who = me;
if (_boundary)
- for (AreaBoundary const* boundary : *_boundary)
- if (!boundary->IsWithinBoundary(who))
+ for (AreaBoundary const* areaBoundary : *_boundary)
+ if (!areaBoundary->IsWithinBoundary(who))
return false;
return true;
}
+bool CreatureAI::IsInBounds(CreatureBoundary const* boundary, Position const* pos)
+{
+ if (!boundary)
+ return true;
+
+ for (AreaBoundary const* areaBoundary : *boundary)
+ if (!areaBoundary->IsWithinBoundary(pos))
+ return false;
+
+ return true;
+}
+
void CreatureAI::SetBoundary(CreatureBoundary const* boundary)
{
_boundary = boundary;
diff --git a/src/server/game/AI/CreatureAI.h b/src/server/game/AI/CreatureAI.h
index e36a41795a0..5fe93e7675a 100644
--- a/src/server/game/AI/CreatureAI.h
+++ b/src/server/game/AI/CreatureAI.h
@@ -31,7 +31,7 @@ class PlayerAI;
class WorldObject;
struct Position;
-typedef std::set<AreaBoundary const*> CreatureBoundary;
+typedef std::vector<AreaBoundary const*> CreatureBoundary;
#define TIME_INTERVAL_LOOK 5000
#define VISIBILITY_RANGE 10000
@@ -82,6 +82,7 @@ class TC_GAME_API CreatureAI : public UnitAI
Creature* DoSummonFlyer(uint32 entry, WorldObject* obj, float flightZ, float radius = 5.0f, uint32 despawnTime = 30000, TempSummonType summonType = TEMPSUMMON_CORPSE_TIMED_DESPAWN);
bool CheckBoundary(Position const* who = nullptr) const;
+
void SetBoundary(CreatureBoundary const* boundary);
public:
enum EvadeReason
@@ -214,6 +215,8 @@ class TC_GAME_API CreatureAI : public UnitAI
virtual bool CheckInRoom();
CreatureBoundary const* GetBoundary() const { return _boundary; }
+ static bool IsInBounds(CreatureBoundary const* boundary, Position const* who);
+
protected:
virtual void MoveInLineOfSight(Unit* /*who*/);
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index 8bee4794975..6224533846e 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -2341,12 +2341,8 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
{
if (Creature* creature = (*itr)->ToCreature())
- {
- creature->GetMotionMaster()->Clear();
creature->GetMotionMaster()->MoveJump(e.target.x, e.target.y, e.target.z, 0.0f, (float)e.action.jump.speedxy, (float)e.action.jump.speedz); // @todo add optional jump orientation support?
- }
}
- /// @todo Resume path when reached jump location
delete targets;
break;
diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp
index 77ed2075a33..12e33cf9ee3 100644
--- a/src/server/game/Achievements/AchievementMgr.cpp
+++ b/src/server/game/Achievements/AchievementMgr.cpp
@@ -1016,6 +1016,9 @@ bool AchievementGlobalMgr::IsRealmCompleted(AchievementEntry const* achievement)
if (itr->second == std::chrono::system_clock::time_point::min())
return false;
+ if (itr->second == std::chrono::system_clock::time_point::max())
+ return true;
+
// Allow completing the realm first kill for entire minute after first person did it
// it may allow more than one group to achieve it (highly unlikely)
// but apparently this is how blizz handles it as well
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 748e1ac26ee..4bbb29d43c1 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -536,12 +536,12 @@ bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/,
UpdateLevelDependantStats(); // We still re-initialize level dependant stats on entry update
SetMeleeDamageSchool(SpellSchools(cInfo->dmgschool));
- SetModifierValue(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_HOLY]));
- SetModifierValue(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_FIRE]));
- SetModifierValue(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_NATURE]));
- SetModifierValue(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_FROST]));
- SetModifierValue(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_SHADOW]));
- SetModifierValue(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_ARCANE]));
+ SetStatFlatModifier(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_HOLY]));
+ SetStatFlatModifier(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_FIRE]));
+ SetStatFlatModifier(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_NATURE]));
+ SetStatFlatModifier(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_FROST]));
+ SetStatFlatModifier(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_SHADOW]));
+ SetStatFlatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_ARCANE]));
SetCanModifyStats(true);
UpdateAllStats();
@@ -1043,8 +1043,7 @@ bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 entry, float
LastUsedScriptID = GetScriptId();
- /// @todo Replace with spell, handle from DB
- if (IsSpiritHealer() || IsSpiritGuide())
+ if (IsSpiritHealer() || IsSpiritGuide() || (GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_GHOST_VISIBILITY))
{
m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_GHOST);
m_serverSideVisibilityDetect.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_GHOST);
@@ -1409,7 +1408,7 @@ void Creature::UpdateLevelDependantStats()
break;
}
- SetModifierValue(UNIT_MOD_HEALTH, BASE_VALUE, (float)health);
+ SetStatFlatModifier(UNIT_MOD_HEALTH, BASE_VALUE, (float)health);
// damage
float basedamage = stats->GenerateBaseDamage(cInfo);
@@ -1426,11 +1425,11 @@ void Creature::UpdateLevelDependantStats()
SetBaseWeaponDamage(RANGED_ATTACK, MINDAMAGE, weaponBaseMinDamage);
SetBaseWeaponDamage(RANGED_ATTACK, MAXDAMAGE, weaponBaseMaxDamage);
- SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, stats->AttackPower);
- SetModifierValue(UNIT_MOD_ATTACK_POWER_RANGED, BASE_VALUE, stats->RangedAttackPower);
+ SetStatFlatModifier(UNIT_MOD_ATTACK_POWER, BASE_VALUE, stats->AttackPower);
+ SetStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, BASE_VALUE, stats->RangedAttackPower);
float armor = (float)stats->GenerateArmor(cInfo); /// @todo Why is this treated as uint32 when it's a float?
- SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, armor);
+ SetStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, armor);
}
float Creature::_GetHealthMod(int32 Rank)
@@ -1906,7 +1905,7 @@ void Creature::setDeathState(DeathState s)
SetCannotReachTarget(false);
UpdateMovementFlags();
- ClearUnitState(uint32(UNIT_STATE_ALL_STATE & ~UNIT_STATE_IGNORE_PATHFINDING));
+ ClearUnitState(UNIT_STATE_ALL_ERASABLE);
if (!IsPet())
{
@@ -2437,7 +2436,7 @@ bool Creature::CanCreatureAttack(Unit const* victim, bool /*force*/) const
else
{
// include sizes for huge npcs
- dist += GetObjectSize() + victim->GetObjectSize();
+ dist += GetCombatReach() + victim->GetCombatReach();
// to prevent creatures in air ignore attacks because distance is already too high...
if (GetCreatureTemplate()->InhabitType & INHABIT_AIR)
@@ -2755,7 +2754,8 @@ std::string Creature::GetScriptName() const
uint32 Creature::GetScriptId() const
{
if (CreatureData const* creatureData = GetCreatureData())
- return creatureData->ScriptId;
+ if (uint32 scriptId = creatureData->ScriptId)
+ return scriptId;
return sObjectMgr->GetCreatureTemplate(GetEntry())->ScriptID;
}
@@ -2995,7 +2995,7 @@ void Creature::SetObjectScale(float scale)
if (CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelInfo(GetDisplayId()))
{
SetBoundingRadius((IsPet() ? 1.0f : minfo->bounding_radius) * scale);
- SetCombatReach((IsPet() ? DEFAULT_COMBAT_REACH : minfo->combat_reach) * scale);
+ SetCombatReach((IsPet() ? DEFAULT_PLAYER_COMBAT_REACH : minfo->combat_reach) * scale);
}
}
@@ -3006,7 +3006,7 @@ void Creature::SetDisplayId(uint32 modelId, float displayScale /*= 1.f*/)
if (CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelInfo(modelId))
{
SetBoundingRadius((IsPet() ? 1.0f : minfo->bounding_radius) * GetObjectScale());
- SetCombatReach((IsPet() ? DEFAULT_COMBAT_REACH : minfo->combat_reach) * GetObjectScale());
+ SetCombatReach((IsPet() ? DEFAULT_PLAYER_COMBAT_REACH : minfo->combat_reach) * GetObjectScale());
}
}
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index afd07d44053..1be3e00e39a 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -155,7 +155,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
void UpdateMaxPower(Powers power) override;
uint32 GetPowerIndex(Powers power) const override;
void UpdateAttackPowerAndDamage(bool ranged = false) override;
- void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) override;
+ void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) const override;
void SetCanDualWield(bool value) override;
int8 GetOriginalEquipmentId() const { return m_originalEquipmentId; }
diff --git a/src/server/game/Entities/Creature/CreatureData.h b/src/server/game/Entities/Creature/CreatureData.h
index f94e8dbe22a..d5657ced163 100644
--- a/src/server/game/Entities/Creature/CreatureData.h
+++ b/src/server/game/Entities/Creature/CreatureData.h
@@ -255,7 +255,7 @@ enum CreatureDifficultyFlags7
CREATURE_DIFFICULTYFLAGS_7_UNK1 = 0x00000008
};
-enum CreatureFlagsExtra
+enum CreatureFlagsExtra : uint32
{
CREATURE_FLAG_EXTRA_INSTANCE_BIND = 0x00000001, // creature kill bind instance with killer and killer's group
CREATURE_FLAG_EXTRA_CIVILIAN = 0x00000002, // not aggro (ignore faction/reputation hostility)
@@ -267,24 +267,37 @@ enum CreatureFlagsExtra
CREATURE_FLAG_EXTRA_TRIGGER = 0x00000080, // trigger creature
CREATURE_FLAG_EXTRA_NO_TAUNT = 0x00000100, // creature is immune to taunt auras and effect attack me
CREATURE_FLAG_EXTRA_NO_MOVE_FLAGS_UPDATE = 0x00000200, // creature won't update movement flags
+ CREATURE_FLAG_EXTRA_GHOST_VISIBILITY = 0x00000400, // creature will be only visible for dead players
+ CREATURE_FLAG_EXTRA_UNUSED_11 = 0x00000800,
+ CREATURE_FLAG_EXTRA_UNUSED_12 = 0x00001000,
+ CREATURE_FLAG_EXTRA_UNUSED_13 = 0x00002000,
CREATURE_FLAG_EXTRA_WORLDEVENT = 0x00004000, // custom flag for world event creatures (left room for merging)
CREATURE_FLAG_EXTRA_GUARD = 0x00008000, // Creature is guard
+ CREATURE_FLAG_EXTRA_UNUSED_16 = 0x00010000,
CREATURE_FLAG_EXTRA_NO_CRIT = 0x00020000, // creature can't do critical strikes
CREATURE_FLAG_EXTRA_NO_SKILLGAIN = 0x00040000, // creature won't increase weapon skills
CREATURE_FLAG_EXTRA_TAUNT_DIMINISH = 0x00080000, // Taunt is a subject to diminishing returns on this creautre
CREATURE_FLAG_EXTRA_ALL_DIMINISH = 0x00100000, // creature is subject to all diminishing returns as player are
CREATURE_FLAG_EXTRA_NO_PLAYER_DAMAGE_REQ = 0x00200000, // creature does not need to take player damage for kill credit
+ CREATURE_FLAG_EXTRA_UNUSED_22 = 0x00400000,
+ CREATURE_FLAG_EXTRA_UNUSED_23 = 0x00800000,
+ CREATURE_FLAG_EXTRA_UNUSED_24 = 0x01000000,
+ CREATURE_FLAG_EXTRA_UNUSED_25 = 0x02000000,
+ CREATURE_FLAG_EXTRA_UNUSED_26 = 0x04000000,
+ CREATURE_FLAG_EXTRA_UNUSED_27 = 0x08000000,
CREATURE_FLAG_EXTRA_DUNGEON_BOSS = 0x10000000, // creature is a dungeon boss (SET DYNAMICALLY, DO NOT ADD IN DB)
CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING = 0x20000000, // creature ignore pathfinding
- CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK = 0x40000000 // creature is immune to knockback effects
-};
+ CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK = 0x40000000, // creature is immune to knockback effects
+ CREATURE_FLAG_EXTRA_UNUSED_31 = 0x80000000,
+
+ // Masks
+ CREATURE_FLAG_EXTRA_UNUSED = (CREATURE_FLAG_EXTRA_UNUSED_11 | CREATURE_FLAG_EXTRA_UNUSED_12 | CREATURE_FLAG_EXTRA_UNUSED_13 |
+ CREATURE_FLAG_EXTRA_UNUSED_16 | CREATURE_FLAG_EXTRA_UNUSED_22 | CREATURE_FLAG_EXTRA_UNUSED_23 |
+ CREATURE_FLAG_EXTRA_UNUSED_24 | CREATURE_FLAG_EXTRA_UNUSED_25 | CREATURE_FLAG_EXTRA_UNUSED_26 |
+ CREATURE_FLAG_EXTRA_UNUSED_27 | CREATURE_FLAG_EXTRA_UNUSED_31),
-#define CREATURE_FLAG_EXTRA_DB_ALLOWED (CREATURE_FLAG_EXTRA_INSTANCE_BIND | CREATURE_FLAG_EXTRA_CIVILIAN | \
- CREATURE_FLAG_EXTRA_NO_PARRY | CREATURE_FLAG_EXTRA_NO_PARRY_HASTEN | CREATURE_FLAG_EXTRA_NO_BLOCK | \
- CREATURE_FLAG_EXTRA_NO_CRUSH | CREATURE_FLAG_EXTRA_NO_XP_AT_KILL | CREATURE_FLAG_EXTRA_TRIGGER | \
- CREATURE_FLAG_EXTRA_NO_TAUNT | CREATURE_FLAG_EXTRA_NO_MOVE_FLAGS_UPDATE | CREATURE_FLAG_EXTRA_WORLDEVENT | CREATURE_FLAG_EXTRA_NO_CRIT | \
- CREATURE_FLAG_EXTRA_NO_SKILLGAIN | CREATURE_FLAG_EXTRA_TAUNT_DIMINISH | CREATURE_FLAG_EXTRA_ALL_DIMINISH | \
- CREATURE_FLAG_EXTRA_GUARD | CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING | CREATURE_FLAG_EXTRA_NO_PLAYER_DAMAGE_REQ | CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK)
+ CREATURE_FLAG_EXTRA_DB_ALLOWED = (0xFFFFFFFF & ~(CREATURE_FLAG_EXTRA_UNUSED | CREATURE_FLAG_EXTRA_DUNGEON_BOSS))
+};
const uint32 CREATURE_REGEN_INTERVAL = 2 * IN_MILLISECONDS;
const uint32 PET_FOCUS_REGEN_INTERVAL = 4 * IN_MILLISECONDS;
diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp
index 05aadcc1709..76be982fdb2 100644
--- a/src/server/game/Entities/Creature/GossipDef.cpp
+++ b/src/server/game/Entities/Creature/GossipDef.cpp
@@ -598,13 +598,13 @@ void PlayerMenu::SendQuestGiverRequestItems(Quest const* quest, ObjectGuid npcGU
if (canComplete)
{
- packet.CompEmoteDelay = quest->EmoteOnCompleteDelay;
- packet.CompEmoteType = quest->EmoteOnComplete;
+ packet.CompEmoteDelay = quest->GetCompleteEmoteDelay();
+ packet.CompEmoteType = quest->GetCompleteEmote();
}
else
{
- packet.CompEmoteDelay = quest->EmoteOnIncompleteDelay;
- packet.CompEmoteType = quest->EmoteOnIncomplete;
+ packet.CompEmoteDelay = quest->GetIncompleteEmoteDelay();
+ packet.CompEmoteType = quest->GetIncompleteEmote();
}
packet.QuestFlags[0] = quest->GetFlags();
diff --git a/src/server/game/Entities/Creature/TemporarySummon.h b/src/server/game/Entities/Creature/TemporarySummon.h
index 056fe78c99d..c91af442cef 100644
--- a/src/server/game/Entities/Creature/TemporarySummon.h
+++ b/src/server/game/Entities/Creature/TemporarySummon.h
@@ -120,6 +120,7 @@ class TC_GAME_API Guardian : public Minion
void UpdateDamagePhysical(WeaponAttackType attType) override;
int32 GetBonusDamage() const { return m_bonusSpellDamage; }
+ float GetBonusStatFromOwner(Stats stat) const { return m_statFromOwner[stat]; }
void SetBonusDamage(int32 damage);
protected:
int32 m_bonusSpellDamage;
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index b9e17565702..4e34c8b4785 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -2183,7 +2183,8 @@ void GameObject::EventInform(uint32 eventId, WorldObject* invoker /*= nullptr*/)
uint32 GameObject::GetScriptId() const
{
if (GameObjectData const* gameObjectData = GetGOData())
- return gameObjectData->ScriptId;
+ if (uint32 scriptId = gameObjectData->ScriptId)
+ return scriptId;
return GetGOInfo()->ScriptId;
}
diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h
index b34f5e7951d..da06d1842f8 100644
--- a/src/server/game/Entities/GameObject/GameObject.h
+++ b/src/server/game/Entities/GameObject/GameObject.h
@@ -280,7 +280,7 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject>
void EventInform(uint32 eventId, WorldObject* invoker = NULL);
- virtual uint32 GetScriptId() const;
+ uint32 GetScriptId() const;
GameObjectAI* AI() const { return m_AI; }
std::string GetAIName() const;
@@ -363,7 +363,7 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject>
void UpdatePackedRotation();
//! Object distance/size - overridden from Object::_IsWithinDist. Needs to take in account proper GO size.
- bool _IsWithinDist(WorldObject const* obj, float dist2compare, bool /*is3D*/) const override
+ bool _IsWithinDist(WorldObject const* obj, float dist2compare, bool /*is3D*/, bool /*incOwnRadius*/, bool /*incTargetRadius*/) const override
{
//! Following check does check 3d distance
return IsInRange(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), dist2compare);
diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp
index 57be82a51ef..8b7eea39e98 100644
--- a/src/server/game/Entities/Item/Item.cpp
+++ b/src/server/game/Entities/Item/Item.cpp
@@ -844,7 +844,9 @@ bool Item::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid ownerGuid, Field* fie
SetDurability(durability);
// update max durability (and durability) if need
SetUpdateFieldValue(m_values.ModifyValue(&Item::m_itemData).ModifyValue(&UF::ItemData::MaxDurability), proto->MaxDurability);
- if (durability > proto->MaxDurability)
+
+ // do not overwrite durability for wrapped items
+ if (durability > proto->MaxDurability && !HasItemFlag(ITEM_FIELD_FLAG_WRAPPED))
{
SetDurability(proto->MaxDurability);
need_save = true;
diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h
index 13f0cb7de66..c4c5ee62d5a 100644
--- a/src/server/game/Entities/Item/Item.h
+++ b/src/server/game/Entities/Item/Item.h
@@ -258,6 +258,7 @@ class TC_GAME_API Item : public Object
bool IsNotEmptyBag() const;
bool IsBroken() const { return *m_itemData->MaxDurability > 0 && *m_itemData->Durability == 0; }
void SetDurability(uint32 durability) { SetUpdateFieldValue(m_values.ModifyValue(&Item::m_itemData).ModifyValue(&UF::ItemData::Durability), durability); }
+ void SetMaxDurability(uint32 maxDurability) { SetUpdateFieldValue(m_values.ModifyValue(&Item::m_itemData).ModifyValue(&UF::ItemData::MaxDurability), maxDurability); }
bool CanBeTraded(bool mail = false, bool trade = false) const;
void SetInTrade(bool b = true) { mb_in_trade = b; }
bool IsInTrade() const { return mb_in_trade; }
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index b34b3523fc4..94fd3e932c8 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -969,39 +969,31 @@ InstanceScript* WorldObject::GetInstanceScript()
float WorldObject::GetDistanceZ(const WorldObject* obj) const
{
float dz = std::fabs(GetPositionZ() - obj->GetPositionZ());
- float sizefactor = GetObjectSize() + obj->GetObjectSize();
+ float sizefactor = GetCombatReach() + obj->GetCombatReach();
float dist = dz - sizefactor;
return (dist > 0 ? dist : 0);
}
-bool WorldObject::_IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D) const
+bool WorldObject::_IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D, bool incOwnRadius, bool incTargetRadius) const
{
- float sizefactor = GetObjectSize() + obj->GetObjectSize();
+ float sizefactor = 0;
+ sizefactor += incOwnRadius ? GetCombatReach() : 0.0f;
+ sizefactor += incTargetRadius ? obj->GetCombatReach() : 0.0f;
float maxdist = dist2compare + sizefactor;
+ Position const* thisOrTransport = this;
+ Position const* objOrObjTransport = obj;
+
if (GetTransport() && obj->GetTransport() && obj->GetTransport()->GetGUID() == GetTransport()->GetGUID())
{
- float dtx = m_movementInfo.transport.pos.m_positionX - obj->m_movementInfo.transport.pos.m_positionX;
- float dty = m_movementInfo.transport.pos.m_positionY - obj->m_movementInfo.transport.pos.m_positionY;
- float disttsq = dtx * dtx + dty * dty;
- if (is3D)
- {
- float dtz = m_movementInfo.transport.pos.m_positionZ - obj->m_movementInfo.transport.pos.m_positionZ;
- disttsq += dtz * dtz;
- }
- return disttsq < (maxdist * maxdist);
+ thisOrTransport = &m_movementInfo.transport.pos;
+ objOrObjTransport = &obj->m_movementInfo.transport.pos;
}
- float dx = GetPositionX() - obj->GetPositionX();
- float dy = GetPositionY() - obj->GetPositionY();
- float distsq = dx*dx + dy*dy;
if (is3D)
- {
- float dz = GetPositionZ() - obj->GetPositionZ();
- distsq += dz*dz;
- }
-
- return distsq < maxdist * maxdist;
+ return thisOrTransport->IsInDist(objOrObjTransport, maxdist);
+ else
+ return thisOrTransport->IsInDist2d(objOrObjTransport, maxdist);
}
bool WorldObject::IsWithinLOSInMap(const WorldObject* obj, VMAP::ModelIgnoreFlags ignoreFlags) const
@@ -1020,31 +1012,31 @@ bool WorldObject::IsWithinLOSInMap(const WorldObject* obj, VMAP::ModelIgnoreFlag
float WorldObject::GetDistance(const WorldObject* obj) const
{
- float d = GetExactDist(obj) - GetObjectSize() - obj->GetObjectSize();
+ float d = GetExactDist(obj) - GetCombatReach() - obj->GetCombatReach();
return d > 0.0f ? d : 0.0f;
}
float WorldObject::GetDistance(const Position &pos) const
{
- float d = GetExactDist(&pos) - GetObjectSize();
+ float d = GetExactDist(&pos) - GetCombatReach();
return d > 0.0f ? d : 0.0f;
}
float WorldObject::GetDistance(float x, float y, float z) const
{
- float d = GetExactDist(x, y, z) - GetObjectSize();
+ float d = GetExactDist(x, y, z) - GetCombatReach();
return d > 0.0f ? d : 0.0f;
}
float WorldObject::GetDistance2d(const WorldObject* obj) const
{
- float d = GetExactDist2d(obj) - GetObjectSize() - obj->GetObjectSize();
+ float d = GetExactDist2d(obj) - GetCombatReach() - obj->GetCombatReach();
return d > 0.0f ? d : 0.0f;
}
float WorldObject::GetDistance2d(float x, float y) const
{
- float d = GetExactDist2d(x, y) - GetObjectSize();
+ float d = GetExactDist2d(x, y) - GetCombatReach();
return d > 0.0f ? d : 0.0f;
}
@@ -1064,22 +1056,22 @@ bool WorldObject::IsInMap(const WorldObject* obj) const
bool WorldObject::IsWithinDist3d(float x, float y, float z, float dist) const
{
- return IsInDist(x, y, z, dist + GetObjectSize());
+ return IsInDist(x, y, z, dist + GetCombatReach());
}
bool WorldObject::IsWithinDist3d(const Position* pos, float dist) const
{
- return IsInDist(pos, dist + GetObjectSize());
+ return IsInDist(pos, dist + GetCombatReach());
}
bool WorldObject::IsWithinDist2d(float x, float y, float dist) const
{
- return IsInDist2d(x, y, dist + GetObjectSize());
+ return IsInDist2d(x, y, dist + GetCombatReach());
}
bool WorldObject::IsWithinDist2d(const Position* pos, float dist) const
{
- return IsInDist2d(pos, dist + GetObjectSize());
+ return IsInDist2d(pos, dist + GetCombatReach());
}
bool WorldObject::IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D /*= true*/) const
@@ -1087,9 +1079,9 @@ bool WorldObject::IsWithinDist(WorldObject const* obj, float dist2compare, bool
return obj && _IsWithinDist(obj, dist2compare, is3D);
}
-bool WorldObject::IsWithinDistInMap(WorldObject const* obj, float dist2compare, bool is3D /*= true*/) const
+bool WorldObject::IsWithinDistInMap(WorldObject const* obj, float dist2compare, bool is3D /*= true*/, bool incOwnRadius /*= true*/, bool incTargetRadius /*= true*/) const
{
- return obj && IsInMap(obj) && IsInPhase(obj) && _IsWithinDist(obj, dist2compare, is3D);
+ return obj && IsInMap(obj) && IsInPhase(obj) && _IsWithinDist(obj, dist2compare, is3D, incOwnRadius, incTargetRadius);
}
bool WorldObject::IsWithinLOS(float ox, float oy, float oz, VMAP::ModelIgnoreFlags ignoreFlags) const
@@ -1116,7 +1108,7 @@ Position WorldObject::GetHitSpherePointFor(Position const& dest) const
{
G3D::Vector3 vThis(GetPositionX(), GetPositionY(), GetPositionZ());
G3D::Vector3 vObj(dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ());
- G3D::Vector3 contactPoint = vThis + (vObj - vThis).directionOrZero() * GetObjectSize();
+ G3D::Vector3 contactPoint = vThis + (vObj - vThis).directionOrZero() * std::min(dest.GetExactDist(GetPosition()), GetCombatReach());
return Position(contactPoint.x, contactPoint.y, contactPoint.z, GetAngle(contactPoint.x, contactPoint.y));
}
@@ -1163,7 +1155,7 @@ bool WorldObject::IsInRange(WorldObject const* obj, float minRange, float maxRan
distsq += dz*dz;
}
- float sizefactor = GetObjectSize() + obj->GetObjectSize();
+ float sizefactor = GetCombatReach() + obj->GetCombatReach();
// check only for real range
if (minRange > 0.0f)
@@ -1183,7 +1175,7 @@ bool WorldObject::IsInRange2d(float x, float y, float minRange, float maxRange)
float dy = GetPositionY() - y;
float distsq = dx*dx + dy*dy;
- float sizefactor = GetObjectSize();
+ float sizefactor = GetCombatReach();
// check only for real range
if (minRange > 0.0f)
@@ -1204,7 +1196,7 @@ bool WorldObject::IsInRange3d(float x, float y, float z, float minRange, float m
float dz = GetPositionZ() - z;
float distsq = dx*dx + dy*dy + dz*dz;
- float sizefactor = GetObjectSize();
+ float sizefactor = GetCombatReach();
// check only for real range
if (minRange > 0.0f)
@@ -1227,7 +1219,7 @@ bool WorldObject::IsInBetween(Position const& pos1, Position const& pos2, float
return false;
if (!size)
- size = GetObjectSize() / 2;
+ size = GetCombatReach() / 2;
float angle = pos1.GetAngle(pos2);
@@ -1837,7 +1829,7 @@ TempSummon* WorldObject::SummonCreature(uint32 id, float x, float y, float z, fl
{
if (!x && !y && !z)
{
- GetClosePoint(x, y, z, GetObjectSize());
+ GetClosePoint(x, y, z, GetCombatReach());
ang = GetOrientation();
}
@@ -1879,7 +1871,7 @@ GameObject* WorldObject::SummonGameObject(uint32 entry, float x, float y, float
{
if (!x && !y && !z)
{
- GetClosePoint(x, y, z, GetObjectSize());
+ GetClosePoint(x, y, z, GetCombatReach());
ang = GetOrientation();
}
@@ -1993,8 +1985,8 @@ void WorldObject::GetPlayerListInGrid(Container& playerContainer, float maxSearc
void WorldObject::GetNearPoint2D(float &x, float &y, float distance2d, float absAngle) const
{
- x = GetPositionX() + (GetObjectSize() + distance2d) * std::cos(absAngle);
- y = GetPositionY() + (GetObjectSize() + distance2d) * std::sin(absAngle);
+ x = GetPositionX() + (GetCombatReach() + distance2d) * std::cos(absAngle);
+ y = GetPositionY() + (GetCombatReach() + distance2d) * std::sin(absAngle);
Trinity::NormalizeMapCoord(x);
Trinity::NormalizeMapCoord(y);
@@ -2066,15 +2058,7 @@ Position WorldObject::GetRandomNearPosition(float radius)
void WorldObject::GetContactPoint(const WorldObject* obj, float &x, float &y, float &z, float distance2d /*= CONTACT_DISTANCE*/) const
{
// angle to face `obj` to `this` using distance includes size of `obj`
- GetNearPoint(obj, x, y, z, obj->GetObjectSize(), distance2d, GetAngle(obj));
-}
-
-float WorldObject::GetObjectSize() const
-{
- if (Unit const* thisUnit = ToUnit())
- return thisUnit->m_unitData->CombatReach;
-
- return DEFAULT_WORLD_OBJECT_SIZE;
+ GetNearPoint(obj, x, y, z, obj->GetCombatReach(), distance2d, GetAngle(obj));
}
void WorldObject::MovePosition(Position &pos, float dist, float angle)
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index c5e22c86c3a..1d48e1f2384 100644
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -395,7 +395,7 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation
Position GetRandomNearPosition(float radius);
void GetContactPoint(WorldObject const* obj, float &x, float &y, float &z, float distance2d = CONTACT_DISTANCE) const;
- float GetObjectSize() const;
+ virtual float GetCombatReach() const { return 0.0f; } // overridden (only) in Unit
void UpdateGroundPositionZ(float x, float y, float &z) const;
void UpdateAllowedPositionZ(float x, float y, float &z) const;
@@ -445,7 +445,7 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation
bool IsWithinDist2d(Position const* pos, float dist) const;
// use only if you will sure about placing both object at same map
bool IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D = true) const;
- bool IsWithinDistInMap(WorldObject const* obj, float dist2compare, bool is3D = true) const;
+ bool IsWithinDistInMap(WorldObject const* obj, float dist2compare, bool is3D = true, bool incOwnRadius = true, bool incTargetRadius = true) const;
bool IsWithinLOS(float x, float y, float z, VMAP::ModelIgnoreFlags ignoreFlags = VMAP::ModelIgnoreFlags::Nothing) const;
bool IsWithinLOSInMap(WorldObject const* obj, VMAP::ModelIgnoreFlags ignoreFlags = VMAP::ModelIgnoreFlags::Nothing) const;
Position GetHitSpherePointFor(Position const& dest) const;
@@ -605,7 +605,7 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation
uint16 m_notifyflags;
uint16 m_executed_notifies;
- virtual bool _IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D) const;
+ virtual bool _IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D, bool incOwnRadius = true, bool incTargetRadius = true) const;
bool CanNeverSee(WorldObject const* obj) const;
virtual bool CanAlwaysSee(WorldObject const* /*obj*/) const { return false; }
diff --git a/src/server/game/Entities/Object/ObjectDefines.h b/src/server/game/Entities/Object/ObjectDefines.h
index b0db49bcf9f..43f2ea15a4d 100644
--- a/src/server/game/Entities/Object/ObjectDefines.h
+++ b/src/server/game/Entities/Object/ObjectDefines.h
@@ -36,11 +36,11 @@
#define DEFAULT_VISIBILITY_INSTANCE 170.0f // default visible distance in instances, 170 yards
#define DEFAULT_VISIBILITY_BGARENAS 533.0f // default visible distance in BG/Arenas, roughly 533 yards
-#define DEFAULT_WORLD_OBJECT_SIZE 0.388999998569489f // player size, also currently used (correctly?) for any non Unit world objects
-#define DEFAULT_COMBAT_REACH 1.5f
-#define MIN_MELEE_REACH 2.0f
-#define NOMINAL_MELEE_RANGE 5.0f
-#define MELEE_RANGE (NOMINAL_MELEE_RANGE - MIN_MELEE_REACH * 2) //center to center for players
+#define DEFAULT_PLAYER_BOUNDING_RADIUS 0.388999998569489f // player size, also currently used (correctly?) for any non Unit world objects
+#define DEFAULT_PLAYER_COMBAT_REACH 1.5f
+#define MIN_MELEE_REACH 2.0f
+#define NOMINAL_MELEE_RANGE 5.0f
+#define MELEE_RANGE (NOMINAL_MELEE_RANGE - MIN_MELEE_REACH * 2) //center to center for players
enum class VisibilityDistanceType : uint8
{
diff --git a/src/server/game/Entities/Object/Position.cpp b/src/server/game/Entities/Object/Position.cpp
index ae0fc14e173..a63a3da76d6 100644
--- a/src/server/game/Entities/Object/Position.cpp
+++ b/src/server/game/Entities/Object/Position.cpp
@@ -148,6 +148,12 @@ bool Position::IsWithinBox(const Position& center, float xradius, float yradius,
return true;
}
+bool Position::IsWithinDoubleVerticalCylinder(Position const* center, float radius, float height) const
+{
+ float verticalDelta = GetPositionZ() - center->GetPositionZ();
+ return IsInDist2d(center, radius) && std::abs(verticalDelta) <= height;
+}
+
bool Position::HasInArc(float arc, const Position* obj, float border) const
{
// always have self in arc
diff --git a/src/server/game/Entities/Object/Position.h b/src/server/game/Entities/Object/Position.h
index 37f1231e709..f247c7fb860 100644
--- a/src/server/game/Entities/Object/Position.h
+++ b/src/server/game/Entities/Object/Position.h
@@ -218,6 +218,11 @@ public:
}
bool IsWithinBox(const Position& center, float xradius, float yradius, float zradius) const;
+
+ /*
+ search using this relation: dist2d < radius && abs(dz) < height
+ */
+ bool IsWithinDoubleVerticalCylinder(Position const* center, float radius, float height) const;
bool HasInArc(float arcangle, Position const* pos, float border = 2.0f) const;
bool HasInLine(Position const* pos, float objSize, float width) const;
std::string ToString() const;
diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp
index 7563289b480..9c16502dd25 100644
--- a/src/server/game/Entities/Pet/Pet.cpp
+++ b/src/server/game/Entities/Pet/Pet.cpp
@@ -192,7 +192,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
if (IsCritter())
{
float px, py, pz;
- owner->GetClosePoint(px, py, pz, GetObjectSize(), PET_FOLLOW_DIST, GetFollowAngle());
+ owner->GetClosePoint(px, py, pz, GetCombatReach(), PET_FOLLOW_DIST, GetFollowAngle());
Relocate(px, py, pz, owner->GetOrientation());
if (!IsPositionValid())
@@ -245,7 +245,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
// Set pet's position after setting level, its size depends on it
float px, py, pz;
- owner->GetClosePoint(px, py, pz, GetObjectSize(), PET_FOLLOW_DIST, GetFollowAngle());
+ owner->GetClosePoint(px, py, pz, GetCombatReach(), PET_FOLLOW_DIST, GetFollowAngle());
Relocate(px, py, pz, owner->GetOrientation());
if (!IsPositionValid())
{
@@ -375,6 +375,8 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
if (owner->GetTypeId() == TYPEID_PLAYER && isControlled() && !isTemporarySummoned() && (getPetType() == SUMMON_PET || getPetType() == HUNTER_PET))
owner->ToPlayer()->SetLastPetNumber(petId);
+ // must be after SetMinion (owner guid check)
+ LoadMechanicTemplateImmunity();
m_loading = false;
return true;
@@ -794,7 +796,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
SetMeleeDamageSchool(SpellSchools(cinfo->dmgschool));
- SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(petlevel*50));
+ SetStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(petlevel * 50));
SetBaseAttackTime(BASE_ATTACK, BASE_ATTACK_TIME);
SetBaseAttackTime(OFF_ATTACK, BASE_ATTACK_TIME);
@@ -819,7 +821,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
// Hunters pet should not inherit resistances from creature_template, they have separate auras for that
if (!IsHunterPet())
for (uint8 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
- SetModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + i), BASE_VALUE, float(cinfo->resistance[i]));
+ SetStatFlatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), BASE_VALUE, float(cinfo->resistance[i]));
// Health, Mana or Power, Armor
PetLevelInfo const* pInfo = sObjectMgr->GetPetLevelInfo(creature_ID, petlevel);
@@ -829,7 +831,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
SetCreateMana(pInfo->mana);
if (pInfo->armor > 0)
- SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(pInfo->armor));
+ SetStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(pInfo->armor));
for (uint8 stat = 0; stat < MAX_STATS; ++stat)
SetCreateStat(Stats(stat), float(pInfo->stats[stat]));
@@ -875,7 +877,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)));
SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)));
- //SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, float(cinfo->attackpower));
+ //SetStatFlatModifier(UNIT_MOD_ATTACK_POWER, BASE_VALUE, float(cinfo->attackpower));
break;
}
case HUNTER_PET:
@@ -963,8 +965,8 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float((petlevel * 4 - petlevel)));
SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float((petlevel * 4 + petlevel)));
- SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(GetOwner()->GetArmor()) * 0.35f); // Bonus Armor (35% of player armor)
- SetModifierValue(UNIT_MOD_STAT_STAMINA, BASE_VALUE, float(GetOwner()->GetStat(STAT_STAMINA)) * 0.3f); // Bonus Stamina (30% of player stamina)
+ SetStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(GetOwner()->GetArmor()) * 0.35f); // Bonus Armor (35% of player armor)
+ SetStatFlatModifier(UNIT_MOD_STAT_STAMINA, BASE_VALUE, float(GetOwner()->GetStat(STAT_STAMINA)) * 0.3f); // Bonus Stamina (30% of player stamina)
if (!HasAura(58877))//prevent apply twice for the 2 wolves
AddAura(58877, this);//Spirit Hunt, passive, Spirit Wolves' attacks heal them and their master for 150% of damage done.
break;
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index daeaf3d8877..5f2199d9f52 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -269,8 +269,8 @@ Player::Player(WorldSession* session) : Unit(true), m_sceneMgr(this)
for (uint8 i = 0; i < BASEMOD_END; ++i)
{
- m_auraBaseMod[i][FLAT_MOD] = 0.0f;
- m_auraBaseMod[i][PCT_MOD] = 1.0f;
+ m_auraBaseFlatMod[i] = 0.0f;
+ m_auraBasePctMod[i] = 1.0f;
}
for (uint8 i = 0; i < MAX_COMBAT_RATING; i++)
@@ -1767,8 +1767,8 @@ void Player::RemoveFromWorld()
void Player::SetObjectScale(float scale)
{
Unit::SetObjectScale(scale);
- SetBoundingRadius(scale * DEFAULT_WORLD_OBJECT_SIZE);
- SetCombatReach(scale * DEFAULT_COMBAT_REACH);
+ SetBoundingRadius(scale * DEFAULT_PLAYER_BOUNDING_RADIUS);
+ SetCombatReach(scale * DEFAULT_PLAYER_COMBAT_REACH);
if (IsInWorld())
SendMovementSetCollisionHeight(scale * GetCollisionHeight(IsMounted()));
}
@@ -4952,20 +4952,104 @@ void Player::LeaveLFGChannel()
}
}
-void Player::HandleBaseModValue(BaseModGroup modGroup, BaseModType modType, float amount, bool apply)
+void Player::HandleBaseModFlatValue(BaseModGroup modGroup, float amount, bool apply)
{
- if (modGroup >= BASEMOD_END || modType >= MOD_END)
+ if (modGroup >= BASEMOD_END)
{
TC_LOG_ERROR("spells", "Player::HandleBaseModValue: Invalid BaseModGroup/BaseModType (%u/%u) for player '%s' (%s)",
- modGroup, modType, GetName().c_str(), GetGUID().ToString().c_str());
+ modGroup, FLAT_MOD, GetName().c_str(), GetGUID().ToString().c_str());
+ return;
+ }
+
+ m_auraBaseFlatMod[modGroup] += apply ? amount : -amount;
+ UpdateBaseModGroup(modGroup);
+}
+
+void Player::ApplyBaseModPctValue(BaseModGroup modGroup, float pct)
+{
+ if (modGroup >= BASEMOD_END)
+ {
+ TC_LOG_ERROR("spells", "Player::HandleBaseModValue: Invalid BaseModGroup/BaseModType (%u/%u) for player '%s' (%s)",
+ modGroup, FLAT_MOD, GetName().c_str(), GetGUID().ToString().c_str());
+ return;
+ }
+
+ AddPct(m_auraBasePctMod[modGroup], pct);
+ UpdateBaseModGroup(modGroup);
+}
+
+void Player::SetBaseModFlatValue(BaseModGroup modGroup, float val)
+{
+ if (m_auraBaseFlatMod[modGroup] == val)
+ return;
+
+ m_auraBaseFlatMod[modGroup] = val;
+ UpdateBaseModGroup(modGroup);
+}
+
+void Player::SetBaseModPctValue(BaseModGroup modGroup, float val)
+{
+ if (m_auraBasePctMod[modGroup] == val)
return;
+
+ m_auraBasePctMod[modGroup] = val;
+ UpdateBaseModGroup(modGroup);
+}
+
+void Player::UpdateDamageDoneMods(WeaponAttackType attackType)
+{
+ Unit::UpdateDamageDoneMods(attackType);
+
+ UnitMods unitMod;
+ switch (attackType)
+ {
+ case BASE_ATTACK:
+ unitMod = UNIT_MOD_DAMAGE_MAINHAND;
+ break;
+ case OFF_ATTACK:
+ unitMod = UNIT_MOD_DAMAGE_OFFHAND;
+ break;
+ case RANGED_ATTACK:
+ unitMod = UNIT_MOD_DAMAGE_RANGED;
+ break;
+ default:
+ ABORT();
+ break;
}
- if (modType == FLAT_MOD)
- m_auraBaseMod[modGroup][modType] += apply ? amount : -amount;
- else // PCT_MOD
- ApplyPercentModFloatVar(m_auraBaseMod[modGroup][modType], amount, apply);
+ float amount = 0.0f;
+ Item* item = GetWeaponForAttack(attackType, true);
+ if (!item)
+ return;
+ for (uint8 slot = 0; slot < MAX_ENCHANTMENT_SLOT; ++slot)
+ {
+ SpellItemEnchantmentEntry const* enchantmentEntry = sSpellItemEnchantmentStore.LookupEntry(item->GetEnchantmentId(EnchantmentSlot(slot)));
+ if (!enchantmentEntry)
+ continue;
+
+ for (uint8 i = 0; i < MAX_ITEM_ENCHANTMENT_EFFECTS; ++i)
+ {
+ switch (enchantmentEntry->Effect[i])
+ {
+ case ITEM_ENCHANTMENT_TYPE_DAMAGE:
+ amount += enchantmentEntry->EffectScalingPoints[i];
+ break;
+ case ITEM_ENCHANTMENT_TYPE_TOTEM:
+ if (getClass() == CLASS_SHAMAN)
+ amount += enchantmentEntry->EffectScalingPoints[i] * item->GetTemplate()->GetDelay() / 1000.0f;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ HandleStatFlatModifier(unitMod, TOTAL_VALUE, amount, true);
+}
+
+void Player::UpdateBaseModGroup(BaseModGroup modGroup)
+{
if (!CanModifyStats())
return;
@@ -4987,10 +5071,7 @@ float Player::GetBaseModValue(BaseModGroup modGroup, BaseModType modType) const
return 0.0f;
}
- if (modType == PCT_MOD && m_auraBaseMod[modGroup][PCT_MOD] <= 0.0f)
- return 0.0f;
-
- return m_auraBaseMod[modGroup][modType];
+ return (modType == FLAT_MOD ? m_auraBaseFlatMod[modGroup] : m_auraBasePctMod[modGroup]);
}
float Player::GetTotalBaseModValue(BaseModGroup modGroup) const
@@ -5002,10 +5083,7 @@ float Player::GetTotalBaseModValue(BaseModGroup modGroup) const
return 0.0f;
}
- if (m_auraBaseMod[modGroup][PCT_MOD] <= 0.0f)
- return 0.0f;
-
- return m_auraBaseMod[modGroup][FLAT_MOD] * m_auraBaseMod[modGroup][PCT_MOD];
+ return m_auraBaseFlatMod[modGroup] * m_auraBasePctMod[modGroup];
}
void Player::GetDodgeFromAgility(float &/*diminishing*/, float &/*nondiminishing*/) const
@@ -5053,7 +5131,7 @@ void Player::GetDodgeFromAgility(float &/*diminishing*/, float &/*nondiminishing
// return;
///// @todo research if talents/effects that increase total agility by x% should increase non-diminishing part
- //float base_agility = GetCreateStat(STAT_AGILITY) * m_auraModifiersGroup[UNIT_MOD_STAT_START + STAT_AGILITY][BASE_PCT];
+ //float base_agility = GetCreateStat(STAT_AGILITY) * GetPctModifierValue(UnitMods(UNIT_MOD_STAT_START + STAT_AGILITY), BASE_PCT);
//float bonus_agility = GetStat(STAT_AGILITY) - base_agility;
//// calculate diminishing (green in char screen) and non-diminishing (white) contribution
@@ -5312,7 +5390,7 @@ void Player::UpdateRating(CombatRating cr)
void Player::UpdateAllRatings()
{
- for (int cr = 0; cr < MAX_COMBAT_RATING; ++cr)
+ for (uint8 cr = 0; cr < MAX_COMBAT_RATING; ++cr)
UpdateRating(CombatRating(cr));
}
@@ -7419,7 +7497,13 @@ void Player::_ApplyItemMods(Item* item, uint8 slot, bool apply, bool updateItemA
_ApplyItemBonuses(item, slot, apply);
ApplyItemEquipSpell(item, apply);
if (updateItemAuras)
+ {
ApplyItemDependentAuras(item, apply);
+
+ WeaponAttackType const attackType = Player::GetAttackBySlot(slot, item->GetTemplate()->GetInventoryType());
+ if (attackType != MAX_ATTACK)
+ UpdateWeaponDependentAuras(attackType);
+ }
ApplyArtifactPowers(item, apply);
ApplyAzeritePowers(item, apply);
ApplyEnchantment(item, apply);
@@ -7452,22 +7536,22 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply)
switch (statType)
{
case ITEM_MOD_MANA:
- HandleStatModifier(UNIT_MOD_MANA, BASE_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_MANA, BASE_VALUE, float(val), apply);
break;
case ITEM_MOD_HEALTH: // modify HP
- HandleStatModifier(UNIT_MOD_HEALTH, BASE_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_HEALTH, BASE_VALUE, float(val), apply);
break;
case ITEM_MOD_AGILITY: // modify agility
- HandleStatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply);
- ApplyStatBuffMod(STAT_AGILITY, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_AGILITY, BASE_PCT_EXCLUDE_CREATE)), apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply);
+ UpdateStatBuffMod(STAT_AGILITY);
break;
case ITEM_MOD_STRENGTH: //modify strength
- HandleStatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply);
- ApplyStatBuffMod(STAT_STRENGTH, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_STRENGTH, BASE_PCT_EXCLUDE_CREATE)), apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply);
+ UpdateStatBuffMod(STAT_STRENGTH);
break;
case ITEM_MOD_INTELLECT: //modify intellect
- HandleStatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply);
- ApplyStatBuffMod(STAT_INTELLECT, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_INTELLECT, BASE_PCT_EXCLUDE_CREATE)), apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply);
+ UpdateStatBuffMod(STAT_INTELLECT);
break;
// case ITEM_MOD_SPIRIT: //modify spirit
// HandleStatModifier(UNIT_MOD_STAT_SPIRIT, BASE_VALUE, float(val), apply);
@@ -7477,8 +7561,8 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply)
{
if (GtStaminaMultByILvl const* staminaMult = sStaminaMultByILvlGameTable.GetRow(itemLevel))
val = int32(val * GetIlvlStatMultiplier(staminaMult, proto->GetInventoryType()));
- HandleStatModifier(UNIT_MOD_STAT_STAMINA, BASE_VALUE, float(val), apply);
- ApplyStatBuffMod(STAT_STAMINA, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_STAMINA, BASE_PCT_EXCLUDE_CREATE)), apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_STAMINA, BASE_VALUE, float(val), apply);
+ UpdateStatBuffMod(STAT_STAMINA);
break;
}
case ITEM_MOD_DEFENSE_SKILL_RATING:
@@ -7570,11 +7654,11 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply)
ApplyRatingMod(CR_EXPERTISE, int32(val * combatRatingMultiplier), apply);
break;
case ITEM_MOD_ATTACK_POWER:
- HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(val), apply);
- HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(val), apply);
break;
case ITEM_MOD_RANGED_ATTACK_POWER:
- HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(val), apply);
break;
case ITEM_MOD_VERSATILITY:
ApplyRatingMod(CR_VERSATILITY_DAMAGE_DONE, int32(val * combatRatingMultiplier), apply);
@@ -7600,25 +7684,25 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply)
ApplyRatingMod(CR_MASTERY, int32(val * combatRatingMultiplier), apply);
break;
case ITEM_MOD_EXTRA_ARMOR:
- HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(val), apply);
break;
case ITEM_MOD_FIRE_RESISTANCE:
- HandleStatModifier(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(val), apply);
break;
case ITEM_MOD_FROST_RESISTANCE:
- HandleStatModifier(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(val), apply);
break;
case ITEM_MOD_HOLY_RESISTANCE:
- HandleStatModifier(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(val), apply);
break;
case ITEM_MOD_SHADOW_RESISTANCE:
- HandleStatModifier(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(val), apply);
break;
case ITEM_MOD_NATURE_RESISTANCE:
- HandleStatModifier(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(val), apply);
break;
case ITEM_MOD_ARCANE_RESISTANCE:
- HandleStatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(val), apply);
break;
case ITEM_MOD_PVP_POWER:
ApplyRatingMod(CR_PVP_POWER, int32(val), apply);
@@ -7654,36 +7738,36 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply)
ApplyRatingMod(CR_UNUSED_12, int32(val), apply);
break;
case ITEM_MOD_AGI_STR_INT:
- HandleStatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply);
- HandleStatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply);
- HandleStatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply);
- ApplyStatBuffMod(STAT_AGILITY, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_AGILITY, BASE_PCT_EXCLUDE_CREATE)), apply);
- ApplyStatBuffMod(STAT_STRENGTH, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_STRENGTH, BASE_PCT_EXCLUDE_CREATE)), apply);
- ApplyStatBuffMod(STAT_INTELLECT, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_INTELLECT, BASE_PCT_EXCLUDE_CREATE)), apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply);
+ UpdateStatBuffMod(STAT_AGILITY);
+ UpdateStatBuffMod(STAT_STRENGTH);
+ UpdateStatBuffMod(STAT_INTELLECT);
break;
case ITEM_MOD_AGI_STR:
- HandleStatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply);
- HandleStatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply);
- ApplyStatBuffMod(STAT_AGILITY, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_AGILITY, BASE_PCT_EXCLUDE_CREATE)), apply);
- ApplyStatBuffMod(STAT_STRENGTH, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_STRENGTH, BASE_PCT_EXCLUDE_CREATE)), apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply);
+ UpdateStatBuffMod(STAT_AGILITY);
+ UpdateStatBuffMod(STAT_STRENGTH);
break;
case ITEM_MOD_AGI_INT:
- HandleStatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply);
- HandleStatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply);
- ApplyStatBuffMod(STAT_AGILITY, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_AGILITY, BASE_PCT_EXCLUDE_CREATE)), apply);
- ApplyStatBuffMod(STAT_INTELLECT, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_INTELLECT, BASE_PCT_EXCLUDE_CREATE)), apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply);
+ UpdateStatBuffMod(STAT_AGILITY);
+ UpdateStatBuffMod(STAT_INTELLECT);
break;
case ITEM_MOD_STR_INT:
- HandleStatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply);
- HandleStatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply);
- ApplyStatBuffMod(STAT_STRENGTH, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_STRENGTH, BASE_PCT_EXCLUDE_CREATE)), apply);
- ApplyStatBuffMod(STAT_INTELLECT, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_INTELLECT, BASE_PCT_EXCLUDE_CREATE)), apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply);
+ UpdateStatBuffMod(STAT_STRENGTH);
+ UpdateStatBuffMod(STAT_INTELLECT);
break;
}
}
if (uint32 armor = item->GetArmor(this))
- HandleStatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(armor), apply);
+ HandleStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(armor), apply);
WeaponAttackType attType = BASE_ATTACK;
@@ -7775,6 +7859,49 @@ void Player::ApplyItemObtainSpells(Item* item, bool apply)
}
}
+// this one rechecks weapon auras and stores them in BaseModGroup container
+// needed for things like axe specialization applying only to axe weapons in case of dual-wield
+void Player::UpdateWeaponDependentCritAuras(WeaponAttackType attackType)
+{
+ BaseModGroup modGroup;
+ switch (attackType)
+ {
+ case BASE_ATTACK:
+ modGroup = CRIT_PERCENTAGE;
+ break;
+ case OFF_ATTACK:
+ modGroup = OFFHAND_CRIT_PERCENTAGE;
+ break;
+ case RANGED_ATTACK:
+ modGroup = RANGED_CRIT_PERCENTAGE;
+ break;
+ default:
+ ABORT();
+ break;
+ }
+
+ float amount = 0.0f;
+ amount += GetTotalAuraModifier(SPELL_AURA_MOD_WEAPON_CRIT_PERCENT, std::bind(&Unit::CheckAttackFitToAuraRequirement, this, attackType, std::placeholders::_1));
+
+ // these auras don't have item requirement (only Combat Expertise in 3.3.5a)
+ amount += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_PCT);
+
+ SetBaseModFlatValue(modGroup, amount);
+}
+
+void Player::UpdateAllWeaponDependentCritAuras()
+{
+ for (uint8 i = BASE_ATTACK; i < MAX_ATTACK; ++i)
+ UpdateWeaponDependentCritAuras(WeaponAttackType(i));
+}
+
+void Player::UpdateWeaponDependentAuras(WeaponAttackType attackType)
+{
+ UpdateWeaponDependentCritAuras(attackType);
+ UpdateDamageDoneMods(attackType);
+ UpdateDamagePctDoneMods(attackType);
+}
+
void Player::ApplyItemDependentAuras(Item* item, bool apply)
{
if (apply)
@@ -7797,6 +7924,19 @@ void Player::ApplyItemDependentAuras(Item* item, bool apply)
RemoveItemDependentAurasAndCasts(item);
}
+bool Player::CheckAttackFitToAuraRequirement(WeaponAttackType attackType, AuraEffect const* aurEff) const
+{
+ SpellInfo const* spellInfo = aurEff->GetSpellInfo();
+ if (spellInfo->EquippedItemClass == -1)
+ return true;
+
+ Item* item = GetWeaponForAttack(attackType, true);
+ if (!item || !item->IsFitToSpellRequirements(spellInfo))
+ return false;
+
+ return true;
+}
+
void Player::ApplyItemEquipSpell(Item* item, bool apply, bool formChange /*= false*/)
{
if (!item)
@@ -8427,6 +8567,10 @@ void Player::_ApplyAllItemMods()
ApplyItemDependentAuras(m_items[i], true);
_ApplyItemBonuses(m_items[i], i, true);
+
+ WeaponAttackType const attackType = Player::GetAttackBySlot(i, m_items[i]->GetTemplate()->GetInventoryType());
+ if (attackType != MAX_ATTACK)
+ UpdateWeaponDependentAuras(attackType);
}
}
@@ -10094,7 +10238,7 @@ Item* Player::GetChildItemByGuid(ObjectGuid guid) const
return nullptr;
}
-uint8 Player::GetAttackBySlot(uint8 slot, InventoryType inventoryType)
+WeaponAttackType Player::GetAttackBySlot(uint8 slot, InventoryType inventoryType)
{
switch (slot)
{
@@ -14124,16 +14268,12 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
// processed in Player::CastItemCombatSpell
break;
case ITEM_ENCHANTMENT_TYPE_DAMAGE:
- if (item->GetSlot() == EQUIPMENT_SLOT_MAINHAND)
- {
- if (item->GetTemplate()->GetInventoryType() != INVTYPE_RANGED && item->GetTemplate()->GetInventoryType() != INVTYPE_RANGEDRIGHT)
- HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(enchant_amount), apply);
- else
- HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(enchant_amount), apply);
- }
- else if (item->GetSlot() == EQUIPMENT_SLOT_OFFHAND)
- HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(enchant_amount), apply);
+ {
+ WeaponAttackType const attackType = Player::GetAttackBySlot(item->GetSlot(), item->GetTemplate()->GetInventoryType());
+ if (attackType != MAX_ATTACK)
+ UpdateDamageDoneMods(attackType);
break;
+ }
case ITEM_ENCHANTMENT_TYPE_EQUIP_SPELL:
if (enchant_spell_id)
{
@@ -14163,7 +14303,7 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
enchant_amount = uint32(pEnchant->EffectScalingPoints[s] * GetSpellScalingColumnForClass(spellScaling, scalingClass));
}
enchant_amount = std::max(enchant_amount, 1u);
- HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + enchant_spell_id), TOTAL_VALUE, float(enchant_amount), apply);
+ HandleStatFlatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + enchant_spell_id), TOTAL_VALUE, float(enchant_amount), apply);
break;
case ITEM_ENCHANTMENT_TYPE_STAT:
{
@@ -14193,26 +14333,26 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
{
case ITEM_MOD_MANA:
TC_LOG_DEBUG("entities.player.items", "+ %u MANA", enchant_amount);
- HandleStatModifier(UNIT_MOD_MANA, BASE_VALUE, float(enchant_amount), apply);
+ HandleStatFlatModifier(UNIT_MOD_MANA, BASE_VALUE, float(enchant_amount), apply);
break;
case ITEM_MOD_HEALTH:
TC_LOG_DEBUG("entities.player.items", "+ %u HEALTH", enchant_amount);
- HandleStatModifier(UNIT_MOD_HEALTH, BASE_VALUE, float(enchant_amount), apply);
+ HandleStatFlatModifier(UNIT_MOD_HEALTH, BASE_VALUE, float(enchant_amount), apply);
break;
case ITEM_MOD_AGILITY:
TC_LOG_DEBUG("entities.player.items", "+ %u AGILITY", enchant_amount);
- HandleStatModifier(UNIT_MOD_STAT_AGILITY, TOTAL_VALUE, float(enchant_amount), apply);
- ApplyStatBuffMod(STAT_AGILITY, (float)enchant_amount, apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_AGILITY, TOTAL_VALUE, float(enchant_amount), apply);
+ UpdateStatBuffMod(STAT_AGILITY);
break;
case ITEM_MOD_STRENGTH:
TC_LOG_DEBUG("entities.player.items", "+ %u STRENGTH", enchant_amount);
- HandleStatModifier(UNIT_MOD_STAT_STRENGTH, TOTAL_VALUE, float(enchant_amount), apply);
- ApplyStatBuffMod(STAT_STRENGTH, (float)enchant_amount, apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_STRENGTH, TOTAL_VALUE, float(enchant_amount), apply);
+ UpdateStatBuffMod(STAT_STRENGTH);
break;
case ITEM_MOD_INTELLECT:
TC_LOG_DEBUG("entities.player.items", "+ %u INTELLECT", enchant_amount);
- HandleStatModifier(UNIT_MOD_STAT_INTELLECT, TOTAL_VALUE, float(enchant_amount), apply);
- ApplyStatBuffMod(STAT_INTELLECT, (float)enchant_amount, apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_INTELLECT, TOTAL_VALUE, float(enchant_amount), apply);
+ UpdateStatBuffMod(STAT_INTELLECT);
break;
// case ITEM_MOD_SPIRIT:
// TC_LOG_DEBUG("entities.player.items", "+ %u SPIRIT", enchant_amount);
@@ -14221,8 +14361,8 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
// break;
case ITEM_MOD_STAMINA:
TC_LOG_DEBUG("entities.player.items", "+ %u STAMINA", enchant_amount);
- HandleStatModifier(UNIT_MOD_STAT_STAMINA, TOTAL_VALUE, float(enchant_amount), apply);
- ApplyStatBuffMod(STAT_STAMINA, (float)enchant_amount, apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_STAMINA, TOTAL_VALUE, float(enchant_amount), apply);
+ UpdateStatBuffMod(STAT_STAMINA);
break;
case ITEM_MOD_DEFENSE_SKILL_RATING:
ApplyRatingMod(CR_DEFENSE_SKILL, enchant_amount, apply);
@@ -14330,12 +14470,12 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
TC_LOG_DEBUG("entities.player.items", "+ %u EXPERTISE", enchant_amount);
break;
case ITEM_MOD_ATTACK_POWER:
- HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(enchant_amount), apply);
- HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply);
+ HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(enchant_amount), apply);
+ HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply);
TC_LOG_DEBUG("entities.player.items", "+ %u ATTACK_POWER", enchant_amount);
break;
case ITEM_MOD_RANGED_ATTACK_POWER:
- HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply);
+ HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply);
TC_LOG_DEBUG("entities.player.items", "+ %u RANGED_ATTACK_POWER", enchant_amount);
break;
case ITEM_MOD_MANA_REGENERATION:
@@ -14359,7 +14499,7 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
TC_LOG_DEBUG("entities.player.items", "+ %u SPELL_PENETRATION", enchant_amount);
break;
case ITEM_MOD_BLOCK_VALUE:
- HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(enchant_amount), apply);
+ HandleBaseModFlatValue(SHIELD_BLOCK_VALUE, float(enchant_amount), apply);
TC_LOG_DEBUG("entities.player.items", "+ %u BLOCK_VALUE", enchant_amount);
break;
case ITEM_MOD_MASTERY_RATING:
@@ -14379,20 +14519,9 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
}
case ITEM_ENCHANTMENT_TYPE_TOTEM: // Shaman Rockbiter Weapon
{
- if (getClass() == CLASS_SHAMAN)
- {
- float addValue;
- if (item->GetSlot() == EQUIPMENT_SLOT_MAINHAND)
- {
- addValue = float(enchant_amount * item->GetTemplate()->GetDelay() / 1000.0f);
- HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, addValue, apply);
- }
- else if (item->GetSlot() == EQUIPMENT_SLOT_OFFHAND)
- {
- addValue = float(enchant_amount * item->GetTemplate()->GetDelay() / 1000.0f);
- HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, addValue, apply);
- }
- }
+ WeaponAttackType const attackType = Player::GetAttackBySlot(item->GetSlot(), item->GetTemplate()->GetInventoryType());
+ if (attackType != MAX_ATTACK)
+ UpdateDamageDoneMods(attackType);
break;
}
case ITEM_ENCHANTMENT_TYPE_USE_SPELL:
@@ -15075,7 +15204,7 @@ bool Player::CanSeeStartQuest(Quest const* quest)
{
if (!DisableMgr::IsDisabledFor(DISABLE_TYPE_QUEST, quest->GetQuestId(), this) && SatisfyQuestClass(quest, false) && SatisfyQuestRace(quest, false) &&
SatisfyQuestSkill(quest, false) && SatisfyQuestExclusiveGroup(quest, false) && SatisfyQuestReputation(quest, false) &&
- SatisfyQuestPreviousQuest(quest, false) && SatisfyQuestNextChain(quest, false) &&
+ SatisfyQuestDependentQuests(quest, false) && SatisfyQuestNextChain(quest, false) &&
SatisfyQuestPrevChain(quest, false) && SatisfyQuestDay(quest, false) && SatisfyQuestWeek(quest, false) &&
SatisfyQuestMonth(quest, false) && SatisfyQuestSeasonal(quest, false))
{
@@ -15091,7 +15220,7 @@ bool Player::CanTakeQuest(Quest const* quest, bool msg)
&& SatisfyQuestStatus(quest, msg) && SatisfyQuestExclusiveGroup(quest, msg)
&& SatisfyQuestClass(quest, msg) && SatisfyQuestRace(quest, msg) && SatisfyQuestLevel(quest, msg)
&& SatisfyQuestSkill(quest, msg) && SatisfyQuestReputation(quest, msg)
- && SatisfyQuestPreviousQuest(quest, msg) && SatisfyQuestTimed(quest, msg)
+ && SatisfyQuestDependentQuests(quest, msg) && SatisfyQuestTimed(quest, msg)
&& SatisfyQuestNextChain(quest, msg) && SatisfyQuestPrevChain(quest, msg)
&& SatisfyQuestDay(quest, msg) && SatisfyQuestWeek(quest, msg)
&& SatisfyQuestMonth(quest, msg) && SatisfyQuestSeasonal(quest, msg)
@@ -15956,97 +16085,90 @@ bool Player::SatisfyQuestLog(bool msg) const
return false;
}
-bool Player::SatisfyQuestPreviousQuest(Quest const* qInfo, bool msg)
+bool Player::SatisfyQuestDependentQuests(Quest const* qInfo, bool msg) const
+{
+ return SatisfyQuestPreviousQuest(qInfo, msg) && SatisfyQuestDependentPreviousQuests(qInfo, msg);
+}
+
+bool Player::SatisfyQuestPreviousQuest(Quest const* qInfo, bool msg) const
{
// No previous quest (might be first quest in a series)
- if (qInfo->prevQuests.empty())
+ if (!qInfo->GetPrevQuestId())
return true;
- for (Quest::PrevQuests::const_iterator iter = qInfo->prevQuests.begin(); iter != qInfo->prevQuests.end(); ++iter)
- {
- uint32 prevId = abs(*iter);
+ uint32 prevId = std::abs(qInfo->GetPrevQuestId());
+ // If positive previous quest rewarded, return true
+ if (qInfo->GetPrevQuestId() > 0 && m_RewardedQuests.count(prevId) > 0)
+ return true;
- Quest const* qPrevInfo = sObjectMgr->GetQuestTemplate(prevId);
+ // If negative previous quest active, return true
+ if (qInfo->GetPrevQuestId() < 0 && GetQuestStatus(prevId) == QUEST_STATUS_INCOMPLETE)
+ return true;
- if (qPrevInfo)
- {
- // If any of the positive previous quests completed, return true
- if (*iter > 0 && m_RewardedQuests.find(prevId) != m_RewardedQuests.end())
- {
- // skip one-from-all exclusive group
- if (qPrevInfo->GetExclusiveGroup() >= 0)
- return true;
+ // Has positive prev. quest in non-rewarded state
+ // and negative prev. quest in non-active state
+ if (msg)
+ {
+ SendCanTakeQuestResponse(QUEST_ERR_NONE);
+ TC_LOG_DEBUG("misc", "Player::SatisfyQuestPreviousQuest: Sent QUEST_ERR_NONE (QuestID: %u) because player '%s' (%s) doesn't have required quest %u.",
+ qInfo->GetQuestId(), GetName().c_str(), GetGUID().ToString().c_str(), prevId);
+ }
- // each-from-all exclusive group (< 0)
- // can be start if only all quests in prev quest exclusive group completed and rewarded
- ObjectMgr::ExclusiveQuestGroupsBounds range(sObjectMgr->mExclusiveQuestGroups.equal_range(qPrevInfo->GetExclusiveGroup()));
+ return false;
+}
- for (; range.first != range.second; ++range.first)
- {
- uint32 exclude_Id = range.first->second;
+bool Player::SatisfyQuestDependentPreviousQuests(Quest const* qInfo, bool msg) const
+{
+ // No previous quest (might be first quest in a series)
+ if (qInfo->DependentPreviousQuests.empty())
+ return true;
- // skip checked quest id, only state of other quests in group is interesting
- if (exclude_Id == prevId)
- continue;
+ for (uint32 prevId : qInfo->DependentPreviousQuests)
+ {
+ // checked in startup
+ Quest const* questInfo = sObjectMgr->GetQuestTemplate(prevId);
+ ASSERT(questInfo);
- // alternative quest from group also must be completed and rewarded (reported)
- if (m_RewardedQuests.find(exclude_Id) == m_RewardedQuests.end())
- {
- if (msg)
- {
- SendCanTakeQuestResponse(QUEST_ERR_NONE);
- TC_LOG_DEBUG("misc", "Player::SatisfyQuestPreviousQuest: Sent QUEST_ERR_NONE (QuestID: %u) because player '%s' (%s) doesn't have the required quest (1).",
- qInfo->GetQuestId(), GetName().c_str(), GetGUID().ToString().c_str());
- }
- return false;
- }
- }
+ // If any of the previous quests completed, return true
+ if (IsQuestRewarded(prevId))
+ {
+ // skip one-from-all exclusive group
+ if (questInfo->GetExclusiveGroup() >= 0)
return true;
- }
- // If any of the negative previous quests active, return true
- if (*iter < 0 && GetQuestStatus(prevId) != QUEST_STATUS_NONE)
+ // each-from-all exclusive group (< 0)
+ // can be start if only all quests in prev quest exclusive group completed and rewarded
+ auto bounds = sObjectMgr->GetExclusiveQuestGroupBounds(questInfo->GetExclusiveGroup());
+ for (auto itr = bounds.first; itr != bounds.second; ++itr)
{
- // skip one-from-all exclusive group
- if (qPrevInfo->GetExclusiveGroup() >= 0)
- return true;
-
- // each-from-all exclusive group (< 0)
- // can be start if only all quests in prev quest exclusive group active
- ObjectMgr::ExclusiveQuestGroupsBounds range(sObjectMgr->mExclusiveQuestGroups.equal_range(qPrevInfo->GetExclusiveGroup()));
+ // skip checked quest id, only state of other quests in group is interesting
+ uint32 exclusiveQuestId = itr->second;
+ if (exclusiveQuestId == prevId)
+ continue;
- for (; range.first != range.second; ++range.first)
+ // alternative quest from group also must be completed and rewarded (reported)
+ if (!IsQuestRewarded(exclusiveQuestId))
{
- uint32 exclude_Id = range.first->second;
-
- // skip checked quest id, only state of other quests in group is interesting
- if (exclude_Id == prevId)
- continue;
-
- // alternative quest from group also must be active
- if (GetQuestStatus(exclude_Id) != QUEST_STATUS_NONE)
+ if (msg)
{
- if (msg)
- {
- SendCanTakeQuestResponse(QUEST_ERR_NONE);
- TC_LOG_DEBUG("misc", "Player::SatisfyQuestPreviousQuest: Sent QUEST_ERR_NONE (QuestID: %u) because player '%s' (%s) doesn't have the required quest (2).",
- qInfo->GetQuestId(), GetName().c_str(), GetGUID().ToString().c_str());
-
- }
- return false;
+ SendCanTakeQuestResponse(QUEST_ERR_NONE);
+ TC_LOG_DEBUG("misc", "Player::SatisfyQuestDependentPreviousQuests: Sent QUEST_ERR_NONE (QuestID: %u) because player '%s' (%s) doesn't have the required quest (1).",
+ qInfo->GetQuestId(), GetName().c_str(), GetGUID().ToString().c_str());
}
+
+ return false;
}
- return true;
}
+
+ return true;
}
}
- // Has only positive prev. quests in non-rewarded state
- // and negative prev. quests in non-active state
+ // Has only prev. quests in non-rewarded state
if (msg)
{
SendCanTakeQuestResponse(QUEST_ERR_NONE);
- TC_LOG_DEBUG("misc", "Player::SatisfyQuestPreviousQuest: Sent QUEST_ERR_NONE (QuestID: %u) because player '%s' (%s) doesn't have required quest (3).",
+ TC_LOG_DEBUG("misc", "Player::SatisfyQuestDependentPreviousQuests: Sent QUEST_ERR_NONE (QuestID: %u) because player '%s' (%s) doesn't have required quest (2).",
qInfo->GetQuestId(), GetName().c_str(), GetGUID().ToString().c_str());
}
@@ -16191,17 +16313,16 @@ bool Player::SatisfyQuestTimed(Quest const* qInfo, bool msg) const
return true;
}
-bool Player::SatisfyQuestExclusiveGroup(Quest const* qInfo, bool msg)
+bool Player::SatisfyQuestExclusiveGroup(Quest const* qInfo, bool msg) const
{
// non positive exclusive group, if > 0 then can be start if any other quest in exclusive group already started/completed
if (qInfo->GetExclusiveGroup() <= 0)
return true;
- ObjectMgr::ExclusiveQuestGroupsBounds range(sObjectMgr->mExclusiveQuestGroups.equal_range(qInfo->GetExclusiveGroup()));
-
- for (; range.first != range.second; ++range.first)
+ auto bounds = sObjectMgr->GetExclusiveQuestGroupBounds(qInfo->GetExclusiveGroup());
+ for (auto itr = bounds.first; itr != bounds.second; ++itr)
{
- uint32 exclude_Id = range.first->second;
+ uint32 exclude_Id = itr->second;
// skip checked quest id, only state of other quests in group is interesting
if (exclude_Id == qInfo->GetQuestId())
@@ -16264,12 +16385,12 @@ bool Player::SatisfyQuestNextChain(Quest const* qInfo, bool msg) const
bool Player::SatisfyQuestPrevChain(Quest const* qInfo, bool msg)
{
// No previous quest in chain
- if (qInfo->prevChainQuests.empty())
+ if (qInfo->PrevChainQuests.empty())
return true;
- for (Quest::PrevChainQuests::const_iterator iter = qInfo->prevChainQuests.begin(); iter != qInfo->prevChainQuests.end(); ++iter)
+ for (uint32 prevQuestId : qInfo->PrevChainQuests)
{
- QuestStatusMap::const_iterator itr = m_QuestStatus.find(*iter);
+ auto itr = m_QuestStatus.find(prevQuestId);
// If any of the previous quests in chain active, return false
if (itr != m_QuestStatus.end() && itr->second.Status != QUEST_STATUS_NONE)
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 476aa0d7492..acbc5dd6086 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1128,8 +1128,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
Item* GetWeaponForAttack(WeaponAttackType attackType, bool useable = false) const;
Item* GetShield(bool useable = false) const;
Item* GetChildItemByGuid(ObjectGuid guid) const;
- static uint8 GetAttackBySlot(uint8 slot, InventoryType inventoryType); // MAX_ATTACK if not weapon slot
- std::vector<Item*> &GetItemUpdateQueue() { return m_itemUpdateQueue; }
+ static WeaponAttackType GetAttackBySlot(uint8 slot, InventoryType inventoryType); // MAX_ATTACK if not weapon slot
+ std::vector<Item*>& GetItemUpdateQueue() { return m_itemUpdateQueue; }
static bool IsInventoryPos(uint16 pos) { return IsInventoryPos(pos >> 8, pos & 255); }
static bool IsInventoryPos(uint8 bag, uint8 slot);
static bool IsEquipmentPos(uint16 pos) { return IsEquipmentPos(pos >> 8, pos & 255); }
@@ -1342,14 +1342,16 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
bool SatisfyQuestSkill(Quest const* qInfo, bool msg) const;
bool SatisfyQuestLevel(Quest const* qInfo, bool msg) const;
bool SatisfyQuestLog(bool msg) const;
- bool SatisfyQuestPreviousQuest(Quest const* qInfo, bool msg);
+ bool SatisfyQuestDependentQuests(Quest const* qInfo, bool msg) const;
+ bool SatisfyQuestPreviousQuest(Quest const* qInfo, bool msg) const;
+ bool SatisfyQuestDependentPreviousQuests(Quest const* qInfo, bool msg) const;
bool SatisfyQuestClass(Quest const* qInfo, bool msg) const;
bool SatisfyQuestRace(Quest const* qInfo, bool msg) const;
bool SatisfyQuestReputation(Quest const* qInfo, bool msg);
bool SatisfyQuestStatus(Quest const* qInfo, bool msg) const;
bool SatisfyQuestConditions(Quest const* qInfo, bool msg);
bool SatisfyQuestTimed(Quest const* qInfo, bool msg) const;
- bool SatisfyQuestExclusiveGroup(Quest const* qInfo, bool msg);
+ bool SatisfyQuestExclusiveGroup(Quest const* qInfo, bool msg) const;
bool SatisfyQuestNextChain(Quest const* qInfo, bool msg) const;
bool SatisfyQuestPrevChain(Quest const* qInfo, bool msg);
bool SatisfyQuestDay(Quest const* qInfo, bool msg) const;
@@ -1771,6 +1773,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void ApplyModDamageDonePos(SpellSchools school, int32 mod, bool apply) { ApplyModUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::ModDamageDonePos, school), mod, apply); }
void ApplyModDamageDoneNeg(SpellSchools school, int32 mod, bool apply) { ApplyModUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::ModDamageDoneNeg, school), mod, apply); }
void ApplyModDamageDonePercent(SpellSchools school, float pct, bool apply) { ApplyPercentModUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::ModDamageDonePercent, school), pct, apply); }
+ void SetModDamageDonePercent(uint8 school, float pct) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::ModDamageDonePercent, school), pct); }
void ApplyRatingMod(CombatRating cr, int32 value, bool apply);
void UpdateRating(CombatRating cr);
void UpdateAllRatings();
@@ -1779,7 +1782,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void UpdateHealingDonePercentMod();
bool CanUseMastery() const;
- void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) override;
+ void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) const override;
void RecalculateRating(CombatRating cr) { ApplyRatingMod(cr, 0, true);}
void GetDodgeFromAgility(float &diminishing, float &nondiminishing) const;
@@ -2003,11 +2006,19 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
bool CanTameExoticPets() const { return IsGameMaster() || HasAuraType(SPELL_AURA_ALLOW_TAME_PET_TYPE); }
void SetRegularAttackTime();
- void SetBaseModValue(BaseModGroup modGroup, BaseModType modType, float value) { m_auraBaseMod[modGroup][modType] = value; }
- void HandleBaseModValue(BaseModGroup modGroup, BaseModType modType, float amount, bool apply);
+
+ void HandleBaseModFlatValue(BaseModGroup modGroup, float amount, bool apply);
+ void ApplyBaseModPctValue(BaseModGroup modGroup, float pct);
+
+ void SetBaseModFlatValue(BaseModGroup modGroup, float val);
+ void SetBaseModPctValue(BaseModGroup modGroup, float val);
+
+ void UpdateDamageDoneMods(WeaponAttackType attackType) override;
+ void UpdateBaseModGroup(BaseModGroup modGroup);
+
float GetBaseModValue(BaseModGroup modGroup, BaseModType modType) const;
float GetTotalBaseModValue(BaseModGroup modGroup) const;
- float GetTotalPercentageModValue(BaseModGroup modGroup) const { return m_auraBaseMod[modGroup][FLAT_MOD] + m_auraBaseMod[modGroup][PCT_MOD]; }
+
void _ApplyAllStatBonuses();
void _RemoveAllStatBonuses();
@@ -2015,8 +2026,15 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void CastAllObtainSpells();
void ApplyItemObtainSpells(Item* item, bool apply);
+
+ void UpdateWeaponDependentCritAuras(WeaponAttackType attackType);
+ void UpdateAllWeaponDependentCritAuras();
+
+ void UpdateWeaponDependentAuras(WeaponAttackType attackType);
void ApplyItemDependentAuras(Item* item, bool apply);
+ bool CheckAttackFitToAuraRequirement(WeaponAttackType attackType, AuraEffect const* aurEff) const override;
+
void _ApplyItemMods(Item* item, uint8 slot, bool apply, bool updateItemAuras = true);
void _RemoveAllItemMods();
void _ApplyAllItemMods();
@@ -2651,7 +2669,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
ActionButtonList m_actionButtons;
- float m_auraBaseMod[BASEMOD_END][MOD_END];
+ float m_auraBaseFlatMod[BASEMOD_END];
+ float m_auraBasePctMod[BASEMOD_END];
int16 m_baseRatingValue[MAX_COMBAT_RATING];
uint32 m_baseSpellPower;
uint32 m_baseManaRegen;
diff --git a/src/server/game/Entities/Player/SocialMgr.cpp b/src/server/game/Entities/Player/SocialMgr.cpp
index 96b400892de..201e3ef4db6 100644
--- a/src/server/game/Entities/Player/SocialMgr.cpp
+++ b/src/server/game/Entities/Player/SocialMgr.cpp
@@ -203,8 +203,13 @@ void SocialMgr::GetFriendInfo(Player* player, ObjectGuid const& friendGUID, Frie
else if (target->isAFK())
friendInfo.Status = FRIEND_STATUS_AFK;
else
+ {
friendInfo.Status = FRIEND_STATUS_ONLINE;
+ if (target->GetSession()->GetRecruiterId() == player->GetSession()->GetAccountId() || target->GetSession()->GetAccountId() == player->GetSession()->GetRecruiterId())
+ friendInfo.Status = FriendStatus(uint32(friendInfo.Status) | FRIEND_STATUS_RAF);
+ }
+
friendInfo.Area = target->GetZoneId();
friendInfo.Level = target->getLevel();
friendInfo.Class = target->getClass();
diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp
index e9f1fc359d9..2170ba4d7c7 100644
--- a/src/server/game/Entities/Unit/StatSystem.cpp
+++ b/src/server/game/Entities/Unit/StatSystem.cpp
@@ -200,7 +200,7 @@ void Player::UpdateSpellDamageAndHealingBonus()
bool Player::UpdateAllStats()
{
- for (int8 i = STAT_STRENGTH; i < MAX_STATS; ++i)
+ for (uint8 i = STAT_STRENGTH; i < MAX_STATS; ++i)
{
float value = GetTotalStatValue(Stats(i));
SetStat(Stats(i), int32(value));
@@ -254,10 +254,10 @@ void Player::UpdateArmor()
{
UnitMods unitMod = UNIT_MOD_ARMOR;
- float value = GetModifierValue(unitMod, BASE_VALUE); // base armor (from items)
+ float value = GetFlatModifierValue(unitMod, BASE_VALUE); // base armor (from items)
float baseValue = value;
- value *= GetModifierValue(unitMod, BASE_PCT); // armor percent from items
- value += GetModifierValue(unitMod, TOTAL_VALUE);
+ value *= GetPctModifierValue(unitMod, BASE_PCT); // armor percent from items
+ value += GetFlatModifierValue(unitMod, TOTAL_VALUE);
//add dynamic flat mods
AuraEffectList const& mResbyIntellect = GetAuraEffectsByType(SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT);
@@ -267,7 +267,7 @@ void Player::UpdateArmor()
value += CalculatePct(GetStat(Stats((*i)->GetMiscValueB())), (*i)->GetAmount());
}
- value *= GetModifierValue(unitMod, TOTAL_PCT);
+ value *= GetPctModifierValue(unitMod, TOTAL_PCT);
SetArmor(int32(baseValue), int32(value - baseValue));
@@ -294,10 +294,10 @@ void Player::UpdateMaxHealth()
{
UnitMods unitMod = UNIT_MOD_HEALTH;
- float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreateHealth();
- value *= GetModifierValue(unitMod, BASE_PCT);
- value += GetModifierValue(unitMod, TOTAL_VALUE) + GetHealthBonusFromStamina();
- value *= GetModifierValue(unitMod, TOTAL_PCT);
+ float value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetCreateHealth();
+ value *= GetPctModifierValue(unitMod, BASE_PCT);
+ value += GetFlatModifierValue(unitMod, TOTAL_VALUE) + GetHealthBonusFromStamina();
+ value *= GetPctModifierValue(unitMod, TOTAL_PCT);
SetMaxHealth((uint32)value);
}
@@ -315,10 +315,10 @@ void Player::UpdateMaxPower(Powers power)
UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + power);
- float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power);
- value *= GetModifierValue(unitMod, BASE_PCT);
- value += GetModifierValue(unitMod, TOTAL_VALUE);
- value *= GetModifierValue(unitMod, TOTAL_PCT);
+ float value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power);
+ value *= GetPctModifierValue(unitMod, BASE_PCT);
+ value += GetFlatModifierValue(unitMod, TOTAL_VALUE);
+ value *= GetPctModifierValue(unitMod, TOTAL_PCT);
SetMaxPower(power, (int32)std::lroundf(value));
}
@@ -357,11 +357,11 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
val2 = CalculatePct(float(minSpellPower), *m_activePlayerData->OverrideAPBySpellPowerPercent);
}
- SetModifierValue(unitMod, BASE_VALUE, val2);
+ SetStatFlatModifier(unitMod, BASE_VALUE, val2);
- float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT);
- float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE);
- float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f;
+ float base_attPower = GetFlatModifierValue(unitMod, BASE_VALUE) * GetPctModifierValue(unitMod, BASE_PCT);
+ float attPowerMod = GetFlatModifierValue(unitMod, TOTAL_VALUE);
+ float attPowerMultiplier = GetPctModifierValue(unitMod, TOTAL_PCT) - 1.0f;
if (ranged)
{
@@ -405,7 +405,7 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
}
}
-void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage)
+void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) const
{
UnitMods unitMod;
@@ -425,10 +425,10 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bo
float attackPowerMod = std::max(GetAPMultiplier(attType, normalized), 0.25f);
- float baseValue = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType) / 3.5f * attackPowerMod;
- float basePct = GetModifierValue(unitMod, BASE_PCT);
- float totalValue = GetModifierValue(unitMod, TOTAL_VALUE);
- float totalPct = addTotalPct ? GetModifierValue(unitMod, TOTAL_PCT) : 1.0f;
+ float baseValue = GetFlatModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType) / 3.5f * attackPowerMod;
+ float basePct = GetPctModifierValue(unitMod, BASE_PCT);
+ float totalValue = GetFlatModifierValue(unitMod, TOTAL_VALUE);
+ float totalPct = addTotalPct ? GetPctModifierValue(unitMod, TOTAL_PCT) : 1.0f;
float weaponMinDamage = GetWeaponDamageRange(attType, MINDAMAGE);
float weaponMaxDamage = GetWeaponDamageRange(attType, MAXDAMAGE);
@@ -492,16 +492,16 @@ void Player::UpdateCritPercentage(WeaponAttackType attType)
{
case OFF_ATTACK:
SetUpdateFieldStatValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::OffhandCritPercentage),
- applyCritLimit(GetTotalPercentageModValue(OFFHAND_CRIT_PERCENTAGE) + GetRatingBonusValue(CR_CRIT_MELEE)));
+ applyCritLimit(GetBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD) + GetBaseModValue(OFFHAND_CRIT_PERCENTAGE, PCT_MOD) + GetRatingBonusValue(CR_CRIT_MELEE)));
break;
case RANGED_ATTACK:
SetUpdateFieldStatValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::RangedCritPercentage),
- applyCritLimit(GetTotalPercentageModValue(RANGED_CRIT_PERCENTAGE) + GetRatingBonusValue(CR_CRIT_RANGED)));
+ applyCritLimit(GetBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD) + GetBaseModValue(RANGED_CRIT_PERCENTAGE, PCT_MOD) + GetRatingBonusValue(CR_CRIT_RANGED)));
break;
case BASE_ATTACK:
default:
SetUpdateFieldStatValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::CritPercentage),
- applyCritLimit(GetTotalPercentageModValue(CRIT_PERCENTAGE) + GetRatingBonusValue(CR_CRIT_MELEE)));
+ applyCritLimit(GetBaseModValue(CRIT_PERCENTAGE, FLAT_MOD) + GetBaseModValue(CRIT_PERCENTAGE, PCT_MOD) + GetRatingBonusValue(CR_CRIT_MELEE)));
break;
}
}
@@ -510,9 +510,9 @@ void Player::UpdateAllCritPercentages()
{
float value = 5.0f;
- SetBaseModValue(CRIT_PERCENTAGE, PCT_MOD, value);
- SetBaseModValue(OFFHAND_CRIT_PERCENTAGE, PCT_MOD, value);
- SetBaseModValue(RANGED_CRIT_PERCENTAGE, PCT_MOD, value);
+ SetBaseModPctValue(CRIT_PERCENTAGE, value);
+ SetBaseModPctValue(OFFHAND_CRIT_PERCENTAGE, value);
+ SetBaseModPctValue(RANGED_CRIT_PERCENTAGE, value);
UpdateCritPercentage(BASE_ATTACK);
UpdateCritPercentage(OFF_ATTACK);
@@ -835,7 +835,7 @@ bool Creature::UpdateAllStats()
void Creature::UpdateArmor()
{
- float baseValue = GetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE);
+ float baseValue = GetFlatModifierValue(UNIT_MOD_ARMOR, BASE_VALUE);
float value = GetTotalAuraModValue(UNIT_MOD_ARMOR);
SetArmor(int32(baseValue), int32(value - baseValue));
}
@@ -864,10 +864,10 @@ void Creature::UpdateMaxPower(Powers power)
UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + power);
- float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power);
- value *= GetModifierValue(unitMod, BASE_PCT);
- value += GetModifierValue(unitMod, TOTAL_VALUE);
- value *= GetModifierValue(unitMod, TOTAL_PCT);
+ float value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power);
+ value *= GetPctModifierValue(unitMod, BASE_PCT);
+ value += GetFlatModifierValue(unitMod, TOTAL_VALUE);
+ value *= GetPctModifierValue(unitMod, TOTAL_PCT);
SetMaxPower(power, (int32)std::lroundf(value));
}
@@ -876,8 +876,8 @@ void Creature::UpdateAttackPowerAndDamage(bool ranged)
{
UnitMods unitMod = ranged ? UNIT_MOD_ATTACK_POWER_RANGED : UNIT_MOD_ATTACK_POWER;
- float baseAttackPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT);
- float attackPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f;
+ float baseAttackPower = GetFlatModifierValue(unitMod, BASE_VALUE) * GetPctModifierValue(unitMod, BASE_PCT);
+ float attackPowerMultiplier = GetPctModifierValue(unitMod, TOTAL_PCT) - 1.0f;
if (ranged)
{
@@ -900,7 +900,7 @@ void Creature::UpdateAttackPowerAndDamage(bool ranged)
}
}
-void Creature::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage)
+void Creature::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) const
{
float variance = 1.0f;
UnitMods unitMod;
@@ -939,10 +939,10 @@ void Creature::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized,
float attackPower = GetTotalAttackPowerValue(attType);
float attackSpeedMulti = GetAPMultiplier(attType, normalized);
- float baseValue = GetModifierValue(unitMod, BASE_VALUE) + (attackPower / 3.5f) * variance;
- float basePct = GetModifierValue(unitMod, BASE_PCT) * attackSpeedMulti;
- float totalValue = GetModifierValue(unitMod, TOTAL_VALUE);
- float totalPct = addTotalPct ? GetModifierValue(unitMod, TOTAL_PCT) : 1.0f;
+ float baseValue = GetFlatModifierValue(unitMod, BASE_VALUE) + (attackPower / 3.5f) * variance;
+ float basePct = GetPctModifierValue(unitMod, BASE_PCT) * attackSpeedMulti;
+ float totalValue = GetFlatModifierValue(unitMod, TOTAL_VALUE);
+ float totalPct = addTotalPct ? GetPctModifierValue(unitMod, TOTAL_PCT) : 1.0f;
float dmgMultiplier = GetCreatureTemplate()->ModDamage; // = ModDamage * _GetDamageMod(rank);
minDamage = ((weaponMinDamage + baseValue) * dmgMultiplier * basePct + totalValue) * totalPct;
@@ -970,7 +970,7 @@ bool Guardian::UpdateStats(Stats stat)
{
// value = ((base_value * base_pct) + total_value) * total_pct
float value = GetTotalStatValue(stat);
- ApplyStatBuffMod(stat, m_statFromOwner[stat], false);
+ UpdateStatBuffMod(stat);
float ownersBonus = 0.0f;
Unit* owner = GetOwner();
@@ -1010,7 +1010,7 @@ bool Guardian::UpdateStats(Stats stat)
SetStat(stat, int32(value));
m_statFromOwner[stat] = ownersBonus;
- ApplyStatBuffMod(stat, m_statFromOwner[stat], true);
+ UpdateStatBuffMod(stat);
switch (stat)
{
@@ -1044,7 +1044,7 @@ void Guardian::UpdateResistances(uint32 school)
{
if (school > SPELL_SCHOOL_NORMAL)
{
- float baseValue = GetModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + school), BASE_VALUE);
+ float baseValue = GetFlatModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + school), BASE_VALUE);
float bonusValue = GetTotalAuraModValue(UnitMods(UNIT_MOD_RESISTANCE_START + school)) - baseValue;
// hunter and warlock pets gain 40% of owner's resistance
@@ -1074,11 +1074,11 @@ void Guardian::UpdateArmor()
else if (IsPet())
bonus_armor = m_owner->GetArmor();
- value = GetModifierValue(unitMod, BASE_VALUE);
+ value = GetFlatModifierValue(unitMod, BASE_VALUE);
baseValue = value;
- value *= GetModifierValue(unitMod, BASE_PCT);
- value += GetModifierValue(unitMod, TOTAL_VALUE) + bonus_armor;
- value *= GetModifierValue(unitMod, TOTAL_PCT);
+ value *= GetPctModifierValue(unitMod, BASE_PCT);
+ value += GetFlatModifierValue(unitMod, TOTAL_VALUE) + bonus_armor;
+ value *= GetPctModifierValue(unitMod, TOTAL_PCT);
SetArmor(int32(baseValue), int32(value - baseValue));
}
@@ -1100,10 +1100,10 @@ void Guardian::UpdateMaxHealth()
default: multiplicator = 10.0f; break;
}
- float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreateHealth();
- value *= GetModifierValue(unitMod, BASE_PCT);
- value += GetModifierValue(unitMod, TOTAL_VALUE) + stamina * multiplicator;
- value *= GetModifierValue(unitMod, TOTAL_PCT);
+ float value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetCreateHealth();
+ value *= GetPctModifierValue(unitMod, BASE_PCT);
+ value += GetFlatModifierValue(unitMod, TOTAL_VALUE) + stamina * multiplicator;
+ value *= GetPctModifierValue(unitMod, TOTAL_PCT);
SetMaxHealth((uint32)value);
}
@@ -1115,10 +1115,10 @@ void Guardian::UpdateMaxPower(Powers power)
UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + power);
- float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power);
- value *= GetModifierValue(unitMod, BASE_PCT);
- value += GetModifierValue(unitMod, TOTAL_VALUE);
- value *= GetModifierValue(unitMod, TOTAL_PCT);
+ float value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power);
+ value *= GetPctModifierValue(unitMod, BASE_PCT);
+ value += GetFlatModifierValue(unitMod, TOTAL_VALUE);
+ value *= GetPctModifierValue(unitMod, TOTAL_PCT);
SetMaxPower(power, int32(value));
}
@@ -1178,11 +1178,11 @@ void Guardian::UpdateAttackPowerAndDamage(bool ranged)
}
}
- SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, val + bonusAP);
+ SetStatFlatModifier(UNIT_MOD_ATTACK_POWER, BASE_VALUE, val + bonusAP);
//in BASE_VALUE of UNIT_MOD_ATTACK_POWER for creatures we store data of meleeattackpower field in DB
- float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT);
- float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f;
+ float base_attPower = GetFlatModifierValue(unitMod, BASE_VALUE) * GetPctModifierValue(unitMod, BASE_PCT);
+ float attPowerMultiplier = GetPctModifierValue(unitMod, TOTAL_PCT) - 1.0f;
SetAttackPower(int32(base_attPower));
SetAttackPowerMultiplier(attPowerMultiplier);
@@ -1219,10 +1219,10 @@ void Guardian::UpdateDamagePhysical(WeaponAttackType attType)
float att_speed = float(GetBaseAttackTime(BASE_ATTACK))/1000.0f;
- float base_value = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType)/ 3.5f * att_speed + bonusDamage;
- float base_pct = GetModifierValue(unitMod, BASE_PCT);
- float total_value = GetModifierValue(unitMod, TOTAL_VALUE);
- float total_pct = GetModifierValue(unitMod, TOTAL_PCT);
+ float base_value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType)/ 3.5f * att_speed + bonusDamage;
+ float base_pct = GetPctModifierValue(unitMod, BASE_PCT);
+ float total_value = GetFlatModifierValue(unitMod, TOTAL_VALUE);
+ float total_pct = GetPctModifierValue(unitMod, TOTAL_PCT);
float weapon_mindamage = GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE);
float weapon_maxdamage = GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE);
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 62790919a9c..a0ddb919106 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -331,14 +331,14 @@ Unit::Unit(bool isWorldObject) :
for (uint8 i = 0; i < UNIT_MOD_END; ++i)
{
- m_auraModifiersGroup[i][BASE_VALUE] = 0.0f;
- m_auraModifiersGroup[i][BASE_PCT_EXCLUDE_CREATE] = 100.0f;
- m_auraModifiersGroup[i][BASE_PCT] = 1.0f;
- m_auraModifiersGroup[i][TOTAL_VALUE] = 0.0f;
- m_auraModifiersGroup[i][TOTAL_PCT] = 1.0f;
+ m_auraFlatModifiersGroup[i][BASE_VALUE] = 0.0f;
+ m_auraFlatModifiersGroup[i][BASE_PCT_EXCLUDE_CREATE] = 100.0f;
+ m_auraFlatModifiersGroup[i][TOTAL_VALUE] = 0.0f;
+ m_auraPctModifiersGroup[i][BASE_PCT] = 1.0f;
+ m_auraPctModifiersGroup[i][TOTAL_PCT] = 1.0f;
}
// implement 50% base damage from offhand
- m_auraModifiersGroup[UNIT_MOD_DAMAGE_OFFHAND][TOTAL_PCT] = 0.5f;
+ m_auraPctModifiersGroup[UNIT_MOD_DAMAGE_OFFHAND][TOTAL_PCT] = 0.5f;
for (uint8 i = 0; i < MAX_ATTACK; ++i)
{
@@ -627,7 +627,7 @@ void Unit::GetRandomContactPoint(const Unit* obj, float &x, float &y, float &z,
{
float combat_reach = GetCombatReach();
if (combat_reach < 0.1f) // sometimes bugged for players
- combat_reach = DEFAULT_COMBAT_REACH;
+ combat_reach = DEFAULT_PLAYER_COMBAT_REACH;
uint32 attacker_number = uint32(getAttackers().size());
if (attacker_number > 0)
@@ -2258,7 +2258,7 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(Unit const* victim, WeaponAttackTy
return MELEE_HIT_NORMAL;
}
-uint32 Unit::CalculateDamage(WeaponAttackType attType, bool normalized, bool addTotalPct)
+uint32 Unit::CalculateDamage(WeaponAttackType attType, bool normalized, bool addTotalPct) const
{
float minDamage = 0.0f;
float maxDamage = 0.0f;
@@ -4892,16 +4892,69 @@ void Unit::InitStatBuffMods()
}
}
-void Unit::ApplyStatBuffMod(Stats stat, float val, bool apply)
+void Unit::UpdateStatBuffMod(Stats stat)
{
- ApplyPercentModFloatVar((val > 0 ? m_floatStatPosBuff[stat] : m_floatStatNegBuff[stat]), val, apply);
- UpdateStatBuffModForClient(stat);
-}
+ float modPos = 0.0f;
+ float modNeg = 0.0f;
+ float factor = 0.0f;
-void Unit::ApplyStatPercentBuffMod(Stats stat, float val, bool apply)
-{
- ApplyPercentModFloatVar(m_floatStatPosBuff[stat], val, apply);
- ApplyPercentModFloatVar(m_floatStatNegBuff[stat], val, apply);
+ UnitMods const unitMod = static_cast<UnitMods>(UNIT_MOD_STAT_START + stat);
+
+ // includes value from items and enchantments
+ float modValue = GetFlatModifierValue(unitMod, BASE_VALUE);
+ if (modValue > 0.f)
+ modPos += modValue;
+ else
+ modNeg += modValue;
+
+ if (IsGuardian())
+ {
+ modValue = static_cast<Guardian*>(this)->GetBonusStatFromOwner(stat);
+ if (modValue > 0.f)
+ modPos += modValue;
+ else
+ modNeg += modValue;
+ }
+
+ // SPELL_AURA_MOD_STAT_BONUS_PCT only affects BASE_VALUE
+ modPos = CalculatePct(modPos, std::max(GetFlatModifierValue(unitMod, BASE_PCT_EXCLUDE_CREATE), -100.0f));
+ modNeg = CalculatePct(modNeg, std::max(GetFlatModifierValue(unitMod, BASE_PCT_EXCLUDE_CREATE), -100.0f));
+
+ modPos += GetTotalAuraModifier(SPELL_AURA_MOD_STAT, [stat](AuraEffect const* aurEff) -> bool
+ {
+ if ((aurEff->GetMiscValue() < 0 || aurEff->GetMiscValue() == stat) && aurEff->GetAmount() > 0)
+ return true;
+ return false;
+ });
+
+ modNeg += GetTotalAuraModifier(SPELL_AURA_MOD_STAT, [stat](AuraEffect const* aurEff) -> bool
+ {
+ if ((aurEff->GetMiscValue() < 0 || aurEff->GetMiscValue() == stat) && aurEff->GetAmount() < 0)
+ return true;
+ return false;
+ });
+
+ factor = GetTotalAuraMultiplier(SPELL_AURA_MOD_PERCENT_STAT, [stat](AuraEffect const* aurEff) -> bool
+ {
+ if (aurEff->GetMiscValue() == -1 || aurEff->GetMiscValue() == stat)
+ return true;
+ return false;
+ });
+
+ factor *= GetTotalAuraMultiplier(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, [stat](AuraEffect const* aurEff) -> bool
+ {
+ if (aurEff->GetMiscValue() == -1 || aurEff->GetMiscValue() == stat)
+ return true;
+ return false;
+ });
+
+ modPos *= factor;
+ modNeg *= factor;
+
+ m_floatStatPosBuff[stat] = modPos;
+ m_floatStatNegBuff[stat] = modNeg;
+
+ UpdateStatBuffModForClient(stat);
}
void Unit::UpdateStatBuffModForClient(Stats stat)
@@ -9371,31 +9424,99 @@ bool Unit::IsDisallowedMountForm(uint32 spellId, ShapeshiftForm form, uint32 dis
######## ########
#######################################*/
-bool Unit::HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, float amount, bool apply)
+void Unit::HandleStatFlatModifier(UnitMods unitMod, UnitModifierFlatType modifierType, float amount, bool apply)
{
- if (unitMod >= UNIT_MOD_END || modifierType >= MODIFIER_TYPE_END)
+ if (unitMod >= UNIT_MOD_END || modifierType >= MODIFIER_TYPE_FLAT_END)
{
- TC_LOG_ERROR("entities.unit", "ERROR in HandleStatModifier(): non-existing UnitMods or wrong UnitModifierType!");
- return false;
+ TC_LOG_ERROR("entities.unit", "ERROR in HandleStatFlatModifier(): non-existing UnitMods or wrong UnitModifierType!");
+ return;
}
+ if (!amount)
+ return;
+
switch (modifierType)
{
case BASE_VALUE:
case BASE_PCT_EXCLUDE_CREATE:
case TOTAL_VALUE:
- m_auraModifiersGroup[unitMod][modifierType] += apply ? amount : -amount;
+ m_auraFlatModifiersGroup[unitMod][modifierType] += apply ? amount : -amount;
break;
+ default:
+ break;
+ }
+
+ UpdateUnitMod(unitMod);
+}
+
+void Unit::ApplyStatPctModifier(UnitMods unitMod, UnitModifierPctType modifierType, float pct)
+{
+ if (unitMod >= UNIT_MOD_END || modifierType >= MODIFIER_TYPE_PCT_END)
+ {
+ TC_LOG_ERROR("entities.unit", "ERROR in ApplyStatPctModifier(): non-existing UnitMods or wrong UnitModifierType!");
+ return;
+ }
+
+ if (!pct)
+ return;
+
+ switch (modifierType)
+ {
case BASE_PCT:
case TOTAL_PCT:
- ApplyPercentModFloatVar(m_auraModifiersGroup[unitMod][modifierType], amount, apply);
+ AddPct(m_auraPctModifiersGroup[unitMod][modifierType], pct);
break;
default:
break;
}
+ UpdateUnitMod(unitMod);
+}
+
+void Unit::SetStatFlatModifier(UnitMods unitMod, UnitModifierFlatType modifierType, float val)
+{
+ if (m_auraFlatModifiersGroup[unitMod][modifierType] == val)
+ return;
+
+ m_auraFlatModifiersGroup[unitMod][modifierType] = val;
+ UpdateUnitMod(unitMod);
+}
+
+void Unit::SetStatPctModifier(UnitMods unitMod, UnitModifierPctType modifierType, float val)
+{
+ if (m_auraPctModifiersGroup[unitMod][modifierType] == val)
+ return;
+
+ m_auraPctModifiersGroup[unitMod][modifierType] = val;
+ UpdateUnitMod(unitMod);
+}
+
+float Unit::GetFlatModifierValue(UnitMods unitMod, UnitModifierFlatType modifierType) const
+{
+ if (unitMod >= UNIT_MOD_END || modifierType >= MODIFIER_TYPE_FLAT_END)
+ {
+ TC_LOG_ERROR("entities.unit", "attempt to access non-existing modifier value from UnitMods!");
+ return 0.0f;
+ }
+
+ return m_auraFlatModifiersGroup[unitMod][modifierType];
+}
+
+float Unit::GetPctModifierValue(UnitMods unitMod, UnitModifierPctType modifierType) const
+{
+ if (unitMod >= UNIT_MOD_END || modifierType >= MODIFIER_TYPE_PCT_END)
+ {
+ TC_LOG_ERROR("entities.unit", "attempt to access non-existing modifier value from UnitMods!");
+ return 0.0f;
+ }
+
+ return m_auraPctModifiersGroup[unitMod][modifierType];
+}
+
+void Unit::UpdateUnitMod(UnitMods unitMod)
+{
if (!CanModifyStats())
- return false;
+ return;
switch (unitMod)
{
@@ -9445,37 +9566,92 @@ bool Unit::HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, f
ASSERT(false, "Not implemented UnitMod %u", unitMod);
break;
}
+}
+
+void Unit::UpdateDamageDoneMods(WeaponAttackType attackType)
+{
+ UnitMods unitMod;
+ switch (attackType)
+ {
+ case BASE_ATTACK:
+ unitMod = UNIT_MOD_DAMAGE_MAINHAND;
+ break;
+ case OFF_ATTACK:
+ unitMod = UNIT_MOD_DAMAGE_OFFHAND;
+ break;
+ case RANGED_ATTACK:
+ unitMod = UNIT_MOD_DAMAGE_RANGED;
+ break;
+ default:
+ ABORT();
+ break;
+ }
- return true;
+ float amount = GetTotalAuraModifier(SPELL_AURA_MOD_DAMAGE_DONE, std::bind(&Unit::CheckAttackFitToAuraRequirement, this, attackType, std::placeholders::_1));
+
+ SetStatFlatModifier(unitMod, TOTAL_VALUE, amount);
+}
+
+void Unit::UpdateAllDamageDoneMods()
+{
+ for (uint8 i = BASE_ATTACK; i < MAX_ATTACK; ++i)
+ UpdateDamageDoneMods(WeaponAttackType(i));
}
-float Unit::GetModifierValue(UnitMods unitMod, UnitModifierType modifierType) const
+void Unit::UpdateDamagePctDoneMods(WeaponAttackType attackType)
{
- if (unitMod >= UNIT_MOD_END || modifierType >= MODIFIER_TYPE_END)
+ float factor;
+ UnitMods unitMod;
+ switch (attackType)
{
- TC_LOG_ERROR("entities.unit", "attempt to access non-existing modifier value from UnitMods!");
- return 0.0f;
+ case BASE_ATTACK:
+ factor = 1.0f;
+ unitMod = UNIT_MOD_DAMAGE_MAINHAND;
+ break;
+ case OFF_ATTACK:
+ // off hand has 50% penalty
+ factor = 0.5f;
+ unitMod = UNIT_MOD_DAMAGE_OFFHAND;
+ break;
+ case RANGED_ATTACK:
+ factor = 1.0f;
+ unitMod = UNIT_MOD_DAMAGE_RANGED;
+ break;
+ default:
+ ABORT();
+ break;
}
- if (modifierType == TOTAL_PCT && m_auraModifiersGroup[unitMod][modifierType] <= 0.0f)
- return 0.0f;
+ factor *= GetTotalAuraMultiplier(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, [attackType, this](AuraEffect const* aurEff) -> bool
+ {
+ if (!(aurEff->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL))
+ return false;
+
+ return CheckAttackFitToAuraRequirement(attackType, aurEff);
+ });
+
+ if (attackType == OFF_ATTACK)
+ factor *= GetTotalAuraMultiplier(SPELL_AURA_MOD_OFFHAND_DAMAGE_PCT, std::bind(&Unit::CheckAttackFitToAuraRequirement, this, attackType, std::placeholders::_1));
- return m_auraModifiersGroup[unitMod][modifierType];
+ SetStatPctModifier(unitMod, TOTAL_PCT, factor);
+}
+
+void Unit::UpdateAllDamagePctDoneMods()
+{
+ for (uint8 i = BASE_ATTACK; i < MAX_ATTACK; ++i)
+ UpdateDamagePctDoneMods(WeaponAttackType(i));
}
float Unit::GetTotalStatValue(Stats stat) const
{
UnitMods unitMod = UnitMods(UNIT_MOD_STAT_START + stat);
- if (m_auraModifiersGroup[unitMod][TOTAL_PCT] <= 0.0f)
- return 0.0f;
-
// value = ((base_value * base_pct) + total_value) * total_pct
- float value = CalculatePct(m_auraModifiersGroup[unitMod][BASE_VALUE], std::max(m_auraModifiersGroup[unitMod][BASE_PCT_EXCLUDE_CREATE], -100.0f));
+ float value = CalculatePct(GetFlatModifierValue(unitMod, BASE_VALUE), std::max(GetFlatModifierValue(unitMod, BASE_PCT_EXCLUDE_CREATE), -100.0f));
value += GetCreateStat(stat);
- value *= m_auraModifiersGroup[unitMod][BASE_PCT];
- value += m_auraModifiersGroup[unitMod][TOTAL_VALUE];
- value *= m_auraModifiersGroup[unitMod][TOTAL_PCT];
+ value *= GetPctModifierValue(unitMod, BASE_PCT);
+ value += GetFlatModifierValue(unitMod, TOTAL_VALUE);
+ value *= GetPctModifierValue(unitMod, TOTAL_PCT);
return value;
}
@@ -9488,13 +9664,10 @@ float Unit::GetTotalAuraModValue(UnitMods unitMod) const
return 0.0f;
}
- if (m_auraModifiersGroup[unitMod][TOTAL_PCT] <= 0.0f)
- return 0.0f;
-
- float value = CalculatePct(m_auraModifiersGroup[unitMod][BASE_VALUE], std::max(m_auraModifiersGroup[unitMod][BASE_PCT_EXCLUDE_CREATE], -100.0f));
- value *= m_auraModifiersGroup[unitMod][BASE_PCT];
- value += m_auraModifiersGroup[unitMod][TOTAL_VALUE];
- value *= m_auraModifiersGroup[unitMod][TOTAL_PCT];
+ float value = CalculatePct(GetFlatModifierValue(unitMod, BASE_VALUE), std::max(GetFlatModifierValue(unitMod, BASE_PCT_EXCLUDE_CREATE), -100.0f));
+ value *= GetPctModifierValue(unitMod, BASE_PCT);
+ value += GetFlatModifierValue(unitMod, TOTAL_VALUE);
+ value *= GetPctModifierValue(unitMod, TOTAL_PCT);
return value;
}
@@ -9542,7 +9715,7 @@ void Unit::UpdateResistances(uint32 school)
{
UnitMods unitMod = UnitMods(UNIT_MOD_RESISTANCE_START + school);
- SetResistance(SpellSchools(school), int32(m_auraModifiersGroup[unitMod][BASE_VALUE]));
+ SetResistance(SpellSchools(school), int32(GetFlatModifierValue(unitMod, BASE_VALUE)));
SetBonusResistanceMod(SpellSchools(school), int32(GetTotalAuraModValue(unitMod) - GetResistance(SpellSchools(school))));
}
else
@@ -9802,7 +9975,6 @@ void Unit::CleanupBeforeRemoveFromMap(bool finalCleanup)
CombatStop();
DeleteThreatList();
getHostileRefManager().deleteReferences();
- GetMotionMaster()->Clear(false); // remove different non-standard movement generators.
}
void Unit::CleanupsBeforeDelete(bool finalCleanup)
@@ -10609,7 +10781,10 @@ void Unit::RestoreDisplayId(bool ignorePositiveAurasPreventingMounting /*= false
// transform aura was found
if (handledAura)
+ {
handledAura->HandleEffect(this, AURA_EFFECT_HANDLE_SEND_FOR_CLIENT, true);
+ return;
+ }
// we've found shapeshift
else if (!shapeshiftAura.empty()) // we've found shapeshift
{
@@ -10620,11 +10795,11 @@ void Unit::RestoreDisplayId(bool ignorePositiveAurasPreventingMounting /*= false
SetDisplayId(modelId);
else
SetDisplayId(GetNativeDisplayId());
+ return;
}
}
// no auras found - set modelid to default
- else
- SetDisplayId(GetNativeDisplayId());
+ SetDisplayId(GetNativeDisplayId());
}
void Unit::ClearAllReactives()
@@ -10734,10 +10909,15 @@ void Unit::UpdateAttackTimeField(WeaponAttackType att)
}
}
+void ApplyPercentModFloatVar(float& var, float val, bool apply)
+{
+ var *= (apply ? (100.0f + val) / 100.0f : 100.0f / (100.0f + val));
+}
+
void Unit::ApplyAttackTimePercentMod(WeaponAttackType att, float val, bool apply)
{
float remainingTimePct = float(m_attackTimer[att]) / (m_baseAttackSpeed[att] * m_modAttackSpeedPct[att]);
- if (val > 0)
+ if (val > 0.f)
{
ApplyPercentModFloatVar(m_modAttackSpeedPct[att], val, !apply);
@@ -10762,7 +10942,7 @@ void Unit::ApplyAttackTimePercentMod(WeaponAttackType att, float val, bool apply
void Unit::ApplyCastTimePercentMod(float val, bool apply)
{
- if (val > 0)
+ if (val > 0.f)
{
ApplyPercentModUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::ModCastingSpeed), val, !apply);
ApplyPercentModUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::ModSpellHaste), val, !apply);
@@ -10920,7 +11100,7 @@ float Unit::CalculateDefaultCoefficient(SpellInfo const* spellInfo, DamageEffect
return (CastingTime / 3500.0f) * DotFactor;
}
-float Unit::GetAPMultiplier(WeaponAttackType attType, bool normalized)
+float Unit::GetAPMultiplier(WeaponAttackType attType, bool normalized) const
{
if (GetTypeId() != TYPEID_PLAYER || (IsInFeralForm() && !normalized))
return GetBaseAttackTime(attType) / 1000.0f;
@@ -11999,8 +12179,8 @@ bool Unit::IsInPartyWith(Unit const* unit) const
if (this == unit)
return true;
- const Unit* u1 = GetCharmerOrOwnerOrSelf();
- const Unit* u2 = unit->GetCharmerOrOwnerOrSelf();
+ Unit const* u1 = GetCharmerOrOwnerOrSelf();
+ Unit const* u2 = unit->GetCharmerOrOwnerOrSelf();
if (u1 == u2)
return true;
@@ -12010,8 +12190,7 @@ bool Unit::IsInPartyWith(Unit const* unit) const
(u1->GetTypeId() == TYPEID_PLAYER && u2->GetTypeId() == TYPEID_UNIT && u2->ToCreature()->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT))
return true;
- // else u1->GetTypeId() == u2->GetTypeId() == TYPEID_UNIT
- return u1->getFaction() == u2->getFaction();
+ return u1->GetTypeId() == TYPEID_UNIT && u2->GetTypeId() == TYPEID_UNIT && u1->getFaction() == u2->getFaction();
}
bool Unit::IsInRaidWith(Unit const* unit) const
@@ -12019,8 +12198,8 @@ bool Unit::IsInRaidWith(Unit const* unit) const
if (this == unit)
return true;
- const Unit* u1 = GetCharmerOrOwnerOrSelf();
- const Unit* u2 = unit->GetCharmerOrOwnerOrSelf();
+ Unit const* u1 = GetCharmerOrOwnerOrSelf();
+ Unit const* u2 = unit->GetCharmerOrOwnerOrSelf();
if (u1 == u2)
return true;
@@ -12030,8 +12209,7 @@ bool Unit::IsInRaidWith(Unit const* unit) const
(u1->GetTypeId() == TYPEID_PLAYER && u2->GetTypeId() == TYPEID_UNIT && u2->ToCreature()->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT))
return true;
- // else u1->GetTypeId() == u2->GetTypeId() == TYPEID_UNIT
- return u1->getFaction() == u2->getFaction();
+ return u1->GetTypeId() == TYPEID_UNIT && u2->GetTypeId() == TYPEID_UNIT && u1->getFaction() == u2->getFaction();
}
void Unit::GetPartyMembers(std::list<Unit*> &TagUnitMap)
@@ -12852,6 +13030,8 @@ bool Unit::HandleSpellClick(Unit* clicker, int8 seatId)
{
bool result = false;
uint32 spellClickEntry = GetVehicleKit() ? GetVehicleKit()->GetCreatureEntry() : GetEntry();
+ TriggerCastFlags const flags = GetVehicleKit() ? TRIGGERED_IGNORE_CASTER_MOUNTED_OR_ON_VEHICLE : TRIGGERED_NONE;
+
SpellClickInfoMapBounds clickPair = sObjectMgr->GetSpellClickInfoMapBounds(spellClickEntry);
for (SpellClickInfoContainer::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr)
{
@@ -12894,7 +13074,7 @@ bool Unit::HandleSpellClick(Unit* clicker, int8 seatId)
}
if (IsInMap(caster))
- caster->CastCustomSpell(itr->second.spellId, SpellValueMod(SPELLVALUE_BASE_POINT0+i), seatId + 1, target, GetVehicleKit() ? TRIGGERED_IGNORE_CASTER_MOUNTED_OR_ON_VEHICLE : TRIGGERED_NONE, NULL, NULL, origCasterGUID);
+ caster->CastCustomSpell(itr->second.spellId, SpellValueMod(SPELLVALUE_BASE_POINT0 + i), seatId + 1, target, flags, NULL, NULL, origCasterGUID);
else // This can happen during Player::_LoadAuras
{
int32 bp0[MAX_SPELL_EFFECTS];
@@ -12909,7 +13089,7 @@ bool Unit::HandleSpellClick(Unit* clicker, int8 seatId)
else
{
if (IsInMap(caster))
- caster->CastSpell(target, spellEntry, GetVehicleKit() ? TRIGGERED_IGNORE_CASTER_MOUNTED_OR_ON_VEHICLE : TRIGGERED_NONE, NULL, NULL, origCasterGUID);
+ caster->CastSpell(target, spellEntry, flags, NULL, NULL, origCasterGUID);
else
Aura::TryRefreshStackOrCreate(spellEntry, ObjectGuid::Create<HighGuid::Cast>(SPELL_CAST_SOURCE_NORMAL, GetMapId(), spellEntry->Id, GetMap()->GenerateLowGuid<HighGuid::Cast>()), MAX_EFFECT_MASK, this, clicker, NULL, NULL, origCasterGUID);
}
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 1f9de500ad1..7db8583f69f 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -257,14 +257,19 @@ typedef std::vector<DispelableAura> DispelChargesList;
typedef std::unordered_multimap<uint32 /*type*/, uint32 /*spellId*/> SpellImmuneContainer;
-enum UnitModifierType
+enum UnitModifierFlatType
{
BASE_VALUE = 0,
BASE_PCT_EXCLUDE_CREATE = 1, // percent modifier affecting all stat values from auras and gear but not player base for level
- BASE_PCT = 2,
- TOTAL_VALUE = 3,
- TOTAL_PCT = 4,
- MODIFIER_TYPE_END = 5
+ TOTAL_VALUE = 2,
+ MODIFIER_TYPE_FLAT_END = 3
+};
+
+enum UnitModifierPctType
+{
+ BASE_PCT = 0,
+ TOTAL_PCT = 1,
+ MODIFIER_TYPE_PCT_END = 2
};
enum WeaponDamageRange
@@ -378,66 +383,60 @@ enum DeathState
JUST_RESPAWNED = 4
};
-enum UnitState
+enum UnitState : uint32
{
- UNIT_STATE_DIED = 0x00000001, // player has fake death aura
- UNIT_STATE_MELEE_ATTACKING = 0x00000002, // player is melee attacking someone
- //UNIT_STATE_MELEE_ATTACK_BY = 0x00000004, // player is melee attack by someone
- UNIT_STATE_STUNNED = 0x00000008,
- UNIT_STATE_ROAMING = 0x00000010,
- UNIT_STATE_CHASE = 0x00000020,
- //UNIT_STATE_SEARCHING = 0x00000040,
- UNIT_STATE_FLEEING = 0x00000080,
- UNIT_STATE_IN_FLIGHT = 0x00000100, // player is in flight mode
- UNIT_STATE_FOLLOW = 0x00000200,
- UNIT_STATE_ROOT = 0x00000400,
- UNIT_STATE_CONFUSED = 0x00000800,
- UNIT_STATE_DISTRACTED = 0x00001000,
- UNIT_STATE_ISOLATED = 0x00002000, // area auras do not affect other players
- UNIT_STATE_ATTACK_PLAYER = 0x00004000,
- UNIT_STATE_CASTING = 0x00008000,
- UNIT_STATE_POSSESSED = 0x00010000,
- UNIT_STATE_CHARGING = 0x00020000,
- UNIT_STATE_JUMPING = 0x00040000,
- UNIT_STATE_MOVE = 0x00100000,
- UNIT_STATE_ROTATING = 0x00200000,
- UNIT_STATE_EVADE = 0x00400000,
- UNIT_STATE_ROAMING_MOVE = 0x00800000,
- UNIT_STATE_CONFUSED_MOVE = 0x01000000,
- UNIT_STATE_FLEEING_MOVE = 0x02000000,
- UNIT_STATE_CHASE_MOVE = 0x04000000,
- UNIT_STATE_FOLLOW_MOVE = 0x08000000,
- UNIT_STATE_IGNORE_PATHFINDING = 0x10000000, // do not use pathfinding in any MovementGenerator
+ UNIT_STATE_DIED = 0x00000001, // player has fake death aura
+ UNIT_STATE_MELEE_ATTACKING = 0x00000002, // player is melee attacking someone
+ //UNIT_STATE_MELEE_ATTACK_BY = 0x00000004, // player is melee attack by someone
+ UNIT_STATE_STUNNED = 0x00000008,
+ UNIT_STATE_ROAMING = 0x00000010,
+ UNIT_STATE_CHASE = 0x00000020,
+ //UNIT_STATE_SEARCHING = 0x00000040,
+ UNIT_STATE_FLEEING = 0x00000080,
+ UNIT_STATE_IN_FLIGHT = 0x00000100, // player is in flight mode
+ UNIT_STATE_FOLLOW = 0x00000200,
+ UNIT_STATE_ROOT = 0x00000400,
+ UNIT_STATE_CONFUSED = 0x00000800,
+ UNIT_STATE_DISTRACTED = 0x00001000,
+ UNIT_STATE_ISOLATED = 0x00002000, // area auras do not affect other players
+ UNIT_STATE_ATTACK_PLAYER = 0x00004000,
+ UNIT_STATE_CASTING = 0x00008000,
+ UNIT_STATE_POSSESSED = 0x00010000,
+ UNIT_STATE_CHARGING = 0x00020000,
+ UNIT_STATE_JUMPING = 0x00040000,
+ UNIT_STATE_MOVE = 0x00100000,
+ UNIT_STATE_ROTATING = 0x00200000,
+ UNIT_STATE_EVADE = 0x00400000,
+ UNIT_STATE_ROAMING_MOVE = 0x00800000,
+ UNIT_STATE_CONFUSED_MOVE = 0x01000000,
+ UNIT_STATE_FLEEING_MOVE = 0x02000000,
+ UNIT_STATE_CHASE_MOVE = 0x04000000,
+ UNIT_STATE_FOLLOW_MOVE = 0x08000000,
+ UNIT_STATE_IGNORE_PATHFINDING = 0x10000000, // do not use pathfinding in any MovementGenerator
+
UNIT_STATE_ALL_STATE_SUPPORTED = UNIT_STATE_DIED | UNIT_STATE_MELEE_ATTACKING | UNIT_STATE_STUNNED | UNIT_STATE_ROAMING | UNIT_STATE_CHASE
| UNIT_STATE_FLEEING | UNIT_STATE_IN_FLIGHT | UNIT_STATE_FOLLOW | UNIT_STATE_ROOT | UNIT_STATE_CONFUSED
| UNIT_STATE_DISTRACTED | UNIT_STATE_ISOLATED | UNIT_STATE_ATTACK_PLAYER | UNIT_STATE_CASTING
| UNIT_STATE_POSSESSED | UNIT_STATE_CHARGING | UNIT_STATE_JUMPING | UNIT_STATE_MOVE | UNIT_STATE_ROTATING
| UNIT_STATE_EVADE | UNIT_STATE_ROAMING_MOVE | UNIT_STATE_CONFUSED_MOVE | UNIT_STATE_FLEEING_MOVE
| UNIT_STATE_CHASE_MOVE | UNIT_STATE_FOLLOW_MOVE | UNIT_STATE_IGNORE_PATHFINDING,
- UNIT_STATE_UNATTACKABLE = UNIT_STATE_IN_FLIGHT,
- // for real move using movegen check and stop (except unstoppable flight)
- UNIT_STATE_MOVING = UNIT_STATE_ROAMING_MOVE | UNIT_STATE_CONFUSED_MOVE | UNIT_STATE_FLEEING_MOVE | UNIT_STATE_CHASE_MOVE | UNIT_STATE_FOLLOW_MOVE,
- UNIT_STATE_CONTROLLED = (UNIT_STATE_CONFUSED | UNIT_STATE_STUNNED | UNIT_STATE_FLEEING),
- UNIT_STATE_LOST_CONTROL = (UNIT_STATE_CONTROLLED | UNIT_STATE_JUMPING | UNIT_STATE_CHARGING),
- UNIT_STATE_SIGHTLESS = (UNIT_STATE_LOST_CONTROL | UNIT_STATE_EVADE),
- UNIT_STATE_CANNOT_AUTOATTACK = (UNIT_STATE_LOST_CONTROL | UNIT_STATE_CASTING),
- UNIT_STATE_CANNOT_TURN = (UNIT_STATE_LOST_CONTROL | UNIT_STATE_ROTATING),
- // stay by different reasons
- UNIT_STATE_NOT_MOVE = UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DIED | UNIT_STATE_DISTRACTED,
- UNIT_STATE_ALL_STATE = 0xffffffff //(UNIT_STATE_STOPPED | UNIT_STATE_MOVING | UNIT_STATE_IN_COMBAT | UNIT_STATE_IN_FLIGHT)
+
+ UNIT_STATE_UNATTACKABLE = UNIT_STATE_IN_FLIGHT,
+ UNIT_STATE_MOVING = UNIT_STATE_ROAMING_MOVE | UNIT_STATE_CONFUSED_MOVE | UNIT_STATE_FLEEING_MOVE | UNIT_STATE_CHASE_MOVE | UNIT_STATE_FOLLOW_MOVE,
+ UNIT_STATE_CONTROLLED = UNIT_STATE_CONFUSED | UNIT_STATE_STUNNED | UNIT_STATE_FLEEING,
+ UNIT_STATE_LOST_CONTROL = UNIT_STATE_CONTROLLED | UNIT_STATE_JUMPING | UNIT_STATE_CHARGING,
+ UNIT_STATE_SIGHTLESS = UNIT_STATE_LOST_CONTROL | UNIT_STATE_EVADE,
+ UNIT_STATE_CANNOT_AUTOATTACK = UNIT_STATE_LOST_CONTROL | UNIT_STATE_CASTING,
+ UNIT_STATE_CANNOT_TURN = UNIT_STATE_LOST_CONTROL | UNIT_STATE_ROTATING,
+ UNIT_STATE_NOT_MOVE = UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DIED | UNIT_STATE_DISTRACTED,
+
+ UNIT_STATE_ALL_ERASABLE = UNIT_STATE_ALL_STATE_SUPPORTED & ~(UNIT_STATE_IGNORE_PATHFINDING),
+ UNIT_STATE_ALL_STATE = 0xffffffff
};
TC_GAME_API extern float baseMoveSpeed[MAX_MOVE_TYPE];
TC_GAME_API extern float playerBaseMoveSpeed[MAX_MOVE_TYPE];
-enum WeaponAttackType : uint8
-{
- BASE_ATTACK = 0,
- OFF_ATTACK = 1,
- RANGED_ATTACK = 2,
- MAX_ATTACK
-};
-
enum CombatRating
{
CR_AMPLIFY = 0,
@@ -966,7 +965,7 @@ class TC_GAME_API Unit : public WorldObject
bool haveOffhandWeapon() const;
bool CanDualWield() const { return m_canDualWield; }
virtual void SetCanDualWield(bool value) { m_canDualWield = value; }
- float GetCombatReach() const { return m_unitData->CombatReach; }
+ float GetCombatReach() const override { return m_unitData->CombatReach; }
void SetCombatReach(float combatReach) { SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::CombatReach), combatReach); }
float GetBoundingRadius() const { return m_unitData->BoundingRadius; }
void SetBoundingRadius(float boundingRadius) { SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::BoundingRadius), boundingRadius); }
@@ -1608,8 +1607,7 @@ class TC_GAME_API Unit : public WorldObject
int32 GetMaxNegativeAuraModifierByAffectMask(AuraType auratype, SpellInfo const* affectedSpell) const;
void InitStatBuffMods();
- void ApplyStatBuffMod(Stats stat, float val, bool apply);
- void ApplyStatPercentBuffMod(Stats stat, float val, bool apply);
+ void UpdateStatBuffMod(Stats stat);
void UpdateStatBuffModForClient(Stats stat);
void SetCreateStat(Stats stat, float val) { m_createStats[stat] = val; }
void SetCreateHealth(uint32 val) { SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::BaseHealth), val); }
@@ -1693,9 +1691,26 @@ class TC_GAME_API Unit : public WorldObject
EventProcessor m_Events;
// stat system
- bool HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, float amount, bool apply);
- void SetModifierValue(UnitMods unitMod, UnitModifierType modifierType, float value) { m_auraModifiersGroup[unitMod][modifierType] = value; }
- float GetModifierValue(UnitMods unitMod, UnitModifierType modifierType) const;
+ void HandleStatFlatModifier(UnitMods unitMod, UnitModifierFlatType modifierType, float amount, bool apply);
+ void ApplyStatPctModifier(UnitMods unitMod, UnitModifierPctType modifierType, float amount);
+
+ void SetStatFlatModifier(UnitMods unitMod, UnitModifierFlatType modifierType, float val);
+ void SetStatPctModifier(UnitMods unitMod, UnitModifierPctType modifierType, float val);
+
+ float GetFlatModifierValue(UnitMods unitMod, UnitModifierFlatType modifierType) const;
+ float GetPctModifierValue(UnitMods unitMod, UnitModifierPctType modifierType) const;
+
+ void UpdateUnitMod(UnitMods unitMod);
+
+ // only players have item requirements
+ virtual bool CheckAttackFitToAuraRequirement(WeaponAttackType /*attackType*/, AuraEffect const* /*aurEff*/) const { return true; }
+
+ virtual void UpdateDamageDoneMods(WeaponAttackType attackType);
+ void UpdateAllDamageDoneMods();
+
+ void UpdateDamagePctDoneMods(WeaponAttackType attackType);
+ void UpdateAllDamagePctDoneMods();
+
float GetTotalStatValue(Stats stat) const;
float GetTotalAuraModValue(UnitMods unitMod) const;
SpellSchools GetSpellSchoolByAuraGroup(UnitMods unitMod) const;
@@ -1723,9 +1738,9 @@ class TC_GAME_API Unit : public WorldObject
float GetTotalAttackPowerValue(WeaponAttackType attType) const;
float GetWeaponDamageRange(WeaponAttackType attType, WeaponDamageRange type) const;
void SetBaseWeaponDamage(WeaponAttackType attType, WeaponDamageRange damageRange, float value) { m_weaponDamage[attType][damageRange] = value; }
- virtual void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) = 0;
- uint32 CalculateDamage(WeaponAttackType attType, bool normalized, bool addTotalPct);
- float GetAPMultiplier(WeaponAttackType attType, bool normalized);
+ virtual void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) const = 0;
+ uint32 CalculateDamage(WeaponAttackType attType, bool normalized, bool addTotalPct) const;
+ float GetAPMultiplier(WeaponAttackType attType, bool normalized) const;
bool isInFrontInMap(Unit const* target, float distance, float arc = float(M_PI)) const;
bool isInBackInMap(Unit const* target, float distance, float arc = float(M_PI)) const;
@@ -2066,7 +2081,8 @@ class TC_GAME_API Unit : public WorldObject
AuraStateAurasMap m_auraStateAuras; // Used for improve performance of aura state checks on aura apply/remove
std::array<uint32, 2> m_interruptMask;
- float m_auraModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_END];
+ float m_auraFlatModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_FLAT_END];
+ float m_auraPctModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_PCT_END];
float m_weaponDamage[MAX_ATTACK][2];
bool m_canModifyStats;
diff --git a/src/server/game/Entities/Unit/UnitDefines.h b/src/server/game/Entities/Unit/UnitDefines.h
index 158943800c8..9bf875ee810 100644
--- a/src/server/game/Entities/Unit/UnitDefines.h
+++ b/src/server/game/Entities/Unit/UnitDefines.h
@@ -21,7 +21,6 @@
#include "Define.h"
#include <string>
-#define DEFAULT_COMBAT_REACH 1.5f
#define MIN_MELEE_REACH 2.0f
#define NOMINAL_MELEE_RANGE 5.0f
#define MELEE_RANGE (NOMINAL_MELEE_RANGE - MIN_MELEE_REACH * 2) //center to center for players
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index abc2a7b9189..4ab04447914 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -1538,7 +1538,7 @@ void ObjectMgr::LoadCreatureModelInfo()
}
if (modelInfo.combat_reach < 0.1f)
- modelInfo.combat_reach = DEFAULT_COMBAT_REACH;
+ modelInfo.combat_reach = DEFAULT_PLAYER_COMBAT_REACH;
if (CreatureModelDataEntry const* modelData = sCreatureModelDataStore.LookupEntry(creatureDisplay->ModelID))
{
@@ -1986,8 +1986,6 @@ void ObjectMgr::LoadCreatures()
data.phaseGroup = fields[25].GetUInt32();
data.terrainSwapMap = fields[26].GetInt32();
data.ScriptId = GetScriptId(fields[27].GetString());
- if (!data.ScriptId)
- data.ScriptId = cInfo->ScriptID;
MapEntry const* mapEntry = sMapStore.LookupEntry(data.mapid);
if (!mapEntry)
@@ -2459,8 +2457,6 @@ void ObjectMgr::LoadGameobjects()
}
data.ScriptId = GetScriptId(fields[21].GetString());
- if (!data.ScriptId)
- data.ScriptId = gInfo->ScriptId;
if (std::abs(data.orientation) > 2 * float(M_PI))
{
@@ -3874,12 +3870,12 @@ void ObjectMgr::LoadQuests()
uint32 oldMSTime = getMSTime();
// For reload case
- for (QuestMap::const_iterator itr=_questTemplates.begin(); itr != _questTemplates.end(); ++itr)
+ for (auto itr = _questTemplates.begin(); itr != _questTemplates.end(); ++itr)
delete itr->second;
_questTemplates.clear();
_questObjectives.clear();
- mExclusiveQuestGroups.clear();
+ _exclusiveQuestGroups.clear();
QueryResult result = WorldDatabase.Query("SELECT "
//0 1 2 3 4 5 6 7 8 9 10 11 12
@@ -3930,123 +3926,63 @@ void ObjectMgr::LoadQuests()
_questTemplates[newQuest->GetQuestId()] = newQuest;
} while (result->NextRow());
- // Load `quest_details`
- // 0 1 2 3 4 5 6 7 8
- result = WorldDatabase.Query("SELECT ID, Emote1, Emote2, Emote3, Emote4, EmoteDelay1, EmoteDelay2, EmoteDelay3, EmoteDelay4 FROM quest_details");
-
- if (!result)
- {
- TC_LOG_ERROR("server.loading", ">> Loaded 0 quest details. DB table `quest_details` is empty.");
- }
- else
+ struct QuestLoaderHelper
{
- do
- {
- Field* fields = result->Fetch();
- uint32 questId = fields[0].GetUInt32();
-
- auto itr = _questTemplates.find(questId);
- if (itr != _questTemplates.end())
- itr->second->LoadQuestDetails(fields);
- else
- TC_LOG_ERROR("server.loading", "Table `quest_details` has data for quest %u but such quest does not exist", questId);
- } while (result->NextRow());
- }
+ typedef void(Quest::* QuestLoaderFunction)(Field* fields);
- // Load `quest_request_items`
- // 0 1 2 3 4 5
- result = WorldDatabase.Query("SELECT ID, EmoteOnComplete, EmoteOnIncomplete, EmoteOnCompleteDelay, EmoteOnIncompleteDelay, CompletionText FROM quest_request_items");
+ char const* QueryFields;
+ char const* TableName;
+ char const* QueryExtra;
+ char const* TableDesc;
+ QuestLoaderFunction LoaderFunction;
+ };
- if (!result)
+ static std::vector<QuestLoaderHelper> const QuestLoaderHelpers =
{
- TC_LOG_ERROR("server.loading", ">> Loaded 0 quest request items. DB table `quest_request_items` is empty.");
- }
- else
- {
- do
- {
- Field* fields = result->Fetch();
- uint32 questId = fields[0].GetUInt32();
+ // 0 1 2 3 4 5 6 7 8
+ { "ID, Emote1, Emote2, Emote3, Emote4, EmoteDelay1, EmoteDelay2, EmoteDelay3, EmoteDelay4", "quest_details", "", "details", &Quest::LoadQuestDetails },
- auto itr = _questTemplates.find(questId);
- if (itr != _questTemplates.end())
- itr->second->LoadQuestRequestItems(fields);
- else
- TC_LOG_ERROR("server.loading", "Table `quest_request_items` has data for quest %u but such quest does not exist", questId);
- } while (result->NextRow());
- }
+ // 0 1 2 3 4 5
+ { "ID, EmoteOnComplete, EmoteOnIncomplete, EmoteOnCompleteDelay, EmoteOnIncompleteDelay, CompletionText", "quest_request_items", "", "request items", &Quest::LoadQuestRequestItems },
- // Load `quest_offer_reward`
- // 0 1 2 3 4 5 6 7 8 9
- result = WorldDatabase.Query("SELECT ID, Emote1, Emote2, Emote3, Emote4, EmoteDelay1, EmoteDelay2, EmoteDelay3, EmoteDelay4, RewardText FROM quest_offer_reward");
+ // 0 1 2 3 4 5 6 7 8 9
+ { "ID, Emote1, Emote2, Emote3, Emote4, EmoteDelay1, EmoteDelay2, EmoteDelay3, EmoteDelay4, RewardText", "quest_offer_reward", "", "reward emotes", &Quest::LoadQuestOfferReward },
- if (!result)
- {
- TC_LOG_ERROR("server.loading", ">> Loaded 0 quest reward emotes. DB table `quest_offer_reward` is empty.");
- }
- else
- {
- do
- {
- Field* fields = result->Fetch();
- uint32 questId = fields[0].GetUInt32();
+ // 0 1 2 3 4 5 6 7 8
+ { "ID, MaxLevel, AllowableClasses, SourceSpellID, PrevQuestID, NextQuestID, ExclusiveGroup, RewardMailTemplateID, RewardMailDelay,"
+ // 9 10 11 12 13 14 15 16
+ " RequiredSkillID, RequiredSkillPoints, RequiredMinRepFaction, RequiredMaxRepFaction, RequiredMinRepValue, RequiredMaxRepValue, ProvidedItemCount, SpecialFlags,"
+ // 17
+ " ScriptName", "quest_template_addon", "", "template addons", &Quest::LoadQuestTemplateAddon },
- auto itr = _questTemplates.find(questId);
- if (itr != _questTemplates.end())
- itr->second->LoadQuestOfferReward(fields);
- else
- TC_LOG_ERROR("server.loading", "Table `quest_offer_reward` has data for quest %u but such quest does not exist", questId);
- } while (result->NextRow());
- }
+ // 0 1
+ { "QuestId, RewardMailSenderEntry", "quest_mail_sender", "", "mail sender entries", &Quest::LoadQuestMailSender },
- // Load `quest_template_addon`
- // 0 1 2 3 4 5 6 7 8
- result = WorldDatabase.Query("SELECT ID, MaxLevel, AllowableClasses, SourceSpellID, PrevQuestID, NextQuestID, ExclusiveGroup, RewardMailTemplateID, RewardMailDelay, "
- //9 10 11 12 13 14 15 16
- "RequiredSkillID, RequiredSkillPoints, RequiredMinRepFaction, RequiredMaxRepFaction, RequiredMinRepValue, RequiredMaxRepValue, ProvidedItemCount, RewardMailSenderEntry, "
- //17 18
- "SpecialFlags, ScriptName FROM quest_template_addon LEFT JOIN quest_mail_sender ON Id=QuestId");
+ // QuestID needs to be fields[0]
+ // 0 1 2 3 4 5 6 7 8 9
+ { "QuestID, ID, Type, StorageIndex, ObjectID, Amount, Flags, Flags2, ProgressBarWeight, Description", "quest_objectives", "ORDER BY `Order` ASC, StorageIndex ASC", "quest objectives", &Quest::LoadQuestObjective }
+ };
- if (!result)
- {
- TC_LOG_ERROR("server.loading", ">> Loaded 0 quest template addons. DB table `quest_template_addon` is empty.");
- }
- else
+ for (QuestLoaderHelper const& loader : QuestLoaderHelpers)
{
- do
- {
- Field* fields = result->Fetch();
- uint32 questId = fields[0].GetUInt32();
-
- auto itr = _questTemplates.find(questId);
- if (itr != _questTemplates.end())
- itr->second->LoadQuestTemplateAddon(fields);
- else
- TC_LOG_ERROR("server.loading", "Table `quest_template_addon` has data for quest %u but such quest does not exist", questId);
- } while (result->NextRow());
- }
-
- // Load `quest_objectives`
- // 0 1 2 3 4 5 6 7 8 9
- result = WorldDatabase.Query("SELECT ID, QuestID, Type, StorageIndex, ObjectID, Amount, Flags, Flags2, ProgressBarWeight, Description FROM quest_objectives ORDER BY `Order` ASC, StorageIndex ASC");
+ QueryResult result = WorldDatabase.PQuery("SELECT %s FROM %s", loader.QueryFields, loader.TableName, loader.QueryExtra);
- if (!result)
- {
- TC_LOG_ERROR("server.loading", ">> Loaded 0 quest objectives. DB table `quest_objectives` is empty.");
- }
- else
- {
- do
+ if (!result)
+ TC_LOG_ERROR("server.loading", ">> Loaded 0 quest %s. DB table `%s` is empty.", loader.TableDesc, loader.TableName);
+ else
{
- Field* fields = result->Fetch();
- uint32 questId = fields[1].GetUInt32();
+ do
+ {
+ Field* fields = result->Fetch();
+ uint32 questId = fields[0].GetUInt32();
- auto itr = _questTemplates.find(questId);
- if (itr != _questTemplates.end())
- itr->second->LoadQuestObjective(fields);
- else
- TC_LOG_ERROR("server.loading", "Table `quest_objectives` has objective for quest %u but such quest does not exist", questId);
- } while (result->NextRow());
+ auto itr = _questTemplates.find(questId);
+ if (itr != _questTemplates.end())
+ (itr->second->*loader.LoaderFunction)(fields);
+ else
+ TC_LOG_ERROR("server.loading", "Table `%s` has data for quest %u but such quest does not exist", loader.TableName, questId);
+ } while (result->NextRow());
+ }
}
// Load `quest_visual_effect` join table with quest_objectives because visual effects are based on objective ID (core stores objectives by their index in quest)
@@ -4103,223 +4039,223 @@ void ObjectMgr::LoadQuests()
if (qinfo->GetQuestType() >= MAX_QUEST_TYPES)
TC_LOG_ERROR("sql.sql", "Quest %u has `Method` = %u, expected values are 0, 1 or 2.", qinfo->GetQuestId(), qinfo->GetQuestType());
- if (qinfo->SpecialFlags & ~QUEST_SPECIAL_FLAGS_DB_ALLOWED)
+ if (qinfo->_specialFlags & ~QUEST_SPECIAL_FLAGS_DB_ALLOWED)
{
TC_LOG_ERROR("sql.sql", "Quest %u has `SpecialFlags` = %u > max allowed value. Correct `SpecialFlags` to value <= %u",
- qinfo->GetQuestId(), qinfo->SpecialFlags, QUEST_SPECIAL_FLAGS_DB_ALLOWED);
- qinfo->SpecialFlags &= QUEST_SPECIAL_FLAGS_DB_ALLOWED;
+ qinfo->GetQuestId(), qinfo->_specialFlags, QUEST_SPECIAL_FLAGS_DB_ALLOWED);
+ qinfo->_specialFlags &= QUEST_SPECIAL_FLAGS_DB_ALLOWED;
}
- if (qinfo->Flags & QUEST_FLAGS_DAILY && qinfo->Flags & QUEST_FLAGS_WEEKLY)
+ if (qinfo->_flags & QUEST_FLAGS_DAILY && qinfo->_flags & QUEST_FLAGS_WEEKLY)
{
TC_LOG_ERROR("sql.sql", "Weekly Quest %u is marked as daily quest in `Flags`, removed daily flag.", qinfo->GetQuestId());
- qinfo->Flags &= ~QUEST_FLAGS_DAILY;
+ qinfo->_flags &= ~QUEST_FLAGS_DAILY;
}
- if (qinfo->Flags & QUEST_FLAGS_DAILY)
+ if (qinfo->_flags & QUEST_FLAGS_DAILY)
{
- if (!(qinfo->SpecialFlags & QUEST_SPECIAL_FLAGS_REPEATABLE))
+ if (!(qinfo->_specialFlags & QUEST_SPECIAL_FLAGS_REPEATABLE))
{
TC_LOG_DEBUG("sql.sql", "Daily Quest %u not marked as repeatable in `SpecialFlags`, added.", qinfo->GetQuestId());
- qinfo->SpecialFlags |= QUEST_SPECIAL_FLAGS_REPEATABLE;
+ qinfo->_specialFlags |= QUEST_SPECIAL_FLAGS_REPEATABLE;
}
}
- if (qinfo->Flags & QUEST_FLAGS_WEEKLY)
+ if (qinfo->_flags & QUEST_FLAGS_WEEKLY)
{
- if (!(qinfo->SpecialFlags & QUEST_SPECIAL_FLAGS_REPEATABLE))
+ if (!(qinfo->_specialFlags & QUEST_SPECIAL_FLAGS_REPEATABLE))
{
TC_LOG_DEBUG("sql.sql", "Weekly Quest %u not marked as repeatable in `SpecialFlags`, added.", qinfo->GetQuestId());
- qinfo->SpecialFlags |= QUEST_SPECIAL_FLAGS_REPEATABLE;
+ qinfo->_specialFlags |= QUEST_SPECIAL_FLAGS_REPEATABLE;
}
}
- if (qinfo->SpecialFlags & QUEST_SPECIAL_FLAGS_MONTHLY)
+ if (qinfo->_specialFlags & QUEST_SPECIAL_FLAGS_MONTHLY)
{
- if (!(qinfo->SpecialFlags & QUEST_SPECIAL_FLAGS_REPEATABLE))
+ if (!(qinfo->_specialFlags & QUEST_SPECIAL_FLAGS_REPEATABLE))
{
TC_LOG_DEBUG("sql.sql", "Monthly quest %u not marked as repeatable in `SpecialFlags`, added.", qinfo->GetQuestId());
- qinfo->SpecialFlags |= QUEST_SPECIAL_FLAGS_REPEATABLE;
+ qinfo->_specialFlags |= QUEST_SPECIAL_FLAGS_REPEATABLE;
}
}
- if (qinfo->Flags & QUEST_FLAGS_TRACKING)
+ if (qinfo->_flags & QUEST_FLAGS_TRACKING)
{
// at auto-reward can be rewarded only RewardChoiceItemId[0]
- for (int j = 1; j < QUEST_REWARD_CHOICES_COUNT; ++j )
+ for (uint32 j = 1; j < QUEST_REWARD_CHOICES_COUNT; ++j )
{
if (uint32 id = qinfo->RewardChoiceItemId[j])
{
TC_LOG_ERROR("sql.sql", "Quest %u has `RewardChoiceItemId%d` = %u but item from `RewardChoiceItemId%d` can't be rewarded with quest flag QUEST_FLAGS_TRACKING.",
- qinfo->GetQuestId(), j+1, id, j+1);
+ qinfo->GetQuestId(), j + 1, id, j + 1);
// no changes, quest ignore this data
}
}
}
- if (qinfo->MinLevel == -1 || qinfo->MinLevel > DEFAULT_MAX_LEVEL)
+ if (qinfo->_minLevel == -1 || qinfo->_minLevel > DEFAULT_MAX_LEVEL)
{
- TC_LOG_ERROR("sql.sql", "Quest %u should be disabled because `MinLevel` = %i", qinfo->GetQuestId(), int32(qinfo->MinLevel));
+ TC_LOG_ERROR("sql.sql", "Quest %u should be disabled because `MinLevel` = %i", qinfo->GetQuestId(), int32(qinfo->_minLevel));
// no changes needed, sending -1 in SMSG_QUEST_QUERY_RESPONSE is valid
}
// client quest log visual (area case)
- if (qinfo->QuestSortID > 0)
+ if (qinfo->_questSortID > 0)
{
- if (!sAreaTableStore.LookupEntry(qinfo->QuestSortID))
+ if (!sAreaTableStore.LookupEntry(qinfo->_questSortID))
{
TC_LOG_ERROR("sql.sql", "Quest %u has `QuestSortID` = %u (zone case) but zone with this id does not exist.",
- qinfo->GetQuestId(), qinfo->QuestSortID);
+ qinfo->GetQuestId(), qinfo->_questSortID);
// no changes, quest not dependent from this value but can have problems at client
}
}
// client quest log visual (sort case)
- if (qinfo->QuestSortID < 0)
+ if (qinfo->_questSortID < 0)
{
- QuestSortEntry const* qSort = sQuestSortStore.LookupEntry(-int32(qinfo->QuestSortID));
+ QuestSortEntry const* qSort = sQuestSortStore.LookupEntry(-int32(qinfo->_questSortID));
if (!qSort)
{
TC_LOG_ERROR("sql.sql", "Quest %u has `QuestSortID` = %i (sort case) but quest sort with this id does not exist.",
- qinfo->GetQuestId(), qinfo->QuestSortID);
+ qinfo->GetQuestId(), qinfo->_questSortID);
// no changes, quest not dependent from this value but can have problems at client (note some may be 0, we must allow this so no check)
}
//check for proper RequiredSkillId value (skill case)
- if (uint32 skill_id = SkillByQuestSort(-int32(qinfo->QuestSortID)))
+ if (uint32 skill_id = SkillByQuestSort(-int32(qinfo->_questSortID)))
{
- if (qinfo->RequiredSkillId != skill_id)
+ if (qinfo->_requiredSkillId != skill_id)
{
TC_LOG_ERROR("sql.sql", "Quest %u has `QuestSortID` = %i but `RequiredSkillId` does not have a corresponding value (%d).",
- qinfo->GetQuestId(), qinfo->QuestSortID, skill_id);
+ qinfo->GetQuestId(), qinfo->_questSortID, skill_id);
//override, and force proper value here?
}
}
}
// AllowableClasses, can be 0/CLASSMASK_ALL_PLAYABLE to allow any class
- if (qinfo->AllowableClasses)
+ if (qinfo->_allowableClasses)
{
- if (!(qinfo->AllowableClasses & CLASSMASK_ALL_PLAYABLE))
+ if (!(qinfo->_allowableClasses & CLASSMASK_ALL_PLAYABLE))
{
- TC_LOG_ERROR("sql.sql", "Quest %u does not contain any playable classes in `AllowableClasses` (%u), value set to 0 (all classes).", qinfo->GetQuestId(), qinfo->AllowableClasses);
- qinfo->AllowableClasses = 0;
+ TC_LOG_ERROR("sql.sql", "Quest %u does not contain any playable classes in `AllowableClasses` (%u), value set to 0 (all classes).", qinfo->GetQuestId(), qinfo->_allowableClasses);
+ qinfo->_allowableClasses = 0;
}
}
// AllowableRaces, can be -1/RACEMASK_ALL_PLAYABLE to allow any race
- if (qinfo->AllowableRaces.RawValue != uint64(-1))
+ if (qinfo->_allowableRaces.RawValue != uint64(-1))
{
- if (qinfo->AllowableRaces && !(qinfo->AllowableRaces.RawValue & RACEMASK_ALL_PLAYABLE))
+ if (qinfo->_allowableRaces && !(qinfo->_allowableRaces.RawValue & RACEMASK_ALL_PLAYABLE))
{
- TC_LOG_ERROR("sql.sql", "Quest %u does not contain any playable races in `AllowableRaces` (" UI64FMTD "), value set to -1 (all races).", qinfo->GetQuestId(), qinfo->AllowableRaces.RawValue);
- qinfo->AllowableRaces.RawValue = uint64(-1);
+ TC_LOG_ERROR("sql.sql", "Quest %u does not contain any playable races in `AllowableRaces` (" UI64FMTD "), value set to -1 (all races).", qinfo->GetQuestId(), qinfo->_allowableRaces.RawValue);
+ qinfo->_allowableRaces.RawValue = uint64(-1);
}
}
// RequiredSkillId, can be 0
- if (qinfo->RequiredSkillId)
+ if (qinfo->_requiredSkillId)
{
- if (!sSkillLineStore.LookupEntry(qinfo->RequiredSkillId))
+ if (!sSkillLineStore.LookupEntry(qinfo->_requiredSkillId))
{
TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredSkillId` = %u but this skill does not exist",
- qinfo->GetQuestId(), qinfo->RequiredSkillId);
+ qinfo->GetQuestId(), qinfo->_requiredSkillId);
}
}
- if (qinfo->RequiredSkillPoints)
+ if (qinfo->_requiredSkillPoints)
{
- if (qinfo->RequiredSkillPoints > sWorld->GetConfigMaxSkillValue())
+ if (qinfo->_requiredSkillPoints > sWorld->GetConfigMaxSkillValue())
{
TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredSkillPoints` = %u but max possible skill is %u, quest can't be done.",
- qinfo->GetQuestId(), qinfo->RequiredSkillPoints, sWorld->GetConfigMaxSkillValue());
+ qinfo->GetQuestId(), qinfo->_requiredSkillPoints, sWorld->GetConfigMaxSkillValue());
// no changes, quest can't be done for this requirement
}
}
// else Skill quests can have 0 skill level, this is ok
- if (qinfo->RequiredMinRepFaction && !sFactionStore.LookupEntry(qinfo->RequiredMinRepFaction))
+ if (qinfo->_requiredMinRepFaction && !sFactionStore.LookupEntry(qinfo->_requiredMinRepFaction))
{
TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredMinRepFaction` = %u but faction template %u does not exist, quest can't be done.",
- qinfo->GetQuestId(), qinfo->RequiredMinRepFaction, qinfo->RequiredMinRepFaction);
+ qinfo->GetQuestId(), qinfo->_requiredMinRepFaction, qinfo->_requiredMinRepFaction);
// no changes, quest can't be done for this requirement
}
- if (qinfo->RequiredMaxRepFaction && !sFactionStore.LookupEntry(qinfo->RequiredMaxRepFaction))
+ if (qinfo->_requiredMaxRepFaction && !sFactionStore.LookupEntry(qinfo->_requiredMaxRepFaction))
{
TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredMaxRepFaction` = %u but faction template %u does not exist, quest can't be done.",
- qinfo->GetQuestId(), qinfo->RequiredMaxRepFaction, qinfo->RequiredMaxRepFaction);
+ qinfo->GetQuestId(), qinfo->_requiredMaxRepFaction, qinfo->_requiredMaxRepFaction);
// no changes, quest can't be done for this requirement
}
- if (qinfo->RequiredMinRepValue && qinfo->RequiredMinRepValue > ReputationMgr::Reputation_Cap)
+ if (qinfo->_requiredMinRepValue && qinfo->_requiredMinRepValue > ReputationMgr::Reputation_Cap)
{
TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredMinRepValue` = %d but max reputation is %u, quest can't be done.",
- qinfo->GetQuestId(), qinfo->RequiredMinRepValue, ReputationMgr::Reputation_Cap);
+ qinfo->GetQuestId(), qinfo->_requiredMinRepValue, ReputationMgr::Reputation_Cap);
// no changes, quest can't be done for this requirement
}
- if (qinfo->RequiredMinRepValue && qinfo->RequiredMaxRepValue && qinfo->RequiredMaxRepValue <= qinfo->RequiredMinRepValue)
+ if (qinfo->_requiredMinRepValue && qinfo->_requiredMaxRepValue && qinfo->_requiredMaxRepValue <= qinfo->_requiredMinRepValue)
{
TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredMaxRepValue` = %d and `RequiredMinRepValue` = %d, quest can't be done.",
- qinfo->GetQuestId(), qinfo->RequiredMaxRepValue, qinfo->RequiredMinRepValue);
+ qinfo->GetQuestId(), qinfo->_requiredMaxRepValue, qinfo->_requiredMinRepValue);
// no changes, quest can't be done for this requirement
}
- if (!qinfo->RequiredMinRepFaction && qinfo->RequiredMinRepValue != 0)
+ if (!qinfo->_requiredMinRepFaction && qinfo->_requiredMinRepValue != 0)
{
TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredMinRepValue` = %d but `RequiredMinRepFaction` is 0, value has no effect",
- qinfo->GetQuestId(), qinfo->RequiredMinRepValue);
+ qinfo->GetQuestId(), qinfo->_requiredMinRepValue);
// warning
}
- if (!qinfo->RequiredMaxRepFaction && qinfo->RequiredMaxRepValue != 0)
+ if (!qinfo->_requiredMaxRepFaction && qinfo->_requiredMaxRepValue != 0)
{
TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredMaxRepValue` = %d but `RequiredMaxRepFaction` is 0, value has no effect",
- qinfo->GetQuestId(), qinfo->RequiredMaxRepValue);
+ qinfo->GetQuestId(), qinfo->_requiredMaxRepValue);
// warning
}
- if (qinfo->RewardTitleId && !sCharTitlesStore.LookupEntry(qinfo->RewardTitleId))
+ if (qinfo->_rewardTitleId && !sCharTitlesStore.LookupEntry(qinfo->_rewardTitleId))
{
TC_LOG_ERROR("sql.sql", "Quest %u has `RewardTitleId` = %u but CharTitle Id %u does not exist, quest can't be rewarded with title.",
- qinfo->GetQuestId(), qinfo->RewardTitleId, qinfo->RewardTitleId);
- qinfo->RewardTitleId = 0;
+ qinfo->GetQuestId(), qinfo->_rewardTitleId, qinfo->_rewardTitleId);
+ qinfo->_rewardTitleId = 0;
// quest can't reward this title
}
- if (qinfo->SourceItemId)
+ if (qinfo->_sourceItemId)
{
- if (!sObjectMgr->GetItemTemplate(qinfo->SourceItemId))
+ if (!sObjectMgr->GetItemTemplate(qinfo->_sourceItemId))
{
TC_LOG_ERROR("sql.sql", "Quest %u has `SourceItemId` = %u but item with entry %u does not exist, quest can't be done.",
- qinfo->GetQuestId(), qinfo->SourceItemId, qinfo->SourceItemId);
- qinfo->SourceItemId = 0; // quest can't be done for this requirement
+ qinfo->GetQuestId(), qinfo->_sourceItemId, qinfo->_sourceItemId);
+ qinfo->_sourceItemId = 0; // quest can't be done for this requirement
}
- else if (qinfo->SourceItemIdCount == 0)
+ else if (qinfo->_sourceItemIdCount == 0)
{
TC_LOG_ERROR("sql.sql", "Quest %u has `StartItem` = %u but `ProvidedItemCount` = 0, set to 1 but need fix in DB.",
- qinfo->GetQuestId(), qinfo->SourceItemId);
- qinfo->SourceItemIdCount = 1; // update to 1 for allow quest work for backward compatibility with DB
+ qinfo->GetQuestId(), qinfo->_sourceItemId);
+ qinfo->_sourceItemIdCount = 1; // update to 1 for allow quest work for backward compatibility with DB
}
}
- else if (qinfo->SourceItemIdCount>0)
+ else if (qinfo->_sourceItemIdCount > 0)
{
TC_LOG_ERROR("sql.sql", "Quest %u has `SourceItemId` = 0 but `SourceItemIdCount` = %u, useless value.",
- qinfo->GetQuestId(), qinfo->SourceItemIdCount);
- qinfo->SourceItemIdCount=0; // no quest work changes in fact
+ qinfo->GetQuestId(), qinfo->_sourceItemIdCount);
+ qinfo->_sourceItemIdCount = 0; // no quest work changes in fact
}
- if (qinfo->SourceSpellID)
+ if (qinfo->_sourceSpellID)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(qinfo->SourceSpellID);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(qinfo->_sourceSpellID);
if (!spellInfo)
{
TC_LOG_ERROR("sql.sql", "Quest %u has `SourceSpellid` = %u but spell %u doesn't exist, quest can't be done.",
- qinfo->GetQuestId(), qinfo->SourceSpellID, qinfo->SourceSpellID);
- qinfo->SourceSpellID = 0; // quest can't be done for this requirement
+ qinfo->GetQuestId(), qinfo->_sourceSpellID, qinfo->_sourceSpellID);
+ qinfo->_sourceSpellID = 0; // quest can't be done for this requirement
}
else if (!SpellMgr::IsSpellValid(spellInfo))
{
TC_LOG_ERROR("sql.sql", "Quest %u has `SourceSpellid` = %u but spell %u is broken, quest can't be done.",
- qinfo->GetQuestId(), qinfo->SourceSpellID, qinfo->SourceSpellID);
- qinfo->SourceSpellID = 0; // quest can't be done for this requirement
+ qinfo->GetQuestId(), qinfo->_sourceSpellID, qinfo->_sourceSpellID);
+ qinfo->_sourceSpellID = 0; // quest can't be done for this requirement
}
}
@@ -4501,7 +4437,7 @@ void ObjectMgr::LoadQuests()
{
if (qinfo->RewardFactionId[j])
{
- if (abs(qinfo->RewardFactionValue[j]) > 9)
+ if (std::abs(qinfo->RewardFactionValue[j]) > 9)
{
TC_LOG_ERROR("sql.sql", "Quest %u has RewardFactionValueId%d = %i. That is outside the range of valid values (-9 to 9).", qinfo->GetQuestId(), j+1, qinfo->RewardFactionValue[j]);
}
@@ -4542,59 +4478,59 @@ void ObjectMgr::LoadQuests()
}
}
- if (qinfo->RewardSpell > 0)
+ if (qinfo->_rewardSpell > 0)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(qinfo->RewardSpell);
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(qinfo->_rewardSpell);
if (!spellInfo)
{
TC_LOG_ERROR("sql.sql", "Quest %u has `RewardSpellCast` = %u but spell %u does not exist, quest will not have a spell reward.",
- qinfo->GetQuestId(), qinfo->RewardSpell, qinfo->RewardSpell);
- qinfo->RewardSpell = 0; // no spell will be cast on player
+ qinfo->GetQuestId(), qinfo->_rewardSpell, qinfo->_rewardSpell);
+ qinfo->_rewardSpell = 0; // no spell will be cast on player
}
else if (!SpellMgr::IsSpellValid(spellInfo))
{
TC_LOG_ERROR("sql.sql", "Quest %u has `RewardSpellCast` = %u but spell %u is broken, quest will not have a spell reward.",
- qinfo->GetQuestId(), qinfo->RewardSpell, qinfo->RewardSpell);
- qinfo->RewardSpell = 0; // no spell will be cast on player
+ qinfo->GetQuestId(), qinfo->_rewardSpell, qinfo->_rewardSpell);
+ qinfo->_rewardSpell = 0; // no spell will be cast on player
}
}
- if (qinfo->RewardMailTemplateId)
+ if (qinfo->_rewardMailTemplateId)
{
- if (!sMailTemplateStore.LookupEntry(qinfo->RewardMailTemplateId))
+ if (!sMailTemplateStore.LookupEntry(qinfo->_rewardMailTemplateId))
{
TC_LOG_ERROR("sql.sql", "Quest %u has `RewardMailTemplateId` = %u but mail template %u does not exist, quest will not have a mail reward.",
- qinfo->GetQuestId(), qinfo->RewardMailTemplateId, qinfo->RewardMailTemplateId);
- qinfo->RewardMailTemplateId = 0; // no mail will send to player
- qinfo->RewardMailDelay = 0; // no mail will send to player
- qinfo->RewardMailSenderEntry = 0;
+ qinfo->GetQuestId(), qinfo->_rewardMailTemplateId, qinfo->_rewardMailTemplateId);
+ qinfo->_rewardMailTemplateId = 0; // no mail will send to player
+ qinfo->_rewardMailDelay = 0; // no mail will send to player
+ qinfo->_rewardMailSenderEntry = 0;
}
- else if (usedMailTemplates.find(qinfo->RewardMailTemplateId) != usedMailTemplates.end())
+ else if (usedMailTemplates.find(qinfo->_rewardMailTemplateId) != usedMailTemplates.end())
{
- std::map<uint32, uint32>::const_iterator used_mt_itr = usedMailTemplates.find(qinfo->RewardMailTemplateId);
+ auto used_mt_itr = usedMailTemplates.find(qinfo->_rewardMailTemplateId);
TC_LOG_ERROR("sql.sql", "Quest %u has `RewardMailTemplateId` = %u but mail template %u already used for quest %u, quest will not have a mail reward.",
- qinfo->GetQuestId(), qinfo->RewardMailTemplateId, qinfo->RewardMailTemplateId, used_mt_itr->second);
- qinfo->RewardMailTemplateId = 0; // no mail will send to player
- qinfo->RewardMailDelay = 0; // no mail will send to player
- qinfo->RewardMailSenderEntry = 0;
+ qinfo->GetQuestId(), qinfo->_rewardMailTemplateId, qinfo->_rewardMailTemplateId, used_mt_itr->second);
+ qinfo->_rewardMailTemplateId = 0; // no mail will send to player
+ qinfo->_rewardMailDelay = 0; // no mail will send to player
+ qinfo->_rewardMailSenderEntry = 0;
}
else
- usedMailTemplates[qinfo->RewardMailTemplateId] = qinfo->GetQuestId();
+ usedMailTemplates.emplace(qinfo->_rewardMailTemplateId, qinfo->GetQuestId());
}
- if (qinfo->NextQuestInChain)
+ if (qinfo->_nextQuestInChain)
{
- QuestMap::iterator qNextItr = _questTemplates.find(qinfo->NextQuestInChain);
+ auto qNextItr = _questTemplates.find(qinfo->_nextQuestInChain);
if (qNextItr == _questTemplates.end())
{
TC_LOG_ERROR("sql.sql", "Quest %u has `NextQuestInChain` = %u but quest %u does not exist, quest chain will not work.",
- qinfo->GetQuestId(), qinfo->NextQuestInChain, qinfo->NextQuestInChain);
- qinfo->NextQuestInChain = 0;
+ qinfo->GetQuestId(), qinfo->_nextQuestInChain, qinfo->_nextQuestInChain);
+ qinfo->_nextQuestInChain = 0;
}
else
- qNextItr->second->prevChainQuests.push_back(qinfo->GetQuestId());
+ qNextItr->second->PrevChainQuests.push_back(qinfo->GetQuestId());
}
for (uint8 j = 0; j < QUEST_REWARD_CURRENCY_COUNT; ++j)
@@ -4623,79 +4559,74 @@ void ObjectMgr::LoadQuests()
}
}
- if (qinfo->SoundAccept)
+ if (qinfo->_soundAccept)
{
- if (!sSoundKitStore.LookupEntry(qinfo->SoundAccept))
+ if (!sSoundKitStore.LookupEntry(qinfo->_soundAccept))
{
TC_LOG_ERROR("sql.sql", "Quest %u has `SoundAccept` = %u but sound %u does not exist, set to 0.",
- qinfo->GetQuestId(), qinfo->SoundAccept, qinfo->SoundAccept);
- qinfo->SoundAccept = 0; // no sound will be played
+ qinfo->GetQuestId(), qinfo->_soundAccept, qinfo->_soundAccept);
+ qinfo->_soundAccept = 0; // no sound will be played
}
}
- if (qinfo->SoundTurnIn)
+ if (qinfo->_soundTurnIn)
{
- if (!sSoundKitStore.LookupEntry(qinfo->SoundTurnIn))
+ if (!sSoundKitStore.LookupEntry(qinfo->_soundTurnIn))
{
TC_LOG_ERROR("sql.sql", "Quest %u has `SoundTurnIn` = %u but sound %u does not exist, set to 0.",
- qinfo->GetQuestId(), qinfo->SoundTurnIn, qinfo->SoundTurnIn);
- qinfo->SoundTurnIn = 0; // no sound will be played
+ qinfo->GetQuestId(), qinfo->_soundTurnIn, qinfo->_soundTurnIn);
+ qinfo->_soundTurnIn = 0; // no sound will be played
}
}
- if (qinfo->RewardSkillId)
+ if (qinfo->_rewardSkillId)
{
- if (!sSkillLineStore.LookupEntry(qinfo->RewardSkillId))
+ if (!sSkillLineStore.LookupEntry(qinfo->_rewardSkillId))
{
TC_LOG_ERROR("sql.sql", "Quest %u has `RewardSkillId` = %u but this skill does not exist",
- qinfo->GetQuestId(), qinfo->RewardSkillId);
+ qinfo->GetQuestId(), qinfo->_rewardSkillId);
}
- if (!qinfo->RewardSkillPoints)
+ if (!qinfo->_rewardSkillPoints)
{
TC_LOG_ERROR("sql.sql", "Quest %u has `RewardSkillId` = %u but `RewardSkillPoints` is 0",
- qinfo->GetQuestId(), qinfo->RewardSkillId);
+ qinfo->GetQuestId(), qinfo->_rewardSkillId);
}
}
- if (qinfo->RewardSkillPoints)
+ if (qinfo->_rewardSkillPoints)
{
- if (qinfo->RewardSkillPoints > sWorld->GetConfigMaxSkillValue())
+ if (qinfo->_rewardSkillPoints > sWorld->GetConfigMaxSkillValue())
{
TC_LOG_ERROR("sql.sql", "Quest %u has `RewardSkillPoints` = %u but max possible skill is %u, quest can't be done.",
- qinfo->GetQuestId(), qinfo->RewardSkillPoints, sWorld->GetConfigMaxSkillValue());
+ qinfo->GetQuestId(), qinfo->_rewardSkillPoints, sWorld->GetConfigMaxSkillValue());
// no changes, quest can't be done for this requirement
}
- if (!qinfo->RewardSkillId)
+ if (!qinfo->_rewardSkillId)
{
TC_LOG_ERROR("sql.sql", "Quest %u has `RewardSkillPoints` = %u but `RewardSkillId` is 0",
- qinfo->GetQuestId(), qinfo->RewardSkillPoints);
+ qinfo->GetQuestId(), qinfo->_rewardSkillPoints);
}
}
// fill additional data stores
- if (qinfo->PrevQuestID)
+ if (qinfo->_prevQuestID)
{
if (_questTemplates.find(abs(qinfo->GetPrevQuestId())) == _questTemplates.end())
TC_LOG_ERROR("sql.sql", "Quest %d has PrevQuestId %i, but no such quest", qinfo->GetQuestId(), qinfo->GetPrevQuestId());
- else
- qinfo->prevQuests.push_back(qinfo->PrevQuestID);
}
- if (qinfo->NextQuestID)
+ if (qinfo->_nextQuestID)
{
- QuestMap::iterator qNextItr = _questTemplates.find(abs(qinfo->GetNextQuestId()));
+ auto qNextItr = _questTemplates.find(qinfo->GetNextQuestId());
if (qNextItr == _questTemplates.end())
- TC_LOG_ERROR("sql.sql", "Quest %d has NextQuestId %i, but no such quest", qinfo->GetQuestId(), qinfo->GetNextQuestId());
+ TC_LOG_ERROR("sql.sql", "Quest %d has NextQuestId %u, but no such quest", qinfo->GetQuestId(), qinfo->GetNextQuestId());
else
- {
- int32 signedQuestId = qinfo->NextQuestID < 0 ? -int32(qinfo->GetQuestId()) : int32(qinfo->GetQuestId());
- qNextItr->second->prevQuests.push_back(signedQuestId);
- }
+ qNextItr->second->DependentPreviousQuests.push_back(qinfo->GetQuestId());
}
- if (qinfo->ExclusiveGroup)
- mExclusiveQuestGroups.insert(std::pair<int32, uint32>(qinfo->ExclusiveGroup, qinfo->GetQuestId()));
- if (qinfo->LimitTime)
+ if (qinfo->_exclusiveGroup)
+ _exclusiveQuestGroups.insert(std::pair<int32, uint32>(qinfo->_exclusiveGroup, qinfo->GetQuestId()));
+ if (qinfo->_limitTime)
qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED);
}
@@ -9223,6 +9154,8 @@ void ObjectMgr::LoadScriptNames()
return;
}
+ _scriptNamesStore.reserve(result->GetRowCount() + 1);
+
do
{
_scriptNamesStore.push_back((*result)[0].GetString());
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index 7a2105cf346..6506eb3d80d 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -540,6 +540,9 @@ typedef std::multimap<uint32, uint32> QuestRelationsReverse; // quest -> unit/go
typedef std::pair<QuestRelations::const_iterator, QuestRelations::const_iterator> QuestRelationBounds;
typedef std::pair<QuestRelationsReverse::const_iterator, QuestRelationsReverse::const_iterator> QuestRelationReverseBounds;
+typedef std::multimap<int32, uint32> ExclusiveQuestGroups; // exclusiveGroupId -> quest
+typedef std::pair<ExclusiveQuestGroups::const_iterator, ExclusiveQuestGroups::const_iterator> ExclusiveQuestGroupsBounds;
+
struct PlayerCreateInfoItem
{
PlayerCreateInfoItem(uint32 id, uint32 amount) : item_id(id), item_amount(amount) { }
@@ -1206,6 +1209,11 @@ class TC_GAME_API ObjectMgr
return _creatureQuestInvolvedRelationsReverse.equal_range(questId);
}
+ ExclusiveQuestGroupsBounds GetExclusiveQuestGroupBounds(int32 exclusiveGroupId) const
+ {
+ return _exclusiveQuestGroups.equal_range(exclusiveGroupId);
+ }
+
bool LoadTrinityStrings();
void LoadEventScripts();
@@ -1344,11 +1352,6 @@ class TC_GAME_API ObjectMgr
uint64 GenerateCreatureSpawnId();
uint64 GenerateGameObjectSpawnId();
- typedef std::multimap<int32, uint32> ExclusiveQuestGroups;
- typedef std::pair<ExclusiveQuestGroups::const_iterator, ExclusiveQuestGroups::const_iterator> ExclusiveQuestGroupsBounds;
-
- ExclusiveQuestGroups mExclusiveQuestGroups;
-
MailLevelReward const* GetMailLevelReward(uint8 level, uint8 race)
{
MailLevelRewardContainer::const_iterator map_itr = _mailLevelRewardStore.find(level);
@@ -1677,6 +1680,8 @@ class TC_GAME_API ObjectMgr
QuestRelations _creatureQuestInvolvedRelations;
QuestRelationsReverse _creatureQuestInvolvedRelationsReverse;
+ ExclusiveQuestGroups _exclusiveQuestGroups;
+
//character reserved names
typedef std::set<std::wstring> ReservedNamesContainer;
ReservedNamesContainer _reservedNamesStore;
diff --git a/src/server/game/Grids/Cells/CellImpl.h b/src/server/game/Grids/Cells/CellImpl.h
index a06a84eaebc..3b343851bb2 100644
--- a/src/server/game/Grids/Cells/CellImpl.h
+++ b/src/server/game/Grids/Cells/CellImpl.h
@@ -64,7 +64,7 @@ inline void Cell::Visit(CellCoord const& standing_cell, TypeContainerVisitor<T,
{
//we should increase search radius by object's radius, otherwise
//we could have problems with huge creatures, which won't attack nearest players etc
- Visit(standing_cell, visitor, map, obj.GetPositionX(), obj.GetPositionY(), radius + obj.GetObjectSize());
+ Visit(standing_cell, visitor, map, obj.GetPositionX(), obj.GetPositionY(), radius + obj.GetCombatReach());
}
template<class T, class CONTAINER>
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h
index e786935b538..23f3cf2ddc0 100644
--- a/src/server/game/Grids/Notifiers/GridNotifiers.h
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.h
@@ -944,14 +944,27 @@ namespace Trinity
class AnyFriendlyUnitInObjectRangeCheck
{
public:
- AnyFriendlyUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, bool playerOnly = false) : i_obj(obj), i_funit(funit), i_range(range), i_playerOnly(playerOnly) { }
+ AnyFriendlyUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, bool playerOnly = false, bool incOwnRadius = true, bool incTargetRadius = true)
+ : i_obj(obj), i_funit(funit), i_range(range), i_playerOnly(playerOnly), i_incOwnRadius(incOwnRadius), i_incTargetRadius(incTargetRadius) { }
bool operator()(Unit* u) const
{
- if (u->IsAlive() && i_obj->IsWithinDistInMap(u, i_range) && i_funit->IsFriendlyTo(u) && (!i_playerOnly || u->GetTypeId() == TYPEID_PLAYER))
- return true;
- else
+ if (!u->IsAlive())
+ return false;
+
+ float searchRadius = i_range;
+ if (i_incOwnRadius)
+ searchRadius += i_obj->GetCombatReach();
+ if (i_incTargetRadius)
+ searchRadius += u->GetCombatReach();
+
+ if (!u->IsInMap(i_obj) || !u->IsInPhase(i_obj) || !u->IsWithinDoubleVerticalCylinder(i_obj, searchRadius, searchRadius))
return false;
+
+ if (!i_funit->IsFriendlyTo(u))
+ return false;
+
+ return !i_playerOnly || u->GetTypeId() == TYPEID_PLAYER;
}
private:
@@ -959,12 +972,15 @@ namespace Trinity
Unit const* i_funit;
float i_range;
bool i_playerOnly;
+ bool i_incOwnRadius;
+ bool i_incTargetRadius;
};
class AnyGroupedUnitInObjectRangeCheck
{
public:
- AnyGroupedUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, bool raid, bool playerOnly = false) : _source(obj), _refUnit(funit), _range(range), _raid(raid), _playerOnly(playerOnly) { }
+ AnyGroupedUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, bool raid, bool playerOnly = false, bool incOwnRadius = true, bool incTargetRadius = true)
+ : _source(obj), _refUnit(funit), _range(range), _raid(raid), _playerOnly(playerOnly), i_incOwnRadius(incOwnRadius), i_incTargetRadius(incTargetRadius) { }
bool operator()(Unit* u) const
{
@@ -979,7 +995,19 @@ namespace Trinity
else if (!_refUnit->IsInPartyWith(u))
return false;
- return !_refUnit->IsHostileTo(u) && u->IsAlive() && _source->IsWithinDistInMap(u, _range);
+ if (_refUnit->IsHostileTo(u))
+ return false;
+
+ if (!u->IsAlive())
+ return false;
+
+ float searchRadius = _range;
+ if (i_incOwnRadius)
+ searchRadius += _source->GetCombatReach();
+ if (i_incTargetRadius)
+ searchRadius += u->GetCombatReach();
+
+ return u->IsInMap(_source) && u->IsInPhase(_source) && u->IsWithinDoubleVerticalCylinder(_source, searchRadius, searchRadius);
}
private:
@@ -988,6 +1016,8 @@ namespace Trinity
float _range;
bool _raid;
bool _playerOnly;
+ bool i_incOwnRadius;
+ bool i_incTargetRadius;
};
class AnyUnitInObjectRangeCheck
@@ -1039,8 +1069,8 @@ namespace Trinity
class AnyAoETargetUnitInObjectRangeCheck
{
public:
- AnyAoETargetUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, SpellInfo const* spellInfo = nullptr)
- : i_obj(obj), i_funit(funit), _spellInfo(spellInfo), i_range(range)
+ AnyAoETargetUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, SpellInfo const* spellInfo = nullptr, bool incOwnRadius = true, bool incTargetRadius = true)
+ : i_obj(obj), i_funit(funit), _spellInfo(spellInfo), i_range(range), i_incOwnRadius(incOwnRadius), i_incTargetRadius(incTargetRadius)
{
if (!_spellInfo)
if (DynamicObject const* dynObj = i_obj->ToDynObject())
@@ -1056,7 +1086,16 @@ namespace Trinity
if (_spellInfo && _spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS) && u->GetTypeId() != TYPEID_PLAYER)
return false;
- return i_funit->_IsValidAttackTarget(u, _spellInfo, i_obj->GetTypeId() == TYPEID_DYNAMICOBJECT ? i_obj : nullptr) && i_obj->IsWithinDistInMap(u, i_range);
+ if (!i_funit->_IsValidAttackTarget(u, _spellInfo, i_obj->GetTypeId() == TYPEID_DYNAMICOBJECT ? i_obj : nullptr))
+ return false;
+
+ float searchRadius = i_range;
+ if (i_incOwnRadius)
+ searchRadius += i_obj->GetCombatReach();
+ if (i_incTargetRadius)
+ searchRadius += u->GetCombatReach();
+
+ return u->IsInMap(i_obj) && u->IsInPhase(i_obj) && u->IsWithinDoubleVerticalCylinder(i_obj, searchRadius, searchRadius);
}
private:
@@ -1064,6 +1103,8 @@ namespace Trinity
Unit const* i_funit;
SpellInfo const* _spellInfo;
float i_range;
+ bool i_incOwnRadius;
+ bool i_incTargetRadius;
};
// do attack at call of help to friendly crearture
diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp
index bf2f9dc3cd5..1ae93079145 100644
--- a/src/server/game/Handlers/SpellHandler.cpp
+++ b/src/server/game/Handlers/SpellHandler.cpp
@@ -228,6 +228,7 @@ void WorldSession::HandleOpenWrappedItemCallback(uint16 pos, ObjectGuid itemGuid
item->SetGiftCreator(ObjectGuid::Empty);
item->SetEntry(entry);
item->SetItemFlags(ItemFieldFlags(flags));
+ item->SetMaxDurability(item->GetTemplate()->MaxDurability);
item->SetState(ITEM_CHANGED, GetPlayer());
GetPlayer()->SaveInventoryAndGoldToDB(trans);
diff --git a/src/server/game/Instances/InstanceScript.cpp b/src/server/game/Instances/InstanceScript.cpp
index 90582235948..4f124dd9567 100644
--- a/src/server/game/Instances/InstanceScript.cpp
+++ b/src/server/game/Instances/InstanceScript.cpp
@@ -145,7 +145,7 @@ void InstanceScript::LoadBossBoundaries(const BossBoundaryData& data)
{
for (BossBoundaryEntry const& entry : data)
if (entry.BossId < bosses.size())
- bosses[entry.BossId].boundary.insert(entry.Boundary);
+ bosses[entry.BossId].boundary.push_back(entry.Boundary);
}
void InstanceScript::LoadMinionData(const MinionData* data)
diff --git a/src/server/game/Instances/InstanceScript.h b/src/server/game/Instances/InstanceScript.h
index 0fc37d470ec..a87779f7f22 100644
--- a/src/server/game/Instances/InstanceScript.h
+++ b/src/server/game/Instances/InstanceScript.h
@@ -119,7 +119,7 @@ struct ObjectData
uint32 type;
};
-typedef std::set<AreaBoundary const*> CreatureBoundary;
+typedef std::vector<AreaBoundary const*> CreatureBoundary;
struct BossInfo
{
diff --git a/src/server/game/Maps/AreaBoundary.cpp b/src/server/game/Maps/AreaBoundary.cpp
index f7ae5b4c9b6..407b5c27e53 100644
--- a/src/server/game/Maps/AreaBoundary.cpp
+++ b/src/server/game/Maps/AreaBoundary.cpp
@@ -21,7 +21,7 @@
// ---== RECTANGLE ==---
RectangleBoundary::RectangleBoundary(float southX, float northX, float eastY, float westY, bool isInverted) :
- AreaBoundary(BoundaryType::BOUNDARY_RECTANGLE, isInverted), _minX(southX), _maxX(northX), _minY(eastY), _maxY(westY) { }
+ AreaBoundary(isInverted), _minX(southX), _maxX(northX), _minY(eastY), _maxY(westY) { }
bool RectangleBoundary::IsWithinBoundaryArea(Position const* pos) const
{
if (!pos)
@@ -38,13 +38,9 @@ bool RectangleBoundary::IsWithinBoundaryArea(Position const* pos) const
// ---== CIRCLE ==---
CircleBoundary::CircleBoundary(Position const& center, double radius, bool isInverted) :
- CircleBoundary(DoublePosition(center), radius, isInverted) { }
-CircleBoundary::CircleBoundary(DoublePosition const& center, double radius, bool isInverted) :
- AreaBoundary(BoundaryType::BOUNDARY_CIRCLE, isInverted), _center(center), _radiusSq(radius*radius) { }
+ AreaBoundary(isInverted), _center(center), _radiusSq(radius*radius) { }
CircleBoundary::CircleBoundary(Position const& center, Position const& pointOnCircle, bool isInverted) :
- CircleBoundary(DoublePosition(center), DoublePosition(pointOnCircle), isInverted) { }
-CircleBoundary::CircleBoundary(DoublePosition const& center, DoublePosition const& pointOnCircle, bool isInverted) :
- AreaBoundary(BoundaryType::BOUNDARY_CIRCLE, isInverted), _center(center), _radiusSq(center.GetDoubleExactDist2dSq(pointOnCircle)) { }
+ AreaBoundary(isInverted), _center(center), _radiusSq(_center.GetDoubleExactDist2dSq(pointOnCircle)) { }
bool CircleBoundary::IsWithinBoundaryArea(Position const* pos) const
{
if (!pos)
@@ -58,9 +54,7 @@ bool CircleBoundary::IsWithinBoundaryArea(Position const* pos) const
// ---== ELLIPSE ==---
EllipseBoundary::EllipseBoundary(Position const& center, double radiusX, double radiusY, bool isInverted) :
- EllipseBoundary(DoublePosition(center), radiusX, radiusY, isInverted) { }
-EllipseBoundary::EllipseBoundary(DoublePosition const& center, double radiusX, double radiusY, bool isInverted) :
- AreaBoundary(BoundaryType::BOUNDARY_ELLIPSE, isInverted), _center(center), _radiusYSq(radiusY*radiusY), _scaleXSq(_radiusYSq / (radiusX*radiusX)) { }
+ AreaBoundary(isInverted), _center(center), _radiusYSq(radiusY*radiusY), _scaleXSq(_radiusYSq / (radiusX*radiusX)) { }
bool EllipseBoundary::IsWithinBoundaryArea(Position const* pos) const
{
if (!pos)
@@ -73,9 +67,7 @@ bool EllipseBoundary::IsWithinBoundaryArea(Position const* pos) const
// ---== TRIANGLE ==---
TriangleBoundary::TriangleBoundary(Position const& pointA, Position const& pointB, Position const& pointC, bool isInverted) :
- TriangleBoundary(DoublePosition(pointA), DoublePosition(pointB), DoublePosition(pointC), isInverted) { }
-TriangleBoundary::TriangleBoundary(DoublePosition const& pointA, DoublePosition const& pointB, DoublePosition const& pointC, bool isInverted) :
- AreaBoundary(BoundaryType::BOUNDARY_TRIANGLE, isInverted), _a(pointA), _b(pointB), _c(pointC), _abx(_b.GetDoublePositionX()-_a.GetDoublePositionX()), _bcx(_c.GetDoublePositionX()-_b.GetDoublePositionX()), _cax(_a.GetDoublePositionX() - _c.GetDoublePositionX()), _aby(_b.GetDoublePositionY()-_a.GetDoublePositionY()), _bcy(_c.GetDoublePositionY()-_b.GetDoublePositionY()), _cay(_a.GetDoublePositionY() - _c.GetDoublePositionY()) { }
+ AreaBoundary(isInverted), _a(pointA), _b(pointB), _c(pointC), _abx(_b.GetDoublePositionX()-_a.GetDoublePositionX()), _bcx(_c.GetDoublePositionX()-_b.GetDoublePositionX()), _cax(_a.GetDoublePositionX() - _c.GetDoublePositionX()), _aby(_b.GetDoublePositionY()-_a.GetDoublePositionY()), _bcy(_c.GetDoublePositionY()-_b.GetDoublePositionY()), _cay(_a.GetDoublePositionY() - _c.GetDoublePositionY()) { }
bool TriangleBoundary::IsWithinBoundaryArea(Position const* pos) const
{
if (!pos)
@@ -93,9 +85,7 @@ bool TriangleBoundary::IsWithinBoundaryArea(Position const* pos) const
// ---== PARALLELOGRAM ==---
ParallelogramBoundary::ParallelogramBoundary(Position const& cornerA, Position const& cornerB, Position const& cornerD, bool isInverted) :
- ParallelogramBoundary(DoublePosition(cornerA), DoublePosition(cornerB), DoublePosition(cornerD), isInverted) { }
-ParallelogramBoundary::ParallelogramBoundary(DoublePosition const& cornerA, DoublePosition const& cornerB, DoublePosition const& cornerD, bool isInverted) :
- AreaBoundary(BoundaryType::BOUNDARY_PARALLELOGRAM, isInverted), _a(cornerA), _b(cornerB), _d(cornerD), _c(DoublePosition(_d.GetDoublePositionX() + (_b.GetDoublePositionX() - _a.GetDoublePositionX()), _d.GetDoublePositionY() + (_b.GetDoublePositionY() - _a.GetDoublePositionY()))), _abx(_b.GetDoublePositionX() - _a.GetDoublePositionX()), _dax(_a.GetDoublePositionX() - _d.GetDoublePositionX()), _aby(_b.GetDoublePositionY() - _a.GetDoublePositionY()), _day(_a.GetDoublePositionY() - _d.GetDoublePositionY()) { }
+ AreaBoundary(isInverted), _a(cornerA), _b(cornerB), _d(cornerD), _c(DoublePosition(_d.GetDoublePositionX() + (_b.GetDoublePositionX() - _a.GetDoublePositionX()), _d.GetDoublePositionY() + (_b.GetDoublePositionY() - _a.GetDoublePositionY()))), _abx(_b.GetDoublePositionX() - _a.GetDoublePositionX()), _dax(_a.GetDoublePositionX() - _d.GetDoublePositionX()), _aby(_b.GetDoublePositionY() - _a.GetDoublePositionY()), _day(_a.GetDoublePositionY() - _d.GetDoublePositionY()) { }
bool ParallelogramBoundary::IsWithinBoundaryArea(Position const* pos) const
{
if (!pos)
@@ -114,7 +104,7 @@ bool ParallelogramBoundary::IsWithinBoundaryArea(Position const* pos) const
// ---== Z RANGE ==---
ZRangeBoundary::ZRangeBoundary(float minZ, float maxZ, bool isInverted) :
- AreaBoundary(BoundaryType::BOUNDARY_Z_RANGE, isInverted), _minZ(minZ), _maxZ(maxZ) { }
+ AreaBoundary(isInverted), _minZ(minZ), _maxZ(maxZ) { }
bool ZRangeBoundary::IsWithinBoundaryArea(Position const* pos) const
{
if (!pos)
diff --git a/src/server/game/Maps/AreaBoundary.h b/src/server/game/Maps/AreaBoundary.h
index 069701775eb..6aa7e4185cc 100644
--- a/src/server/game/Maps/AreaBoundary.h
+++ b/src/server/game/Maps/AreaBoundary.h
@@ -23,48 +23,52 @@
class TC_GAME_API AreaBoundary
{
public:
- enum BoundaryType
- {
- BOUNDARY_RECTANGLE, // Rectangle aligned with the coordinate axis
- BOUNDARY_CIRCLE,
- BOUNDARY_ELLIPSE,
- BOUNDARY_TRIANGLE,
- BOUNDARY_PARALLELOGRAM,
- BOUNDARY_Z_RANGE,
- };
- virtual ~AreaBoundary() { }
- BoundaryType GetBoundaryType() const { return m_boundaryType; }
- bool IsWithinBoundary(Position const* pos) const { return (IsWithinBoundaryArea(pos) != m_isInvertedBoundary); }
+ bool IsWithinBoundary(Position const* pos) const { return (IsWithinBoundaryArea(pos) != _isInvertedBoundary); }
bool IsWithinBoundary(Position const& pos) const { return IsWithinBoundary(&pos); }
+ virtual ~AreaBoundary() { }
+
+ protected:
+ explicit AreaBoundary(bool isInverted) : _isInvertedBoundary(isInverted) { }
+
struct DoublePosition : Position
{
- double d_positionX, d_positionY, d_positionZ;
DoublePosition(double x = 0.0, double y = 0.0, double z = 0.0, float o = 0.0f)
- : Position(float(x), float(y), float(z), o), d_positionX(x), d_positionY(y), d_positionZ(z) { }
+ : Position(float(x), float(y), float(z), o), DoublePosX(x), DoublePosY(y), DoublePosZ(z) { }
+
DoublePosition(float x, float y = 0.0f, float z = 0.0f, float o = 0.0f)
- : Position(x, y, z, o), d_positionX(x), d_positionY(y), d_positionZ(z) { }
+ : Position(x, y, z, o), DoublePosX(x), DoublePosY(y), DoublePosZ(z) { }
+
DoublePosition(Position const & pos)
- : DoublePosition(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation()) { }
+ : Position(pos), DoublePosX(pos.m_positionX), DoublePosY(pos.m_positionY), DoublePosZ(pos.m_positionZ) { }
- double GetDoublePositionX() const { return d_positionX; }
- double GetDoublePositionY() const { return d_positionY; }
- double GetDoublePositionZ() const { return d_positionZ; }
+ double GetDoublePositionX() const { return DoublePosX; }
+ double GetDoublePositionY() const { return DoublePosY; }
+ double GetDoublePositionZ() const { return DoublePosZ; }
double GetDoubleExactDist2dSq(DoublePosition const& pos) const {
- double offX = GetDoublePositionX() - pos.GetDoublePositionX();
- double offY = GetDoublePositionY() - pos.GetDoublePositionY();
- return (offX*offX) + (offY*offY);
+ double const offX = GetDoublePositionX() - pos.GetDoublePositionX();
+ double const offY = GetDoublePositionY() - pos.GetDoublePositionY();
+ return (offX * offX) + (offY * offY);
+ }
+
+ Position* sync()
+ {
+ m_positionX = float(DoublePosX);
+ m_positionY = float(DoublePosY);
+ m_positionZ = float(DoublePosZ);
+ return this;
}
- Position* sync() { m_positionX = (float)d_positionX; m_positionY = (float)d_positionY; m_positionZ = (float)d_positionZ; return this; }
+ double DoublePosX;
+ double DoublePosY;
+ double DoublePosZ;
};
- protected:
- AreaBoundary(BoundaryType bType, bool isInverted) : m_boundaryType(bType), m_isInvertedBoundary(isInverted) { }
virtual bool IsWithinBoundaryArea(Position const* pos) const = 0;
- const BoundaryType m_boundaryType;
- bool m_isInvertedBoundary;
+
+ private:
+ bool _isInvertedBoundary;
};
class TC_GAME_API RectangleBoundary : public AreaBoundary
@@ -77,51 +81,47 @@ class TC_GAME_API RectangleBoundary : public AreaBoundary
bool IsWithinBoundaryArea(Position const* pos) const override;
private:
- const float _minX, _maxX, _minY, _maxY;
+ float const _minX, _maxX, _minY, _maxY;
};
class TC_GAME_API CircleBoundary : public AreaBoundary
{
public:
CircleBoundary(Position const& center, double radius, bool isInverted = false);
- CircleBoundary(DoublePosition const& center, double radius, bool isInverted = false);
CircleBoundary(Position const& center, Position const& pointOnCircle, bool isInverted = false);
- CircleBoundary(DoublePosition const& center, DoublePosition const& pointOnCircle, bool isInverted = false);
protected:
bool IsWithinBoundaryArea(Position const* pos) const override;
private:
- const DoublePosition _center;
- const double _radiusSq;
+ DoublePosition const _center;
+ double const _radiusSq;
};
class TC_GAME_API EllipseBoundary : public AreaBoundary
{
public:
EllipseBoundary(Position const& center, double radiusX, double radiusY, bool isInverted = false);
- EllipseBoundary(DoublePosition const& center, double radiusX, double radiusY, bool isInverted = false);
protected:
bool IsWithinBoundaryArea(Position const* pos) const override;
private:
- const DoublePosition _center;
- const double _radiusYSq, _scaleXSq;
+ DoublePosition const _center;
+ double const _radiusYSq, _scaleXSq;
};
class TC_GAME_API TriangleBoundary : public AreaBoundary
{
public:
TriangleBoundary(Position const& pointA, Position const& pointB, Position const& pointC, bool isInverted = false);
- TriangleBoundary(DoublePosition const& pointA, DoublePosition const& pointB, DoublePosition const& pointC, bool isInverted = false);
protected:
bool IsWithinBoundaryArea(Position const* pos) const override;
private:
- const DoublePosition _a, _b, _c;
- const double _abx, _bcx, _cax, _aby, _bcy, _cay;
+ DoublePosition const _a, _b, _c;
+ double const _abx, _bcx, _cax, _aby, _bcy, _cay;
};
class TC_GAME_API ParallelogramBoundary : public AreaBoundary
@@ -129,14 +129,13 @@ class TC_GAME_API ParallelogramBoundary : public AreaBoundary
public:
// Note: AB must be orthogonal to AD
ParallelogramBoundary(Position const& cornerA, Position const& cornerB, Position const& cornerD, bool isInverted = false);
- ParallelogramBoundary(DoublePosition const& cornerA, DoublePosition const& cornerB, DoublePosition const& cornerD, bool isInverted = false);
protected:
bool IsWithinBoundaryArea(Position const* pos) const override;
private:
- const DoublePosition _a, _b, _d, _c;
- const double _abx, _dax, _aby, _day;
+ DoublePosition const _a, _b, _d, _c;
+ double const _abx, _dax, _aby, _day;
};
class TC_GAME_API ZRangeBoundary : public AreaBoundary
@@ -148,7 +147,7 @@ class TC_GAME_API ZRangeBoundary : public AreaBoundary
bool IsWithinBoundaryArea(Position const* pos) const override;
private:
- const float _minZ, _maxZ;
+ float const _minZ, _maxZ;
};
#endif //TRINITY_AREA_BOUNDARY_H
diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h
index 283b0b42fc7..4355789458a 100644
--- a/src/server/game/Miscellaneous/Language.h
+++ b/src/server/game/Miscellaneous/Language.h
@@ -547,7 +547,7 @@ enum TrinityStrings
LANG_MOVEGENS_IDLE = 527,
LANG_MOVEGENS_RANDOM = 528,
LANG_MOVEGENS_WAYPOINT = 529,
- LANG_MOVEGENS_ANIMAL_RANDOM = 530,
+ // = 530, not used
LANG_MOVEGENS_CONFUSED = 531,
LANG_MOVEGENS_CHASE_PLAYER = 532,
LANG_MOVEGENS_CHASE_CREATURE = 533,
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index 1edeb4218fe..1002ab50684 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -5392,6 +5392,14 @@ enum DiminishingLevels
DIMINISHING_LEVEL_TAUNT_IMMUNE = 4
};
+enum WeaponAttackType : uint8
+{
+ BASE_ATTACK = 0,
+ OFF_ATTACK = 1,
+ RANGED_ATTACK = 2,
+ MAX_ATTACK
+};
+
enum TokenResult
{
TOKEN_RESULT_SUCCESS = 0,
diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp
index f4190f2520c..3e775d238a4 100644
--- a/src/server/game/Movement/MotionMaster.cpp
+++ b/src/server/game/Movement/MotionMaster.cpp
@@ -43,10 +43,16 @@ MotionMaster::~MotionMaster()
// clear ALL movement generators (including default)
while (!empty())
{
- MovementGenerator *curr = top();
+ MovementGenerator* movement = top();
pop();
- if (curr && !IsStatic(curr))
- delete curr; // Skip finalizing on delete, it might launch new movement
+ if (movement && !IsStatic(movement))
+ delete movement;
+ }
+
+ while (!_expireList.empty())
+ {
+ delete _expireList.back();
+ _expireList.pop_back();
}
}
@@ -89,13 +95,15 @@ void MotionMaster::UpdateMotion(uint32 diff)
ASSERT(!empty());
_cleanFlag |= MMCF_UPDATE;
- bool isMoveGenUpdateSuccess = top()->Update(_owner, diff);
- _cleanFlag &= ~MMCF_UPDATE;
-
- if (!isMoveGenUpdateSuccess)
+ if (!top()->Update(_owner, diff))
+ {
+ _cleanFlag &= ~MMCF_UPDATE;
MovementExpired();
+ }
+ else
+ _cleanFlag &= ~MMCF_UPDATE;
- if (_expireList)
+ if (!_expireList.empty())
ClearExpireList();
}
@@ -115,14 +123,10 @@ void MotionMaster::Clear(bool reset /*= true*/)
void MotionMaster::ClearExpireList()
{
- for (size_t i = 0; i < _expireList->size(); ++i)
- {
- MovementGenerator* mg = (*_expireList)[i];
- DirectDelete(mg);
- }
+ for (auto itr : _expireList)
+ DirectDelete(itr);
- delete _expireList;
- _expireList = nullptr;
+ _expireList.clear();
if (empty())
Initialize();
@@ -159,7 +163,7 @@ MovementGeneratorType MotionMaster::GetCurrentMovementGeneratorType() const
MovementGeneratorType MotionMaster::GetMotionSlotType(int slot) const
{
if (!_slot[slot])
- return NULL_MOTION_TYPE;
+ return MAX_MOTION_TYPE;
else
return _slot[slot]->GetMovementGeneratorType();
}
@@ -429,7 +433,7 @@ void MotionMaster::MoveKnockbackFrom(float srcX, float srcY, float speedXY, floa
float dist = 2 * moveTimeHalf * speedXY;
float max_height = -Movement::computeFallElevation(moveTimeHalf, false, -speedZ);
- _owner->GetNearPoint(_owner, x, y, z, _owner->GetObjectSize(), dist, _owner->GetAngle(srcX, srcY) + float(M_PI));
+ _owner->GetNearPoint(_owner, x, y, z, _owner->GetCombatReach(), dist, _owner->GetAngle(srcX, srcY) + float(M_PI));
Movement::MoveSplineInit init(_owner);
init.MoveTo(x, y, z);
@@ -453,7 +457,7 @@ void MotionMaster::MoveJumpTo(float angle, float speedXY, float speedZ)
float moveTimeHalf = speedZ / Movement::gravity;
float dist = 2 * moveTimeHalf * speedXY;
- _owner->GetClosePoint(x, y, z, _owner->GetObjectSize(), dist, angle);
+ _owner->GetClosePoint(x, y, z, _owner->GetCombatReach(), dist, angle);
MoveJump(x, y, z, 0.0f, speedXY, speedZ);
}
@@ -835,7 +839,6 @@ void MotionMaster::DelayedDelete(MovementGenerator* curr)
TC_LOG_FATAL("misc", "Unit (Entry %u) is trying to delete its updating Movement Generator (Type %u)!", _owner->GetEntry(), curr->GetMovementGeneratorType());
if (IsStatic(curr))
return;
- if (!_expireList)
- _expireList = new ExpireList();
- _expireList->push_back(curr);
+
+ _expireList.push_back(curr);
}
diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h
index f8dbe43306d..c496a0ec4ec 100644
--- a/src/server/game/Movement/MotionMaster.h
+++ b/src/server/game/Movement/MotionMaster.h
@@ -52,7 +52,6 @@ enum MovementGeneratorType : uint8
RANDOM_MOTION_TYPE = 1, // RandomMovementGenerator.h
WAYPOINT_MOTION_TYPE = 2, // WaypointMovementGenerator.h
MAX_DB_MOTION_TYPE = 3, // Below motion types can't be set in DB.
- ANIMAL_RANDOM_MOTION_TYPE = MAX_DB_MOTION_TYPE, // AnimalRandomMovementGenerator.h
CONFUSED_MOTION_TYPE = 4, // ConfusedMovementGenerator.h
CHASE_MOTION_TYPE = 5, // TargetedMovementGenerator.h
HOME_MOTION_TYPE = 6, // HomeMovementGenerator.h
@@ -60,14 +59,13 @@ enum MovementGeneratorType : uint8
POINT_MOTION_TYPE = 8, // PointMovementGenerator.h
FLEEING_MOTION_TYPE = 9, // FleeingMovementGenerator.h
DISTRACT_MOTION_TYPE = 10, // IdleMovementGenerator.h
- ASSISTANCE_MOTION_TYPE = 11, // PointMovementGenerator.h (first part of flee for assistance)
- ASSISTANCE_DISTRACT_MOTION_TYPE = 12, // IdleMovementGenerator.h (second part of flee for assistance)
- TIMED_FLEEING_MOTION_TYPE = 13, // FleeingMovementGenerator.h (alt.second part of flee for assistance)
+ ASSISTANCE_MOTION_TYPE = 11, // PointMovementGenerator.h
+ ASSISTANCE_DISTRACT_MOTION_TYPE = 12, // IdleMovementGenerator.h
+ TIMED_FLEEING_MOTION_TYPE = 13, // FleeingMovementGenerator.h
FOLLOW_MOTION_TYPE = 14,
ROTATE_MOTION_TYPE = 15,
EFFECT_MOTION_TYPE = 16,
- NULL_MOTION_TYPE = 17,
- SPLINE_CHAIN_MOTION_TYPE = 18, // SplineChainMovementGenerator.h
+ SPLINE_CHAIN_MOTION_TYPE = 17, // SplineChainMovementGenerator.h
MAX_MOTION_TYPE // limit
};
@@ -100,11 +98,8 @@ struct JumpArrivalCastArgs
class TC_GAME_API MotionMaster
{
- private:
- typedef std::vector<MovementGenerator*> ExpireList;
-
public:
- explicit MotionMaster(Unit* unit) : _expireList(nullptr), _top(-1), _owner(unit), _cleanFlag(MMCF_NONE)
+ explicit MotionMaster(Unit* unit) : _owner(unit), _top(-1), _cleanFlag(MMCF_NONE)
{
for (uint8 i = 0; i < MAX_MOTION_SLOT; ++i)
{
@@ -182,6 +177,8 @@ class TC_GAME_API MotionMaster
void MoveRotate(uint32 time, RotateDirection direction);
private:
+ typedef std::vector<MovementGenerator*> MovementList;
+
void pop();
bool NeedInitTop() const;
@@ -197,11 +194,11 @@ class TC_GAME_API MotionMaster
void DelayedDelete(MovementGenerator* curr);
void ClearExpireList();
- ExpireList* _expireList;
MovementGenerator* _slot[MAX_MOTION_SLOT];
- int _top;
- Unit* _owner;
bool _initialize[MAX_MOTION_SLOT];
+ MovementList _expireList;
+ Unit* _owner;
+ int _top;
uint8 _cleanFlag;
};
diff --git a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp
index 51b9641661e..e8fa2ba6c53 100644
--- a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp
@@ -63,7 +63,7 @@ void HomeMovementGenerator<Creature>::_setTargetLocation(Creature* owner)
skipToHome = false;
arrived = false;
- owner->ClearUnitState(uint32(UNIT_STATE_ALL_STATE & ~(UNIT_STATE_EVADE | UNIT_STATE_IGNORE_PATHFINDING)));
+ owner->ClearUnitState(UNIT_STATE_ALL_ERASABLE & ~UNIT_STATE_EVADE);
}
bool HomeMovementGenerator<Creature>::DoUpdate(Creature* owner, const uint32 /*time_diff*/)
diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp
index 6f3b34c0e4f..3cf0711dc41 100755
--- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp
@@ -149,8 +149,6 @@ void EffectMovementGenerator::Finalize(Unit* unit)
{
if (Unit* victim = unit->GetVictim())
unit->GetMotionMaster()->MoveChase(victim);
- else
- unit->GetMotionMaster()->Initialize();
}
if (unit->ToCreature()->AI())
diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
index 0a1206a8d48..54cc97ab418 100755
--- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
@@ -65,7 +65,7 @@ void TargetedMovementGeneratorMedium<T, D>::_setTargetLocation(T* owner, bool up
float size;
// Pets need special handling.
- // We need to subtract GetObjectSize() because it gets added back further down the chain
+ // We need to subtract GetCombatReach() because it gets added back further down the chain
// and that makes pets too far away. Subtracting it allows pets to properly
// be (GetCombatReach() + i_offset) away.
// Only applies when i_target is pet's owner otherwise pets and mobs end up
@@ -73,12 +73,12 @@ void TargetedMovementGeneratorMedium<T, D>::_setTargetLocation(T* owner, bool up
if (owner->IsPet() && i_target->GetTypeId() == TYPEID_PLAYER)
{
dist = 1.0f; //i_target->GetCombatReach();
- size = 1.0f; //i_target->GetCombatReach() - i_target->GetObjectSize();
+ size = 1.0f; //i_target->GetCombatReach() - i_target->GetCombatReach();
}
else
{
dist = i_offset + 1.0f;
- size = owner->GetObjectSize();
+ size = owner->GetCombatReach();
}
if (i_target->IsWithinDistInMap(owner, dist))
diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp
index 92a039344a5..28685dc58ec 100644
--- a/src/server/game/Quests/QuestDef.cpp
+++ b/src/server/game/Quests/QuestDef.cpp
@@ -27,43 +27,36 @@
Quest::Quest(Field* questRecord)
{
- EmoteOnIncomplete = 0;
- EmoteOnComplete = 0;
- _rewItemsCount = 0;
- _rewChoiceItemsCount = 0;
- _eventIdForQuest = 0;
- _rewCurrencyCount = 0;
-
- ID = questRecord[0].GetUInt32();
- Type = questRecord[1].GetUInt8();
- Level = questRecord[2].GetInt32();
- ScalingFactionGroup = questRecord[3].GetInt32();
- MaxScalingLevel = questRecord[4].GetInt32();
- PackageID = questRecord[5].GetUInt32();
- MinLevel = questRecord[6].GetInt32();
- QuestSortID = questRecord[7].GetInt16();
- QuestInfoID = questRecord[8].GetUInt16();
- SuggestedPlayers = questRecord[9].GetUInt8();
- NextQuestInChain = questRecord[10].GetUInt32();
- RewardXPDifficulty = questRecord[11].GetUInt32();
- RewardXPMultiplier = questRecord[12].GetFloat();
- RewardMoney = questRecord[13].GetUInt32();
- RewardMoneyDifficulty = questRecord[14].GetUInt32();
- RewardMoneyMultiplier = questRecord[15].GetFloat();
- RewardBonusMoney = questRecord[16].GetUInt32();
+ _id = questRecord[0].GetUInt32();
+ _type = questRecord[1].GetUInt8();
+ _level = questRecord[2].GetInt32();
+ _scalingFactionGroup = questRecord[3].GetInt32();
+ _maxScalingLevel = questRecord[4].GetInt32();
+ _packageID = questRecord[5].GetUInt32();
+ _minLevel = questRecord[6].GetInt32();
+ _questSortID = questRecord[7].GetInt16();
+ _questInfoID = questRecord[8].GetUInt16();
+ _suggestedPlayers = questRecord[9].GetUInt8();
+ _nextQuestInChain = questRecord[10].GetUInt32();
+ _rewardXPDifficulty = questRecord[11].GetUInt32();
+ _rewardXPMultiplier = questRecord[12].GetFloat();
+ _rewardMoney = questRecord[13].GetUInt32();
+ _rewardMoneyDifficulty = questRecord[14].GetUInt32();
+ _rewardMoneyMultiplier = questRecord[15].GetFloat();
+ _rewardBonusMoney = questRecord[16].GetUInt32();
for (uint32 i = 0; i < QUEST_REWARD_DISPLAY_SPELL_COUNT; ++i)
RewardDisplaySpell[i] = questRecord[17 + i].GetUInt32();
- RewardSpell = questRecord[20].GetUInt32();
- RewardHonor = questRecord[21].GetUInt32();
- RewardKillHonor = questRecord[22].GetUInt32();
- SourceItemId = questRecord[23].GetUInt32();
- RewardArtifactXPDifficulty = questRecord[24].GetUInt32();
- RewardArtifactXPMultiplier = questRecord[25].GetFloat();
- RewardArtifactCategoryID = questRecord[26].GetUInt32();
- Flags = questRecord[27].GetUInt32();
- FlagsEx = questRecord[28].GetUInt32();
- FlagsEx2 = questRecord[29].GetUInt32();
+ _rewardSpell = questRecord[20].GetUInt32();
+ _rewardHonor = questRecord[21].GetUInt32();
+ _rewardKillHonor = questRecord[22].GetUInt32();
+ _sourceItemId = questRecord[23].GetUInt32();
+ _rewardArtifactXPDifficulty = questRecord[24].GetUInt32();
+ _rewardArtifactXPMultiplier = questRecord[25].GetFloat();
+ _rewardArtifactCategoryID = questRecord[26].GetUInt32();
+ _flags = questRecord[27].GetUInt32();
+ _flagsEx = questRecord[28].GetUInt32();
+ _flagsEx2 = questRecord[29].GetUInt32();
for (uint32 i = 0; i < QUEST_ITEM_DROP_COUNT; ++i)
{
@@ -86,19 +79,19 @@ Quest::Quest(Field* questRecord)
++_rewChoiceItemsCount;
}
- POIContinent = questRecord[64].GetUInt32();
- POIx = questRecord[65].GetFloat();
- POIy = questRecord[66].GetFloat();
- POIPriority = questRecord[67].GetUInt32();
+ _poiContinent = questRecord[64].GetUInt32();
+ _poix = questRecord[65].GetFloat();
+ _poiy = questRecord[66].GetFloat();
+ _poiPriority = questRecord[67].GetUInt32();
- RewardTitleId = questRecord[68].GetUInt32();
- RewardArenaPoints = questRecord[69].GetUInt32();
- RewardSkillId = questRecord[70].GetUInt32();
- RewardSkillPoints = questRecord[71].GetUInt32();
+ _rewardTitleId = questRecord[68].GetUInt32();
+ _rewardArenaPoints = questRecord[69].GetUInt32();
+ _rewardSkillId = questRecord[70].GetUInt32();
+ _rewardSkillPoints = questRecord[71].GetUInt32();
- QuestGiverPortrait = questRecord[72].GetUInt32();
- QuestGiverPortraitMount = questRecord[73].GetUInt32();
- QuestTurnInPortrait = questRecord[74].GetUInt32();
+ _questGiverPortrait = questRecord[72].GetUInt32();
+ _questGiverPortraitMount = questRecord[73].GetUInt32();
+ _questTurnInPortrait = questRecord[74].GetUInt32();
for (uint32 i = 0; i < QUEST_REWARD_REPUTATIONS_COUNT; ++i)
{
@@ -108,7 +101,7 @@ Quest::Quest(Field* questRecord)
RewardFactionCapIn[i] = questRecord[78 + i * 4].GetUInt32();
}
- RewardReputationMask = questRecord[95].GetUInt32();
+ _rewardReputationMask = questRecord[95].GetUInt32();
for (uint32 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i)
{
@@ -119,33 +112,25 @@ Quest::Quest(Field* questRecord)
++_rewCurrencyCount;
}
- SoundAccept = questRecord[104].GetUInt32();
- SoundTurnIn = questRecord[105].GetUInt32();
- AreaGroupID = questRecord[106].GetUInt32();
- LimitTime = questRecord[107].GetUInt32();
- AllowableRaces.RawValue = questRecord[108].GetUInt64();
- TreasurePickerID = questRecord[109].GetInt32();
- Expansion = questRecord[110].GetInt32();
- ManagedWorldStateID = questRecord[111].GetInt32();
- QuestSessionBonus = questRecord[112].GetInt32();
-
- LogTitle = questRecord[113].GetString();
- LogDescription = questRecord[114].GetString();
- QuestDescription = questRecord[115].GetString();
- AreaDescription = questRecord[116].GetString();
- PortraitGiverText = questRecord[117].GetString();
- PortraitGiverName = questRecord[118].GetString();
- PortraitTurnInText = questRecord[119].GetString();
- PortraitTurnInName = questRecord[120].GetString();
- QuestCompletionLog = questRecord[121].GetString();
-
- for (uint32 i = 0; i < QUEST_EMOTE_COUNT; ++i)
- {
- DetailsEmote[i] = 0;
- DetailsEmoteDelay[i] = 0;
- OfferRewardEmote[i] = 0;
- OfferRewardEmoteDelay[i] = 0;
- }
+ _soundAccept = questRecord[104].GetUInt32();
+ _soundTurnIn = questRecord[105].GetUInt32();
+ _areaGroupID = questRecord[106].GetUInt32();
+ _limitTime = questRecord[107].GetUInt32();
+ _allowableRaces.RawValue = questRecord[108].GetUInt64();
+ _treasurePickerID = questRecord[109].GetInt32();
+ _expansion = questRecord[110].GetInt32();
+ _managedWorldStateID = questRecord[111].GetInt32();
+ _questSessionBonus = questRecord[112].GetInt32();
+
+ _logTitle = questRecord[113].GetString();
+ _logDescription = questRecord[114].GetString();
+ _questDescription = questRecord[115].GetString();
+ _areaDescription = questRecord[116].GetString();
+ _portraitGiverText = questRecord[117].GetString();
+ _portraitGiverName = questRecord[118].GetString();
+ _portraitTurnInText = questRecord[119].GetString();
+ _portraitTurnInName = questRecord[120].GetString();
+ _questCompletionLog = questRecord[121].GetString();
}
void Quest::LoadQuestDetails(Field* fields)
@@ -167,18 +152,18 @@ void Quest::LoadQuestDetails(Field* fields)
void Quest::LoadQuestRequestItems(Field* fields)
{
- EmoteOnComplete = fields[1].GetUInt16();
- EmoteOnIncomplete = fields[2].GetUInt16();
+ _emoteOnComplete = fields[1].GetUInt16();
+ _emoteOnIncomplete = fields[2].GetUInt16();
- if (!sEmotesStore.LookupEntry(EmoteOnComplete))
- TC_LOG_ERROR("sql.sql", "Table `quest_request_items` has non-existing EmoteOnComplete (%u) set for quest %u.", EmoteOnComplete, fields[0].GetUInt32());
+ if (!sEmotesStore.LookupEntry(_emoteOnComplete))
+ TC_LOG_ERROR("sql.sql", "Table `quest_request_items` has non-existing EmoteOnComplete (%u) set for quest %u.", _emoteOnComplete, fields[0].GetUInt32());
- if (!sEmotesStore.LookupEntry(EmoteOnIncomplete))
- TC_LOG_ERROR("sql.sql", "Table `quest_request_items` has non-existing EmoteOnIncomplete (%u) set for quest %u.", EmoteOnIncomplete, fields[0].GetUInt32());
+ if (!sEmotesStore.LookupEntry(_emoteOnIncomplete))
+ TC_LOG_ERROR("sql.sql", "Table `quest_request_items` has non-existing EmoteOnIncomplete (%u) set for quest %u.", _emoteOnIncomplete, fields[0].GetUInt32());
- EmoteOnCompleteDelay = fields[3].GetUInt32();
- EmoteOnIncompleteDelay = fields[4].GetUInt32();
- RequestItemsText = fields[5].GetString();
+ _emoteOnCompleteDelay = fields[3].GetUInt32();
+ _emoteOnIncompleteDelay = fields[4].GetUInt32();
+ _requestItemsText = fields[5].GetString();
}
void Quest::LoadQuestOfferReward(Field* fields)
@@ -197,39 +182,43 @@ void Quest::LoadQuestOfferReward(Field* fields)
for (uint32 i = 0; i < QUEST_EMOTE_COUNT; ++i)
OfferRewardEmoteDelay[i] = fields[5 + i].GetUInt32();
- OfferRewardText = fields[9].GetString();
+ _offerRewardText = fields[9].GetString();
}
void Quest::LoadQuestTemplateAddon(Field* fields)
{
- MaxLevel = fields[1].GetUInt8();
- AllowableClasses = fields[2].GetUInt32();
- SourceSpellID = fields[3].GetUInt32();
- PrevQuestID = fields[4].GetInt32();
- NextQuestID = fields[5].GetInt32();
- ExclusiveGroup = fields[6].GetInt32();
- RewardMailTemplateId = fields[7].GetUInt32();
- RewardMailDelay = fields[8].GetUInt32();
- RequiredSkillId = fields[9].GetUInt16();
- RequiredSkillPoints = fields[10].GetUInt16();
- RequiredMinRepFaction = fields[11].GetUInt16();
- RequiredMaxRepFaction = fields[12].GetUInt16();
- RequiredMinRepValue = fields[13].GetInt32();
- RequiredMaxRepValue = fields[14].GetInt32();
- SourceItemIdCount = fields[15].GetUInt8();
- RewardMailSenderEntry = fields[16].GetUInt32();
- SpecialFlags = fields[17].GetUInt8();
- ScriptId = sObjectMgr->GetScriptId(fields[18].GetString());
-
- if (SpecialFlags & QUEST_SPECIAL_FLAGS_AUTO_ACCEPT)
- Flags |= QUEST_FLAGS_AUTO_ACCEPT;
+ _maxLevel = fields[1].GetUInt8();
+ _allowableClasses = fields[2].GetUInt32();
+ _sourceSpellID = fields[3].GetUInt32();
+ _prevQuestID = fields[4].GetInt32();
+ _nextQuestID = fields[5].GetUInt32();
+ _exclusiveGroup = fields[6].GetInt32();
+ _rewardMailTemplateId = fields[7].GetUInt32();
+ _rewardMailDelay = fields[8].GetUInt32();
+ _requiredSkillId = fields[9].GetUInt16();
+ _requiredSkillPoints = fields[10].GetUInt16();
+ _requiredMinRepFaction = fields[11].GetUInt16();
+ _requiredMaxRepFaction = fields[12].GetUInt16();
+ _requiredMinRepValue = fields[13].GetInt32();
+ _requiredMaxRepValue = fields[14].GetInt32();
+ _sourceItemIdCount = fields[15].GetUInt8();
+ _specialFlags = fields[16].GetUInt8();
+ _scriptId = sObjectMgr->GetScriptId(fields[17].GetString());
+
+ if (_specialFlags & QUEST_SPECIAL_FLAGS_AUTO_ACCEPT)
+ _flags |= QUEST_FLAGS_AUTO_ACCEPT;
+}
+
+void Quest::LoadQuestMailSender(Field* fields)
+{
+ _rewardMailSenderEntry = fields[1].GetUInt32();
}
void Quest::LoadQuestObjective(Field* fields)
{
QuestObjective obj;
- obj.ID = fields[0].GetUInt32();
- obj.QuestID = fields[1].GetUInt32();
+ obj.QuestID = fields[0].GetUInt32();
+ obj.ID = fields[1].GetUInt32();
obj.Type = fields[2].GetUInt8();
obj.StorageIndex = fields[3].GetInt8();
obj.ObjectID = fields[4].GetInt32();
@@ -252,7 +241,7 @@ void Quest::LoadQuestObjectiveVisualEffect(Field* fields)
{
uint8 effectIndex = fields[3].GetUInt8();
if (effectIndex >= obj.VisualEffects.size())
- obj.VisualEffects.resize(effectIndex+1, 0);
+ obj.VisualEffects.resize(effectIndex + 1, 0);
obj.VisualEffects[effectIndex] = fields[4].GetInt32();
break;
@@ -266,20 +255,20 @@ uint32 Quest::XPValue(Player const* player) const
{
uint32 questLevel = player->GetQuestLevel(this);
QuestXPEntry const* questXp = sQuestXPStore.LookupEntry(questLevel);
- if (!questXp || RewardXPDifficulty >= 10)
+ if (!questXp || _rewardXPDifficulty >= 10)
return 0;
float multiplier = 1.0f;
if (questLevel != player->getLevel())
multiplier = sXpGameTable.GetRow(std::min<int32>(player->getLevel(), questLevel))->Divisor / sXpGameTable.GetRow(player->getLevel())->Divisor;
- int32 diffFactor = 2 * (questLevel + (Level == -1 ? 0 : 5) - player->getLevel()) + 10;
+ int32 diffFactor = 2 * (questLevel + (_level == -1 ? 0 : 5) - player->getLevel()) + 10;
if (diffFactor < 1)
diffFactor = 1;
else if (diffFactor > 10)
diffFactor = 10;
- uint32 xp = diffFactor * questXp->Difficulty[RewardXPDifficulty] * RewardXPMultiplier / 10 * multiplier;
+ uint32 xp = diffFactor * questXp->Difficulty[_rewardXPDifficulty] * _rewardXPMultiplier / 10 * multiplier;
if (xp <= 100)
xp = 5 * ((xp + 2) / 5);
else if (xp <= 500)
@@ -354,7 +343,7 @@ uint32 Quest::GetRewMoneyMaxLevel() const
return 0;
// Else, return the rewarded copper sum modified by the rate
- return uint32(RewardBonusMoney * sWorld->getRate(RATE_MONEY_MAX_LEVEL_QUEST));
+ return uint32(_rewardBonusMoney * sWorld->getRate(RATE_MONEY_MAX_LEVEL_QUEST));
}
bool Quest::IsAutoAccept() const
@@ -364,12 +353,12 @@ bool Quest::IsAutoAccept() const
bool Quest::IsAutoComplete() const
{
- return !sWorld->getBoolConfig(CONFIG_QUEST_IGNORE_AUTO_COMPLETE) && Type == QUEST_TYPE_AUTOCOMPLETE;
+ return !sWorld->getBoolConfig(CONFIG_QUEST_IGNORE_AUTO_COMPLETE) && _type == QUEST_TYPE_AUTOCOMPLETE;
}
bool Quest::IsRaidQuest(Difficulty difficulty) const
{
- switch (QuestInfoID)
+ switch (_questInfoID)
{
case QUEST_INFO_RAID:
return true;
@@ -381,7 +370,7 @@ bool Quest::IsRaidQuest(Difficulty difficulty) const
break;
}
- if ((Flags & QUEST_FLAGS_RAID) != 0)
+ if ((_flags & QUEST_FLAGS_RAID) != 0)
return true;
return false;
@@ -481,7 +470,7 @@ WorldPacket Quest::BuildQueryData(LocaleConstant loc) const
response.Info.RewardXPMultiplier = GetXPMultiplier();
if (!HasFlag(QUEST_FLAGS_HIDDEN_REWARDS))
- response.Info.RewardMoney = RewardMoney;
+ response.Info.RewardMoney = GetRewMoney();
response.Info.RewardMoneyDifficulty = GetRewMoneyDifficulty();
response.Info.RewardMoneyMultiplier = GetMoneyMultiplier();
diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h
index aefd9509f6b..2023a4de8e8 100644
--- a/src/server/game/Quests/QuestDef.h
+++ b/src/server/game/Quests/QuestDef.h
@@ -351,113 +351,138 @@ class TC_GAME_API Quest
void LoadQuestRequestItems(Field* fields);
void LoadQuestOfferReward(Field* fields);
void LoadQuestTemplateAddon(Field* fields);
+ void LoadQuestMailSender(Field* fields);
void LoadQuestObjective(Field* fields);
void LoadQuestObjectiveVisualEffect(Field* fields);
uint32 XPValue(Player const* player) const;
uint32 MoneyValue(Player const* player) const;
- bool HasFlag(QuestFlags flag) const { return (Flags & uint32(flag)) != 0; }
- bool HasFlagEx(QuestFlagsEx flag) const { return (FlagsEx & uint32(flag)) != 0; }
- bool HasFlagEx2(QuestFlagsEx2 flag) const { return (FlagsEx2 & uint32(flag)) != 0; }
+ bool HasFlag(QuestFlags flag) const { return (_flags & uint32(flag)) != 0; }
+ bool HasFlagEx(QuestFlagsEx flag) const { return (_flagsEx & uint32(flag)) != 0; }
+ bool HasFlagEx2(QuestFlagsEx2 flag) const { return (_flagsEx2 & uint32(flag)) != 0; }
- bool HasSpecialFlag(uint32 flag) const { return (SpecialFlags & flag) != 0; }
- void SetSpecialFlag(uint32 flag) { SpecialFlags |= flag; }
+ bool HasSpecialFlag(uint32 flag) const { return (_specialFlags & flag) != 0; }
+ void SetSpecialFlag(uint32 flag) { _specialFlags |= flag; }
// table data accessors:
- uint32 GetQuestId() const { return ID; }
- uint32 GetQuestType() const { return Type; }
- uint32 GetQuestPackageID() const { return PackageID; }
- int32 GetZoneOrSort() const { return QuestSortID; }
- int32 GetMinLevel() const { return MinLevel; }
- uint32 GetMaxLevel() const { return MaxLevel; }
- int32 GetQuestLevel() const { return Level; }
- int32 GetQuestScalingFactionGroup() const { return ScalingFactionGroup; }
- int32 GetQuestMaxScalingLevel() const { return MaxScalingLevel; }
- uint32 GetQuestInfoID() const { return QuestInfoID; }
- uint32 GetAllowableClasses() const { return AllowableClasses; }
- Trinity::RaceMask<uint64> GetAllowableRaces() const { return AllowableRaces; }
- uint32 GetRequiredSkill() const { return RequiredSkillId; }
- uint32 GetRequiredSkillValue() const { return RequiredSkillPoints; }
- uint32 GetRequiredMinRepFaction() const { return RequiredMinRepFaction; }
- int32 GetRequiredMinRepValue() const { return RequiredMinRepValue; }
- uint32 GetRequiredMaxRepFaction() const { return RequiredMaxRepFaction; }
- int32 GetRequiredMaxRepValue() const { return RequiredMaxRepValue; }
- uint32 GetSuggestedPlayers() const { return SuggestedPlayers; }
- uint32 GetLimitTime() const { return LimitTime; }
- int32 GetPrevQuestId() const { return PrevQuestID; }
- int32 GetNextQuestId() const { return NextQuestID; }
- int32 GetExclusiveGroup() const { return ExclusiveGroup; }
- uint32 GetNextQuestInChain() const { return NextQuestInChain; }
- int32 GetRewArenaPoints() const {return RewardArenaPoints; }
- uint32 GetXPDifficulty() const { return RewardXPDifficulty; }
- float GetXPMultiplier() const { return RewardXPMultiplier; }
- float GetMoneyMultiplier() const { return RewardMoneyMultiplier; }
- uint32 GetSrcItemId() const { return SourceItemId; }
- uint32 GetSrcItemCount() const { return SourceItemIdCount; }
- uint32 GetSrcSpell() const { return SourceSpellID; }
- std::string const& GetLogTitle() const { return LogTitle; }
- std::string const& GetLogDescription() const { return LogDescription; }
- std::string const& GetQuestDescription() const { return QuestDescription; }
- std::string const& GetAreaDescription() const { return AreaDescription; }
- std::string const& GetOfferRewardText() const { return OfferRewardText; }
- std::string const& GetRequestItemsText() const { return RequestItemsText; }
- std::string const& GetQuestCompletionLog() const { return QuestCompletionLog; }
- std::string const& GetPortraitGiverText() const { return PortraitGiverText; }
- std::string const& GetPortraitGiverName() const { return PortraitGiverName; }
- std::string const& GetPortraitTurnInText() const { return PortraitTurnInText; }
- std::string const& GetPortraitTurnInName() const { return PortraitTurnInName; }
+ uint32 GetQuestId() const { return _id; }
+ uint32 GetQuestType() const { return _type; }
+ uint32 GetQuestPackageID() const { return _packageID; }
+ int32 GetZoneOrSort() const { return _questSortID; }
+ int32 GetMinLevel() const { return _minLevel; }
+ uint32 GetMaxLevel() const { return _maxLevel; }
+ int32 GetQuestLevel() const { return _level; }
+ int32 GetQuestScalingFactionGroup() const { return _scalingFactionGroup; }
+ int32 GetQuestMaxScalingLevel() const { return _maxScalingLevel; }
+ uint32 GetQuestInfoID() const { return _questInfoID; }
+ uint32 GetAllowableClasses() const { return _allowableClasses; }
+ Trinity::RaceMask<uint64> GetAllowableRaces() const { return _allowableRaces; }
+ uint32 GetRequiredSkill() const { return _requiredSkillId; }
+ uint32 GetRequiredSkillValue() const { return _requiredSkillPoints; }
+ uint32 GetRequiredMinRepFaction() const { return _requiredMinRepFaction; }
+ int32 GetRequiredMinRepValue() const { return _requiredMinRepValue; }
+ uint32 GetRequiredMaxRepFaction() const { return _requiredMaxRepFaction; }
+ int32 GetRequiredMaxRepValue() const { return _requiredMaxRepValue; }
+ uint32 GetSuggestedPlayers() const { return _suggestedPlayers; }
+ uint32 GetLimitTime() const { return _limitTime; }
+ int32 GetPrevQuestId() const { return _prevQuestID; }
+ uint32 GetNextQuestId() const { return _nextQuestID; }
+ int32 GetExclusiveGroup() const { return _exclusiveGroup; }
+ uint32 GetNextQuestInChain() const { return _nextQuestInChain; }
+ int32 GetRewArenaPoints() const {return _rewardArenaPoints; }
+ uint32 GetXPDifficulty() const { return _rewardXPDifficulty; }
+ float GetXPMultiplier() const { return _rewardXPMultiplier; }
+ float GetMoneyMultiplier() const { return _rewardMoneyMultiplier; }
+ uint32 GetSrcItemId() const { return _sourceItemId; }
+ uint32 GetSrcItemCount() const { return _sourceItemIdCount; }
+ uint32 GetSrcSpell() const { return _sourceSpellID; }
+ std::string const& GetLogTitle() const { return _logTitle; }
+ std::string const& GetLogDescription() const { return _logDescription; }
+ std::string const& GetQuestDescription() const { return _questDescription; }
+ std::string const& GetAreaDescription() const { return _areaDescription; }
+ std::string const& GetOfferRewardText() const { return _offerRewardText; }
+ std::string const& GetRequestItemsText() const { return _requestItemsText; }
+ std::string const& GetQuestCompletionLog() const { return _questCompletionLog; }
+ std::string const& GetPortraitGiverText() const { return _portraitGiverText; }
+ std::string const& GetPortraitGiverName() const { return _portraitGiverName; }
+ std::string const& GetPortraitTurnInText() const { return _portraitTurnInText; }
+ std::string const& GetPortraitTurnInName() const { return _portraitTurnInName; }
QuestObjectives const& GetObjectives() const { return Objectives; }
- uint32 GetRewMoneyDifficulty() const { return RewardMoneyDifficulty; }
- uint32 GetRewHonor() const { return RewardHonor; }
- uint32 GetRewKillHonor() const { return RewardKillHonor; }
- uint32 GetArtifactXPDifficulty() const { return RewardArtifactXPDifficulty; }
- float GetArtifactXPMultiplier() const { return RewardArtifactXPMultiplier; }
- uint32 GetArtifactCategoryId() const { return RewardArtifactCategoryID; }
+ uint32 GetRewMoney() const { return _rewardMoney; }
+ uint32 GetRewMoneyDifficulty() const { return _rewardMoneyDifficulty; }
+ uint32 GetRewHonor() const { return _rewardHonor; }
+ uint32 GetRewKillHonor() const { return _rewardKillHonor; }
+ uint32 GetArtifactXPDifficulty() const { return _rewardArtifactXPDifficulty; }
+ float GetArtifactXPMultiplier() const { return _rewardArtifactXPMultiplier; }
+ uint32 GetArtifactCategoryId() const { return _rewardArtifactCategoryID; }
uint32 GetRewMoneyMaxLevel() const; // use in XP calculation at client
- uint32 GetRewSpell() const { return RewardSpell; }
- uint32 GetRewMailTemplateId() const { return RewardMailTemplateId; }
- uint32 GetRewMailDelaySecs() const { return RewardMailDelay; }
- uint32 GetRewMailSenderEntry() const { return RewardMailSenderEntry; }
- uint32 GetRewTitle() const { return RewardTitleId; }
- uint32 GetPOIContinent() const { return POIContinent; }
- float GetPOIx() const { return POIx; }
- float GetPOIy() const { return POIy; }
- uint32 GetPOIPriority() const { return POIPriority; }
- uint32 GetSoundAccept() const { return SoundAccept; }
- uint32 GetSoundTurnIn() const { return SoundTurnIn; }
- uint32 GetIncompleteEmote() const { return EmoteOnIncomplete; }
- uint32 GetCompleteEmote() const { return EmoteOnComplete; }
- bool IsRepeatable() const { return SpecialFlags & QUEST_SPECIAL_FLAGS_REPEATABLE; }
+ uint32 GetRewSpell() const { return _rewardSpell; }
+ uint32 GetRewMailTemplateId() const { return _rewardMailTemplateId; }
+ uint32 GetRewMailDelaySecs() const { return _rewardMailDelay; }
+ uint32 GetRewMailSenderEntry() const { return _rewardMailSenderEntry; }
+ uint32 GetRewTitle() const { return _rewardTitleId; }
+ uint32 GetPOIContinent() const { return _poiContinent; }
+ float GetPOIx() const { return _poix; }
+ float GetPOIy() const { return _poiy; }
+ uint32 GetPOIPriority() const { return _poiPriority; }
+ uint32 GetSoundAccept() const { return _soundAccept; }
+ uint32 GetSoundTurnIn() const { return _soundTurnIn; }
+ uint32 GetIncompleteEmote() const { return _emoteOnIncomplete; }
+ uint32 GetCompleteEmote() const { return _emoteOnComplete; }
+ uint32 GetIncompleteEmoteDelay() const { return _emoteOnIncompleteDelay; }
+ uint32 GetCompleteEmoteDelay() const { return _emoteOnCompleteDelay; }
+ bool IsRepeatable() const { return _specialFlags & QUEST_SPECIAL_FLAGS_REPEATABLE; }
bool IsAutoAccept() const;
bool IsAutoComplete() const;
- uint32 GetFlags() const { return Flags; }
- uint32 GetFlagsEx() const { return FlagsEx; }
- uint32 GetFlagsEx2() const { return FlagsEx2; }
- uint32 GetSpecialFlags() const { return SpecialFlags; }
- uint32 GetScriptId() const { return ScriptId; }
- uint32 GetAreaGroupID() const { return AreaGroupID; }
- uint32 GetRewardSkillId() const { return RewardSkillId; }
- uint32 GetRewardSkillPoints() const { return RewardSkillPoints; }
- uint32 GetRewardReputationMask() const { return RewardReputationMask; }
- int32 GetTreasurePickerId() const { return TreasurePickerID; }
- int32 GetExpansion() const { return Expansion; }
- int32 GetManagedWorldStateId() const { return ManagedWorldStateID; }
- int32 GetQuestSessionBonus() const { return QuestSessionBonus; }
- uint32 GetQuestGiverPortrait() const { return QuestGiverPortrait; }
- int32 GetQuestGiverPortraitMount() const { return QuestGiverPortraitMount; }
- uint32 GetQuestTurnInPortrait() const { return QuestTurnInPortrait; }
- bool IsDaily() const { return (Flags & QUEST_FLAGS_DAILY) != 0; }
- bool IsWeekly() const { return (Flags & QUEST_FLAGS_WEEKLY) != 0; }
- bool IsMonthly() const { return (SpecialFlags & QUEST_SPECIAL_FLAGS_MONTHLY) != 0; }
- bool IsSeasonal() const { return (QuestSortID == -QUEST_SORT_SEASONAL || QuestSortID == -QUEST_SORT_SPECIAL || QuestSortID == -QUEST_SORT_LUNAR_FESTIVAL || QuestSortID == -QUEST_SORT_MIDSUMMER || QuestSortID == -QUEST_SORT_BREWFEST || QuestSortID == -QUEST_SORT_LOVE_IS_IN_THE_AIR || QuestSortID == -QUEST_SORT_NOBLEGARDEN) && !IsRepeatable(); }
- bool IsDailyOrWeekly() const { return (Flags & (QUEST_FLAGS_DAILY | QUEST_FLAGS_WEEKLY)) != 0; }
+ uint32 GetFlags() const { return _flags; }
+ uint32 GetFlagsEx() const { return _flagsEx; }
+ uint32 GetFlagsEx2() const { return _flagsEx2; }
+ uint32 GetSpecialFlags() const { return _specialFlags; }
+ uint32 GetScriptId() const { return _scriptId; }
+ uint32 GetAreaGroupID() const { return _areaGroupID; }
+ uint32 GetRewardSkillId() const { return _rewardSkillId; }
+ uint32 GetRewardSkillPoints() const { return _rewardSkillPoints; }
+ uint32 GetRewardReputationMask() const { return _rewardReputationMask; }
+ int32 GetTreasurePickerId() const { return _treasurePickerID; }
+ int32 GetExpansion() const { return _expansion; }
+ int32 GetManagedWorldStateId() const { return _managedWorldStateID; }
+ int32 GetQuestSessionBonus() const { return _questSessionBonus; }
+ uint32 GetQuestGiverPortrait() const { return _questGiverPortrait; }
+ int32 GetQuestGiverPortraitMount() const { return _questGiverPortraitMount; }
+ uint32 GetQuestTurnInPortrait() const { return _questTurnInPortrait; }
+ bool IsDaily() const { return (_flags & QUEST_FLAGS_DAILY) != 0; }
+ bool IsWeekly() const { return (_flags & QUEST_FLAGS_WEEKLY) != 0; }
+ bool IsMonthly() const { return (_specialFlags & QUEST_SPECIAL_FLAGS_MONTHLY) != 0; }
+ bool IsSeasonal() const { return (_questSortID == -QUEST_SORT_SEASONAL || _questSortID == -QUEST_SORT_SPECIAL || _questSortID == -QUEST_SORT_LUNAR_FESTIVAL || _questSortID == -QUEST_SORT_MIDSUMMER || _questSortID == -QUEST_SORT_BREWFEST || _questSortID == -QUEST_SORT_LOVE_IS_IN_THE_AIR || _questSortID == -QUEST_SORT_NOBLEGARDEN) && !IsRepeatable(); }
+ bool IsDailyOrWeekly() const { return (_flags & (QUEST_FLAGS_DAILY | QUEST_FLAGS_WEEKLY)) != 0; }
bool IsRaidQuest(Difficulty difficulty) const;
bool IsAllowedInRaid(Difficulty difficulty) const;
- bool IsDFQuest() const { return (SpecialFlags & QUEST_SPECIAL_FLAGS_DF_QUEST) != 0; }
+ bool IsDFQuest() const { return (_specialFlags & QUEST_SPECIAL_FLAGS_DF_QUEST) != 0; }
uint32 CalculateHonorGain(uint8 level) const;
bool CanIncreaseRewardedQuestCounters() const;
+ // multiple values
+ uint32 RewardDisplaySpell[QUEST_REWARD_DISPLAY_SPELL_COUNT] = { };
+ uint32 RewardItemId[QUEST_REWARD_ITEM_COUNT] = { };
+ uint32 RewardItemCount[QUEST_REWARD_ITEM_COUNT] = { };
+ uint32 ItemDrop[QUEST_ITEM_DROP_COUNT] = { };
+ uint32 ItemDropQuantity[QUEST_ITEM_DROP_COUNT] = { };
+ uint32 RewardChoiceItemId[QUEST_REWARD_CHOICES_COUNT] = { };
+ uint32 RewardChoiceItemCount[QUEST_REWARD_CHOICES_COUNT] = { };
+ uint32 RewardChoiceItemDisplayId[QUEST_REWARD_CHOICES_COUNT] = { };
+ uint32 RewardFactionId[QUEST_REWARD_REPUTATIONS_COUNT] = { };
+ int32 RewardFactionValue[QUEST_REWARD_REPUTATIONS_COUNT] = { };
+ int32 RewardFactionOverride[QUEST_REWARD_REPUTATIONS_COUNT] = { };
+ uint32 RewardFactionCapIn[QUEST_REWARD_REPUTATIONS_COUNT] = { };
+ uint32 RewardCurrencyId[QUEST_REWARD_CURRENCY_COUNT] = { };
+ uint32 RewardCurrencyCount[QUEST_REWARD_CURRENCY_COUNT] = { };
+ QuestObjectives Objectives = { };
+ uint32 DetailsEmote[QUEST_EMOTE_COUNT] = { };
+ uint32 DetailsEmoteDelay[QUEST_EMOTE_COUNT] = { };
+ uint32 OfferRewardEmote[QUEST_EMOTE_COUNT] = { };
+ uint32 OfferRewardEmoteDelay[QUEST_EMOTE_COUNT] = { };
+
uint32 GetRewChoiceItemsCount() const { return _rewChoiceItemsCount; }
uint32 GetRewItemsCount() const { return _rewItemsCount; }
uint32 GetRewCurrencyCount() const { return _rewCurrencyCount; }
@@ -471,141 +496,111 @@ class TC_GAME_API Quest
void BuildQuestRewards(WorldPackets::Quest::QuestRewards& rewards, Player* player) const;
- typedef std::vector<int32> PrevQuests;
- PrevQuests prevQuests;
- typedef std::vector<uint32> PrevChainQuests;
- PrevChainQuests prevChainQuests;
+ std::vector<uint32> DependentPreviousQuests;
+ std::vector<uint32> PrevChainQuests;
WorldPacket QueryData[TOTAL_LOCALES];
private:
- uint32 _rewChoiceItemsCount;
- uint32 _rewItemsCount;
- uint16 _eventIdForQuest;
- uint32 _rewCurrencyCount;
+ uint32 _rewChoiceItemsCount = 0;
+ uint32 _rewItemsCount = 0;
+ uint16 _eventIdForQuest = 0;
+ uint32 _rewCurrencyCount = 0;
- public:
// wdb data (quest query response)
- uint32 ID;
- uint32 Type;
- int32 Level;
- int32 ScalingFactionGroup;
- int32 MaxScalingLevel;
- uint32 PackageID;
- int32 MinLevel;
- int32 QuestSortID;
- uint32 QuestInfoID;
- uint32 SuggestedPlayers;
- uint32 NextQuestInChain;
- uint32 RewardXPDifficulty;
- float RewardXPMultiplier;
- int32 RewardMoney;
- uint32 RewardMoneyDifficulty;
- float RewardMoneyMultiplier;
- uint32 RewardBonusMoney;
- uint32 RewardDisplaySpell[QUEST_REWARD_DISPLAY_SPELL_COUNT];
- uint32 RewardSpell;
- uint32 RewardHonor;
- uint32 RewardKillHonor;
- uint32 RewardArtifactXPDifficulty;
- float RewardArtifactXPMultiplier;
- uint32 RewardArtifactCategoryID;
- uint32 SourceItemId;
- uint32 Flags;
- uint32 FlagsEx;
- uint32 FlagsEx2;
- uint32 RewardItemId[QUEST_REWARD_ITEM_COUNT];
- uint32 RewardItemCount[QUEST_REWARD_ITEM_COUNT];
- uint32 ItemDrop[QUEST_ITEM_DROP_COUNT];
- uint32 ItemDropQuantity[QUEST_ITEM_DROP_COUNT];
- uint32 RewardChoiceItemId[QUEST_REWARD_CHOICES_COUNT];
- uint32 RewardChoiceItemCount[QUEST_REWARD_CHOICES_COUNT];
- uint32 RewardChoiceItemDisplayId[QUEST_REWARD_CHOICES_COUNT];
- uint32 POIContinent;
- float POIx;
- float POIy;
- uint32 POIPriority;
- uint32 RewardTitleId;
- int32 RewardArenaPoints;
- uint32 RewardSkillId;
- uint32 RewardSkillPoints;
- uint32 QuestGiverPortrait;
- int32 QuestGiverPortraitMount;
- uint32 QuestTurnInPortrait;
- uint32 RewardFactionId[QUEST_REWARD_REPUTATIONS_COUNT];
- int32 RewardFactionValue[QUEST_REWARD_REPUTATIONS_COUNT];
- int32 RewardFactionOverride[QUEST_REWARD_REPUTATIONS_COUNT];
- uint32 RewardFactionCapIn[QUEST_REWARD_REPUTATIONS_COUNT];
- uint32 RewardReputationMask;
- uint32 RewardCurrencyId[QUEST_REWARD_CURRENCY_COUNT];
- uint32 RewardCurrencyCount[QUEST_REWARD_CURRENCY_COUNT];
- uint32 SoundAccept;
- uint32 SoundTurnIn;
- uint32 AreaGroupID;
- uint32 LimitTime;
- Trinity::RaceMask<uint64> AllowableRaces;
- int32 TreasurePickerID;
- int32 Expansion;
- int32 ManagedWorldStateID;
- int32 QuestSessionBonus;
- QuestObjectives Objectives;
- std::string LogTitle;
- std::string LogDescription;
- std::string QuestDescription;
- std::string AreaDescription;
- std::string PortraitGiverText;
- std::string PortraitGiverName;
- std::string PortraitTurnInText;
- std::string PortraitTurnInName;
- std::string QuestCompletionLog;
-
- protected:
-
- // quest_detais table
- uint32 DetailsEmote[QUEST_EMOTE_COUNT] = { };
- uint32 DetailsEmoteDelay[QUEST_EMOTE_COUNT] = { };
+ uint32 _id = 0;
+ uint32 _type = 0;
+ int32 _level = 0;
+ int32 _scalingFactionGroup = 0;
+ int32 _maxScalingLevel = 0;
+ uint32 _packageID = 0;
+ int32 _minLevel = 0;
+ int32 _questSortID = 0;
+ uint32 _questInfoID = 0;
+ uint32 _suggestedPlayers = 0;
+ uint32 _nextQuestInChain = 0;
+ uint32 _rewardXPDifficulty = 0;
+ float _rewardXPMultiplier = 0.f;
+ int32 _rewardMoney = 0;
+ uint32 _rewardMoneyDifficulty = 0;
+ float _rewardMoneyMultiplier = 0.f;
+ uint32 _rewardBonusMoney = 0;
+ uint32 _rewardSpell = 0;
+ uint32 _rewardHonor = 0;
+ uint32 _rewardKillHonor = 0;
+ uint32 _rewardArtifactXPDifficulty = 0;
+ float _rewardArtifactXPMultiplier = 0.f;
+ uint32 _rewardArtifactCategoryID = 0;
+ uint32 _sourceItemId = 0;
+ uint32 _flags = 0;
+ uint32 _flagsEx = 0;
+ uint32 _flagsEx2 = 0;
+ uint32 _poiContinent = 0;
+ float _poix = 0.f;
+ float _poiy = 0.f;
+ uint32 _poiPriority = 0;
+ uint32 _rewardTitleId = 0;
+ int32 _rewardArenaPoints = 0;
+ uint32 _rewardSkillId = 0;
+ uint32 _rewardSkillPoints = 0;
+ uint32 _questGiverPortrait = 0;
+ int32 _questGiverPortraitMount = 0;
+ uint32 _questTurnInPortrait = 0;
+ uint32 _rewardReputationMask;
+ uint32 _soundAccept = 0;
+ uint32 _soundTurnIn = 0;
+ uint32 _areaGroupID = 0;
+ uint32 _limitTime = 0;
+ Trinity::RaceMask<uint64> _allowableRaces;
+ int32 _treasurePickerID = 0;
+ int32 _expansion = 0;
+ int32 _managedWorldStateID = 0;
+ int32 _questSessionBonus = 0;
+ std::string _logTitle;
+ std::string _logDescription;
+ std::string _questDescription;
+ std::string _areaDescription;
+ std::string _portraitGiverText;
+ std::string _portraitGiverName;
+ std::string _portraitTurnInText;
+ std::string _portraitTurnInName;
+ std::string _questCompletionLog;
// quest_request_items table
- uint32 EmoteOnComplete = 0;
- uint32 EmoteOnIncomplete = 0;
- uint32 EmoteOnCompleteDelay = 0;
- uint32 EmoteOnIncompleteDelay = 0;
- std::string RequestItemsText;
+ uint32 _emoteOnComplete = 0;
+ uint32 _emoteOnIncomplete = 0;
+ uint32 _emoteOnCompleteDelay = 0;
+ uint32 _emoteOnIncompleteDelay = 0;
+ std::string _requestItemsText;
// quest_offer_reward table
- uint32 OfferRewardEmote[QUEST_EMOTE_COUNT] = { };
- uint32 OfferRewardEmoteDelay[QUEST_EMOTE_COUNT] = { };
- std::string OfferRewardText;
+ std::string _offerRewardText;
// quest_template_addon table (custom data)
- uint32 MaxLevel = 0;
- uint32 AllowableClasses = 0;
- uint32 SourceSpellID = 0;
- int32 PrevQuestID = 0;
- int32 NextQuestID = 0;
- int32 ExclusiveGroup = 0;
- uint32 RewardMailTemplateId = 0;
- uint32 RewardMailDelay = 0;
- uint32 RequiredSkillId = 0;
- uint32 RequiredSkillPoints = 0;
- uint32 RequiredMinRepFaction = 0;
- int32 RequiredMinRepValue = 0;
- uint32 RequiredMaxRepFaction = 0;
- int32 RequiredMaxRepValue = 0;
- uint32 SourceItemIdCount = 0;
- uint32 RewardMailSenderEntry = 0;
- uint32 SpecialFlags = 0; // custom flags, not sniffed/WDB
- uint32 ScriptId = 0;
+ uint32 _maxLevel = 0;
+ uint32 _allowableClasses = 0;
+ uint32 _sourceSpellID = 0;
+ int32 _prevQuestID = 0;
+ uint32 _nextQuestID = 0;
+ int32 _exclusiveGroup = 0;
+ uint32 _rewardMailTemplateId = 0;
+ uint32 _rewardMailDelay = 0;
+ uint32 _requiredSkillId = 0;
+ uint32 _requiredSkillPoints = 0;
+ uint32 _requiredMinRepFaction = 0;
+ int32 _requiredMinRepValue = 0;
+ uint32 _requiredMaxRepFaction = 0;
+ int32 _requiredMaxRepValue = 0;
+ uint32 _sourceItemIdCount = 0;
+ uint32 _rewardMailSenderEntry = 0;
+ uint32 _specialFlags = 0; // custom flags, not sniffed/WDB
+ uint32 _scriptId = 0;
};
struct QuestStatusData
{
- QuestStatusData(): Status(QUEST_STATUS_NONE), Timer(0)
- {
- }
-
- QuestStatus Status;
- uint32 Timer;
- std::vector<int32> ObjectiveData;
+ QuestStatus Status = QUEST_STATUS_NONE;
+ uint32 Timer = 0;
+ std::vector<int32> ObjectiveData = { };
};
#endif
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 14db03c5b92..566ecfd9df8 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -215,7 +215,7 @@ NonDefaultConstructible<pAuraEffectHandler> AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleModMechanicImmunityMask, //147 SPELL_AURA_MECHANIC_IMMUNITY_MASK
&AuraEffect::HandleAuraRetainComboPoints, //148 SPELL_AURA_RETAIN_COMBO_POINTS
&AuraEffect::HandleNoImmediateEffect, //149 SPELL_AURA_REDUCE_PUSHBACK
- &AuraEffect::HandleShieldBlockValue, //150 SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT
+ &AuraEffect::HandleShieldBlockValuePercent, //150 SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT
&AuraEffect::HandleAuraTrackStealthed, //151 SPELL_AURA_TRACK_STEALTHED
&AuraEffect::HandleNoImmediateEffect, //152 SPELL_AURA_MOD_DETECTED_RANGE implemented in Creature::GetAttackDistance
&AuraEffect::HandleUnused, //153 Unused (4.3.4) old SPELL_AURA_SPLIT_DAMAGE_FLAT
@@ -347,7 +347,7 @@ NonDefaultConstructible<pAuraEffectHandler> AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleNoImmediateEffect, //279 SPELL_AURA_INITIALIZE_IMAGES
&AuraEffect::HandleUnused, //280 unused (4.3.4) old SPELL_AURA_MOD_ARMOR_PENETRATION_PCT
&AuraEffect::HandleNULL, //281 SPELL_AURA_MOD_GUILD_REPUTATION_GAIN_PCT
- &AuraEffect::HandleAuraIncreaseBaseHealthPercent, //282 SPELL_AURA_INCREASE_BASE_HEALTH_PERCENT
+ &AuraEffect::HandleAuraIncreaseBaseHealthPercent, //282 SPELL_AURA_MOD_BASE_HEALTH_PCT
&AuraEffect::HandleNoImmediateEffect, //283 SPELL_AURA_MOD_HEALING_RECEIVED implemented in Unit::SpellHealingBonus
&AuraEffect::HandleAuraLinked, //284 SPELL_AURA_LINKED
&AuraEffect::HandleAuraLinked, //285 SPELL_AURA_LINKED_2
@@ -790,6 +790,9 @@ void AuraEffect::ChangeAmount(int32 newAmount, bool mark, bool onStackOrReapply)
for (AuraApplication* aurApp : effectApplications)
{
+ if (aurApp->GetRemoveMode() != AURA_REMOVE_NONE)
+ continue;
+
aurApp->GetTarget()->_RegisterAuraEffect(this, true);
HandleEffect(aurApp, handleMask, true);
}
@@ -2038,7 +2041,7 @@ void AuraEffect::HandleAuraModScale(AuraApplication const* aurApp, uint8 mode, b
Unit* target = aurApp->GetTarget();
float scale = target->GetObjectScale();
- ApplyPercentModFloatVar(scale, float(GetAmount()), apply);
+ scale += CalculatePct(1.0f, apply ? GetAmount() : -GetAmount());
target->SetObjectScale(scale);
}
@@ -2223,11 +2226,15 @@ void AuraEffect::HandleAuraModDisarm(AuraApplication const* aurApp, uint8 mode,
Player* player = target->ToPlayer();
if (Item* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
{
- uint8 attacktype = Player::GetAttackBySlot(slot, item->GetTemplate()->GetInventoryType());
+ WeaponAttackType const attackType = Player::GetAttackBySlot(slot, item->GetTemplate()->GetInventoryType());
player->ApplyItemDependentAuras(item, !apply);
- if (attacktype < MAX_ATTACK)
+ if (attackType != MAX_ATTACK)
+ {
player->_ApplyWeaponDamage(slot, item, !apply);
+ if (!apply) // apply case already handled on item dependent aura removal (if any)
+ player->UpdateWeaponDependentAuras(attackType);
+ }
}
}
@@ -2719,9 +2726,19 @@ void AuraEffect::HandleModThreat(AuraApplication const* aurApp, uint8 mode, bool
return;
Unit* target = aurApp->GetTarget();
- for (int8 i = 0; i < MAX_SPELL_SCHOOL; ++i)
+ for (uint8 i = 0; i < MAX_SPELL_SCHOOL; ++i)
+ {
if (GetMiscValue() & (1 << i))
- ApplyPercentModFloatVar(target->m_threatModifier[i], float(GetAmount()), apply);
+ {
+ if (apply)
+ AddPct(target->m_threatModifier[i], GetAmount());
+ else
+ {
+ float amount = target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_THREAT, 1 << i);
+ target->m_threatModifier[i] = amount;
+ }
+ }
+ }
}
void AuraEffect::HandleAuraModTotalThreat(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -3210,9 +3227,9 @@ void AuraEffect::HandleAuraModResistance(AuraApplication const* aurApp, uint8 mo
Unit* target = aurApp->GetTarget();
- for (int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; x++)
- if (GetMiscValue() & int32(1<<x))
- target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(GetAmount()), apply);
+ for (uint8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; ++x)
+ if (GetMiscValue() & (1 << x))
+ target->HandleStatFlatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(GetAmount()), apply);
}
void AuraEffect::HandleAuraModBaseResistancePCT(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -3227,36 +3244,50 @@ void AuraEffect::HandleAuraModBaseResistancePCT(AuraApplication const* aurApp, u
{
//pets only have base armor
if (target->IsPet() && (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL))
- target->HandleStatModifier(UNIT_MOD_ARMOR, BASE_PCT, float(GetAmount()), apply);
+ {
+ if (apply)
+ target->ApplyStatPctModifier(UNIT_MOD_ARMOR, BASE_PCT, float(GetAmount()));
+ else
+ {
+ float amount = target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_BASE_RESISTANCE_PCT, SPELL_SCHOOL_MASK_NORMAL);
+ target->SetStatPctModifier(UNIT_MOD_ARMOR, BASE_PCT, amount);
+ }
+ }
}
else
{
- for (int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; x++)
+ for (uint8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; ++x)
{
- if (GetMiscValue() & int32(1<<x))
- target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(GetAmount()), apply);
+ if (GetMiscValue() & (1 << x))
+ {
+ if (apply)
+ target->ApplyStatPctModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(GetAmount()));
+ else
+ {
+ float amount = target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_BASE_RESISTANCE_PCT, 1 << x);
+ target->SetStatPctModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, amount);
+ }
+ }
}
}
}
-void AuraEffect::HandleModResistancePercent(AuraApplication const* aurApp, uint8 mode, bool apply) const
+void AuraEffect::HandleModResistancePercent(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit* target = aurApp->GetTarget();
- int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_RESISTANCE_PCT);
- if (abs(spellGroupVal) >= abs(GetAmount()))
- return;
- for (int8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
+ for (uint8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; ++i)
{
- if (GetMiscValue() & int32(1<<i))
+ if (GetMiscValue() & (1 << i))
{
- if (spellGroupVal)
- target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, (float)spellGroupVal, !apply);
+ float amount = target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_RESISTANCE_PCT, 1 << i);
+ if (target->GetPctModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT) == amount)
+ continue;
- target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(GetAmount()), apply);
+ target->SetStatPctModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, amount);
}
}
}
@@ -3271,15 +3302,15 @@ void AuraEffect::HandleModBaseResistance(AuraApplication const* aurApp, uint8 mo
// only players have base stats
if (target->GetTypeId() != TYPEID_PLAYER)
{
- //only pets have base stats
+ //pets only have base armor
if (target->IsPet() && (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL))
- target->HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(GetAmount()), apply);
+ target->HandleStatFlatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(GetAmount()), apply);
}
else
{
- for (int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
- if (GetMiscValue() & (1<<i))
- target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(GetAmount()), apply);
+ for (uint8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; ++i)
+ if (GetMiscValue() & (1 << i))
+ target->HandleStatFlatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(GetAmount()), apply);
}
}
@@ -3323,22 +3354,21 @@ void AuraEffect::HandleAuraModStat(AuraApplication const* aurApp, uint8 mode, bo
if (abs(spellGroupVal) >= abs(GetAmount()))
return;
- for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
+ for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i)
{
// -1 or -2 is all stats (misc < -2 checked in function beginning)
if (GetMiscValue() < 0 || GetMiscValue() == i)
{
if (spellGroupVal)
{
- target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(spellGroupVal), !apply);
+ target->HandleStatFlatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(spellGroupVal), !apply);
if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet())
- target->ApplyStatBuffMod(Stats(i), float(spellGroupVal), !apply);
+ target->UpdateStatBuffMod(Stats(i));
}
- //target->ApplyStatMod(Stats(i), m_amount, apply);
- target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(GetAmount()), apply);
+ target->HandleStatFlatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(GetAmount()), apply);
if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet())
- target->ApplyStatBuffMod(Stats(i), (float)GetAmount(), apply);
+ target->UpdateStatBuffMod(Stats(i));
}
}
}
@@ -3363,7 +3393,20 @@ void AuraEffect::HandleModPercentStat(AuraApplication const* aurApp, uint8 mode,
for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i)
{
if (GetMiscValue() == i || GetMiscValue() == -1)
- target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(m_amount), apply);
+ {
+ if (apply)
+ target->ApplyStatPctModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(m_amount));
+ else
+ {
+ float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_PERCENT_STAT, [i](AuraEffect const* aurEff) -> bool
+ {
+ if (aurEff->GetMiscValue() == i || aurEff->GetMiscValue() == -1)
+ return true;
+ return false;
+ });
+ target->SetStatPctModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, amount);
+ }
+ }
}
}
@@ -3450,28 +3493,12 @@ void AuraEffect::HandleModHealingDonePct(AuraApplication const* aurApp, uint8 mo
player->UpdateHealingDonePercentMod();
}
-void AuraEffect::HandleModTotalPercentStat(AuraApplication const* aurApp, uint8 mode, bool apply) const
+void AuraEffect::HandleModTotalPercentStat(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit* target = aurApp->GetTarget();
- int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, true, -1);
- if (abs(spellGroupVal) >= abs(GetAmount()))
- return;
-
- if (spellGroupVal)
- {
- for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
- {
- if (GetMiscValue() == i || GetMiscValue() == -1) // affect the same stats
- {
- target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(spellGroupVal), !apply);
- if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet())
- target->ApplyStatPercentBuffMod(Stats(i), float(spellGroupVal), !apply);
- }
- }
- }
// save current health state
float healthPct = target->GetHealthPct();
@@ -3483,30 +3510,29 @@ void AuraEffect::HandleModTotalPercentStat(AuraApplication const* aurApp, uint8
if (target->getDeathState() == CORPSE)
zeroHealth = (target->GetHealth() == 0);
- for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
+ for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i)
{
if (GetMiscValueB() & 1 << i || !GetMiscValueB()) // 0 is also used for all stats
{
- int32 spellGroupVal2 = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, true, i);
- if (abs(spellGroupVal2) >= abs(GetAmount()))
- continue;
-
- if (spellGroupVal2)
+ float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, [i](AuraEffect const* aurEff) -> bool
{
- target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(spellGroupVal2), !apply);
- if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet())
- target->ApplyStatPercentBuffMod(Stats(i), float(spellGroupVal2), !apply);
- }
+ if (aurEff->GetMiscValueB() & 1 << i || !aurEff->GetMiscValueB())
+ return true;
+ return false;
+ });
- target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(GetAmount()), apply);
+ if (target->GetPctModifierValue(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT) == amount)
+ continue;
+
+ target->SetStatPctModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, amount);
if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet())
- target->ApplyStatPercentBuffMod(Stats(i), float(GetAmount()), apply);
+ target->UpdateStatBuffMod(Stats(i));
}
}
- // recalculate current HP/MP after applying aura modifications (only for spells with SPELL_ATTR0_UNK4 0x00000010 flag)
+ // recalculate current HP/MP after applying aura modifications (only for spells with SPELL_ATTR0_ABILITY 0x00000010 flag)
// this check is total bullshit i think
- if (GetMiscValueB() & 1 << STAT_STAMINA && (m_spellInfo->HasAttribute(SPELL_ATTR0_ABILITY)))
+ if ((GetMiscValueB() & 1 << STAT_STAMINA || !GetMiscValueB()) && (m_spellInfo->HasAttribute(SPELL_ATTR0_ABILITY)))
target->SetHealth(std::max<uint32>(CalculatePct(target->GetMaxHealth(), healthPct), (zeroHealth ? 0 : 1)));
}
@@ -3567,8 +3593,8 @@ void AuraEffect::HandleModStatBonusPercent(AuraApplication const* aurApp, uint8
{
if (GetMiscValue() == i || GetMiscValue() == -1)
{
- target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT_EXCLUDE_CREATE, float(m_amount), apply);
- target->ApplyStatPercentBuffMod(Stats(i), float(m_amount), apply);
+ target->HandleStatFlatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT_EXCLUDE_CREATE, float(m_amount), apply);
+ target->UpdateStatBuffMod(Stats(i));
}
}
}
@@ -3623,7 +3649,7 @@ void AuraEffect::HandleAuraModMaxPower(AuraApplication const* aurApp, uint8 mode
Powers power = Powers(GetMiscValue());
UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + power);
- target->HandleStatModifier(unitMod, TOTAL_VALUE, float(GetAmount()), apply);
+ target->HandleStatFlatModifier(unitMod, TOTAL_VALUE, float(GetAmount()), apply);
}
/********************************/
@@ -3688,7 +3714,7 @@ void AuraEffect::HandleAuraModIncreaseHealth(AuraApplication const* aurApp, uint
if (apply)
{
- target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply);
+ target->HandleStatFlatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply);
target->ModifyHealth(GetAmount());
}
else
@@ -3698,7 +3724,7 @@ void AuraEffect::HandleAuraModIncreaseHealth(AuraApplication const* aurApp, uint
int32 value = std::min<int32>(target->GetHealth() - 1, GetAmount());
target->ModifyHealth(-value);
}
- target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply);
+ target->HandleStatFlatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply);
}
}
@@ -3711,7 +3737,7 @@ void AuraEffect::HandleAuraModIncreaseMaxHealth(AuraApplication const* aurApp, u
float percent = target->GetHealthPct();
- target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply);
+ target->HandleStatFlatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply);
// refresh percentage
if (target->GetHealth() > 0)
@@ -3730,7 +3756,7 @@ void AuraEffect::HandleAuraModIncreaseEnergy(AuraApplication const* aurApp, uint
Powers powerType = Powers(GetMiscValue());
UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + powerType);
- target->HandleStatModifier(unitMod, TOTAL_VALUE, float(GetAmount()), apply);
+ target->HandleStatFlatModifier(unitMod, TOTAL_VALUE, float(GetAmount()), apply);
}
void AuraEffect::HandleAuraModIncreaseEnergyPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -3748,7 +3774,26 @@ void AuraEffect::HandleAuraModIncreaseEnergyPercent(AuraApplication const* aurAp
int32 oldMaxPower = target->GetMaxPower(powerType);
// Handle aura effect for max power
- target->HandleStatModifier(unitMod, TOTAL_PCT, float(GetAmount()), apply);
+ if (apply)
+ target->ApplyStatPctModifier(unitMod, TOTAL_PCT, float(GetAmount()));
+ else
+ {
+ float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT, [powerType](AuraEffect const* aurEff) -> bool
+ {
+ if (aurEff->GetMiscValue() == powerType)
+ return true;
+ return false;
+ });
+
+ amount *= target->GetTotalAuraMultiplier(SPELL_AURA_MOD_MAX_POWER_PCT, [powerType](AuraEffect const* aurEff) -> bool
+ {
+ if (aurEff->GetMiscValue() == powerType)
+ return true;
+ return false;
+ });
+
+ target->SetStatPctModifier(unitMod, TOTAL_PCT, amount);
+ }
// Calculate the current power change
int32 change = target->GetMaxPower(powerType) - oldMaxPower;
@@ -3765,11 +3810,17 @@ void AuraEffect::HandleAuraModIncreaseHealthPercent(AuraApplication const* aurAp
// Unit will keep hp% after MaxHealth being modified if unit is alive.
float percent = target->GetHealthPct();
- target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(GetAmount()), apply);
+ if (apply)
+ target->ApplyStatPctModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(GetAmount()));
+ else
+ {
+ float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT);
+ target->SetStatPctModifier(UNIT_MOD_HEALTH, TOTAL_PCT, amount);
+ }
if (target->GetHealth() > 0)
{
- uint32 newHealth = std::max<uint32>(target->CountPctFromMaxHealth(int32(percent)), 1);
+ uint32 newHealth = std::max<uint32>(CalculatePct(target->GetMaxHealth(), percent), 1);
target->SetHealth(newHealth);
}
}
@@ -3781,7 +3832,13 @@ void AuraEffect::HandleAuraIncreaseBaseHealthPercent(AuraApplication const* aurA
Unit* target = aurApp->GetTarget();
- target->HandleStatModifier(UNIT_MOD_HEALTH, BASE_PCT, float(GetAmount()), apply);
+ if (apply)
+ target->ApplyStatPctModifier(UNIT_MOD_HEALTH, BASE_PCT, float(GetAmount()));
+ else
+ {
+ float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_BASE_HEALTH_PCT);
+ target->SetStatPctModifier(UNIT_MOD_HEALTH, BASE_PCT, amount);
+ }
}
void AuraEffect::HandleAuraModIncreaseBaseManaPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -3789,7 +3846,15 @@ void AuraEffect::HandleAuraModIncreaseBaseManaPercent(AuraApplication const* aur
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
- aurApp->GetTarget()->HandleStatModifier(UNIT_MOD_MANA, BASE_PCT, float(GetAmount()), apply);
+ Unit* target = aurApp->GetTarget();
+
+ if (apply)
+ target->ApplyStatPctModifier(UNIT_MOD_MANA, BASE_PCT, float(GetAmount()));
+ else
+ {
+ float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_BASE_MANA_PCT);
+ target->SetStatPctModifier(UNIT_MOD_MANA, BASE_PCT, amount);
+ }
}
void AuraEffect::HandleAuraModPowerDisplay(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -3845,7 +3910,26 @@ void AuraEffect::HandleAuraModMaxPowerPct(AuraApplication const* aurApp, uint8 m
int32 oldMaxPower = target->GetMaxPower(powerType);
// Handle aura effect for max power
- target->HandleStatModifier(unitMod, TOTAL_PCT, float(GetAmount()), apply);
+ if (apply)
+ target->ApplyStatPctModifier(unitMod, TOTAL_PCT, float(GetAmount()));
+ else
+ {
+ float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_MAX_POWER_PCT, [powerType](AuraEffect const* aurEff) -> bool
+ {
+ if (aurEff->GetMiscValue() == powerType)
+ return true;
+ return false;
+ });
+
+ amount *= target->GetTotalAuraMultiplier(SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT, [powerType](AuraEffect const* aurEff) -> bool
+ {
+ if (aurEff->GetMiscValue() == powerType)
+ return true;
+ return false;
+ });
+
+ target->SetStatPctModifier(unitMod, TOTAL_PCT, amount);
+ }
// Calculate the current power change
int32 change = target->GetMaxPower(powerType) - oldMaxPower;
@@ -3901,19 +3985,16 @@ void AuraEffect::HandleAuraModRegenInterrupt(AuraApplication const* aurApp, uint
HandleModManaRegen(aurApp, mode, apply);
}
-void AuraEffect::HandleAuraModWeaponCritPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const
+void AuraEffect::HandleAuraModWeaponCritPercent(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Player* target = aurApp->GetTarget()->ToPlayer();
-
if (!target)
return;
- target->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float(GetAmount()), apply);
- target->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float(GetAmount()), apply);
- target->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float(GetAmount()), apply);
+ target->UpdateAllWeaponDependentCritAuras();
}
void AuraEffect::HandleModHitChance(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -3945,7 +4026,7 @@ void AuraEffect::HandleModSpellHitChance(AuraApplication const* aurApp, uint8 mo
if (target->GetTypeId() == TYPEID_PLAYER)
target->ToPlayer()->UpdateSpellHitChances();
else
- target->m_modSpellHitChance += (apply) ? GetAmount(): (-GetAmount());
+ target->m_modSpellHitChance += (apply) ? GetAmount() : (-GetAmount());
}
void AuraEffect::HandleModSpellCritChance(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -3958,7 +4039,7 @@ void AuraEffect::HandleModSpellCritChance(AuraApplication const* aurApp, uint8 m
if (target->GetTypeId() == TYPEID_PLAYER)
target->ToPlayer()->UpdateSpellCritChance();
else
- target->m_baseSpellCritChance += (apply) ? GetAmount():-GetAmount();
+ target->m_baseSpellCritChance += (apply) ? GetAmount() : -GetAmount();
}
void AuraEffect::HandleAuraModCritPct(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -3970,13 +4051,11 @@ void AuraEffect::HandleAuraModCritPct(AuraApplication const* aurApp, uint8 mode,
if (target->GetTypeId() != TYPEID_PLAYER)
{
- target->m_baseSpellCritChance += (apply) ? GetAmount():-GetAmount();
+ target->m_baseSpellCritChance += (apply) ? GetAmount() : -GetAmount();
return;
}
- target->ToPlayer()->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply);
- target->ToPlayer()->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply);
- target->ToPlayer()->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply);
+ target->ToPlayer()->UpdateAllWeaponDependentCritAuras();
// included in Player::UpdateSpellCritChance calculation
target->ToPlayer()->UpdateSpellCritChance();
@@ -4136,7 +4215,7 @@ void AuraEffect::HandleAuraModAttackPower(AuraApplication const* aurApp, uint8 m
Unit* target = aurApp->GetTarget();
- target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(GetAmount()), apply);
+ target->HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(GetAmount()), apply);
}
void AuraEffect::HandleAuraModRangedAttackPower(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -4149,7 +4228,7 @@ void AuraEffect::HandleAuraModRangedAttackPower(AuraApplication const* aurApp, u
if ((target->getClassMask() & CLASSMASK_WAND_USERS) != 0)
return;
- target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(GetAmount()), apply);
+ target->HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(GetAmount()), apply);
}
void AuraEffect::HandleAuraModAttackPowerPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -4160,7 +4239,13 @@ void AuraEffect::HandleAuraModAttackPowerPercent(AuraApplication const* aurApp,
Unit* target = aurApp->GetTarget();
//UNIT_FIELD_ATTACK_POWER_MULTIPLIER = multiplier - 1
- target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(GetAmount()), apply);
+ if (apply)
+ target->ApplyStatPctModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(GetAmount()));
+ else
+ {
+ float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_ATTACK_POWER_PCT);
+ target->SetStatPctModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, amount);
+ }
}
void AuraEffect::HandleAuraModRangedAttackPowerPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -4174,7 +4259,13 @@ void AuraEffect::HandleAuraModRangedAttackPowerPercent(AuraApplication const* au
return;
//UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = multiplier - 1
- target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(GetAmount()), apply);
+ if (apply)
+ target->ApplyStatPctModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(GetAmount()));
+ else
+ {
+ float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_RANGED_ATTACK_POWER_PCT);
+ target->SetStatPctModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, amount);
+ }
}
/********************************/
@@ -4188,11 +4279,7 @@ void AuraEffect::HandleModDamageDone(AuraApplication const* aurApp, uint8 mode,
Unit* target = aurApp->GetTarget();
if (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)
- {
- target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(GetAmount()), apply);
- target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(GetAmount()), apply);
- target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(GetAmount()), apply);
- }
+ target->UpdateAllDamageDoneMods();
// Magic damage modifiers implemented in Unit::SpellBaseDamageBonusDone
// This information for client side use only
@@ -4212,53 +4299,40 @@ void AuraEffect::HandleModDamageDone(AuraApplication const* aurApp, uint8 mode,
}
}
-void AuraEffect::HandleModDamagePercentDone(AuraApplication const* aurApp, uint8 mode, bool apply) const
+void AuraEffect::HandleModDamagePercentDone(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit* target = aurApp->GetTarget();
- int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
- if (abs(spellGroupVal) >= abs(GetAmount()))
- return;
+ // also handles spell group stacks
if (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)
- {
- if (spellGroupVal)
- {
- target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(spellGroupVal), !apply);
- target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(spellGroupVal), !apply);
- target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(spellGroupVal), !apply);
- }
-
- target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(GetAmount()), apply);
- target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(GetAmount()), apply);
- target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(GetAmount()), apply);
- }
+ target->UpdateAllDamagePctDoneMods();
if (Player* thisPlayer = target->ToPlayer())
{
- for (uint16 i = 0; i < MAX_SPELL_SCHOOL; ++i)
+ for (uint8 i = 0; i < MAX_SPELL_SCHOOL; ++i)
{
if (GetMiscValue() & (1 << i))
{
- if (spellGroupVal)
- thisPlayer->ApplyModDamageDonePercent(SpellSchools(i), float(spellGroupVal), !apply);
-
- thisPlayer->ApplyModDamageDonePercent(SpellSchools(i), float(GetAmount()), apply);
+ // only aura type modifying PLAYER_FIELD_MOD_DAMAGE_DONE_PCT
+ float amount = thisPlayer->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, 1 << i);
+ thisPlayer->SetModDamageDonePercent(i, amount);
}
}
}
}
-void AuraEffect::HandleModOffhandDamagePercent(AuraApplication const* aurApp, uint8 mode, bool apply) const
+void AuraEffect::HandleModOffhandDamagePercent(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit* target = aurApp->GetTarget();
- target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(GetAmount()), apply);
+ // also handles spell group stacks
+ target->UpdateDamagePctDoneMods(OFF_ATTACK);
}
void AuraEffect::HandleShieldBlockValue(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -4267,7 +4341,25 @@ void AuraEffect::HandleShieldBlockValue(AuraApplication const* aurApp, uint8 mod
return;
if (Player* player = aurApp->GetTarget()->ToPlayer())
- player->HandleBaseModValue(SHIELD_BLOCK_VALUE, PCT_MOD, float(GetAmount()), apply);
+ player->HandleBaseModFlatValue(SHIELD_BLOCK_VALUE, float(GetAmount()), apply);
+}
+
+void AuraEffect::HandleShieldBlockValuePercent(AuraApplication const* aurApp, uint8 mode, bool apply) const
+{
+ if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
+ return;
+
+ Player* target = aurApp->GetTarget()->ToPlayer();
+ if (!target)
+ return;
+
+ if (apply)
+ target->ApplyBaseModPctValue(SHIELD_BLOCK_VALUE, float(GetAmount()));
+ else
+ {
+ float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT);
+ target->SetBaseModPctValue(SHIELD_BLOCK_VALUE, amount);
+ }
}
/********************************/
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h
index 138ea474e31..7b74320bdef 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.h
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.h
@@ -290,6 +290,7 @@ class TC_GAME_API AuraEffect
void HandleModDamagePercentDone(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleModOffhandDamagePercent(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleShieldBlockValue(AuraApplication const* aurApp, uint8 mode, bool apply) const;
+ void HandleShieldBlockValuePercent(AuraApplication const* aurApp, uint8 mode, bool apply) const;
// power cost
void HandleModPowerCostPCT(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleModPowerCost(AuraApplication const* aurApp, uint8 mode, bool apply) const;
diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp
index 074da315ad3..175959a15d4 100644
--- a/src/server/game/Spells/Auras/SpellAuras.cpp
+++ b/src/server/game/Spells/Auras/SpellAuras.cpp
@@ -2312,7 +2312,7 @@ void UnitAura::FillTargetMap(std::unordered_map<Unit*, uint32>& targets, Unit* c
case SPELL_EFFECT_APPLY_AREA_AURA_RAID:
{
units.push_back(GetUnitOwner());
- Trinity::AnyGroupedUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius, effect->Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID, m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS));
+ Trinity::AnyGroupedUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius, effect->Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID, m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS), false, true);
Trinity::UnitListSearcher<Trinity::AnyGroupedUnitInObjectRangeCheck> searcher(GetUnitOwner(), units, u_check);
Cell::VisitAllObjects(GetUnitOwner(), searcher, radius);
break;
@@ -2320,14 +2320,14 @@ void UnitAura::FillTargetMap(std::unordered_map<Unit*, uint32>& targets, Unit* c
case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND:
{
units.push_back(GetUnitOwner());
- Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius, m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS));
+ Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius, m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS), false, true);
Trinity::UnitListSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(GetUnitOwner(), units, u_check);
Cell::VisitAllObjects(GetUnitOwner(), searcher, radius);
break;
}
case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY:
{
- Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius, m_spellInfo); // No GetCharmer in searcher
+ Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius, m_spellInfo, false, true); // No GetCharmer in searcher
Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(GetUnitOwner(), units, u_check);
Cell::VisitAllObjects(GetUnitOwner(), searcher, radius);
break;
@@ -2396,13 +2396,13 @@ void DynObjAura::FillTargetMap(std::unordered_map<Unit*, uint32>& targets, Unit*
if (effect->TargetB.GetTarget() == TARGET_DEST_DYNOBJ_ALLY
|| effect->TargetB.GetTarget() == TARGET_UNIT_DEST_AREA_ALLY)
{
- Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(GetDynobjOwner(), dynObjOwnerCaster, radius, m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS));
+ Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(GetDynobjOwner(), dynObjOwnerCaster, radius, m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS), false, true);
Trinity::UnitListSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(GetDynobjOwner(), units, u_check);
Cell::VisitAllObjects(GetDynobjOwner(), searcher, radius);
}
else
{
- Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(GetDynobjOwner(), dynObjOwnerCaster, radius);
+ Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(GetDynobjOwner(), dynObjOwnerCaster, radius, nullptr, false, true);
Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(GetDynobjOwner(), units, u_check);
Cell::VisitAllObjects(GetDynobjOwner(), searcher, radius);
}
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 8ef877e6881..779b0d0495c 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -1245,6 +1245,11 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge
if (!effect)
return;
float radius = effect->CalcRadius(m_caster) * m_spellValue->RadiusMod;
+
+ // if this is a proximity based aoe (Frost Nova, Psychic Scream, ...), include the caster's own combat reach
+ if (targetType.IsProximityBasedAoe())
+ radius += GetCaster()->GetCombatReach();
+
SearchAreaTargets(targets, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), effect->ImplicitTargetConditions);
CallScriptObjectAreaTargetSelectHandlers(targets, effIndex, targetType);
@@ -1300,7 +1305,7 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici
float dist = frand(minDist, maxDist);
float x, y, z;
float angle = float(rand_norm()) * static_cast<float>(M_PI * 35.0f / 180.0f) - static_cast<float>(M_PI * 17.5f / 180.0f);
- m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE, dist, angle);
+ m_caster->GetClosePoint(x, y, z, DEFAULT_PLAYER_BOUNDING_RADIUS, dist, angle);
float ground = m_caster->GetMap()->GetHeight(m_caster->GetPhaseShift(), x, y, z, true, 50.0f);
float liquidLevel = VMAP_INVALID_HEIGHT_VALUE;
@@ -1333,7 +1338,7 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici
{
float dist = effect->CalcRadius(m_caster);
float angle = targetType.CalcDirectionAngle();
- float objSize = m_caster->GetObjectSize();
+ float objSize = m_caster->GetCombatReach();
switch (targetType.GetTarget())
{
@@ -1391,7 +1396,7 @@ void Spell::SelectImplicitTargetDestTargets(SpellEffIndex effIndex, SpellImplici
if (SpellEffectInfo const* effect = GetEffect(effIndex))
{
float angle = targetType.CalcDirectionAngle();
- float objSize = target->GetObjectSize();
+ float objSize = target->GetCombatReach();
float dist = effect->CalcRadius(m_caster);
if (dist < objSize)
dist = objSize;
@@ -1615,7 +1620,7 @@ void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex, SpellImplicitTarge
}
}
- const float size = std::max((*itr)->GetObjectSize(), 1.0f);
+ const float size = std::max((*itr)->GetCombatReach(), 1.0f);
const float objDist2d = srcPos.GetExactDist2d(*itr);
const float dz = (*itr)->GetPositionZ() - srcPos.m_positionZ;
@@ -5300,13 +5305,13 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint
if (!target->IsWithinLOSInMap(m_caster)) //Do full LoS/Path check. Don't exclude m2
return SPELL_FAILED_LINE_OF_SIGHT;
- float objSize = target->GetObjectSize();
+ float objSize = target->GetCombatReach();
float range = m_spellInfo->GetMaxRange(true, m_caster, this) * 1.5f + objSize; // can't be overly strict
m_preGeneratedPath = Trinity::make_unique<PathGenerator>(m_caster);
m_preGeneratedPath->SetPathLengthLimit(range);
// first try with raycast, if it fails fall back to normal path
- float targetObjectSize = std::min(target->GetObjectSize(), 4.0f);
+ float targetObjectSize = std::min(target->GetCombatReach(), 4.0f);
bool result = m_preGeneratedPath->CalculatePath(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ() + targetObjectSize, false, true);
if (m_preGeneratedPath->GetPathType() & PATHFIND_SHORT)
return SPELL_FAILED_OUT_OF_RANGE;
@@ -7895,8 +7900,20 @@ WorldObjectSpellAreaTargetCheck::WorldObjectSpellAreaTargetCheck(float range, Po
bool WorldObjectSpellAreaTargetCheck::operator()(WorldObject* target)
{
- if (!target->IsWithinDist3d(_position, _range) && !(target->ToGameObject() && target->ToGameObject()->IsInRange(_position->GetPositionX(), _position->GetPositionY(), _position->GetPositionZ(), _range)))
- return false;
+ if (target->ToGameObject())
+ {
+ // isInRange including the dimension of the GO
+ bool isInRange = target->ToGameObject()->IsInRange(_position->GetPositionX(), _position->GetPositionY(), _position->GetPositionZ(), _range);
+ if (!isInRange)
+ return false;
+ }
+ else
+ {
+ bool isInsideCylinder = target->IsWithinDist2d(_position, _range) && std::abs(target->GetPositionZ() - _position->GetPositionZ()) <= _range;
+ if (!isInsideCylinder)
+ return false;
+ }
+
return WorldObjectSpellTargetCheck::operator ()(target);
}
@@ -7913,7 +7930,7 @@ bool WorldObjectSpellConeTargetCheck::operator()(WorldObject* target)
}
else if (_spellInfo->HasAttribute(SPELL_ATTR0_CU_CONE_LINE))
{
- if (!_caster->HasInLine(target, target->GetObjectSize(), _caster->GetObjectSize()))
+ if (!_caster->HasInLine(target, target->GetCombatReach(), _caster->GetCombatReach()))
return false;
}
else
@@ -7933,7 +7950,7 @@ WorldObjectSpellTrajTargetCheck::WorldObjectSpellTrajTargetCheck(float range, Po
bool WorldObjectSpellTrajTargetCheck::operator()(WorldObject* target)
{
// return all targets on missile trajectory (0 - size of a missile)
- if (!_caster->HasInLine(target, target->GetObjectSize(), TRAJECTORY_MISSILE_SIZE))
+ if (!_caster->HasInLine(target, target->GetCombatReach(), TRAJECTORY_MISSILE_SIZE))
return false;
if (target->GetExactDist2d(_position) > _range)
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 6acb790d8e8..56a050eea65 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -2306,7 +2306,7 @@ void Spell::EffectTeleUnitsFaceCaster(SpellEffIndex /*effIndex*/)
float dis = effectInfo->CalcRadius(m_caster);
float fx, fy, fz;
- m_caster->GetClosePoint(fx, fy, fz, unitTarget->GetObjectSize(), dis);
+ m_caster->GetClosePoint(fx, fy, fz, unitTarget->GetCombatReach(), dis);
unitTarget->NearTeleportTo(fx, fy, fz, -m_caster->GetOrientation(), unitTarget == m_caster);
}
@@ -2659,7 +2659,7 @@ void Spell::EffectSummonPet(SpellEffIndex effIndex)
//OldSummon->GetMap()->Remove(OldSummon->ToCreature(), false);
float px, py, pz;
- owner->GetClosePoint(px, py, pz, OldSummon->GetObjectSize());
+ owner->GetClosePoint(px, py, pz, OldSummon->GetCombatReach());
OldSummon->NearTeleportTo(px, py, pz, OldSummon->GetOrientation());
//OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation());
@@ -2679,7 +2679,7 @@ void Spell::EffectSummonPet(SpellEffIndex effIndex)
}
float x, y, z;
- owner->GetClosePoint(x, y, z, owner->GetObjectSize());
+ owner->GetClosePoint(x, y, z, owner->GetCombatReach());
Pet* pet = owner->SummonPet(petentry, x, y, z, owner->GetOrientation(), SUMMON_PET, 0);
if (!pet)
return;
@@ -2912,7 +2912,7 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; break;
}
- float weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
+ float weapon_total_pct = m_caster->GetPctModifierValue(unitMod, TOTAL_PCT);
if (fixed_bonus)
fixed_bonus = int32(fixed_bonus * weapon_total_pct);
if (spell_bonus)
@@ -3041,7 +3041,7 @@ void Spell::EffectSummonObjectWild(SpellEffIndex effIndex)
if (m_targets.HasDst())
destTarget->GetPosition(x, y, z);
else
- m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE);
+ m_caster->GetClosePoint(x, y, z, DEFAULT_PLAYER_BOUNDING_RADIUS);
Map* map = target->GetMap();
Position pos = Position(x, y, z, target->GetOrientation());
@@ -3922,7 +3922,7 @@ void Spell::EffectSummonObject(SpellEffIndex effIndex)
destTarget->GetPosition(x, y, z);
// Summon in random point all other units if location present
else
- m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE);
+ m_caster->GetClosePoint(x, y, z, DEFAULT_PLAYER_BOUNDING_RADIUS);
Map* map = m_caster->GetMap();
Position pos = Position(x, y, z, m_caster->GetOrientation());
@@ -4219,7 +4219,7 @@ void Spell::EffectCharge(SpellEffIndex /*effIndex*/)
if (m_preGeneratedPath->GetPathType() == PATHFIND_BLANK)
{
//unitTarget->GetContactPoint(m_caster, pos.m_positionX, pos.m_positionY, pos.m_positionZ);
- Position pos = unitTarget->GetFirstCollisionPosition(unitTarget->GetObjectSize(), unitTarget->GetRelativeAngle(m_caster));
+ Position pos = unitTarget->GetFirstCollisionPosition(unitTarget->GetCombatReach(), unitTarget->GetRelativeAngle(m_caster));
if (G3D::fuzzyGt(m_spellInfo->Speed, 0.0f) && m_spellInfo->HasAttribute(SPELL_ATTR9_SPECIAL_DELAY_CALCULATION))
speed = pos.GetExactDist(m_caster) / speed;
@@ -4493,7 +4493,7 @@ void Spell::EffectResurrectPet(SpellEffIndex /*effIndex*/)
// Reposition the pet's corpse before reviving so as not to grab aggro
// We can use a different, more accurate version of GetClosePoint() since we have a pet
float x, y, z; // Will be used later to reposition the pet if we have one
- player->GetClosePoint(x, y, z, pet->GetObjectSize(), PET_FOLLOW_DIST, pet->GetFollowAngle());
+ player->GetClosePoint(x, y, z, pet->GetCombatReach(), PET_FOLLOW_DIST, pet->GetFollowAngle());
pet->NearTeleportTo(x, y, z, player->GetOrientation());
pet->Relocate(x, y, z, player->GetOrientation()); // This is needed so SaveStayPosition() will get the proper coords.
}
@@ -4501,7 +4501,7 @@ void Spell::EffectResurrectPet(SpellEffIndex /*effIndex*/)
pet->SetDynamicFlags(UNIT_DYNFLAG_NONE);
pet->RemoveUnitFlag(UNIT_FLAG_SKINNABLE);
pet->setDeathState(ALIVE);
- pet->ClearUnitState(uint32(UNIT_STATE_ALL_STATE));
+ pet->ClearUnitState(UNIT_STATE_ALL_ERASABLE);
pet->SetHealth(pet->CountPctFromMaxHealth(damage));
// Reset things for when the AI to takes over
@@ -4656,7 +4656,7 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex)
else if (effectInfo->HasRadius() && m_spellInfo->Speed == 0)
{
float dis = effectInfo->CalcRadius(m_originalCaster);
- m_caster->GetClosePoint(fx, fy, fz, DEFAULT_WORLD_OBJECT_SIZE, dis);
+ m_caster->GetClosePoint(fx, fy, fz, DEFAULT_PLAYER_BOUNDING_RADIUS, dis);
}
else
{
@@ -4665,7 +4665,7 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex)
float max_dis = m_spellInfo->GetMaxRange(true);
float dis = (float)rand_norm() * (max_dis - min_dis) + min_dis;
- m_caster->GetClosePoint(fx, fy, fz, DEFAULT_WORLD_OBJECT_SIZE, dis);
+ m_caster->GetClosePoint(fx, fy, fz, DEFAULT_PLAYER_BOUNDING_RADIUS, dis);
}
Map* cMap = m_caster->GetMap();
@@ -5076,7 +5076,7 @@ void Spell::EffectCreateTamedPet(SpellEffIndex /*effIndex*/)
// relocate
float px, py, pz;
- unitTarget->GetClosePoint(px, py, pz, pet->GetObjectSize(), PET_FOLLOW_DIST, pet->GetFollowAngle());
+ unitTarget->GetClosePoint(px, py, pz, pet->GetCombatReach(), PET_FOLLOW_DIST, pet->GetFollowAngle());
pet->Relocate(px, py, pz, unitTarget->GetOrientation());
// add to world
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index 3266343d8b3..12eb37b6861 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -75,6 +75,35 @@ bool SpellImplicitTargetInfo::IsArea() const
return GetSelectionCategory() == TARGET_SELECT_CATEGORY_AREA || GetSelectionCategory() == TARGET_SELECT_CATEGORY_CONE;
}
+bool SpellImplicitTargetInfo::IsProximityBasedAoe() const
+{
+ switch (_target)
+ {
+ case TARGET_UNIT_SRC_AREA_ENTRY:
+ case TARGET_UNIT_SRC_AREA_ENEMY:
+ case TARGET_UNIT_CASTER_AREA_PARTY:
+ case TARGET_UNIT_SRC_AREA_ALLY:
+ case TARGET_UNIT_SRC_AREA_PARTY:
+ case TARGET_UNIT_LASTTARGET_AREA_PARTY:
+ case TARGET_GAMEOBJECT_SRC_AREA:
+ case TARGET_UNIT_CASTER_AREA_RAID:
+ case TARGET_CORPSE_SRC_AREA_ENEMY:
+ return true;
+
+ case TARGET_UNIT_DEST_AREA_ENTRY:
+ case TARGET_UNIT_DEST_AREA_ENEMY:
+ case TARGET_UNIT_DEST_AREA_ALLY:
+ case TARGET_UNIT_DEST_AREA_PARTY:
+ case TARGET_GAMEOBJECT_DEST_AREA:
+ case TARGET_UNIT_TARGET_AREA_RAID_CLASS:
+ return false;
+
+ default:
+ TC_LOG_WARN("spells", "SpellImplicitTargetInfo::IsProximityBasedAoe called a non-aoe spell");
+ return false;
+ }
+}
+
SpellTargetSelectionCategories SpellImplicitTargetInfo::GetSelectionCategory() const
{
return _data[_target].SelectionCategory;
diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h
index d663c2359f0..e4b8709308b 100644
--- a/src/server/game/Spells/SpellInfo.h
+++ b/src/server/game/Spells/SpellInfo.h
@@ -286,6 +286,7 @@ public:
SpellImplicitTargetInfo(uint32 target);
bool IsArea() const;
+ bool IsProximityBasedAoe() const;
SpellTargetSelectionCategories GetSelectionCategory() const;
SpellTargetReferenceTypes GetReferenceType() const;
SpellTargetObjectTypes GetObjectType() const;
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 5bb9d23c7db..3c15a374d1b 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -369,10 +369,14 @@ bool SpellMgr::AddSameEffectStackRuleSpellGroups(SpellInfo const* spellInfo, int
SpellGroupStackRule SpellMgr::CheckSpellGroupStackRules(SpellInfo const* spellInfo1, SpellInfo const* spellInfo2) const
{
+ ASSERT(spellInfo1);
+ ASSERT(spellInfo2);
+
uint32 spellid_1 = spellInfo1->GetFirstRankSpell()->Id;
uint32 spellid_2 = spellInfo2->GetFirstRankSpell()->Id;
if (spellid_1 == spellid_2)
return SPELL_GROUP_STACK_RULE_DEFAULT;
+
// find SpellGroups which are common for both spells
SpellSpellGroupMapBounds spellGroup1 = GetSpellSpellGroupMapBounds(spellid_1);
std::set<SpellGroup> groups;
@@ -3363,6 +3367,12 @@ void SpellMgr::LoadSpellInfoCorrections()
const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd
});
+ // Val'kyr Target Search
+ ApplySpellFix({ 69030 }, [](SpellInfo* spellInfo)
+ {
+ spellInfo->Attributes |= SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY;
+ });
+
// Raging Spirit Visual
ApplySpellFix({ 69198 }, [](SpellInfo* spellInfo)
{
@@ -3408,14 +3418,16 @@ void SpellMgr::LoadSpellInfoCorrections()
// Jump
ApplySpellFix({ 71809 }, [](SpellInfo* spellInfo)
{
- spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(3); // 20yd
- const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_25_YARDS); // 25yd
+ spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(5); // 40yd
+ const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_10_YARDS); // 10yd
+ const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->MiscValue = 190;
});
// Broken Frostmourne
ApplySpellFix({ 72405 }, [](SpellInfo* spellInfo)
{
- const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd
+ const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_20_YARDS); // 20yd
+ spellInfo->AttributesEx |= SPELL_ATTR1_NO_THREAT;
});
// ENDOF ICECROWN CITADEL SPELLS
@@ -3631,6 +3643,10 @@ void SpellMgr::LoadSpellInfoCorrections()
if (spellInfo->HasAura(DIFFICULTY_NONE, SPELL_AURA_SPELL_MAGNET))
spellInfo->ProcFlags = 0;
+ // due to the way spell system works, unit would change orientation in Spell::_cast
+ if (spellInfo->HasAura(DIFFICULTY_NONE, SPELL_AURA_CONTROL_VEHICLE))
+ spellInfo->AttributesEx5 |= SPELL_ATTR5_DONT_TURN_DURING_CAST;
+
if (spellInfo->ActiveIconFileDataId == 135754) // flight
spellInfo->Attributes |= SPELL_ATTR0_PASSIVE;
}
diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp
index 3cd797d5e00..11417b305a5 100644
--- a/src/server/scripts/Commands/cs_debug.cpp
+++ b/src/server/scripts/Commands/cs_debug.cpp
@@ -918,7 +918,7 @@ public:
uint32 entry = atoul(e);
float x, y, z, o = handler->GetSession()->GetPlayer()->GetOrientation();
- handler->GetSession()->GetPlayer()->GetClosePoint(x, y, z, handler->GetSession()->GetPlayer()->GetObjectSize());
+ handler->GetSession()->GetPlayer()->GetClosePoint(x, y, z, handler->GetSession()->GetPlayer()->GetCombatReach());
if (!i)
return handler->GetSession()->GetPlayer()->SummonCreature(entry, x, y, z, o) != nullptr;
diff --git a/src/server/scripts/Commands/cs_group.cpp b/src/server/scripts/Commands/cs_group.cpp
index afe3b3c2645..f6866734a7c 100644
--- a/src/server/scripts/Commands/cs_group.cpp
+++ b/src/server/scripts/Commands/cs_group.cpp
@@ -143,7 +143,7 @@ public:
// before GM
float x, y, z;
- gmPlayer->GetClosePoint(x, y, z, player->GetObjectSize());
+ gmPlayer->GetClosePoint(x, y, z, player->GetCombatReach());
player->TeleportTo(gmPlayer->GetMapId(), x, y, z, player->GetOrientation());
}
diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp
index 1067283431d..23dbd8e3d1a 100644
--- a/src/server/scripts/Commands/cs_misc.cpp
+++ b/src/server/scripts/Commands/cs_misc.cpp
@@ -591,7 +591,7 @@ public:
// before GM
float x, y, z;
- handler->GetSession()->GetPlayer()->GetClosePoint(x, y, z, target->GetObjectSize());
+ handler->GetSession()->GetPlayer()->GetClosePoint(x, y, z, target->GetCombatReach());
target->TeleportTo(handler->GetSession()->GetPlayer()->GetMapId(), x, y, z, target->GetOrientation());
PhasingHandler::InheritPhaseShift(target, handler->GetSession()->GetPlayer());
target->UpdateObjectVisibility();
@@ -2201,9 +2201,6 @@ public:
case WAYPOINT_MOTION_TYPE:
handler->SendSysMessage(LANG_MOVEGENS_WAYPOINT);
break;
- case ANIMAL_RANDOM_MOTION_TYPE:
- handler->SendSysMessage(LANG_MOVEGENS_ANIMAL_RANDOM);
- break;
case CONFUSED_MOTION_TYPE:
handler->SendSysMessage(LANG_MOVEGENS_CONFUSED);
break;
diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp
index ac4d8abb366..7a2e6cff30e 100644
--- a/src/server/scripts/Commands/cs_npc.cpp
+++ b/src/server/scripts/Commands/cs_npc.cpp
@@ -1457,7 +1457,7 @@ public:
// place pet before player
float x, y, z;
- player->GetClosePoint (x, y, z, creatureTarget->GetObjectSize(), CONTACT_DISTANCE);
+ player->GetClosePoint (x, y, z, creatureTarget->GetCombatReach(), CONTACT_DISTANCE);
pet->Relocate(x, y, z, float(M_PI) - player->GetOrientation());
// set pet to defensive mode by default (some classes can't control controlled pets in fact).
diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp
index 22efdea4071..c0ae774c5f1 100644
--- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp
+++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp
@@ -126,7 +126,7 @@ class boss_selin_fireheart : public CreatureScript
Crystals.remove(CrystalChosen);
float x, y, z;
- CrystalChosen->GetClosePoint(x, y, z, me->GetObjectSize(), CONTACT_DISTANCE);
+ CrystalChosen->GetClosePoint(x, y, z, me->GetCombatReach(), CONTACT_DISTANCE);
events.SetPhase(PHASE_DRAIN);
me->SetWalk(false);
diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/zone_the_scarlet_enclave.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/zone_the_scarlet_enclave.cpp
index d47bf3c7862..fea8c330b9c 100644
--- a/src/server/scripts/EasternKingdoms/ScarletEnclave/zone_the_scarlet_enclave.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/zone_the_scarlet_enclave.cpp
@@ -101,7 +101,7 @@ public:
FlyBackTimer = 500;
break;
case 1:
- player->GetClosePoint(x, y, z, me->GetObjectSize());
+ player->GetClosePoint(x, y, z, me->GetCombatReach());
z += 2.5f;
x -= 2.0f;
y -= 1.5f;
diff --git a/src/server/scripts/EasternKingdoms/SunkenTemple/sunken_temple.h b/src/server/scripts/EasternKingdoms/SunkenTemple/sunken_temple.h
index 9f72ffe8183..c905702d3bc 100644
--- a/src/server/scripts/EasternKingdoms/SunkenTemple/sunken_temple.h
+++ b/src/server/scripts/EasternKingdoms/SunkenTemple/sunken_temple.h
@@ -20,17 +20,9 @@
#define DataHeader "ST"
-#define TROLLBOSS1_DEATH 1
-#define TROLLBOSS2_DEATH 2
-#define TROLLBOSS3_DEATH 3
-#define TROLLBOSS4_DEATH 4
-#define TROLLBOSS5_DEATH 5
-#define TROLLBOSS6_DEATH 6
-#define JAMMALAN_DEATH 7
-#define MORPHAZ_DEATH 8
-#define HAZZAS_DEATH 9
-#define ERANIKUS_DEATH 10
-#define ATALALARION_DEATH 11 //optional
+enum STEvents
+{
+ EVENT_STATE = 1
+};
-#define EVENT_STATE 1
#endif
diff --git a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp
index 58690c3a171..71784911f34 100644
--- a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp
+++ b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp
@@ -539,7 +539,7 @@ public:
/// TODO: Remove this once we find a general rule for WorldObject::MovePosition (this spell shouldn't take the Z change into consideration)
Unit* caster = GetCaster();
float angle = float(rand_norm()) * static_cast<float>(2 * M_PI);
- uint32 dist = caster->GetObjectSize() + GetSpellInfo()->GetEffect(EFFECT_0)->CalcRadius(caster) * (float)rand_norm();
+ uint32 dist = caster->GetCombatReach() + GetSpellInfo()->GetEffect(EFFECT_0)->CalcRadius(caster) * (float)rand_norm();
float x = caster->GetPositionX() + dist * std::cos(angle);
float y = caster->GetPositionY() + dist * std::sin(angle);
diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp
index f00f96660a8..9112fd9ccd2 100644
--- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp
+++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp
@@ -483,15 +483,6 @@ class npc_anubarak_anub_ar_assassin : public CreatureScript
{
npc_anubarak_anub_ar_assassinAI(Creature* creature) : npc_anubarak_pet_template(creature, false), _backstabTimer(6 * IN_MILLISECONDS) { }
- bool IsInBounds(Position const& jumpTo, CreatureBoundary const* boundary)
- {
- if (!boundary)
- return true;
- for (AreaBoundary const* it : *boundary)
- if (!it->IsWithinBoundary(&jumpTo))
- return false;
- return true;
- }
Position GetRandomPositionAround(Creature* anubarak)
{
static float DISTANCE_MIN = 10.0f;
@@ -508,7 +499,7 @@ class npc_anubarak_anub_ar_assassin : public CreatureScript
Position jumpTo;
do
jumpTo = GetRandomPositionAround(anubarak);
- while (!IsInBounds(jumpTo, boundary));
+ while (!CreatureAI::IsInBounds(boundary, &jumpTo));
me->GetMotionMaster()->MoveJump(jumpTo, 40.0f, 40.0f);
DoCastSelf(SPELL_ASSASSIN_VISUAL, true);
}
diff --git a/src/server/scripts/Northrend/DraktharonKeep/boss_king_dred.cpp b/src/server/scripts/Northrend/DraktharonKeep/boss_king_dred.cpp
index 1df68607625..ff4343f31fd 100644
--- a/src/server/scripts/Northrend/DraktharonKeep/boss_king_dred.cpp
+++ b/src/server/scripts/Northrend/DraktharonKeep/boss_king_dred.cpp
@@ -146,7 +146,7 @@ class boss_king_dred : public CreatureScript
float x, y, z;
- me->GetClosePoint(x, y, z, me->GetObjectSize() / 3, 10.0f);
+ me->GetClosePoint(x, y, z, me->GetCombatReach() / 3, 10.0f);
me->SummonCreature(RAND(NPC_DRAKKARI_GUTRIPPER, NPC_DRAKKARI_SCYTHECLAW), x, y, z, 0, TEMPSUMMON_DEAD_DESPAWN, 1000);
events.ScheduleEvent(EVENT_RAPTOR_CALL, urand(20000, 25000));
break;
diff --git a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp
index c67179d67eb..c78424c0078 100644
--- a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp
@@ -131,7 +131,7 @@ class boss_bronjahm : public CreatureScript
{
summons.Summon(summon);
summon->SetReactState(REACT_PASSIVE);
- summon->GetMotionMaster()->MoveFollow(me, me->GetObjectSize(), 0.0f);
+ summon->GetMotionMaster()->MoveFollow(me, me->GetCombatReach(), 0.0f);
summon->CastSpell(summon, SPELL_PURPLE_BANISH_VISUAL, true);
}
}
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp
index 98ee4e6194e..80ab44fe32a 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp
@@ -790,7 +790,7 @@ class npc_high_overlord_saurfang_icc : public CreatureScript
if (Creature* deathbringer = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_DEATHBRINGER_SAURFANG)))
{
float x, y, z;
- deathbringer->GetClosePoint(x, y, z, deathbringer->GetObjectSize());
+ deathbringer->GetClosePoint(x, y, z, deathbringer->GetCombatReach());
me->SetWalk(true);
me->GetMotionMaster()->MovePoint(POINT_CORPSE, x, y, z);
}
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
index 99060220471..1ab35165e5a 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
@@ -387,7 +387,7 @@ class npc_coldflame : public CreatureScript
{
float ang = Position::NormalizeOrientation(pos.GetAngle(me));
me->SetOrientation(ang);
- owner->GetNearPoint2D(pos.m_positionX, pos.m_positionY, 5.0f - owner->GetObjectSize(), ang);
+ owner->GetNearPoint2D(pos.m_positionX, pos.m_positionY, 5.0f - owner->GetCombatReach(), ang);
}
else
{
@@ -400,7 +400,7 @@ class npc_coldflame : public CreatureScript
float ang = Position::NormalizeOrientation(pos.GetAngle(target));
me->SetOrientation(ang);
- owner->GetNearPoint2D(pos.m_positionX, pos.m_positionY, 15.0f - owner->GetObjectSize(), ang);
+ owner->GetNearPoint2D(pos.m_positionX, pos.m_positionY, 15.0f - owner->GetCombatReach(), ang);
}
me->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), me->GetPositionZ(), me->GetOrientation());
@@ -518,7 +518,7 @@ class spell_marrowgar_coldflame : public SpellScriptLoader
{
targets.clear();
// select any unit but not the tank (by owners threatlist)
- Unit* target = GetCaster()->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 1, -GetCaster()->GetObjectSize(), true, -SPELL_IMPALED);
+ Unit* target = GetCaster()->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 1, -GetCaster()->GetCombatReach(), true, -SPELL_IMPALED);
if (!target)
target = GetCaster()->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true); // or the tank if its solo
if (!target)
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
index e525c2efa45..94bf769b771 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
@@ -197,77 +197,80 @@ enum Events
{
// The Lich King
// intro events
- EVENT_INTRO_MOVE_1 = 1,
- EVENT_INTRO_MOVE_2 = 2,
- EVENT_INTRO_MOVE_3 = 3,
- EVENT_INTRO_TALK_1 = 4,
- EVENT_EMOTE_CAST_SHOUT = 5,
- EVENT_INTRO_EMOTE_1 = 6,
- EVENT_INTRO_CHARGE = 7,
- EVENT_INTRO_CAST_FREEZE = 8,
- EVENT_FINISH_INTRO = 9,
+ EVENT_INTRO_MOVE_1 = 1,
+ EVENT_INTRO_MOVE_2,
+ EVENT_INTRO_MOVE_3,
+ EVENT_INTRO_TALK_1,
+ EVENT_EMOTE_CAST_SHOUT,
+ EVENT_INTRO_EMOTE_1,
+ EVENT_INTRO_CHARGE,
+ EVENT_INTRO_CAST_FREEZE,
+ EVENT_FINISH_INTRO,
// combat events
- EVENT_SUMMON_SHAMBLING_HORROR = 10,
- EVENT_SUMMON_DRUDGE_GHOUL = 11,
- EVENT_INFEST = 12,
- EVENT_NECROTIC_PLAGUE = 13,
- EVENT_SHADOW_TRAP = 14, // heroic only
- EVENT_SOUL_REAPER = 15,
- EVENT_DEFILE = 16,
- EVENT_HARVEST_SOUL = 17, // normal mode only
- EVENT_PAIN_AND_SUFFERING = 18,
- EVENT_SUMMON_ICE_SPHERE = 19,
- EVENT_SUMMON_RAGING_SPIRIT = 20,
- EVENT_QUAKE = 21,
- EVENT_SUMMON_VALKYR = 22,
- EVENT_GRAB_PLAYER = 23,
- EVENT_MOVE_TO_DROP_POS = 24,
- EVENT_LIFE_SIPHON = 25, // heroic only
- EVENT_START_ATTACK = 26,
- EVENT_QUAKE_2 = 27,
- EVENT_VILE_SPIRITS = 28,
- EVENT_HARVEST_SOULS = 29, // heroic only
- EVENT_BERSERK = 30,
- EVENT_SOUL_RIP = 31,
- EVENT_DESTROY_SOUL = 32,
- EVENT_FROSTMOURNE_TALK_1 = 33,
- EVENT_FROSTMOURNE_TALK_2 = 34,
- EVENT_FROSTMOURNE_TALK_3 = 35,
- EVENT_TELEPORT_BACK = 36,
- EVENT_FROSTMOURNE_HEROIC = 37,
- EVENT_OUTRO_TALK_1 = 38,
- EVENT_OUTRO_TALK_2 = 39,
- EVENT_OUTRO_EMOTE_TALK = 40,
- EVENT_OUTRO_TALK_3 = 41,
- EVENT_OUTRO_MOVE_CENTER = 42,
- EVENT_OUTRO_TALK_4 = 43,
- EVENT_OUTRO_RAISE_DEAD = 44,
- EVENT_OUTRO_TALK_5 = 45,
- EVENT_OUTRO_BLESS = 46,
- EVENT_OUTRO_REMOVE_ICE = 47,
- EVENT_OUTRO_MOVE_1 = 48,
- EVENT_OUTRO_JUMP = 49,
- EVENT_OUTRO_TALK_6 = 50,
- EVENT_OUTRO_KNOCK_BACK = 51,
- EVENT_OUTRO_SOUL_BARRAGE = 52,
- EVENT_OUTRO_SUMMON_TERENAS = 53,
- EVENT_OUTRO_TERENAS_TALK_1 = 54,
- EVENT_OUTRO_TERENAS_TALK_2 = 55,
- EVENT_OUTRO_TALK_7 = 56,
- EVENT_OUTRO_TALK_8 = 57,
+ EVENT_SUMMON_SHAMBLING_HORROR,
+ EVENT_SUMMON_DRUDGE_GHOUL,
+ EVENT_INFEST,
+ EVENT_NECROTIC_PLAGUE,
+ EVENT_SHADOW_TRAP, // heroic only
+ EVENT_SOUL_REAPER,
+ EVENT_DEFILE,
+ EVENT_HARVEST_SOUL, // normal mode only
+ EVENT_PAIN_AND_SUFFERING,
+ EVENT_SUMMON_ICE_SPHERE,
+ EVENT_SUMMON_RAGING_SPIRIT,
+ EVENT_QUAKE,
+ EVENT_SUMMON_VALKYR,
+ EVENT_GRAB_PLAYER,
+ EVENT_MOVE_TO_DROP_POS,
+ EVENT_LIFE_SIPHON, // heroic only
+ EVENT_MOVE_TO_CENTER, // heroic only
+ EVENT_START_ATTACK,
+ EVENT_SUMMON_RAGING_SPIRIT_2,
+ EVENT_QUAKE_2,
+ EVENT_VILE_SPIRITS,
+ EVENT_HARVEST_SOULS, // heroic only
+ EVENT_BERSERK,
+ EVENT_SOUL_RIP,
+ EVENT_DESTROY_SOUL,
+ EVENT_FROSTMOURNE_TALK_1,
+ EVENT_FROSTMOURNE_TALK_2,
+ EVENT_FROSTMOURNE_TALK_3,
+ EVENT_TELEPORT_BACK,
+ EVENT_FROSTMOURNE_HEROIC,
+ EVENT_OUTRO_TALK_1,
+ EVENT_OUTRO_TALK_2,
+ EVENT_OUTRO_EMOTE_TALK,
+ EVENT_OUTRO_TALK_3,
+ EVENT_OUTRO_MOVE_CENTER,
+ EVENT_OUTRO_TALK_4,
+ EVENT_OUTRO_RAISE_DEAD,
+ EVENT_OUTRO_TALK_5,
+ EVENT_OUTRO_BLESS,
+ EVENT_OUTRO_REMOVE_ICE,
+ EVENT_OUTRO_MOVE_1,
+ EVENT_OUTRO_JUMP,
+ EVENT_OUTRO_TALK_6,
+ EVENT_OUTRO_KNOCK_BACK,
+ EVENT_OUTRO_SOUL_BARRAGE,
+ EVENT_OUTRO_SUMMON_TERENAS,
+ EVENT_OUTRO_TERENAS_TALK_1,
+ EVENT_OUTRO_TERENAS_TALK_2,
+ EVENT_OUTRO_TALK_7,
+ EVENT_OUTRO_TALK_8,
// Shambling Horror
- EVENT_SHOCKWAVE = 58,
- EVENT_ENRAGE = 59,
+ EVENT_SHOCKWAVE,
+ EVENT_ENRAGE,
// Raging Spirit
- EVENT_SOUL_SHRIEK = 60,
+ EVENT_SOUL_SHRIEK,
+ EVENT_SET_AGRESSIVE,
// Strangulate Vehicle (Harvest Soul)
- EVENT_TELEPORT = 61,
- EVENT_MOVE_TO_LICH_KING = 62,
- EVENT_DESPAWN_SELF = 63,
+ EVENT_TELEPORT,
+ EVENT_MOVE_TO_LICH_KING,
+ EVENT_DESPAWN_SELF,
};
enum EventGroups
@@ -320,6 +323,7 @@ enum MovePoints
POINT_OUTRO_JUMP = 11,
POINT_LK_OUTRO_2 = 12,
POINT_GROUND = 13,
+ POINT_SIPHON = 14,
POINT_CHARGE = 1003, // globally used number for charge spell effects
};
@@ -334,12 +338,14 @@ enum EncounterActions
ACTION_SUMMON_TERENAS = 6,
ACTION_FINISH_OUTRO = 7,
ACTION_TELEPORT_BACK = 8,
+ ACTION_DISABLE_RAGING = 9
};
enum MiscData
{
LIGHT_SNOWSTORM = 2490,
LIGHT_SOULSTORM = 2508,
+ LIGHT_FOG = 2509,
MUSIC_FROZEN_THRONE = 17457,
MUSIC_SPECIAL = 17458, // Summon Shambling Horror, Remorseless Winter, Quake, Summon Val'kyr Periodic, Harvest Soul, Vile Spirits
@@ -499,17 +505,7 @@ class boss_the_lich_king : public CreatureScript
_vileSpiritExplosions = 0;
}
- void InitializeAI() override
- {
- SetupEncounter();
- }
-
- void JustRespawned() override
- {
- SetupEncounter();
- }
-
- void SetupEncounter()
+ void Reset() override
{
_Reset();
me->AddUnitFlag(UNIT_FLAG_IMMUNE_TO_PC);
@@ -524,9 +520,10 @@ class boss_the_lich_king : public CreatureScript
Cell::VisitGridObjects(me, worker, 333.0f);
// Reset any light override
- me->GetMap()->SetZoneOverrideLight(AREA_THE_FROZEN_THRONE, 0, 5000);
+ me->GetMap()->SetZoneOverrideLight(AREA_ICECROWN_CITADEL, 0, 5000);
- me->SummonCreature(NPC_HIGHLORD_TIRION_FORDRING_LK, TirionSpawn, TEMPSUMMON_MANUAL_DESPAWN);
+ if (!ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HIGHLORD_TIRION_FORDRING)))
+ me->SummonCreature(NPC_HIGHLORD_TIRION_FORDRING_LK, TirionSpawn, TEMPSUMMON_MANUAL_DESPAWN);
}
void JustDied(Unit* /*killer*/) override
@@ -538,6 +535,8 @@ class boss_the_lich_king : public CreatureScript
me->GetMotionMaster()->MoveFall();
if (Creature* frostmourne = me->FindNearestCreature(NPC_FROSTMOURNE_TRIGGER, 50.0f))
frostmourne->DespawnOrUnsummon();
+ me->GetMap()->SetZoneOverrideLight(AREA_ICECROWN_CITADEL, LIGHT_FOG, 5000);
+ me->GetMap()->SetZoneWeather(AREA_ICECROWN_CITADEL, WEATHER_STATE_FOG, 0.0f);
}
void EnterCombat(Unit* target) override
@@ -550,6 +549,7 @@ class boss_the_lich_king : public CreatureScript
}
me->setActive(true);
+ me->SetCombatPulseDelay(5);
DoZoneInCombat();
events.SetPhase(PHASE_ONE);
@@ -592,7 +592,7 @@ class boss_the_lich_king : public CreatureScript
case ACTION_START_ENCOUNTER:
instance->SetBossState(DATA_THE_LICH_KING, IN_PROGRESS);
Talk(SAY_LK_INTRO_1);
- me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_FROZEN_THRONE);
+ me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_FROZEN_THRONE);
// schedule talks
me->SetStandState(UNIT_STAND_STATE_STAND);
events.ScheduleEvent(EVENT_INTRO_MOVE_1, 4000);
@@ -601,10 +601,10 @@ class boss_the_lich_king : public CreatureScript
events.ScheduleEvent(EVENT_START_ATTACK, 5000);
break;
case ACTION_PLAY_MUSIC:
- me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_FINAL);
+ me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_FINAL);
break;
case ACTION_RESTORE_LIGHT:
- me->GetMap()->SetZoneOverrideLight(AREA_THE_FROZEN_THRONE, 0, 5000);
+ me->GetMap()->SetZoneOverrideLight(AREA_ICECROWN_CITADEL, 0, 5000);
break;
case ACTION_BREAK_FROSTMOURNE:
me->CastSpell((Unit*)NULL, SPELL_SUMMON_BROKEN_FROSTMOURNE, TRIGGERED_IGNORE_CAST_IN_PROGRESS);
@@ -666,6 +666,7 @@ class boss_the_lich_king : public CreatureScript
events.SetPhase(PHASE_TRANSITION);
me->SetReactState(REACT_PASSIVE);
me->AttackStop();
+ me->InterruptNonMeleeSpells(true);
me->GetMotionMaster()->MovePoint(POINT_CENTER_1, CenterPosition);
return;
}
@@ -675,6 +676,7 @@ class boss_the_lich_king : public CreatureScript
events.SetPhase(PHASE_TRANSITION);
me->SetReactState(REACT_PASSIVE);
me->AttackStop();
+ me->InterruptNonMeleeSpells(true);
me->GetMotionMaster()->MovePoint(POINT_CENTER_2, CenterPosition);
return;
}
@@ -686,7 +688,7 @@ class boss_the_lich_king : public CreatureScript
events.Reset();
events.SetPhase(PHASE_OUTRO);
summons.DespawnAll();
- me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_FURY_OF_FROSTMOURNE);
+ me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_FURY_OF_FROSTMOURNE);
me->InterruptNonMeleeSpells(true);
me->CastSpell((Unit*)NULL, SPELL_FURY_OF_FROSTMOURNE, TRIGGERED_NONE);
me->SetWalk(true);
@@ -738,8 +740,8 @@ class boss_the_lich_king : public CreatureScript
{
summon->CastSpell((Unit*)NULL, SPELL_BROKEN_FROSTMOURNE, true);
- me->GetMap()->SetZoneOverrideLight(AREA_THE_FROZEN_THRONE, LIGHT_SOULSTORM, 10000);
- me->GetMap()->SetZoneWeather(AREA_THE_FROZEN_THRONE, WEATHER_STATE_BLACKSNOW, 0.5f);
+ me->GetMap()->SetZoneOverrideLight(AREA_ICECROWN_CITADEL, LIGHT_SOULSTORM, 10000);
+ me->GetMap()->SetZoneWeather(AREA_ICECROWN_CITADEL, WEATHER_STATE_BLACKSNOW, 0.5f);
events.ScheduleEvent(EVENT_OUTRO_SOUL_BARRAGE, 5000, 0, PHASE_OUTRO);
return;
@@ -793,8 +795,8 @@ class boss_the_lich_king : public CreatureScript
{
if (spell->Id == REMORSELESS_WINTER_1 || spell->Id == REMORSELESS_WINTER_2)
{
- me->GetMap()->SetZoneOverrideLight(AREA_THE_FROZEN_THRONE, LIGHT_SNOWSTORM, 5000);
- me->GetMap()->SetZoneWeather(AREA_THE_FROZEN_THRONE, WEATHER_STATE_LIGHT_SNOW, 0.5f);
+ me->GetMap()->SetZoneOverrideLight(AREA_ICECROWN_CITADEL, LIGHT_SNOWSTORM, 5000);
+ me->GetMap()->SetZoneWeather(AREA_ICECROWN_CITADEL, WEATHER_STATE_LIGHT_SNOW, 0.5f);
}
}
@@ -820,13 +822,14 @@ class boss_the_lich_king : public CreatureScript
case POINT_CENTER_1:
me->SetFacingTo(0.0f, true);
Talk(SAY_LK_REMORSELESS_WINTER);
- me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL);
+ me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_SPECIAL);
DoCast(me, SPELL_REMORSELESS_WINTER_1);
+ summons.DespawnEntry(NPC_SHADOW_TRAP);
events.DelayEvents(62500, EVENT_GROUP_BERSERK); // delay berserk timer, its not ticking during phase transitions
events.ScheduleEvent(EVENT_QUAKE, 62500, 0, PHASE_TRANSITION);
events.ScheduleEvent(EVENT_PAIN_AND_SUFFERING, 4000, 0, PHASE_TRANSITION);
events.ScheduleEvent(EVENT_SUMMON_ICE_SPHERE, 8000, 0, PHASE_TRANSITION);
- events.ScheduleEvent(EVENT_SUMMON_RAGING_SPIRIT, 3000, 0, PHASE_TRANSITION);
+ events.ScheduleEvent(EVENT_SUMMON_RAGING_SPIRIT, 6000, 0, PHASE_TRANSITION);
events.ScheduleEvent(EVENT_SUMMON_VALKYR, 78000, 0, PHASE_TWO);
events.ScheduleEvent(EVENT_INFEST, 70000, 0, PHASE_TWO);
events.ScheduleEvent(EVENT_DEFILE, 97000, 0, PHASE_TWO);
@@ -835,14 +838,14 @@ class boss_the_lich_king : public CreatureScript
case POINT_CENTER_2:
me->SetFacingTo(0.0f, true);
Talk(SAY_LK_REMORSELESS_WINTER);
- me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL);
+ me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_SPECIAL);
DoCast(me, SPELL_REMORSELESS_WINTER_2);
summons.DespawnEntry(NPC_VALKYR_SHADOWGUARD);
events.DelayEvents(62500, EVENT_GROUP_BERSERK); // delay berserk timer, its not ticking during phase transitions
events.ScheduleEvent(EVENT_QUAKE_2, 62500, 0, PHASE_TRANSITION);
events.ScheduleEvent(EVENT_PAIN_AND_SUFFERING, 6000, 0, PHASE_TRANSITION);
events.ScheduleEvent(EVENT_SUMMON_ICE_SPHERE, 8000, 0, PHASE_TRANSITION);
- events.ScheduleEvent(EVENT_SUMMON_RAGING_SPIRIT, 5000, 0, PHASE_TRANSITION);
+ events.ScheduleEvent(EVENT_SUMMON_RAGING_SPIRIT_2, 5000, 0, PHASE_TRANSITION);
events.ScheduleEvent(EVENT_DEFILE, 95500, 0, PHASE_THREE);
events.ScheduleEvent(EVENT_SOUL_REAPER, 99500, 0, PHASE_THREE);
events.ScheduleEvent(EVENT_VILE_SPIRITS, 79500, EVENT_GROUP_VILE_SPIRITS, PHASE_THREE);
@@ -921,7 +924,7 @@ class boss_the_lich_king : public CreatureScript
break;
case EVENT_SUMMON_SHAMBLING_HORROR:
DoCast(me, SPELL_SUMMON_SHAMBLING_HORROR);
- me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL);
+ me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_SPECIAL);
events.ScheduleEvent(EVENT_SUMMON_SHAMBLING_HORROR, 60000, 0, PHASE_ONE);
break;
case EVENT_SUMMON_DRUDGE_GHOUL:
@@ -977,24 +980,29 @@ class boss_the_lich_king : public CreatureScript
me->CastSpell(target, SPELL_RAGING_SPIRIT, TRIGGERED_NONE);
events.ScheduleEvent(EVENT_SUMMON_RAGING_SPIRIT, urand(22000, 23000), 0, PHASE_TRANSITION);
break;
+ case EVENT_SUMMON_RAGING_SPIRIT_2:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
+ me->CastSpell(target, SPELL_RAGING_SPIRIT, TRIGGERED_NONE);
+ events.ScheduleEvent(EVENT_SUMMON_RAGING_SPIRIT, 18000, 0, PHASE_TRANSITION);
+ break;
case EVENT_QUAKE:
events.SetPhase(PHASE_TWO);
me->ClearUnitState(UNIT_STATE_CASTING); // clear state to ensure check in DoCastAOE passes
DoCastAOE(SPELL_QUAKE);
- me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL);
+ me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_SPECIAL);
Talk(SAY_LK_QUAKE);
break;
case EVENT_QUAKE_2:
events.SetPhase(PHASE_THREE);
me->ClearUnitState(UNIT_STATE_CASTING); // clear state to ensure check in DoCastAOE passes
DoCastAOE(SPELL_QUAKE);
- me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL);
+ me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_SPECIAL);
Talk(SAY_LK_QUAKE);
break;
case EVENT_SUMMON_VALKYR:
- me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL);
+ me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_SPECIAL);
Talk(SAY_LK_SUMMON_VALKYR);
- DoCastAOE(SUMMON_VALKYR);
+ DoCastAOE(SUMMON_VALKYR, true);
events.ScheduleEvent(EVENT_SUMMON_VALKYR, urand(45000, 50000), 0, PHASE_TWO);
break;
case EVENT_START_ATTACK:
@@ -1003,7 +1011,7 @@ class boss_the_lich_king : public CreatureScript
events.SetPhase(PHASE_THREE);
break;
case EVENT_VILE_SPIRITS:
- me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL);
+ me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_SPECIAL);
DoCastAOE(SPELL_VILE_SPIRITS);
events.ScheduleEvent(EVENT_VILE_SPIRITS, urand(35000, 40000), EVENT_GROUP_VILE_SPIRITS, PHASE_THREE);
break;
@@ -1019,6 +1027,25 @@ class boss_the_lich_king : public CreatureScript
events.RescheduleEvent(EVENT_SOUL_REAPER, urand(57000, 62000), 0, PHASE_THREE);
events.ScheduleEvent(EVENT_START_ATTACK, 49000);
events.ScheduleEvent(EVENT_FROSTMOURNE_HEROIC, 6500);
+ for (ObjectGuid guid : summons)
+ {
+ if (Creature* summon = ObjectAccessor::GetCreature(*me, guid))
+ {
+ if (summon->GetEntry() == NPC_VILE_SPIRIT)
+ {
+ summon->m_Events.KillAllEvents(true);
+ summon->m_Events.AddEvent(new VileSpiritActivateEvent(summon), summon->m_Events.CalculateTime(56500));
+ summon->SetReactState(REACT_PASSIVE);
+ summon->CombatStop(true);
+ summon->RemoveAurasDueToSpell(SPELL_VILE_SPIRIT_MOVE_SEARCH);
+ summon->RemoveAurasDueToSpell(SPELL_VILE_SPIRIT_DAMAGE_SEARCH);
+ summon->GetMotionMaster()->MoveTargetedHome();
+ summon->GetMotionMaster()->MoveRandom(10.0f);
+ }
+ else if (summon->GetEntry() == NPC_RAGING_SPIRIT)
+ summon->AI()->DoAction(ACTION_DISABLE_RAGING);
+ }
+ }
break;
case EVENT_FROSTMOURNE_HEROIC:
if (TempSummon* terenas = me->GetMap()->SummonCreature(NPC_TERENAS_MENETHIL_FROSTMOURNE_H, TerenasSpawnHeroic, NULL, 50000))
@@ -1034,18 +1061,6 @@ class boss_the_lich_king : public CreatureScript
spawner->CastSpell(spawner, SPELL_SUMMON_SPIRIT_BOMB_2, true); // summons bombs on players
spawner->m_Events.AddEvent(new TriggerWickedSpirit(spawner), spawner->m_Events.CalculateTime(3000));
}
-
- for (SummonList::iterator i = summons.begin(); i != summons.end(); ++i)
- {
- Creature* summon = ObjectAccessor::GetCreature(*me, *i);
- if (summon && summon->GetEntry() == NPC_VILE_SPIRIT)
- {
- summon->m_Events.KillAllEvents(true);
- summon->m_Events.AddEvent(new VileSpiritActivateEvent(summon), summon->m_Events.CalculateTime(50000));
- summon->GetMotionMaster()->MoveRandom(10.0f);
- summon->SetReactState(REACT_PASSIVE);
- }
- }
}
break;
case EVENT_OUTRO_TALK_1:
@@ -1074,7 +1089,7 @@ class boss_the_lich_king : public CreatureScript
case EVENT_OUTRO_RAISE_DEAD:
DoCastAOE(SPELL_RAISE_DEAD);
me->ClearUnitState(UNIT_STATE_CASTING);
- me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_FINAL);
+ me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_FINAL);
break;
case EVENT_OUTRO_TALK_5:
Talk(SAY_LK_OUTRO_5);
@@ -1189,7 +1204,7 @@ class npc_tirion_fordring_tft : public CreatureScript
if (spell->Id == SPELL_ICE_LOCK)
me->SetFacingTo(3.085098f);
else if (spell->Id == SPELL_BROKEN_FROSTMOURNE_KNOCK)
- SetEquipmentSlots(true); // remove glow on ashbringer
+ me->LoadEquipment(1); // remove glow on ashbringer
}
void sGossipSelect(Player* /*player*/, uint32 menuId, uint32 gossipListId) override
@@ -1357,7 +1372,9 @@ class npc_raging_spirit : public CreatureScript
void Reset() override
{
+ me->SetReactState(REACT_PASSIVE);
_events.Reset();
+ _events.ScheduleEvent(EVENT_SET_AGRESSIVE, 2000);
_events.ScheduleEvent(EVENT_SOUL_SHRIEK, urand(12000, 15000));
DoCast(me, SPELL_PLAGUE_AVOIDANCE, true);
DoCast(me, SPELL_RAGING_SPIRIT_VISUAL, true);
@@ -1367,6 +1384,19 @@ class npc_raging_spirit : public CreatureScript
DoCast(me, SPELL_BOSS_HITTIN_YA, true);
}
+ void DoAction(int32 action) override
+ {
+ if (action == ACTION_DISABLE_RAGING)
+ {
+ _events.Reset();
+ _events.SetPhase(PHASE_FROSTMOURNE);
+ _events.ScheduleEvent(EVENT_SET_AGRESSIVE, 52000);
+ me->SetReactState(REACT_PASSIVE);
+ me->AttackStop();
+ me->InterruptNonMeleeSpells(true);
+ }
+ }
+
void IsSummonedBy(Unit* /*summoner*/) override
{
// player is the spellcaster so register summon manually
@@ -1384,7 +1414,7 @@ class npc_raging_spirit : public CreatureScript
void UpdateAI(uint32 diff) override
{
- if (!UpdateVictim())
+ if (!_events.IsInPhase(PHASE_FROSTMOURNE) && !UpdateVictim())
return;
_events.Update(diff);
@@ -1400,6 +1430,14 @@ class npc_raging_spirit : public CreatureScript
DoCastAOE(SPELL_SOUL_SHRIEK);
_events.ScheduleEvent(EVENT_SOUL_SHRIEK, urand(12000, 15000));
break;
+ case EVENT_SET_AGRESSIVE:
+ me->SetReactState(REACT_AGGRESSIVE);
+ if (_events.IsInPhase(PHASE_FROSTMOURNE))
+ {
+ _events.SetPhase(PHASE_THREE);
+ _events.ScheduleEvent(EVENT_SOUL_SHRIEK, urand(12000, 15000));
+ }
+ break;
default:
break;
}
@@ -1454,19 +1492,18 @@ class npc_valkyr_shadowguard : public CreatureScript
if (me->HealthBelowPctDamaged(50, damage))
{
- _events.Reset();
DoCastAOE(SPELL_EJECT_ALL_PASSENGERS);
- me->GetMotionMaster()->MoveTargetedHome();
- me->ClearUnitState(UNIT_STATE_EVADE);
+ ScheduleHeroicEvents();
}
}
- void JustReachedHome() override
+ void ScheduleHeroicEvents()
{
- // schedule siphon life event (heroic only)
DoZoneInCombat();
_events.Reset();
+ _events.ScheduleEvent(EVENT_MOVE_TO_CENTER, 1);
_events.ScheduleEvent(EVENT_LIFE_SIPHON, 2000);
+ me->ClearUnitState(UNIT_STATE_EVADE);
}
void AttackStart(Unit* /*target*/) override
@@ -1482,7 +1519,10 @@ class npc_valkyr_shadowguard : public CreatureScript
{
case POINT_DROP_PLAYER:
DoCastAOE(SPELL_EJECT_ALL_PASSENGERS);
- me->DespawnOrUnsummon(1000);
+ if (IsHeroic())
+ ScheduleHeroicEvents();
+ else
+ me->DespawnOrUnsummon(1000);
break;
case POINT_CHARGE:
if (Player* target = ObjectAccessor::GetPlayer(*me, _grabbedPlayer))
@@ -1545,6 +1585,13 @@ class npc_valkyr_shadowguard : public CreatureScript
DoCast(target, SPELL_LIFE_SIPHON);
_events.ScheduleEvent(EVENT_LIFE_SIPHON, 2500);
break;
+ case EVENT_MOVE_TO_CENTER:
+ {
+ Position pos = me->GetRandomPoint(CenterPosition, 4.0f);
+ pos.m_positionZ = me->GetHomePosition().m_positionZ;
+ me->GetMotionMaster()->MovePoint(POINT_SIPHON, pos);
+ break;
+ }
default:
break;
}
@@ -1607,6 +1654,7 @@ class npc_strangulate_vehicle : public CreatureScript
if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_THE_LICH_KING)))
lichKing->AI()->SummonedCreatureDespawn(me);
+ me->DespawnOrUnsummon();
}
void UpdateAI(uint32 diff) override
@@ -2099,7 +2147,7 @@ class spell_the_lich_king_necrotic_plague_jump : public SpellScriptLoader
}
private:
- void SelectTarget(std::list<Unit*>& targets)
+ void SelectTarget(std::list<WorldObject*>& targets)
{
targets.sort(Trinity::ObjectDistanceOrderPred(GetCaster()));
if (targets.size() < 2)
@@ -2125,6 +2173,7 @@ class spell_the_lich_king_necrotic_plague_jump : public SpellScriptLoader
void Register() override
{
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_necrotic_plague_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
BeforeHit += BeforeSpellHitFn(spell_the_lich_king_necrotic_plague_SpellScript::CheckAura);
OnHit += SpellHitFn(spell_the_lich_king_necrotic_plague_SpellScript::AddMissingStack);
}
@@ -2357,12 +2406,6 @@ class spell_the_lich_king_raging_spirit : public SpellScriptLoader
{
PrepareSpellScript(spell_the_lich_king_raging_spirit_SpellScript);
- bool Validate(SpellInfo const* spell) override
- {
- SpellEffectInfo const* effect0 = spell->GetEffect(EFFECT_0);
- return effect0 && ValidateSpellInfo({ uint32(effect0->CalcValue()) });
- }
-
void HandleScript(SpellEffIndex effIndex)
{
PreventHitDefaultEffect(effIndex);
@@ -3134,6 +3177,34 @@ class spell_the_lich_king_jump_remove_aura : public SpellScriptLoader
}
};
+class spell_the_lich_king_harvest_souls_teleport : public SpellScriptLoader
+{
+public:
+ spell_the_lich_king_harvest_souls_teleport() : SpellScriptLoader("spell_the_lich_king_harvest_souls_teleport") { }
+
+ class spell_the_lich_king_harvest_souls_teleport_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_the_lich_king_harvest_souls_teleport_SpellScript);
+
+ void RelocateTransportOffset(SpellEffIndex /*effIndex*/)
+ {
+ float randCoordX = frand(-18.0f, 18.0f);
+ float randCoordY = frand(-18.0f, 18.0f);
+ GetHitDest()->RelocateOffset({ randCoordX, randCoordY, 0.0f, 0.0f });
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_harvest_souls_teleport_SpellScript::RelocateTransportOffset, EFFECT_1, SPELL_EFFECT_TELEPORT_UNITS);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_the_lich_king_harvest_souls_teleport_SpellScript();
+ }
+};
+
class achievement_been_waiting_long_time : public AchievementCriteriaScript
{
public:
@@ -3203,6 +3274,7 @@ void AddSC_boss_the_lich_king()
new spell_the_lich_king_jump();
new spell_the_lich_king_jump_remove_aura();
new spell_trigger_spell_from_caster("spell_the_lich_king_mass_resurrection", SPELL_MASS_RESURRECTION_REAL);
+ new spell_the_lich_king_harvest_souls_teleport();
new achievement_been_waiting_long_time();
new achievement_neck_deep_in_vile();
}
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h
index 1f9d88ea885..8fff8922983 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h
+++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h
@@ -321,6 +321,7 @@ enum ICCreaturesIds
NPC_WORLD_TRIGGER_INFINITE_AOI = 36171,
NPC_SPIRIT_BOMB = 39189,
NPC_FROSTMOURNE_TRIGGER = 38584,
+ NPC_SHADOW_TRAP = 39137,
// Generic
NPC_INVISIBLE_STALKER = 30298
@@ -524,8 +525,7 @@ enum ICWorldStatesICC
enum ICAreaIds
{
- AREA_ICECROWN_CITADEL = 4812,
- AREA_THE_FROZEN_THRONE = 4859
+ AREA_ICECROWN_CITADEL = 4812
};
class spell_trigger_spell_from_caster : public SpellScriptLoader
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp
index 1d0ef4ccea0..d70f0d07c54 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp
@@ -881,26 +881,20 @@ public:
{
PrepareAuraScript(spell_kelthuzad_chains_AuraScript);
- void HandleApply(AuraEffect const* /*eff*/, AuraEffectHandleModes /*mode*/)
+ void HandleApply(AuraEffect const* aurEff, AuraEffectHandleModes mode)
{
- Unit* target = GetTarget();
- float scale = target->GetObjectScale();
- ApplyPercentModFloatVar(scale, 200.0f, true);
- target->SetObjectScale(scale);
+ aurEff->HandleAuraModScale(GetTargetApplication(), mode, true);
}
- void HandleRemove(AuraEffect const* /*eff*/, AuraEffectHandleModes /*mode*/)
+ void HandleRemove(AuraEffect const* aurEff, AuraEffectHandleModes mode)
{
- Unit* target = GetTarget();
- float scale = target->GetObjectScale();
- ApplyPercentModFloatVar(scale, 200.0f, false);
- target->SetObjectScale(scale);
+ aurEff->HandleAuraModScale(GetTargetApplication(), mode, false);
}
void Register() override
{
- 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);
+ AfterEffectApply += AuraEffectApplyFn(spell_kelthuzad_chains_AuraScript::HandleApply, EFFECT_1, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, AURA_EFFECT_HANDLE_REAL);
+ AfterEffectRemove += AuraEffectApplyFn(spell_kelthuzad_chains_AuraScript::HandleRemove, EFFECT_1, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, AURA_EFFECT_HANDLE_REAL);
}
};
diff --git a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp
index b61e42974ac..1569697c81c 100644
--- a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp
@@ -43,7 +43,7 @@ BossBoundaryData const boundaries =
/* Military Quarter */
{ BOSS_RAZUVIOUS, new ZRangeBoundary(260.0f, 287.0f) }, // will not chase onto the upper floor
{ BOSS_GOTHIK, new RectangleBoundary(2627.0f, 2764.0f, -3440.0f, -3275.0f) },
- { BOSS_HORSEMEN, new ParallelogramBoundary(AreaBoundary::DoublePosition(2646.0, -2959.0), AreaBoundary::DoublePosition(2529.0, -3075.0), AreaBoundary::DoublePosition(2506.0, -2854.0)) },
+ { BOSS_HORSEMEN, new ParallelogramBoundary(Position(2646.0f, -2959.0f), Position(2529.0f, -3075.0f), Position(2506.0f, -2854.0f)) },
/* Construct Quarter */
{ BOSS_PATCHWERK, new CircleBoundary(Position(3204.0f, -3241.4f), 240.0f) },
@@ -51,9 +51,9 @@ BossBoundaryData const boundaries =
{ BOSS_GROBBULUS, new CircleBoundary(Position(3204.0f, -3241.4f), 240.0f) },
{ BOSS_GROBBULUS, new RectangleBoundary(3295.0f, 3340.0f, -3254.2f, -3230.18f, true) }, // entrance door blocker
{ BOSS_GLUTH, new CircleBoundary(Position(3293.0f, -3142.0f), 80.0) },
- { BOSS_GLUTH, new ParallelogramBoundary(AreaBoundary::DoublePosition(3401.0, -3149.0), AreaBoundary::DoublePosition(3261.0, -3028.0), AreaBoundary::DoublePosition(3320.0, -3267.0)) },
+ { BOSS_GLUTH, new ParallelogramBoundary(Position(3401.0f, -3149.0f), Position(3261.0f, -3028.0f), Position(3320.0f, -3267.0f)) },
{ BOSS_GLUTH, new ZRangeBoundary(285.0f, 310.0f) },
- { BOSS_THADDIUS, new ParallelogramBoundary(AreaBoundary::DoublePosition(3478.3, -3070.0), AreaBoundary::DoublePosition(3370.0, -2961.5), AreaBoundary::DoublePosition(3580.0, -2961.5)) },
+ { BOSS_THADDIUS, new ParallelogramBoundary(Position(3478.3f, -3070.0f), Position(3370.0f, -2961.5f), Position(3580.0f, -2961.5f)) },
/* Frostwyrm Lair */
{ BOSS_SAPPHIRON, new CircleBoundary(Position(3517.627f, -5255.5f), 110.0) },
diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h b/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h
index b066eb59bea..4c3faf67b5a 100644
--- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h
+++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h
@@ -23,7 +23,7 @@
#define EoEScriptName "instance_eye_of_eternity"
#define DataHeader "EOE"
-enum InstanceData
+enum EOEInstanceData
{
DATA_MALYGOS_EVENT,
MAX_ENCOUNTER,
@@ -33,7 +33,7 @@ enum InstanceData
DATA_RESPAWN_IRIS
};
-enum InstanceData64
+enum EOEInstanceData64
{
DATA_TRIGGER,
DATA_MALYGOS,
@@ -44,7 +44,7 @@ enum InstanceData64
DATA_GIFT_BOX_BUNNY_GUID
};
-enum InstanceNpcs
+enum EOEInstanceNpcs
{
NPC_MALYGOS = 28859,
NPC_VORTEX_TRIGGER = 30090,
@@ -60,7 +60,7 @@ enum InstanceNpcs
NPC_SURGE_OF_POWER = 30334
};
-enum InstanceGameObjects
+enum EOEInstanceGameObjects
{
GO_NEXUS_RAID_PLATFORM = 193070,
GO_EXIT_PORTAL = 193908,
@@ -72,12 +72,12 @@ enum InstanceGameObjects
GO_HEART_OF_MAGIC_25 = 194159
};
-enum InstanceEvents
+enum EOEInstanceEvents
{
EVENT_FOCUSING_IRIS = 20711
};
-enum InstanceSpells
+enum EOEInstanceSpells
{
SPELL_VORTEX_4 = 55853, // damage | used to enter to the vehicle
SPELL_VORTEX_5 = 56263, // damage | used to enter to the vehicle
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
index 818485e4440..4e5019618ec 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
@@ -410,7 +410,7 @@ class boss_algalon_the_observer : public CreatureScript
{
_firstPull = false;
Talk(SAY_ALGALON_START_TIMER);
- if (Creature* brann = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_BRANN_BRONZEBEARD_ALG)))
+ if (Creature* brann = instance->GetCreature(DATA_BRANN_BRONZEBEARD_ALG))
brann->AI()->DoAction(ACTION_FINISH_INTRO);
me->setActive(true);
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp
index b8f23964df6..fe01a917cd6 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp
@@ -393,8 +393,8 @@ class npc_sanctum_sentry : public CreatureScript
void JustDied(Unit* /*killer*/) override
{
- if (Creature* Auriaya = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_AURIAYA)))
- Auriaya->AI()->DoAction(ACTION_CRAZY_CAT_LADY);
+ if (Creature* auriaya = instance->GetCreature(BOSS_AURIAYA))
+ auriaya->AI()->DoAction(ACTION_CRAZY_CAT_LADY);
}
private:
@@ -472,8 +472,8 @@ class npc_feral_defender : public CreatureScript
void JustDied(Unit* /*killer*/) override
{
DoCast(me, SPELL_SUMMON_ESSENCE);
- if (Creature* Auriaya = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_AURIAYA)))
- Auriaya->AI()->DoAction(ACTION_RESPAWN_DEFENDER);
+ if (Creature* auriaya = instance->GetCreature(BOSS_AURIAYA))
+ auriaya->AI()->DoAction(ACTION_RESPAWN_DEFENDER);
}
private:
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp
index b2958daf07c..8e734e6d3e7 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp
@@ -974,11 +974,6 @@ class npc_mimirons_inferno : public CreatureScript
public:
npc_mimirons_inferno() : CreatureScript("npc_mimirons_inferno") { }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetUlduarAI<npc_mimirons_infernoAI>(creature);
- }
-
struct npc_mimirons_infernoAI : public npc_escortAI
{
npc_mimirons_infernoAI(Creature* creature) : npc_escortAI(creature)
@@ -1031,6 +1026,10 @@ public:
}
};
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetUlduarAI<npc_mimirons_infernoAI>(creature);
+ }
};
class npc_hodirs_fury : public CreatureScript
@@ -1247,7 +1246,7 @@ class npc_lorekeeper : public CreatureScript
CloseGossipMenuFor(player);
me->GetMap()->LoadGrid(364, -16); // make sure leviathan is loaded
- if (Creature* leviathan = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(BOSS_LEVIATHAN)))
+ if (Creature* leviathan = _instance->GetCreature(BOSS_LEVIATHAN))
{
leviathan->AI()->DoAction(ACTION_START_HARD_MODE);
me->SetVisible(false);
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp
index ad4b7c6413f..5cfc0d75481 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp
@@ -1061,8 +1061,8 @@ class npc_ancient_water_spirit : public CreatureScript
{
Initialize();
instance = me->GetInstanceScript();
- if (Creature* Freya = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_FREYA)))
- waveCount = ENSURE_AI(boss_freya::boss_freyaAI, Freya->AI())->trioWaveCount;
+ if (Creature* freya = instance->GetCreature(BOSS_FREYA))
+ waveCount = ENSURE_AI(boss_freya::boss_freyaAI, freya->AI())->trioWaveCount;
else
waveCount = 0;
}
@@ -1099,10 +1099,10 @@ class npc_ancient_water_spirit : public CreatureScript
void JustDied(Unit* /*killer*/) override
{
- if (Creature* Freya = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_FREYA)))
+ if (Creature* freya = instance->GetCreature(BOSS_FREYA))
{
- ENSURE_AI(boss_freya::boss_freyaAI, Freya->AI())->checkElementalAlive[waveCount] = false;
- ENSURE_AI(boss_freya::boss_freyaAI, Freya->AI())->LasherDead(1);
+ ENSURE_AI(boss_freya::boss_freyaAI, freya->AI())->checkElementalAlive[waveCount] = false;
+ ENSURE_AI(boss_freya::boss_freyaAI, freya->AI())->LasherDead(1);
}
}
@@ -1129,8 +1129,8 @@ class npc_storm_lasher : public CreatureScript
{
Initialize();
instance = me->GetInstanceScript();
- if (Creature* Freya = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_FREYA)))
- waveCount = ENSURE_AI(boss_freya::boss_freyaAI, Freya->AI())->trioWaveCount;
+ if (Creature* freya = instance->GetCreature(BOSS_FREYA))
+ waveCount = ENSURE_AI(boss_freya::boss_freyaAI, freya->AI())->trioWaveCount;
else
waveCount = 0;
}
@@ -1173,10 +1173,10 @@ class npc_storm_lasher : public CreatureScript
void JustDied(Unit* /*killer*/) override
{
- if (Creature* Freya = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_FREYA)))
+ if (Creature* freya = instance->GetCreature(BOSS_FREYA))
{
- ENSURE_AI(boss_freya::boss_freyaAI, Freya->AI())->checkElementalAlive[waveCount] = false;
- ENSURE_AI(boss_freya::boss_freyaAI, Freya->AI())->LasherDead(2);
+ ENSURE_AI(boss_freya::boss_freyaAI, freya->AI())->checkElementalAlive[waveCount] = false;
+ ENSURE_AI(boss_freya::boss_freyaAI, freya->AI())->LasherDead(2);
}
}
@@ -1203,8 +1203,8 @@ class npc_snaplasher : public CreatureScript
npc_snaplasherAI(Creature* creature) : ScriptedAI(creature)
{
instance = me->GetInstanceScript();
- if (Creature* Freya = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_FREYA)))
- waveCount = ENSURE_AI(boss_freya::boss_freyaAI, Freya->AI())->trioWaveCount;
+ if (Creature* freya = instance->GetCreature(BOSS_FREYA))
+ waveCount = ENSURE_AI(boss_freya::boss_freyaAI, freya->AI())->trioWaveCount;
else
waveCount = 0;
}
@@ -1222,10 +1222,10 @@ class npc_snaplasher : public CreatureScript
void JustDied(Unit* /*killer*/) override
{
- if (Creature* Freya = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_FREYA)))
+ if (Creature* freya = instance->GetCreature(BOSS_FREYA))
{
- ENSURE_AI(boss_freya::boss_freyaAI, Freya->AI())->checkElementalAlive[waveCount] = false;
- ENSURE_AI(boss_freya::boss_freyaAI, Freya->AI())->LasherDead(4);
+ ENSURE_AI(boss_freya::boss_freyaAI, freya->AI())->checkElementalAlive[waveCount] = false;
+ ENSURE_AI(boss_freya::boss_freyaAI, freya->AI())->LasherDead(4);
}
}
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 9630f1ddbfe..6c03b9f5ecb 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp
@@ -336,8 +336,8 @@ class boss_saronite_animus : public CreatureScript
void JustDied(Unit* /*killer*/) override
{
- if (Creature* Vezax = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_VEZAX)))
- Vezax->AI()->DoAction(ACTION_ANIMUS_DIE);
+ if (Creature* vezax = instance->GetCreature(BOSS_VEZAX))
+ vezax->AI()->DoAction(ACTION_ANIMUS_DIE);
}
void UpdateAI(uint32 diff) override
@@ -434,8 +434,8 @@ class npc_saronite_vapors : public CreatureScript
DoCast(me, SPELL_SARONITE_VAPORS);
me->DespawnOrUnsummon(30000);
- if (Creature* Vezax = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_VEZAX)))
- Vezax->AI()->DoAction(ACTION_VAPORS_DIE);
+ if (Creature* vezax = instance->GetCreature(BOSS_VEZAX))
+ vezax->AI()->DoAction(ACTION_VAPORS_DIE);
}
}
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp
index 57b96e26943..4d8a49160bc 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp
@@ -242,8 +242,8 @@ class npc_flash_freeze : public CreatureScript
// Prevents to have Ice Block on other place than target is
me->NearTeleportTo(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), target->GetOrientation());
if (target->GetTypeId() == TYPEID_PLAYER)
- if (Creature* Hodir = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_HODIR)))
- Hodir->AI()->DoAction(ACTION_CHEESE_THE_FREEZE);
+ if (Creature* hodir = instance->GetCreature(BOSS_HODIR))
+ hodir->AI()->DoAction(ACTION_CHEESE_THE_FREEZE);
}
}
};
@@ -291,21 +291,21 @@ class npc_ice_block : public CreatureScript
void DamageTaken(Unit* who, uint32& /*damage*/) override
{
- if (Creature* Helper = ObjectAccessor::GetCreature(*me, targetGUID))
+ if (Creature* helper = ObjectAccessor::GetCreature(*me, targetGUID))
{
- Helper->RemoveUnitFlag(UnitFlags(UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED));
- Helper->SetControlled(false, UNIT_STATE_ROOT);
+ helper->RemoveUnitFlag(UnitFlags(UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED));
+ helper->SetControlled(false, UNIT_STATE_ROOT);
- if (Creature* Hodir = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_HODIR)))
+ if (Creature* hodir = instance->GetCreature(BOSS_HODIR))
{
- if (!Hodir->IsInCombat())
+ if (!hodir->IsInCombat())
{
- Hodir->SetReactState(REACT_AGGRESSIVE);
- Hodir->AI()->DoZoneInCombat();
- Hodir->AI()->AttackStart(who);
+ hodir->SetReactState(REACT_AGGRESSIVE);
+ hodir->AI()->DoZoneInCombat();
+ hodir->AI()->AttackStart(who);
}
- Helper->AI()->AttackStart(Hodir);
+ helper->AI()->AttackStart(hodir);
}
}
}
@@ -717,8 +717,8 @@ class npc_hodir_priest : public CreatureScript
void JustDied(Unit* /*killer*/) override
{
- if (Creature* Hodir = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_HODIR)))
- Hodir->AI()->DoAction(ACTION_I_HAVE_THE_COOLEST_FRIENDS);
+ if (Creature* hodir = instance->GetCreature(BOSS_HODIR))
+ hodir->AI()->DoAction(ACTION_I_HAVE_THE_COOLEST_FRIENDS);
}
private:
@@ -782,8 +782,8 @@ class npc_hodir_shaman : public CreatureScript
void JustDied(Unit* /*killer*/) override
{
- if (Creature* Hodir = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_HODIR)))
- Hodir->AI()->DoAction(ACTION_I_HAVE_THE_COOLEST_FRIENDS);
+ if (Creature* hodir = instance->GetCreature(BOSS_HODIR))
+ hodir->AI()->DoAction(ACTION_I_HAVE_THE_COOLEST_FRIENDS);
}
private:
@@ -846,8 +846,8 @@ class npc_hodir_druid : public CreatureScript
void JustDied(Unit* /*killer*/) override
{
- if (Creature* Hodir = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_HODIR)))
- Hodir->AI()->DoAction(ACTION_I_HAVE_THE_COOLEST_FRIENDS);
+ if (Creature* hodir = instance->GetCreature(BOSS_HODIR))
+ hodir->AI()->DoAction(ACTION_I_HAVE_THE_COOLEST_FRIENDS);
}
private:
@@ -929,8 +929,8 @@ class npc_hodir_mage : public CreatureScript
void JustDied(Unit* /*killer*/) override
{
- if (Creature* Hodir = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_HODIR)))
- Hodir->AI()->DoAction(ACTION_I_HAVE_THE_COOLEST_FRIENDS);
+ if (Creature* hodir = instance->GetCreature(BOSS_HODIR))
+ hodir->AI()->DoAction(ACTION_I_HAVE_THE_COOLEST_FRIENDS);
}
private:
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp
index e4040a44a36..37141085731 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp
@@ -328,7 +328,7 @@ class npc_iron_construct : public CreatureScript
if (me->HasAura(RAID_MODE(SPELL_BRITTLE, SPELL_BRITTLE_25)) && damage >= 5000)
{
DoCast(SPELL_SHATTER);
- if (Creature* ignis = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(BOSS_IGNIS)))
+ if (Creature* ignis = _instance->GetCreature(BOSS_IGNIS))
if (ignis->AI())
ignis->AI()->DoAction(ACTION_REMOVE_BUFF);
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp
index 5cf1cf67de8..fd4d7b02229 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp
@@ -371,7 +371,7 @@ static bool IsEncounterFinished(Unit* who)
mkii->DespawnOrUnsummon(120000);
vx001->DespawnOrUnsummon(120000);
aerial->DespawnOrUnsummon(120000);
- if (Creature* mimiron = ObjectAccessor::GetCreature(*who, instance->GetGuidData(BOSS_MIMIRON)))
+ if (Creature* mimiron = instance->GetCreature(BOSS_MIMIRON))
mimiron->AI()->JustDied(who);
return true;
}
@@ -428,7 +428,7 @@ class boss_mimiron : public CreatureScript
me->RemoveAurasDueToSpell(SPELL_WELD);
DoCast(me->GetVehicleBase(), SPELL_SEAT_6);
- if (GameObject* button = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_MIMIRON_BUTTON)))
+ if (GameObject* button = instance->GetGameObject(DATA_MIMIRON_BUTTON))
button->AddFlag(GO_FLAG_NOT_SELECTABLE);
if (_fireFighter)
@@ -458,14 +458,14 @@ class boss_mimiron : public CreatureScript
_Reset();
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
- if (GameObject* elevator = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_MIMIRON_ELEVATOR)))
+ if (GameObject* elevator = instance->GetGameObject(DATA_MIMIRON_ELEVATOR))
elevator->SetGoState(GO_STATE_ACTIVE);
if (_fireFighter)
- if (Creature* computer = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_COMPUTER)))
+ if (Creature* computer = instance->GetCreature(DATA_COMPUTER))
computer->AI()->DoAction(DO_DEACTIVATE_COMPUTER);
- if (GameObject* button = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_MIMIRON_BUTTON)))
+ if (GameObject* button = instance->GetGameObject(DATA_MIMIRON_BUTTON))
{
button->SetGoState(GO_STATE_READY);
button->RemoveFlag(GO_FLAG_NOT_SELECTABLE);
@@ -493,7 +493,7 @@ class boss_mimiron : public CreatureScript
switch (eventId)
{
case EVENT_SUMMON_FLAMES:
- if (Unit* worldtrigger = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_MIMIRON_WORLD_TRIGGER)))
+ if (Creature* worldtrigger = instance->GetCreature(DATA_MIMIRON_WORLD_TRIGGER))
worldtrigger->CastCustomSpell(SPELL_SCRIPT_EFFECT_SUMMON_FLAMES_INITIAL, SPELLVALUE_MAX_TARGETS, 3, NULL, true, NULL, NULL, me->GetGUID());
events.RescheduleEvent(EVENT_SUMMON_FLAMES, 28000);
break;
@@ -529,14 +529,14 @@ class boss_mimiron : public CreatureScript
events.ScheduleEvent(EVENT_VX001_ACTIVATION_4, 5000);
break;
case EVENT_VX001_ACTIVATION_4:
- if (GameObject* elevator = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_MIMIRON_ELEVATOR)))
+ if (GameObject* elevator = instance->GetGameObject(DATA_MIMIRON_ELEVATOR))
elevator->SetGoState(GO_STATE_READY);
- if (Unit* worldtrigger = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_MIMIRON_WORLD_TRIGGER)))
+ if (Creature* worldtrigger = instance->GetCreature(DATA_MIMIRON_WORLD_TRIGGER))
worldtrigger->CastSpell(worldtrigger, SPELL_ELEVATOR_KNOCKBACK);
events.ScheduleEvent(EVENT_VX001_ACTIVATION_5, 6000);
break;
case EVENT_VX001_ACTIVATION_5:
- if (GameObject* elevator = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_MIMIRON_ELEVATOR)))
+ if (GameObject* elevator = instance->GetGameObject(DATA_MIMIRON_ELEVATOR))
elevator->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE);
if (Creature* vx001 = me->SummonCreature(NPC_VX_001, VX001SummonPos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 120000))
vx001->CastSpell(vx001, SPELL_FREEZE_ANIM);
@@ -644,7 +644,7 @@ class boss_mimiron : public CreatureScript
Talk(SAY_V07TRON_DEATH);
if (_fireFighter)
{
- if (Creature* computer = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_COMPUTER)))
+ if (Creature* computer = instance->GetCreature(DATA_COMPUTER))
computer->AI()->DoAction(DO_DEACTIVATE_COMPUTER);
me->SummonGameObject(RAID_MODE(GO_CACHE_OF_INNOVATION_FIREFIGHTER, GO_CACHE_OF_INNOVATION_FIREFIGHTER_HERO), 2744.040f, 2569.352f, 364.3135f, 3.124123f, QuaternionData(0.f, 0.f, 0.9999619f, 0.008734641f), 604800);
}
@@ -783,7 +783,7 @@ class boss_leviathan_mk_ii : public CreatureScript
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
- if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_MIMIRON)))
+ if (Creature* mimiron = instance->GetCreature(BOSS_MIMIRON))
mimiron->AI()->Talk(events.IsInPhase(PHASE_LEVIATHAN_MK_II) ? SAY_MKII_SLAY : SAY_V07TRON_SLAY);
}
@@ -798,7 +798,7 @@ class boss_leviathan_mk_ii : public CreatureScript
me->AddUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
DoCast(me, SPELL_HALF_HEAL);
- if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_MIMIRON)))
+ if (Creature* mimiron = instance->GetCreature(BOSS_MIMIRON))
mimiron->AI()->DoAction(DO_ACTIVATE_VX001);
break;
case WP_MKII_P4_POS_1:
@@ -808,7 +808,7 @@ class boss_leviathan_mk_ii : public CreatureScript
events.ScheduleEvent(EVENT_MOVE_POINT_3, 1);
break;
case WP_MKII_P4_POS_3:
- if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_MIMIRON)))
+ if (Creature* mimiron = instance->GetCreature(BOSS_MIMIRON))
mimiron->AI()->DoAction(DO_ACTIVATE_V0L7R0N_2);
break;
case WP_MKII_P4_POS_4:
@@ -951,7 +951,7 @@ class boss_vx_001 : public CreatureScript
me->AddUnitFlag(UNIT_FLAG_NON_ATTACKABLE); // | UNIT_FLAG_NOT_SELECTABLE);
DoCast(me, SPELL_HALF_HEAL); // has no effect, wat
DoCast(me, SPELL_TORSO_DISABLED);
- if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_MIMIRON)))
+ if (Creature* mimiron = instance->GetCreature(BOSS_MIMIRON))
mimiron->AI()->DoAction(DO_ACTIVATE_AERIAL);
}
else if (events.IsInPhase(PHASE_VOL7RON))
@@ -1022,7 +1022,7 @@ class boss_vx_001 : public CreatureScript
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
- if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_MIMIRON)))
+ if (Creature* mimiron = instance->GetCreature(BOSS_MIMIRON))
mimiron->AI()->Talk(events.IsInPhase(PHASE_VX_001) ? SAY_VX001_SLAY : SAY_V07TRON_SLAY);
}
@@ -1201,7 +1201,7 @@ class boss_aerial_command_unit : public CreatureScript
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
- if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_MIMIRON)))
+ if (Creature* mimiron = instance->GetCreature(BOSS_MIMIRON))
mimiron->AI()->Talk(events.IsInPhase(PHASE_AERIAL_COMMAND_UNIT) ? SAY_AERIAL_SLAY : SAY_V07TRON_SLAY);
}
@@ -1211,7 +1211,7 @@ class boss_aerial_command_unit : public CreatureScript
{
me->AddUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
- if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_MIMIRON)))
+ if (Creature* mimiron = instance->GetCreature(BOSS_MIMIRON))
mimiron->AI()->DoAction(DO_ACTIVATE_V0L7R0N_1);
}
}
@@ -1435,7 +1435,7 @@ class npc_mimiron_computer : public CreatureScript
{
case EVENT_SELF_DESTRUCT_10:
Talk(SAY_SELF_DESTRUCT_10);
- if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_MIMIRON)))
+ if (Creature* mimiron = instance->GetCreature(BOSS_MIMIRON))
mimiron->AI()->DoAction(DO_ACTIVATE_HARD_MODE);
events.ScheduleEvent(EVENT_SELF_DESTRUCT_9, 60000);
break;
@@ -1477,7 +1477,7 @@ class npc_mimiron_computer : public CreatureScript
break;
case EVENT_SELF_DESTRUCT_FINALIZED:
Talk(SAY_SELF_DESTRUCT_FINALIZED);
- if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_MIMIRON)))
+ if (Creature* mimiron = instance->GetCreature(BOSS_MIMIRON))
mimiron->AI()->DoAction(DO_ACTIVATE_SELF_DESTRUCT);
DoCast(me, SPELL_SELF_DESTRUCTION_AURA);
DoCast(me, SPELL_SELF_DESTRUCTION_VISUAL);
@@ -1658,7 +1658,7 @@ class go_mimiron_hardmode_button : public GameObjectScript
if (!instance)
return false;
- if (Creature* computer = ObjectAccessor::GetCreature(*go, instance->GetGuidData(DATA_COMPUTER)))
+ if (Creature* computer = instance->GetCreature(DATA_COMPUTER))
computer->AI()->DoAction(DO_ACTIVATE_COMPUTER);
go->SetGoState(GO_STATE_ACTIVE);
go->AddFlag(GO_FLAG_NOT_SELECTABLE);
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp
index 8a1bbfe712c..3f56f4523cc 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp
@@ -189,16 +189,22 @@ class boss_razorscale_controller : public CreatureScript
public:
boss_razorscale_controller() : CreatureScript("boss_razorscale_controller") { }
- struct boss_razorscale_controllerAI : public BossAI
+ struct boss_razorscale_controllerAI : public ScriptedAI
{
- boss_razorscale_controllerAI(Creature* creature) : BossAI(creature, DATA_RAZORSCALE_CONTROL)
+ boss_razorscale_controllerAI(Creature* creature) : ScriptedAI(creature), summons(me)
{
+ instance = creature->GetInstanceScript();
me->SetDisplayFromModel(1);
}
+ InstanceScript* instance;
+ EventMap events;
+ SummonList summons;
+
void Reset() override
{
- _Reset();
+ events.Reset();
+ summons.DespawnAll();
me->SetReactState(REACT_PASSIVE);
}
@@ -207,14 +213,14 @@ class boss_razorscale_controller : public CreatureScript
switch (spell->Id)
{
case SPELL_FLAMED:
- if (GameObject* Harpoon1 = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(GO_RAZOR_HARPOON_1)))
- Harpoon1->RemoveFromWorld();
- if (GameObject* Harpoon2 = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(GO_RAZOR_HARPOON_2)))
- Harpoon2->RemoveFromWorld();
- if (GameObject* Harpoon3 = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(GO_RAZOR_HARPOON_3)))
- Harpoon3->RemoveFromWorld();
- if (GameObject* Harpoon4 = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(GO_RAZOR_HARPOON_4)))
- Harpoon4->RemoveFromWorld();
+ if (GameObject* harpoon = instance->GetGameObject(GO_RAZOR_HARPOON_1))
+ harpoon->RemoveFromWorld();
+ if (GameObject* harpoon = instance->GetGameObject(GO_RAZOR_HARPOON_2))
+ harpoon->RemoveFromWorld();
+ if (GameObject* harpoon = instance->GetGameObject(GO_RAZOR_HARPOON_3))
+ harpoon->RemoveFromWorld();
+ if (GameObject* harpoon = instance->GetGameObject(GO_RAZOR_HARPOON_4))
+ harpoon->RemoveFromWorld();
DoAction(ACTION_HARPOON_BUILD);
DoAction(ACTION_PLACE_BROKEN_HARPOON);
break;
@@ -229,7 +235,8 @@ class boss_razorscale_controller : public CreatureScript
void JustDied(Unit* /*killer*/) override
{
- _JustDied();
+ events.Reset();
+ summons.DespawnAll();
}
void DoAction(int32 action) override
@@ -261,39 +268,39 @@ class boss_razorscale_controller : public CreatureScript
{
case EVENT_BUILD_HARPOON_1:
Talk(EMOTE_HARPOON);
- if (GameObject* Harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_1, PosHarpoon[0].GetPositionX(), PosHarpoon[0].GetPositionY(), PosHarpoon[0].GetPositionZ(), 4.790f, QuaternionData::fromEulerAnglesZYX(4.790f, 0.0f, 0.0f), uint32(me->GetRespawnTime())))
+ if (GameObject* harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_1, PosHarpoon[0].GetPositionX(), PosHarpoon[0].GetPositionY(), PosHarpoon[0].GetPositionZ(), 4.790f, QuaternionData::fromEulerAnglesZYX(4.790f, 0.0f, 0.0f), uint32(me->GetRespawnTime())))
{
- if (GameObject* BrokenHarpoon = Harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f)) //only nearest broken harpoon
- BrokenHarpoon->RemoveFromWorld();
+ if (GameObject* brokenHarpoon = harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f)) //only nearest broken harpoon
+ brokenHarpoon->RemoveFromWorld();
events.ScheduleEvent(EVENT_BUILD_HARPOON_2, 20000);
events.CancelEvent(EVENT_BUILD_HARPOON_1);
}
return;
case EVENT_BUILD_HARPOON_2:
Talk(EMOTE_HARPOON);
- if (GameObject* Harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_2, PosHarpoon[1].GetPositionX(), PosHarpoon[1].GetPositionY(), PosHarpoon[1].GetPositionZ(), 4.659f, QuaternionData::fromEulerAnglesZYX(4.659f, 0.0f, 0.0f), uint32(me->GetRespawnTime())))
+ if (GameObject* harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_2, PosHarpoon[1].GetPositionX(), PosHarpoon[1].GetPositionY(), PosHarpoon[1].GetPositionZ(), 4.659f, QuaternionData::fromEulerAnglesZYX(4.659f, 0.0f, 0.0f), uint32(me->GetRespawnTime())))
{
- if (GameObject* BrokenHarpoon = Harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f))
- BrokenHarpoon->RemoveFromWorld();
+ if (GameObject* brokenHarpoon = harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f))
+ brokenHarpoon->RemoveFromWorld();
events.CancelEvent(EVENT_BUILD_HARPOON_2);
}
return;
case EVENT_BUILD_HARPOON_3:
Talk(EMOTE_HARPOON);
- if (GameObject* Harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_3, PosHarpoon[2].GetPositionX(), PosHarpoon[2].GetPositionY(), PosHarpoon[2].GetPositionZ(), 5.382f, QuaternionData::fromEulerAnglesZYX(5.382f, 0.0f, 0.0f), uint32(me->GetRespawnTime())))
+ if (GameObject* harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_3, PosHarpoon[2].GetPositionX(), PosHarpoon[2].GetPositionY(), PosHarpoon[2].GetPositionZ(), 5.382f, QuaternionData::fromEulerAnglesZYX(5.382f, 0.0f, 0.0f), uint32(me->GetRespawnTime())))
{
- if (GameObject* BrokenHarpoon = Harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f))
- BrokenHarpoon->RemoveFromWorld();
+ if (GameObject* brokenHarpoon = harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f))
+ brokenHarpoon->RemoveFromWorld();
events.ScheduleEvent(EVENT_BUILD_HARPOON_4, 20000);
events.CancelEvent(EVENT_BUILD_HARPOON_3);
}
return;
case EVENT_BUILD_HARPOON_4:
Talk(EMOTE_HARPOON);
- if (GameObject* Harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_4, PosHarpoon[3].GetPositionX(), PosHarpoon[3].GetPositionY(), PosHarpoon[3].GetPositionZ(), 4.266f, QuaternionData::fromEulerAnglesZYX(4.266f, 0.0f, 0.0f), uint32(me->GetRespawnTime())))
+ if (GameObject* harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_4, PosHarpoon[3].GetPositionX(), PosHarpoon[3].GetPositionY(), PosHarpoon[3].GetPositionZ(), 4.266f, QuaternionData::fromEulerAnglesZYX(4.266f, 0.0f, 0.0f), uint32(me->GetRespawnTime())))
{
- if (GameObject* BrokenHarpoon = Harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f))
- BrokenHarpoon->RemoveFromWorld();
+ if (GameObject* brokenHarpoon = harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f))
+ brokenHarpoon->RemoveFromWorld();
events.CancelEvent(EVENT_BUILD_HARPOON_4);
}
return;
@@ -315,9 +322,9 @@ class go_razorscale_harpoon : public GameObjectScript
bool OnGossipHello(Player* /*player*/, GameObject* go) override
{
- InstanceScript* instance = go->GetInstanceScript();
- if (ObjectAccessor::GetCreature(*go, instance->GetGuidData(BOSS_RAZORSCALE)))
- go->AddFlag(GO_FLAG_NOT_SELECTABLE);
+ if (InstanceScript* instance = go->GetInstanceScript())
+ if (instance->GetCreature(BOSS_RAZORSCALE))
+ go->AddFlag(GO_FLAG_NOT_SELECTABLE);
return false;
}
};
@@ -361,14 +368,14 @@ class boss_razorscale : public CreatureScript
me->AddUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->SetReactState(REACT_PASSIVE);
Initialize();
- if (Creature* commander = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EXPEDITION_COMMANDER)))
+ if (Creature* commander = instance->GetCreature(DATA_EXPEDITION_COMMANDER))
commander->AI()->DoAction(ACTION_COMMANDER_RESET);
}
void EnterCombat(Unit* /*who*/) override
{
_EnterCombat();
- if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_RAZORSCALE_CONTROL)))
+ if (Creature* controller = instance->GetCreature(DATA_RAZORSCALE_CONTROL))
controller->AI()->DoAction(ACTION_HARPOON_BUILD);
me->SetSpeedRate(MOVE_FLIGHT, 3.0f);
me->SetReactState(REACT_PASSIVE);
@@ -383,7 +390,7 @@ class boss_razorscale : public CreatureScript
void JustDied(Unit* /*killer*/) override
{
_JustDied();
- if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_RAZORSCALE_CONTROL)))
+ if (Creature* controller = instance->GetCreature(DATA_RAZORSCALE_CONTROL))
controller->AI()->Reset();
}
@@ -459,7 +466,7 @@ class boss_razorscale : public CreatureScript
me->SetCanFly(false);
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->AddUnitFlag(UnitFlags(UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED));
- if (Creature* commander = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EXPEDITION_COMMANDER)))
+ if (Creature* commander = instance->GetCreature(DATA_EXPEDITION_COMMANDER))
commander->AI()->DoAction(ACTION_GROUND_PHASE);
events.ScheduleEvent(EVENT_BREATH, 30000, 0, PHASE_GROUND);
events.ScheduleEvent(EVENT_BUFFET, 33000, 0, PHASE_GROUND);
@@ -475,7 +482,7 @@ class boss_razorscale : public CreatureScript
return;
case EVENT_BUFFET:
DoCastAOE(SPELL_WINGBUFFET);
- if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_RAZORSCALE_CONTROL)))
+ if (Creature* controller = instance->GetCreature(DATA_RAZORSCALE_CONTROL))
controller->CastSpell(controller, SPELL_FLAMED, true);
events.CancelEvent(EVENT_BUFFET);
return;
@@ -717,10 +724,10 @@ class npc_expedition_commander : public CreatureScript
Phase = 5;
break;
case 5:
- if (Creature* Razorscale = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_RAZORSCALE)))
+ if (Creature* razorscale = instance->GetCreature(BOSS_RAZORSCALE))
{
- Razorscale->AI()->DoAction(ACTION_EVENT_START);
- me->SetInCombatWith(Razorscale);
+ razorscale->AI()->DoAction(ACTION_EVENT_START);
+ me->SetInCombatWith(razorscale);
}
if (Creature* firstEngineer = ObjectAccessor::GetCreature(*me, Engineer[0]))
firstEngineer->AI()->Talk(SAY_AGGRO_1);
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp
index 0366f1534ba..c6fc0925bf6 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp
@@ -176,11 +176,6 @@ class boss_xt002 : public CreatureScript
public:
boss_xt002() : CreatureScript("boss_xt002") { }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetUlduarAI<boss_xt002_AI>(creature);
- }
-
struct boss_xt002_AI : public BossAI
{
boss_xt002_AI(Creature* creature) : BossAI(creature, BOSS_XT002)
@@ -441,6 +436,12 @@ class boss_xt002 : public CreatureScript
uint8 _heartExposed;
uint32 _transferHealth;
};
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetUlduarAI<boss_xt002_AI>(creature);
+ }
+
};
/*-------------------------------------------------------
@@ -460,7 +461,7 @@ class npc_xt002_heart : public CreatureScript
void JustDied(Unit* /*killer*/) override
{
- if (Creature* xt002 = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(BOSS_XT002)))
+ if (Creature* xt002 = _instance->GetCreature(BOSS_XT002))
{
xt002->AI()->SetData(DATA_TRANSFERED_HEALTH, me->GetHealth());
xt002->AI()->DoAction(ACTION_ENTER_HARD_MODE);
@@ -487,11 +488,6 @@ class npc_scrapbot : public CreatureScript
public:
npc_scrapbot() : CreatureScript("npc_scrapbot") { }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetUlduarAI<npc_scrapbotAI>(creature);
- }
-
struct npc_scrapbotAI : public ScriptedAI
{
npc_scrapbotAI(Creature* creature) : ScriptedAI(creature)
@@ -511,15 +507,15 @@ class npc_scrapbot : public CreatureScript
Initialize();
- if (Creature* pXT002 = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(BOSS_XT002)))
- me->GetMotionMaster()->MoveFollow(pXT002, 0.0f, 0.0f);
+ if (Creature* xt002 = _instance->GetCreature(BOSS_XT002))
+ me->GetMotionMaster()->MoveFollow(xt002, 0.0f, 0.0f);
}
void UpdateAI(uint32 diff) override
{
if (_rangeCheckTimer <= diff)
{
- if (Creature* xt002 = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(BOSS_XT002)))
+ if (Creature* xt002 = _instance->GetCreature(BOSS_XT002))
{
if (me->IsWithinMeleeRange(xt002))
{
@@ -538,6 +534,12 @@ class npc_scrapbot : public CreatureScript
InstanceScript* _instance;
uint32 _rangeCheckTimer;
};
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetUlduarAI<npc_scrapbotAI>(creature);
+ }
+
};
/*-------------------------------------------------------
@@ -550,11 +552,6 @@ class npc_pummeller : public CreatureScript
public:
npc_pummeller() : CreatureScript("npc_pummeller") { }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetUlduarAI<npc_pummellerAI>(creature);
- }
-
struct npc_pummellerAI : public ScriptedAI
{
npc_pummellerAI(Creature* creature) : ScriptedAI(creature)
@@ -574,7 +571,7 @@ class npc_pummeller : public CreatureScript
{
Initialize();
- if (Creature* xt002 = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(BOSS_XT002)))
+ if (Creature* xt002 = _instance->GetCreature(BOSS_XT002))
{
Position pos = xt002->GetPosition();
me->GetMotionMaster()->MovePoint(0, pos);
@@ -622,6 +619,12 @@ class npc_pummeller : public CreatureScript
uint32 _trampleTimer;
uint32 _uppercutTimer;
};
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetUlduarAI<npc_pummellerAI>(creature);
+ }
+
};
/*-------------------------------------------------------
@@ -657,11 +660,6 @@ class npc_boombot : public CreatureScript
public:
npc_boombot() : CreatureScript("npc_boombot") { }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetUlduarAI<npc_boombotAI>(creature);
- }
-
struct npc_boombotAI : public ScriptedAI
{
npc_boombotAI(Creature* creature) : ScriptedAI(creature)
@@ -682,8 +680,8 @@ class npc_boombot : public CreatureScript
DoCast(SPELL_AURA_BOOMBOT); // For achievement
/// @todo proper waypoints?
- if (Creature* pXT002 = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(BOSS_XT002)))
- me->GetMotionMaster()->MoveFollow(pXT002, 0.0f, 0.0f);
+ if (Creature* xt002 = _instance->GetCreature(BOSS_XT002))
+ me->GetMotionMaster()->MoveFollow(xt002, 0.0f, 0.0f);
}
void DamageTaken(Unit* /*who*/, uint32& damage) override
@@ -723,6 +721,12 @@ class npc_boombot : public CreatureScript
InstanceScript* _instance;
bool _boomed;
};
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetUlduarAI<npc_boombotAI>(creature);
+ }
+
};
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp
index 6c1101d433d..79214b5b0e1 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp
@@ -511,7 +511,7 @@ class boss_voice_of_yogg_saron : public CreatureScript
void EnterCombat(Unit* /*who*/) override
{
- if (Creature* sara = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_SARA)))
+ if (Creature* sara = instance->GetCreature(DATA_SARA))
sara->SetInCombatWith(me);
for (uint8 i = DATA_FREYA_YS; i <= DATA_MIMIRON_YS; ++i)
@@ -531,7 +531,7 @@ class boss_voice_of_yogg_saron : public CreatureScript
void JustDied(Unit* killer) override
{
// don't despawn Yogg-Saron's corpse, remove him from SummonList!
- if (Creature* yogg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_YOGG_SARON)))
+ if (Creature* yogg = instance->GetCreature(BOSS_YOGG_SARON))
summons.Despawn(yogg);
BossAI::JustDied(killer);
@@ -556,7 +556,7 @@ class boss_voice_of_yogg_saron : public CreatureScript
instance->SetBossState(BOSS_YOGG_SARON, IN_PROGRESS);
break;
case EVENT_EXTINGUISH_ALL_LIFE:
- if (Creature* yogg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_YOGG_SARON)))
+ if (Creature* yogg = instance->GetCreature(BOSS_YOGG_SARON))
{
yogg->AI()->Talk(EMOTE_YOGG_SARON_EXTINGUISH_ALL_LIFE, me);
yogg->CastSpell((Unit*)NULL, SPELL_EXTINGUISH_ALL_LIFE, true);
@@ -584,7 +584,7 @@ class boss_voice_of_yogg_saron : public CreatureScript
break;
case EVENT_ILLUSION:
{
- if (Creature* yogg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_YOGG_SARON)))
+ if (Creature* yogg = instance->GetCreature(BOSS_YOGG_SARON))
{
yogg->AI()->Talk(EMOTE_YOGG_SARON_MADNESS);
yogg->AI()->Talk(SAY_YOGG_SARON_MADNESS);
@@ -597,7 +597,7 @@ class boss_voice_of_yogg_saron : public CreatureScript
uint8 illusion = urand(CHAMBER_ILLUSION, STORMWIND_ILLUSION);
instance->SetData(DATA_ILLUSION, illusion);
- if (Creature* brain = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_BRAIN_OF_YOGG_SARON)))
+ if (Creature* brain = instance->GetCreature(DATA_BRAIN_OF_YOGG_SARON))
brain->AI()->DoAction(ACTION_INDUCE_MADNESS);
events.ScheduleEvent(EVENT_ILLUSION, 80000, 0, PHASE_TWO); // wowwiki says 80 secs, wowhead says something about 90 secs
break;
@@ -623,7 +623,7 @@ class boss_voice_of_yogg_saron : public CreatureScript
case ACTION_PHASE_TWO:
events.SetPhase(PHASE_TWO);
me->SummonCreature(NPC_YOGG_SARON, YoggSaronSpawnPos);
- if (Creature* brain = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_BRAIN_OF_YOGG_SARON)))
+ if (Creature* brain = instance->GetCreature(DATA_BRAIN_OF_YOGG_SARON))
brain->SetInCombatWithZone();
events.ScheduleEvent(EVENT_SUMMON_CORRUPTOR_TENTACLE, 1, EVENT_GROUP_SUMMON_TENTACLES, PHASE_TWO);
events.ScheduleEvent(EVENT_SUMMON_CONSTRICTOR_TENTACLE, 1, EVENT_GROUP_SUMMON_TENTACLES, PHASE_TWO);
@@ -722,7 +722,7 @@ class boss_sara : public CreatureScript
if (_events.IsInPhase(PHASE_ONE))
{
- if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VOICE_OF_YOGG_SARON)))
+ if (Creature* voice = _instance->GetCreature(DATA_VOICE_OF_YOGG_SARON))
voice->AI()->DoAction(ACTION_PHASE_TRANSFORM);
Talk(SAY_SARA_TRANSFORM_1);
@@ -818,14 +818,14 @@ class boss_sara : public CreatureScript
Talk(SAY_SARA_TRANSFORM_4);
DoCast(me, SPELL_FULL_HEAL);
me->setFaction(16);
- if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VOICE_OF_YOGG_SARON)))
+ if (Creature* voice = _instance->GetCreature(DATA_VOICE_OF_YOGG_SARON))
voice->AI()->DoAction(ACTION_PHASE_TWO);
if (Creature* mimiron = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_MIMIRON_YS)))
mimiron->AI()->DoAction(ACTION_PHASE_TWO);
break;
case EVENT_TRANSFORM_4:
DoCast(me, SPELL_PHASE_2_TRANSFORM);
- if (Creature* yogg = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(BOSS_YOGG_SARON)))
+ if (Creature* yogg = _instance->GetCreature(BOSS_YOGG_SARON))
DoCast(yogg, SPELL_RIDE_YOGG_SARON_VEHICLE);
DoCast(me, SPELL_SHADOWY_BARRIER_SARA);
_events.SetPhase(PHASE_TWO);
@@ -881,7 +881,7 @@ class boss_sara : public CreatureScript
break;
}
- if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VOICE_OF_YOGG_SARON)))
+ if (Creature* voice = _instance->GetCreature(DATA_VOICE_OF_YOGG_SARON))
voice->AI()->JustSummoned(summon);
}
@@ -948,7 +948,7 @@ class boss_yogg_saron : public CreatureScript
{
Talk(SAY_YOGG_SARON_DEATH);
- if (Creature* creature = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VOICE_OF_YOGG_SARON)))
+ if (Creature* creature = _instance->GetCreature(DATA_VOICE_OF_YOGG_SARON))
me->Kill(creature);
for (uint8 i = DATA_SARA; i <= DATA_BRAIN_OF_YOGG_SARON; ++i)
@@ -1065,11 +1065,11 @@ class boss_brain_of_yogg_saron : public CreatureScript
DoCast(me, SPELL_BRAIN_HURT_VISUAL, true);
me->AddUnitFlag(UnitFlags(UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE));
- if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VOICE_OF_YOGG_SARON)))
+ if (Creature* voice = _instance->GetCreature(DATA_VOICE_OF_YOGG_SARON))
voice->AI()->DoAction(ACTION_PHASE_THREE);
- if (Creature* sara = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_SARA)))
+ if (Creature* sara = _instance->GetCreature(DATA_SARA))
sara->AI()->DoAction(ACTION_PHASE_THREE);
- if (Creature* yogg = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(BOSS_YOGG_SARON)))
+ if (Creature* yogg = _instance->GetCreature(BOSS_YOGG_SARON))
yogg->AI()->DoAction(ACTION_PHASE_THREE);
for (uint8 i = DATA_THORIM_YS; i <= DATA_MIMIRON_YS; ++i)
@@ -1107,7 +1107,7 @@ class boss_brain_of_yogg_saron : public CreatureScript
DoCastAOE(SPELL_SHATTERED_ILLUSION, true);
_instance->HandleGameObject(_instance->GetGuidData(GO_BRAIN_ROOM_DOOR_1 + illusion), true);
- if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VOICE_OF_YOGG_SARON)))
+ if (Creature* voice = _instance->GetCreature(DATA_VOICE_OF_YOGG_SARON))
voice->AI()->DoAction(ACTION_TOGGLE_SHATTERED_ILLUSION);
}
break;
@@ -1214,7 +1214,7 @@ class npc_guardian_of_yogg_saron : public CreatureScript
return;
// Guardian can be summoned both by Voice of Yogg-Saron and by Ominous Cloud
- if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VOICE_OF_YOGG_SARON)))
+ if (Creature* voice = _instance->GetCreature(DATA_VOICE_OF_YOGG_SARON))
voice->AI()->JustSummoned(me);
}
@@ -1317,7 +1317,7 @@ class npc_constrictor_tentacle : public CreatureScript
void IsSummonedBy(Unit* /*summoner*/) override
{
- if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VOICE_OF_YOGG_SARON)))
+ if (Creature* voice = _instance->GetCreature(DATA_VOICE_OF_YOGG_SARON))
voice->AI()->JustSummoned(me);
}
@@ -1408,7 +1408,7 @@ class npc_influence_tentacle : public CreatureScript
void JustDied(Unit* /*killer*/) override
{
- if (Creature* brain = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_BRAIN_OF_YOGG_SARON)))
+ if (Creature* brain = _instance->GetCreature(DATA_BRAIN_OF_YOGG_SARON))
brain->AI()->DoAction(ACTION_TENTACLE_KILLED);
}
@@ -2779,7 +2779,7 @@ class spell_yogg_saron_induce_madness : public SpellScriptLoader // 64059
GetCaster()->CastSpell((Unit*)NULL, SPELL_SHATTERED_ILLUSION_REMOVE);
if (InstanceScript* instance = GetCaster()->GetInstanceScript())
- if (Creature* voice = ObjectAccessor::GetCreature(*GetCaster(), instance->GetGuidData(DATA_VOICE_OF_YOGG_SARON)))
+ if (Creature* voice = instance->GetCreature(DATA_VOICE_OF_YOGG_SARON))
voice->AI()->DoAction(ACTION_TOGGLE_SHATTERED_ILLUSION);
}
@@ -3053,7 +3053,9 @@ class spell_yogg_saron_in_the_maws_of_the_old_god : public SpellScriptLoader
SpellCastResult CheckRequirement()
{
if (InstanceScript* instance = GetCaster()->GetInstanceScript())
- if (Creature* yogg = ObjectAccessor::GetCreature(*GetCaster(), instance->GetGuidData(BOSS_YOGG_SARON)))
+ {
+ if (Creature* yogg = instance->GetCreature(BOSS_YOGG_SARON))
+ {
if (yogg->FindCurrentSpellBySpellId(SPELL_DEAFENING_ROAR))
{
if (GetCaster()->GetDistance(yogg) > 20.0f)
@@ -3061,6 +3063,8 @@ class spell_yogg_saron_in_the_maws_of_the_old_god : public SpellScriptLoader
else
return SPELL_CAST_OK;
}
+ }
+ }
return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW;
}
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
index 3683e9f5ea3..d34a7ac516c 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
@@ -79,6 +79,28 @@ MinionData const minionData[] =
ObjectData const creatureData[] =
{
+ { NPC_FLAME_LEVIATHAN, BOSS_LEVIATHAN },
+ { NPC_IGNIS, BOSS_IGNIS },
+ { NPC_RAZORSCALE, BOSS_RAZORSCALE },
+ { NPC_XT002, BOSS_XT002 },
+ { NPC_KOLOGARN, BOSS_KOLOGARN },
+ { NPC_AURIAYA, BOSS_AURIAYA },
+ { NPC_HODIR, BOSS_HODIR },
+ { NPC_THORIM, BOSS_THORIM },
+ { NPC_FREYA, BOSS_FREYA },
+ { NPC_MIMIRON, BOSS_MIMIRON },
+ { NPC_VEZAX, BOSS_VEZAX },
+ { NPC_YOGG_SARON, BOSS_YOGG_SARON },
+ { NPC_ALGALON, BOSS_ALGALON },
+
+ { NPC_EXPEDITION_COMMANDER, DATA_EXPEDITION_COMMANDER },
+ { NPC_RAZORSCALE_CONTROLLER, DATA_RAZORSCALE_CONTROL },
+ { NPC_COMPUTER, DATA_COMPUTER },
+ { NPC_WORLD_TRIGGER_MIMIRON, DATA_MIMIRON_WORLD_TRIGGER },
+ { NPC_VOICE_OF_YOGG_SARON, DATA_VOICE_OF_YOGG_SARON },
+ { NPC_SARA, DATA_SARA },
+ { NPC_BRAIN_OF_YOGG_SARON, DATA_BRAIN_OF_YOGG_SARON },
+ { NPC_BRANN_BRONZBEARD_ALG, DATA_BRANN_BRONZEBEARD_ALG },
{ NPC_BRANN_BRONZEBEARD_INTRO, DATA_BRANN_BRONZEBEARD_INTRO },
{ NPC_LORE_KEEPER_OF_NORGANNON, DATA_LORE_KEEPER_OF_NORGANNON },
{ NPC_HIGH_EXPLORER_DELLORAH, DATA_DELLORAH },
@@ -86,6 +108,19 @@ ObjectData const creatureData[] =
{ 0, 0, }
};
+ObjectData const objectData[] =
+{
+ { GO_MIMIRON_ELEVATOR, DATA_MIMIRON_ELEVATOR },
+ { GO_MIMIRON_BUTTON, DATA_MIMIRON_BUTTON },
+ { GO_DOODAD_UL_UNIVERSEGLOBE01, DATA_UNIVERSE_GLOBE },
+ { GO_DOODAD_UL_ULDUAR_TRAPDOOR_03, DATA_ALGALON_TRAPDOOR },
+ { GO_RAZOR_HARPOON_1, GO_RAZOR_HARPOON_1 },
+ { GO_RAZOR_HARPOON_2, GO_RAZOR_HARPOON_2 },
+ { GO_RAZOR_HARPOON_3, GO_RAZOR_HARPOON_3 },
+ { GO_RAZOR_HARPOON_4, GO_RAZOR_HARPOON_4 },
+ { 0, 0 }
+};
+
class instance_ulduar : public InstanceMapScript
{
public:
@@ -100,7 +135,7 @@ class instance_ulduar : public InstanceMapScript
LoadBossBoundaries(boundaries);
LoadDoorData(doorData);
LoadMinionData(minionData);
- LoadObjectData(creatureData, nullptr);
+ LoadObjectData(creatureData, objectData);
_algalonTimer = 61;
_maxArmorItemLevel = 0;
@@ -124,51 +159,29 @@ class instance_ulduar : public InstanceMapScript
}
// Creatures
- ObjectGuid LeviathanGUID;
GuidVector LeviathanVehicleGUIDs;
- ObjectGuid IgnisGUID;
- ObjectGuid RazorscaleGUID;
- ObjectGuid RazorscaleController;
- ObjectGuid ExpeditionCommanderGUID;
- ObjectGuid XT002GUID;
+
ObjectGuid XTToyPileGUIDs[4];
ObjectGuid AssemblyGUIDs[3];
- ObjectGuid KologarnGUID;
- ObjectGuid AuriayaGUID;
- ObjectGuid HodirGUID;
- ObjectGuid ThorimGUID;
- ObjectGuid FreyaGUID;
+
ObjectGuid ElderGUIDs[3];
ObjectGuid FreyaAchieveTriggerGUID;
- ObjectGuid MimironGUID;
ObjectGuid MimironVehicleGUIDs[3];
- ObjectGuid MimironComputerGUID;
- ObjectGuid MimironWorldTriggerGUID;
- ObjectGuid VezaxGUID;
- ObjectGuid YoggSaronGUID;
- ObjectGuid VoiceOfYoggSaronGUID;
- ObjectGuid SaraGUID;
- ObjectGuid BrainOfYoggSaronGUID;
ObjectGuid KeeperGUIDs[4];
- ObjectGuid AlgalonGUID;
- ObjectGuid BrannBronzebeardAlgGUID;
// GameObjects
ObjectGuid LeviathanGateGUID;
- ObjectGuid RazorHarpoonGUIDs[4];
ObjectGuid KologarnChestGUID;
ObjectGuid KologarnBridgeGUID;
ObjectGuid ThorimChestGUID;
ObjectGuid HodirRareCacheGUID;
ObjectGuid HodirChestGUID;
ObjectGuid MimironTramGUID;
- ObjectGuid MimironElevatorGUID;
- ObjectGuid MimironButtonGUID;
+
ObjectGuid BrainRoomDoorGUIDs[3];
ObjectGuid AlgalonSigilDoorGUID[3];
ObjectGuid AlgalonFloorGUID[2];
- ObjectGuid AlgalonUniverseGUID;
- ObjectGuid AlgalonTrapdoorGUID;
+
ObjectGuid GiftOfTheObserverGUID;
// Miscellaneous
@@ -239,6 +252,8 @@ class instance_ulduar : public InstanceMapScript
void OnCreatureCreate(Creature* creature) override
{
+ InstanceScript::OnCreatureCreate(creature);
+
if (!TeamInInstance)
{
Map::PlayerList const& Players = instance->GetPlayers();
@@ -249,40 +264,22 @@ class instance_ulduar : public InstanceMapScript
switch (creature->GetEntry())
{
- case NPC_LEVIATHAN:
- LeviathanGUID = creature->GetGUID();
- break;
case NPC_SALVAGED_DEMOLISHER:
case NPC_SALVAGED_SIEGE_ENGINE:
case NPC_SALVAGED_CHOPPER:
LeviathanVehicleGUIDs.push_back(creature->GetGUID());
break;
- case NPC_IGNIS:
- IgnisGUID = creature->GetGUID();
- break;
-
- // Razorscale
- case NPC_RAZORSCALE:
- RazorscaleGUID = creature->GetGUID();
- break;
- case NPC_RAZORSCALE_CONTROLLER:
- RazorscaleController = creature->GetGUID();
- break;
- case NPC_EXPEDITION_COMMANDER:
- ExpeditionCommanderGUID = creature->GetGUID();
- break;
// XT-002 Deconstructor
- case NPC_XT002:
- XT002GUID = creature->GetGUID();
- break;
case NPC_XT_TOY_PILE:
for (uint8 i = 0; i < 4; ++i)
+ {
if (!XTToyPileGUIDs[i])
{
XTToyPileGUIDs[i] = creature->GetGUID();
break;
}
+ }
break;
// Assembly of Iron
@@ -299,17 +296,7 @@ class instance_ulduar : public InstanceMapScript
AddMinion(creature, true);
break;
- case NPC_KOLOGARN:
- KologarnGUID = creature->GetGUID();
- break;
- case NPC_AURIAYA:
- AuriayaGUID = creature->GetGUID();
- break;
-
// Hodir
- case NPC_HODIR:
- HodirGUID = creature->GetGUID();
- break;
case NPC_EIVI_NIGHTFEATHER:
if (TeamInInstance == HORDE)
creature->UpdateEntry(NPC_TOR_GREYCLOUD);
@@ -343,14 +330,7 @@ class instance_ulduar : public InstanceMapScript
creature->UpdateEntry(NPC_BATTLE_PRIEST_GINA);
break;
- case NPC_THORIM:
- ThorimGUID = creature->GetGUID();
- break;
-
// Freya
- case NPC_FREYA:
- FreyaGUID = creature->GetGUID();
- break;
case NPC_IRONBRANCH:
ElderGUIDs[0] = creature->GetGUID();
if (GetBossState(BOSS_FREYA) == DONE)
@@ -371,9 +351,6 @@ class instance_ulduar : public InstanceMapScript
break;
// Mimiron
- case NPC_MIMIRON:
- MimironGUID = creature->GetGUID();
- break;
case NPC_LEVIATHAN_MKII:
MimironVehicleGUIDs[0] = creature->GetGUID();
break;
@@ -383,30 +360,8 @@ class instance_ulduar : public InstanceMapScript
case NPC_AERIAL_COMMAND_UNIT:
MimironVehicleGUIDs[2] = creature->GetGUID();
break;
- case NPC_COMPUTER:
- MimironComputerGUID = creature->GetGUID();
- break;
- case NPC_WORLD_TRIGGER_MIMIRON:
- MimironWorldTriggerGUID = creature->GetGUID();
- break;
-
- case NPC_VEZAX:
- VezaxGUID = creature->GetGUID();
- break;
// Yogg-Saron
- case NPC_YOGG_SARON:
- YoggSaronGUID = creature->GetGUID();
- break;
- case NPC_VOICE_OF_YOGG_SARON:
- VoiceOfYoggSaronGUID = creature->GetGUID();
- break;
- case NPC_BRAIN_OF_YOGG_SARON:
- BrainOfYoggSaronGUID = creature->GetGUID();
- break;
- case NPC_SARA:
- SaraGUID = creature->GetGUID();
- break;
case NPC_FREYA_YS:
KeeperGUIDs[0] = creature->GetGUID();
_summonYSKeeper[0] = false;
@@ -436,12 +391,6 @@ class instance_ulduar : public InstanceMapScript
break;
// Algalon
- case NPC_ALGALON:
- AlgalonGUID = creature->GetGUID();
- break;
- case NPC_BRANN_BRONZBEARD_ALG:
- BrannBronzebeardAlgGUID = creature->GetGUID();
- break;
//! These creatures are summoned by something else than Algalon
//! but need to be controlled/despawned by him - so they need to be
//! registered in his summon list
@@ -449,7 +398,7 @@ class instance_ulduar : public InstanceMapScript
case NPC_ALGALON_STALKER_ASTEROID_TARGET_01:
case NPC_ALGALON_STALKER_ASTEROID_TARGET_02:
case NPC_UNLEASHED_DARK_MATTER:
- if (Creature* algalon = instance->GetCreature(AlgalonGUID))
+ if (Creature* algalon = GetCreature(BOSS_ALGALON))
algalon->AI()->JustSummoned(creature);
break;
}
@@ -459,34 +408,34 @@ class instance_ulduar : public InstanceMapScript
void OnCreatureRemove(Creature* creature) override
{
+ InstanceScript::OnCreatureRemove(creature);
+
switch (creature->GetEntry())
{
case NPC_XT_TOY_PILE:
for (uint8 i = 0; i < 4; ++i)
+ {
if (XTToyPileGUIDs[i] == creature->GetGUID())
{
XTToyPileGUIDs[i].Clear();
break;
}
+ }
break;
case NPC_STEELBREAKER:
case NPC_MOLGEIM:
case NPC_BRUNDIR:
AddMinion(creature, false);
break;
- case NPC_BRANN_BRONZBEARD_ALG:
- if (BrannBronzebeardAlgGUID == creature->GetGUID())
- BrannBronzebeardAlgGUID.Clear();
- break;
default:
break;
}
-
- InstanceScript::OnCreatureRemove(creature);
}
void OnGameObjectCreate(GameObject* gameObject) override
{
+ InstanceScript::OnGameObjectCreate(gameObject);
+
switch (gameObject->GetEntry())
{
case GO_KOLOGARN_CHEST_HERO:
@@ -513,43 +462,11 @@ class instance_ulduar : public InstanceMapScript
case GO_MIMIRON_TRAM:
MimironTramGUID = gameObject->GetGUID();
break;
- case GO_MIMIRON_ELEVATOR:
- MimironElevatorGUID = gameObject->GetGUID();
- break;
- case GO_MIMIRON_BUTTON:
- MimironButtonGUID = gameObject->GetGUID();
- break;
case GO_LEVIATHAN_GATE:
LeviathanGateGUID = gameObject->GetGUID();
if (GetBossState(BOSS_LEVIATHAN) == DONE)
gameObject->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE);
break;
- case GO_LEVIATHAN_DOOR:
- case GO_XT_002_DOOR:
- case GO_IRON_COUNCIL_DOOR:
- case GO_ARCHIVUM_DOOR:
- case GO_HODIR_ENTRANCE:
- case GO_HODIR_DOOR:
- case GO_HODIR_ICE_DOOR:
- case GO_MIMIRON_DOOR_1:
- case GO_MIMIRON_DOOR_2:
- case GO_MIMIRON_DOOR_3:
- case GO_VEZAX_DOOR:
- case GO_YOGG_SARON_DOOR:
- AddDoor(gameObject, true);
- break;
- case GO_RAZOR_HARPOON_1:
- RazorHarpoonGUIDs[0] = gameObject->GetGUID();
- break;
- case GO_RAZOR_HARPOON_2:
- RazorHarpoonGUIDs[1] = gameObject->GetGUID();
- break;
- case GO_RAZOR_HARPOON_3:
- RazorHarpoonGUIDs[2] = gameObject->GetGUID();
- break;
- case GO_RAZOR_HARPOON_4:
- RazorHarpoonGUIDs[3] = gameObject->GetGUID();
- break;
case GO_MOLE_MACHINE:
if (GetBossState(BOSS_RAZORSCALE) == IN_PROGRESS)
gameObject->SetGoState(GO_STATE_ACTIVE);
@@ -580,23 +497,12 @@ class instance_ulduar : public InstanceMapScript
break;
case GO_DOODAD_UL_SIGILDOOR_03:
AlgalonSigilDoorGUID[2] = gameObject->GetGUID();
- AddDoor(gameObject, true);
break;
case GO_DOODAD_UL_UNIVERSEFLOOR_01:
AlgalonFloorGUID[0] = gameObject->GetGUID();
- AddDoor(gameObject, true);
break;
case GO_DOODAD_UL_UNIVERSEFLOOR_02:
AlgalonFloorGUID[1] = gameObject->GetGUID();
- AddDoor(gameObject, true);
- break;
- case GO_DOODAD_UL_UNIVERSEGLOBE01:
- AlgalonUniverseGUID = gameObject->GetGUID();
- AddDoor(gameObject, true);
- break;
- case GO_DOODAD_UL_ULDUAR_TRAPDOOR_03:
- AlgalonTrapdoorGUID = gameObject->GetGUID();
- AddDoor(gameObject, true);
break;
case GO_GIFT_OF_THE_OBSERVER_10:
case GO_GIFT_OF_THE_OBSERVER_25:
@@ -607,40 +513,12 @@ class instance_ulduar : public InstanceMapScript
}
}
- void OnGameObjectRemove(GameObject* gameObject) override
- {
- switch (gameObject->GetEntry())
- {
- case GO_LEVIATHAN_DOOR:
- case GO_XT_002_DOOR:
- case GO_IRON_COUNCIL_DOOR:
- case GO_ARCHIVUM_DOOR:
- case GO_HODIR_ENTRANCE:
- case GO_HODIR_DOOR:
- case GO_HODIR_ICE_DOOR:
- case GO_MIMIRON_DOOR_1:
- case GO_MIMIRON_DOOR_2:
- case GO_MIMIRON_DOOR_3:
- case GO_VEZAX_DOOR:
- case GO_YOGG_SARON_DOOR:
- case GO_DOODAD_UL_SIGILDOOR_03:
- case GO_DOODAD_UL_UNIVERSEFLOOR_01:
- case GO_DOODAD_UL_UNIVERSEFLOOR_02:
- case GO_DOODAD_UL_UNIVERSEGLOBE01:
- case GO_DOODAD_UL_ULDUAR_TRAPDOOR_03:
- AddDoor(gameObject, false);
- break;
- default:
- break;
- }
- }
-
void OnUnitDeath(Unit* unit) override
{
// Champion/Conqueror of Ulduar
if (unit->GetTypeId() == TYPEID_PLAYER)
{
- for (uint8 i = 0; i < BOSS_ALGALON; i++)
+ for (uint8 i = 0; i < BOSS_ALGALON; ++i)
{
if (GetBossState(i) == IN_PROGRESS)
{
@@ -686,27 +564,27 @@ class instance_ulduar : public InstanceMapScript
void ProcessEvent(WorldObject* /*gameObject*/, uint32 eventId) override
{
- // Flame Leviathan's Tower Event triggers
- Creature* FlameLeviathan = instance->GetCreature(LeviathanGUID);
-
switch (eventId)
{
+ // Flame Leviathan's Tower Event triggers
case EVENT_TOWER_OF_STORM_DESTROYED:
- if (FlameLeviathan && FlameLeviathan->IsAlive())
- FlameLeviathan->AI()->DoAction(ACTION_TOWER_OF_STORM_DESTROYED);
+ if (Creature* flameLeviathan = GetCreature(BOSS_LEVIATHAN))
+ flameLeviathan->AI()->DoAction(ACTION_TOWER_OF_STORM_DESTROYED);
break;
case EVENT_TOWER_OF_FROST_DESTROYED:
- if (FlameLeviathan && FlameLeviathan->IsAlive())
- FlameLeviathan->AI()->DoAction(ACTION_TOWER_OF_FROST_DESTROYED);
+ if (Creature* flameLeviathan = GetCreature(BOSS_LEVIATHAN))
+ flameLeviathan->AI()->DoAction(ACTION_TOWER_OF_FROST_DESTROYED);
break;
case EVENT_TOWER_OF_FLAMES_DESTROYED:
- if (FlameLeviathan && FlameLeviathan->IsAlive())
- FlameLeviathan->AI()->DoAction(ACTION_TOWER_OF_FLAMES_DESTROYED);
+ if (Creature* flameLeviathan = GetCreature(BOSS_LEVIATHAN))
+ flameLeviathan->AI()->DoAction(ACTION_TOWER_OF_FLAMES_DESTROYED);
break;
case EVENT_TOWER_OF_LIFE_DESTROYED:
- if (FlameLeviathan && FlameLeviathan->IsAlive())
- FlameLeviathan->AI()->DoAction(ACTION_TOWER_OF_LIFE_DESTROYED);
+ if (Creature* flameLeviathan = GetCreature(BOSS_LEVIATHAN))
+ flameLeviathan->AI()->DoAction(ACTION_TOWER_OF_LIFE_DESTROYED);
break;
+
+ // Yogg-Saron Event triggers
case EVENT_ACTIVATE_SANITY_WELL:
if (Creature* freya = instance->GetCreature(KeeperGUIDs[0]))
freya->AI()->DoAction(4/*ACTION_SANITY_WELLS*/);
@@ -851,9 +729,9 @@ class instance_ulduar : public InstanceMapScript
HodirRareCacheData = data;
if (!HodirRareCacheData)
{
- if (Creature* Hodir = instance->GetCreature(HodirGUID))
+ if (Creature* hodir = GetCreature(BOSS_HODIR))
if (GameObject* gameObject = instance->GetGameObject(HodirRareCacheGUID))
- Hodir->RemoveGameObject(gameObject, false);
+ hodir->RemoveGameObject(gameObject, false);
}
break;
case DATA_UNBROKEN:
@@ -888,30 +766,7 @@ class instance_ulduar : public InstanceMapScript
{
switch (data)
{
- case BOSS_LEVIATHAN:
- return LeviathanGUID;
- case BOSS_IGNIS:
- return IgnisGUID;
-
- // Razorscale
- case BOSS_RAZORSCALE:
- return RazorscaleGUID;
- case DATA_RAZORSCALE_CONTROL:
- return RazorscaleController;
- case DATA_EXPEDITION_COMMANDER:
- return ExpeditionCommanderGUID;
- case GO_RAZOR_HARPOON_1:
- return RazorHarpoonGUIDs[0];
- case GO_RAZOR_HARPOON_2:
- return RazorHarpoonGUIDs[1];
- case GO_RAZOR_HARPOON_3:
- return RazorHarpoonGUIDs[2];
- case GO_RAZOR_HARPOON_4:
- return RazorHarpoonGUIDs[3];
-
// XT-002 Deconstructor
- case BOSS_XT002:
- return XT002GUID;
case DATA_TOY_PILE_0:
case DATA_TOY_PILE_1:
case DATA_TOY_PILE_2:
@@ -926,18 +781,7 @@ class instance_ulduar : public InstanceMapScript
case DATA_BRUNDIR:
return AssemblyGUIDs[2];
- case BOSS_KOLOGARN:
- return KologarnGUID;
- case BOSS_AURIAYA:
- return AuriayaGUID;
- case BOSS_HODIR:
- return HodirGUID;
- case BOSS_THORIM:
- return ThorimGUID;
-
// Freya
- case BOSS_FREYA:
- return FreyaGUID;
case BOSS_BRIGHTLEAF:
return ElderGUIDs[0];
case BOSS_IRONBRANCH:
@@ -946,35 +790,14 @@ class instance_ulduar : public InstanceMapScript
return ElderGUIDs[2];
// Mimiron
- case BOSS_MIMIRON:
- return MimironGUID;
case DATA_LEVIATHAN_MK_II:
return MimironVehicleGUIDs[0];
case DATA_VX_001:
return MimironVehicleGUIDs[1];
case DATA_AERIAL_COMMAND_UNIT:
return MimironVehicleGUIDs[2];
- case DATA_COMPUTER:
- return MimironComputerGUID;
- case DATA_MIMIRON_WORLD_TRIGGER:
- return MimironWorldTriggerGUID;
- case DATA_MIMIRON_ELEVATOR:
- return MimironElevatorGUID;
- case DATA_MIMIRON_BUTTON:
- return MimironButtonGUID;
-
- case BOSS_VEZAX:
- return VezaxGUID;
// Yogg-Saron
- case BOSS_YOGG_SARON:
- return YoggSaronGUID;
- case DATA_VOICE_OF_YOGG_SARON:
- return VoiceOfYoggSaronGUID;
- case DATA_BRAIN_OF_YOGG_SARON:
- return BrainOfYoggSaronGUID;
- case DATA_SARA:
- return SaraGUID;
case GO_BRAIN_ROOM_DOOR_1:
return BrainRoomDoorGUIDs[0];
case GO_BRAIN_ROOM_DOOR_2:
@@ -991,8 +814,6 @@ class instance_ulduar : public InstanceMapScript
return KeeperGUIDs[3];
// Algalon
- case BOSS_ALGALON:
- return AlgalonGUID;
case DATA_SIGILDOOR_01:
return AlgalonSigilDoorGUID[0];
case DATA_SIGILDOOR_02:
@@ -1003,15 +824,9 @@ class instance_ulduar : public InstanceMapScript
return AlgalonFloorGUID[0];
case DATA_UNIVERSE_FLOOR_02:
return AlgalonFloorGUID[1];
- case DATA_UNIVERSE_GLOBE:
- return AlgalonUniverseGUID;
- case DATA_ALGALON_TRAPDOOR:
- return AlgalonTrapdoorGUID;
- case DATA_BRANN_BRONZEBEARD_ALG:
- return BrannBronzebeardAlgGUID;
}
- return ObjectGuid::Empty;
+ return InstanceScript::GetGuidData(data);
}
uint32 GetData(uint32 type) const override
@@ -1179,7 +994,7 @@ class instance_ulduar : public InstanceMapScript
{
DoUpdateWorldState(WORLD_STATE_ALGALON_TIMER_ENABLED, 0);
_events.CancelEvent(EVENT_UPDATE_ALGALON_TIMER);
- if (Creature* algalon = instance->GetCreature(AlgalonGUID))
+ if (Creature* algalon = GetCreature(BOSS_ALGALON))
algalon->AI()->DoAction(EVENT_DESPAWN_ALGALON);
}
break;
@@ -1200,8 +1015,8 @@ class instance_ulduar : public InstanceMapScript
}
break;
case EVENT_LEVIATHAN_BREAK_DOOR:
- if (Creature* Leviathan = instance->GetCreature(LeviathanGUID))
- Leviathan->AI()->DoAction(ACTION_MOVE_TO_CENTER_POSITION);
+ if (Creature* leviathan = GetCreature(BOSS_LEVIATHAN))
+ leviathan->AI()->DoAction(ACTION_MOVE_TO_CENTER_POSITION);
if (GameObject* gameObject = instance->GetGameObject(LeviathanGateGUID))
gameObject->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE);
break;
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h
index 74adb6d1d13..a26b699b396 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h
@@ -279,7 +279,7 @@ enum UlduarGameObjects
GO_GIFT_OF_THE_OBSERVER_25 = 194822,
};
-enum EventIds
+enum UUEventIds
{
EVENT_TOWER_OF_STORM_DESTROYED = 21031,
EVENT_TOWER_OF_FROST_DESTROYED = 21032,
diff --git a/src/server/scripts/Northrend/zone_zuldrak.cpp b/src/server/scripts/Northrend/zone_zuldrak.cpp
index e7f17a1033b..0e42a431d93 100644
--- a/src/server/scripts/Northrend/zone_zuldrak.cpp
+++ b/src/server/scripts/Northrend/zone_zuldrak.cpp
@@ -58,7 +58,7 @@ public:
me->AddUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
float x, y, z;
- me->GetClosePoint(x, y, z, me->GetObjectSize() / 3, 0.1f);
+ me->GetClosePoint(x, y, z, me->GetCombatReach() / 3, 0.1f);
if (Creature* summon = me->SummonCreature(NPC_RAGECLAW, x, y, z, 0, TEMPSUMMON_DEAD_DESPAWN, 1000))
{
@@ -183,7 +183,7 @@ public:
void Reset() override
{
float x, y, z;
- me->GetClosePoint(x, y, z, me->GetObjectSize() / 3, 25.0f);
+ me->GetClosePoint(x, y, z, me->GetCombatReach() / 3, 25.0f);
me->GetMotionMaster()->MovePoint(0, x, y, z);
}
diff --git a/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp b/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp
index e2e8a6bbef7..50fbd937d53 100644
--- a/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp
+++ b/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp
@@ -351,6 +351,8 @@ public:
Talk(SUFF_SAY_RECAP);
me->AttackStop();
me->SetReactState(REACT_PASSIVE);
+ events.Reset();
+ me->InterruptNonMeleeSpells(false);
me->GetMotionMaster()->MovePoint(RELIQUARY_DESPAWN_WAYPOINT, DespawnPoint);
}
}
@@ -479,6 +481,8 @@ public:
Talk(DESI_SAY_RECAP);
me->AttackStop();
me->SetReactState(REACT_PASSIVE);
+ events.Reset();
+ me->InterruptNonMeleeSpells(false);
me->GetMotionMaster()->MovePoint(RELIQUARY_DESPAWN_WAYPOINT, DespawnPoint);
}
}
@@ -743,7 +747,7 @@ class spell_reliquary_of_souls_aura_of_desire : public SpellScriptLoader
caster->CastCustomSpell(SPELL_AURA_OF_DESIRE_DAMAGE, SPELLVALUE_BASE_POINT0, bp, caster, true, nullptr, aurEff);
}
- void UpdateAmount(AuraEffect const* /*effect*/)
+ void UpdateAmount(AuraEffect* /*aurEff*/)
{
if (AuraEffect* effect = GetAura()->GetEffect(EFFECT_1))
effect->ChangeAmount(effect->GetAmount() - 5);
@@ -752,7 +756,7 @@ class spell_reliquary_of_souls_aura_of_desire : public SpellScriptLoader
void Register() override
{
OnEffectProc += AuraEffectProcFn(spell_reliquary_of_souls_aura_of_desire_AuraScript::OnProcSpell, EFFECT_0, SPELL_AURA_MOD_HEALING_PCT);
- OnEffectPeriodic += AuraEffectPeriodicFn(spell_reliquary_of_souls_aura_of_desire_AuraScript::UpdateAmount, EFFECT_2, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_reliquary_of_souls_aura_of_desire_AuraScript::UpdateAmount, EFFECT_2, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
}
};
diff --git a/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/instance_magtheridons_lair.cpp b/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/instance_magtheridons_lair.cpp
index 515039e987b..8cd4bbc9cf0 100644
--- a/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/instance_magtheridons_lair.cpp
+++ b/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/instance_magtheridons_lair.cpp
@@ -55,7 +55,7 @@ ObjectData const gameObjectData[] =
{ 0, 0 } //END
};
-static DataTypes const collapseObjectDatas[] =
+static MLDataTypes const collapseObjectDatas[] =
{
DATA_MAGTHERIDON_COLUMN_0,
DATA_MAGTHERIDON_COLUMN_1,
@@ -116,7 +116,7 @@ class instance_magtheridons_lair : public InstanceMapScript
HandleGameObject(ObjectGuid::Empty, value == ACTION_ENABLE ? true : false, hall);
break;
case DATA_COLLAPSE_2:
- for (DataTypes data : collapseObjectDatas)
+ for (MLDataTypes data : collapseObjectDatas)
if (GameObject* go = GetGameObject(data))
HandleGameObject(ObjectGuid::Empty, value == ACTION_ENABLE ? true : false, go);
break;
diff --git a/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/magtheridons_lair.h b/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/magtheridons_lair.h
index 4e46ecd98e7..87190d446b0 100644
--- a/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/magtheridons_lair.h
+++ b/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/magtheridons_lair.h
@@ -25,7 +25,7 @@
uint32 const EncounterCount = 1;
-enum DataTypes
+enum MLDataTypes
{
DATA_MAGTHERIDON = 0,
DATA_WORLD_TRIGGER = 1,
@@ -42,13 +42,13 @@ enum DataTypes
DATA_CALL_WARDERS = 12
};
-enum Actions
+enum MLActions
{
ACTION_ENABLE = 1,
ACTION_DISABLE = 2
};
-enum CreatureIds
+enum MLCreatureIds
{
NPC_MAGTHERIDON = 17257,
NPC_ABYSSAL = 17454,
@@ -61,7 +61,7 @@ enum CreatureIds
NPC_HELLFIRE_WARDER = 18829
};
-enum GameObjectIds
+enum MLGameObjectIds
{
GO_MAGTHERIDON_DOOR = 183847,
GO_MANTICRON_CUBE = 181713,
diff --git a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp
index a482096ce7c..a8bd85023a2 100644
--- a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp
+++ b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp
@@ -525,7 +525,7 @@ public:
Tapped = true;
float x, y, z;
- caster->GetClosePoint(x, y, z, me->GetObjectSize());
+ caster->GetClosePoint(x, y, z, me->GetCombatReach());
me->SetWalk(false);
me->GetMotionMaster()->MovePoint(1, x, y, z);
diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp
index 7adb0d0d4cf..eb800765b7c 100644
--- a/src/server/scripts/Spells/spell_generic.cpp
+++ b/src/server/scripts/Spells/spell_generic.cpp
@@ -4207,42 +4207,6 @@ class spell_gen_pony_mount_check : public SpellScriptLoader
}
};
-class spell_gen_shroud_of_death : public SpellScriptLoader
-{
-public:
- spell_gen_shroud_of_death() : SpellScriptLoader("spell_gen_shroud_of_death") { }
-
- class spell_gen_shroud_of_death_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_gen_shroud_of_death_AuraScript);
-
- void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- PreventDefaultAction();
- GetUnitOwner()->m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_GHOST);
- GetUnitOwner()->m_serverSideVisibilityDetect.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_GHOST);
- }
-
- void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- PreventDefaultAction();
- GetUnitOwner()->m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE);
- GetUnitOwner()->m_serverSideVisibilityDetect.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE);
- }
-
- void Register() override
- {
- OnEffectApply += AuraEffectApplyFn(spell_gen_shroud_of_death_AuraScript::OnApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
- OnEffectRemove += AuraEffectRemoveFn(spell_gen_shroud_of_death_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
- }
- };
-
- AuraScript* GetAuraScript() const override
- {
- return new spell_gen_shroud_of_death_AuraScript();
- }
-};
-
// 169869 - Transformation Sickness
class spell_gen_decimatus_transformation_sickness : public SpellScriptLoader
{
@@ -4568,7 +4532,6 @@ void AddSC_generic_spell_scripts()
new spell_gen_landmine_knockback_achievement();
new spell_gen_clear_debuffs();
new spell_gen_pony_mount_check();
- new spell_gen_shroud_of_death();
new spell_gen_decimatus_transformation_sickness();
new spell_gen_anetheron_summon_towering_infernal();
new spell_gen_mark_of_kazrogal_hellfire();
diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp
index 9836318f066..7461e52e1b4 100644
--- a/src/server/scripts/Spells/spell_item.cpp
+++ b/src/server/scripts/Spells/spell_item.cpp
@@ -1100,6 +1100,46 @@ class spell_item_gnomish_death_ray : public SpellScriptLoader
}
};
+// Item 10721: Gnomish Harm Prevention Belt
+// 13234 - Harm Prevention Belt
+enum HarmPreventionBelt
+{
+ SPELL_FORCEFIELD_COLLAPSE = 13235
+};
+
+class spell_item_harm_prevention_belt : public SpellScriptLoader
+{
+public:
+ spell_item_harm_prevention_belt() : SpellScriptLoader("spell_item_harm_prevention_belt") { }
+
+ class spell_item_harm_prevention_belt_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_item_harm_prevention_belt_AuraScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_FORCEFIELD_COLLAPSE))
+ return false;
+ return true;
+ }
+
+ void HandleProc(ProcEventInfo& /*eventInfo*/)
+ {
+ GetTarget()->CastSpell((Unit*)nullptr, SPELL_FORCEFIELD_COLLAPSE, true);
+ }
+
+ void Register() override
+ {
+ OnProc += AuraProcFn(spell_item_harm_prevention_belt_AuraScript::HandleProc);
+ }
+ };
+
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_item_harm_prevention_belt_AuraScript();
+ }
+};
+
enum Heartpierce
{
SPELL_INVIGORATION_MANA = 71881,
@@ -4839,6 +4879,7 @@ void AddSC_item_spell_scripts()
new spell_item_flask_of_the_north();
new spell_item_frozen_shadoweave();
new spell_item_gnomish_death_ray();
+ new spell_item_harm_prevention_belt();
new spell_item_heartpierce<SPELL_INVIGORATION_ENERGY, SPELL_INVIGORATION_MANA, SPELL_INVIGORATION_RAGE, SPELL_INVIGORATION_RP>("spell_item_heartpierce");
new spell_item_heartpierce<SPELL_INVIGORATION_ENERGY_HERO, SPELL_INVIGORATION_MANA_HERO, SPELL_INVIGORATION_RAGE_HERO, SPELL_INVIGORATION_RP_HERO>("spell_item_heartpierce_hero");
new spell_item_crystal_spire_of_karabor();
diff --git a/src/server/scripts/Spells/spell_pet.cpp b/src/server/scripts/Spells/spell_pet.cpp
index c0b570cbf46..7aaba87a2da 100644
--- a/src/server/scripts/Spells/spell_pet.cpp
+++ b/src/server/scripts/Spells/spell_pet.cpp
@@ -314,7 +314,7 @@ public:
{
if (AuraEffect* /* aurEff */ect = owner->GetAuraEffect(56246, EFFECT_0))
{
- float base_attPower = pet->GetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE) * pet->GetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_PCT);
+ float base_attPower = pet->GetFlatModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE) * pet->GetPctModifierValue(UNIT_MOD_ATTACK_POWER, BASE_PCT);
amount += CalculatePct(amount+base_attPower, /* aurEff */ect->GetAmount());
}
}
diff --git a/src/server/scripts/World/go_scripts.cpp b/src/server/scripts/World/go_scripts.cpp
index 98814128a34..c0e1fdaae33 100644
--- a/src/server/scripts/World/go_scripts.cpp
+++ b/src/server/scripts/World/go_scripts.cpp
@@ -361,7 +361,7 @@ public:
uint32 BirdEntry = 0;
float fX, fY, fZ;
- go->GetClosePoint(fX, fY, fZ, go->GetObjectSize(), INTERACTION_DISTANCE);
+ go->GetClosePoint(fX, fY, fZ, go->GetCombatReach(), INTERACTION_DISTANCE);
switch (go->GetEntry())
{
diff --git a/src/server/scripts/World/item_scripts.cpp b/src/server/scripts/World/item_scripts.cpp
index 55b7d571d56..628ca0edcae 100644
--- a/src/server/scripts/World/item_scripts.cpp
+++ b/src/server/scripts/World/item_scripts.cpp
@@ -243,7 +243,7 @@ public:
return true;
float x, y, z;
- go->GetClosePoint(x, y, z, go->GetObjectSize() / 3, 7.0f);
+ go->GetClosePoint(x, y, z, go->GetCombatReach() / 3, 7.0f);
go->SummonGameObject(GO_HIGH_QUALITY_FUR, *go, QuaternionData::fromEulerAnglesZYX(go->GetOrientation(), 0.0f, 0.0f), 1);
if (TempSummon* summon = player->SummonCreature(NPC_NESINGWARY_TRAPPER, x, y, z, go->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 1000))
{