diff options
35 files changed, 746 insertions, 31 deletions
diff --git a/sql/updates/world/2016_01_07_01_world.sql b/sql/updates/world/2016_01_07_01_world.sql new file mode 100644 index 00000000000..4a15aa405ec --- /dev/null +++ b/sql/updates/world/2016_01_07_01_world.sql @@ -0,0 +1,2 @@ +-- +DELETE FROM `creature` WHERE `id`=22972; diff --git a/sql/updates/world/2016_01_07_02_world.sql b/sql/updates/world/2016_01_07_02_world.sql new file mode 100644 index 00000000000..7724b42ac9d --- /dev/null +++ b/sql/updates/world/2016_01_07_02_world.sql @@ -0,0 +1,2 @@ +-- fix a start-up warning +UPDATE `creature` SET `spawndist`=0 WHERE `guid` IN (79007,79008,79009); diff --git a/sql/updates/world/2016_01_08_00_world.sql b/sql/updates/world/2016_01_08_00_world.sql new file mode 100644 index 00000000000..55ed3ddf336 --- /dev/null +++ b/sql/updates/world/2016_01_08_00_world.sql @@ -0,0 +1,18 @@ +UPDATE `creature_template` SET +`spell1` = 62225, -- Claw +`spell2` = 47480, -- Thrash +`spell3` = 47481, -- Gnaw +`spell4` = 47482, -- Leap +`spell5` = 47484, -- Huddle +`spell6` = 47496 -- Explode +WHERE `entry` = 30230; + +DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_dk_raise_ally_initial', 'spell_dk_raise_ally', 'spell_dk_ghoul_thrash'); +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(61999, 'spell_dk_raise_ally_initial'), +(46619, 'spell_dk_raise_ally'), +(47480, 'spell_dk_ghoul_thrash'); + +DELETE FROM `spell_dbc` WHERE `Id`=62214; +INSERT INTO `spell_dbc` (`Id`,`Attributes`,`AttributesEx`,`AttributesEx2`,`AttributesEx3`,`AttributesEx4`,`AttributesEx5`,`AttributesEx6`,`DurationIndex`,`RangeIndex`,`Effect1`,`EffectImplicitTargetA1`,`EffectApplyAuraName1`,`Comment`) VALUES +(62214,0xA9800100,0x10000420,0x10084005,0x00130000,0x00800080,0x00060008,0x00001404,21,13,6,25,279,'Mirror Name'); diff --git a/sql/updates/world/2016_01_08_01_world.sql b/sql/updates/world/2016_01_08_01_world.sql new file mode 100644 index 00000000000..ebf4560d326 --- /dev/null +++ b/sql/updates/world/2016_01_08_01_world.sql @@ -0,0 +1,52 @@ +-- +SET @Oguid :=6008; +DELETE FROM `gameobject` WHERE `id`=186487; +INSERT INTO `gameobject` (`guid`, `id`, `map`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `rotation0`, `rotation1`, `rotation2`, `rotation3`, `spawntimesecs`, `animprogress`, `state`) VALUES +(@Oguid, 186487, 571, 1, 1, 2821.75, -3603.67, 245.555, 3.49556, 0, 0, 0.984379, -0.176061, -300, 0, 1); + +SET @CGUID := 76053; +DELETE FROM `creature_template_addon` WHERE `entry` IN (24029); +INSERT INTO `creature_template_addon` (`entry`, `mount`, `bytes1`, `bytes2`, `auras`) VALUES +(24029, 0, 0x0, 0x1, 12544); -- Wyrmcaller Vile - Frost Armor + +DELETE FROM `creature_addon` WHERE `guid` IN (@CGUID+5); +INSERT INTO `creature_addon` (`guid`, `mount`, `bytes1`, `bytes2`, `auras`) VALUES +(@CGUID+5, 0, 0x0, 0x1, 43570); -- Invisible Stalker (Floating) - Frost State + +DELETE FROM `spell_linked_spell` WHERE `spell_trigger` IN(43568,43569); +INSERT INTO `spell_linked_spell` (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES +(43568, 34872, 1, 'Frost Strike'), +(43569, 34872, 1, 'Frost trigger '); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN(43568); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(13,1,43568,0,0,31,0,3,15214,0,0,0,0,'',"Spell 'Frost Strike' Effect 0 can hit 'Invisible Stalker'"); + +DELETE FROM `creature` WHERE `guid` BETWEEN @CGUID AND @CGUID+8; +INSERT INTO `creature` (`guid`, `id`, `map`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `spawndist`, `MovementType`) VALUES +(@CGUID, 15214, 571, 1, 1, 2842.762, -3599.551, 247.2563, 1.658063, 120, 0, 0), -- Invisible Stalker (Area: -Unknown-) +(@CGUID+1, 15214, 571, 1, 1, 2807.391, -3586.93, 247.6916, 3.455752, 120, 0, 0), -- Invisible Stalker (Area: -Unknown-) +(@CGUID+2, 15214, 571, 1, 1, 2833.016, -3621.016, 247.373, 1.850049, 120, 0, 0), -- Invisible Stalker (Area: -Unknown-) +(@CGUID+3, 23033, 571, 1, 1, 2831.685, -3611.948, 257.9287, 0.2479207, 120, 0, 0), -- Invisible Stalker (Floating) (Area: -Unknown-) (Auras: 43570 - Frost State) +(@CGUID+4, 23033, 571, 1, 1, 2832.849, -3638.875, 246.9362, 0.5235988, 120, 0, 0), -- Invisible Stalker (Floating) (Area: -Unknown-) +(@CGUID+5, 23033, 571, 1, 1, 2820.243, -3602.598, 261.4395, 6.161012, 120, 0, 0), -- Invisible Stalker (Floating) (Area: -Unknown-) +(@CGUID+6, 23033, 571, 1, 1, 2855.824, -3596.345, 248.4855, 5.131268, 120, 0, 0), -- Invisible Stalker (Floating) (Area: -Unknown-) +(@CGUID+7, 24029, 571, 1, 1, 2820.328, -3602.552, 247.9988, 3.665191, 120, 0, 0), -- Wyrmcaller Vile (Area: -Unknown-) (Auras: 12544 - Frost Armor) +(@CGUID+8, 23033, 571, 1, 1, 2818.341, -3604.437, 252.666, 3.845377, 120, 0, 0); -- Invisible Stalker (Floating) (Area: -Unknown-) + +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=24029; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (24029,-106031,-@CGUID,-(@CGUID+1),-(@CGUID+2),-(@CGUID+5),-(@CGUID+8)) AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@CGUID*100,@CGUID*100+1) 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 +(24029,0,0,0,1,0,100,1,0,0,3000,3000,11,43576,2,0,0,0,0,1,0,0,0,0,0,0,0,'Wyrmcaller Vile - OOC - Cast \'Frost Power\''), +(24029,0,1,0,0,0,100,0,0,0,4000,4000,11,9672,0,0,0,0,0,2,0,0,0,0,0,0,0,'Wyrmcaller Vile - IC - Cast \'Frostbolt\''), +(24029,0,2,0,0,0,100,0,0,0,6000,10000,11,15532,0,0,0,0,0,2,0,0,0,0,0,0,0,'Wyrmcaller Vile - IC - Cast \'Frost Nova\''), +(24029,0,3,0,1,0,100,0,0,0,3000,3000,45,0,1,0,0,0,0,19,23033,10,0,0,0,0,0,'Wyrmcaller Vile - OOC - Cast \'Set Data\''), +(-106031,0,0,0,8,0,100,0,43568,0,0,0,80,@CGUID*100,0,0,0,0,0,1,0,0,0,0,0,0,0,'Invisible Stalker - On SpellHit \'Frost Strike\' - Call ActionList'), +(-@CGUID,0,0,0,8,0,100,0,43568,0,0,0,80,@CGUID*100,0,0,0,0,0,1,0,0,0,0,0,0,0,'Invisible Stalker - On SpellHit \'Frost Strike\' - Call ActionList'), +(-(@CGUID+1),0,0,0,8,0,100,0,43568,0,0,0,80,@CGUID*100,0,0,0,0,0,1,0,0,0,0,0,0,0,'Invisible Stalker - On SpellHit \'Frost Strike\' - Call ActionList'), +(-(@CGUID+2),0,0,0,8,0,100,0,43568,0,0,0,80,@CGUID*100+1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Invisible Stalker - On SpellHit \'Frost Strike\' - Call ActionList'), +(@CGUID*100,9,0,0,0,0,100,0,2400,2400,0,0,11,43569,2,0,0,0,0,19,23033,19,0,0,0,0,0,'Invisible Stalker - Action list - Cast \'Frost\''), +(@CGUID*100+1,9,0,0,0,0,100,0,2400,2400,0,0,11,43569,2,0,0,0,0,10,@CGUID+4,23033,0,0,0,0,0,'Invisible Stalker - Action list - Cast \'Frost\''), +(-(@CGUID+5),0,0,0,1,0,100,0,0,0,5000,7000,11,43591,2,0,0,0,0,19,24029,16,0,0,0,0,0,'Invisible Stalker - OOC - Cast \'Soul Siphon\''), +(-(@CGUID+8),0,0,0,38,0,100,0,0,1,0,0,11,43568,2,0,0,0,0,1,0,0,0,0,0,0,0,'Invisible Stalker - On data set - Cast \'Frost Strike\''); diff --git a/sql/updates/world/2016_01_08_02_world.sql b/sql/updates/world/2016_01_08_02_world.sql new file mode 100644 index 00000000000..28e55dfba3b --- /dev/null +++ b/sql/updates/world/2016_01_08_02_world.sql @@ -0,0 +1,35 @@ +-- +DELETE FROM `creature_formations` WHERE `leaderGUID`=79010; +INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES +(79010, 79010, 0, 0, 2, 0, 0), +(79010, 79012, 6, 360, 2, 0, 0); + +-- Pathing for Entry: 22987 'TDB FORMAT' +SET @NPC := 79010; +SET @PATH := @NPC * 10; +UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-3376.641,`position_y`=3642.897,`position_z`=285.1084 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,-3376.641,3642.897,285.1084,0,0,0,0,100,0), -- 00:15:15 +(@PATH,2,-3372.496,3645.907,284.7475,0,0,0,0,100,0), -- 00:15:16 +(@PATH,3,-3376.866,3642.62,285.2078,0,0,0,0,100,0), -- 00:15:22 +(@PATH,4,-3381.402,3626.403,279.4974,0,0,0,0,100,0), -- 00:15:26 +(@PATH,5,-3382.558,3624.162,278.2544,0,0,0,0,100,0), -- 00:15:31 +(@PATH,6,-3385.898,3620.779,276.7867,0,0,0,0,100,0), -- 00:15:33 +(@PATH,7,-3389.558,3619.429,276.3516,0,0,0,0,100,0), -- 00:15:35 +(@PATH,8,-3393.407,3613.085,276.4259,0,0,0,0,100,0), -- 00:15:38 +(@PATH,9,-3390.018,3604.891,276.2281,0,0,0,0,100,0), -- 00:15:41 +(@PATH,10,-3397.005,3597.193,277.0055,0,0,0,0,100,0), -- 00:15:44 +(@PATH,11,-3393.93,3598.741,276.5433,0,0,0,0,100,0), -- 00:15:48 +(@PATH,12,-3390.969,3600.254,276.3882,0,0,0,0,100,0), -- 00:15:50 +(@PATH,13,-3389.908,3605.303,276.3074,0,0,0,0,100,0), -- 00:15:51 +(@PATH,14,-3390.732,3618.796,276.4376,0,0,0,0,100,0), -- 00:15:55 +(@PATH,15,-3384.879,3620.886,277.2273,0,0,0,0,100,0), -- 00:15:58 +(@PATH,16,-3382.095,3624.67,278.3322,0,0,0,0,100,0), -- 00:16:01 +(@PATH,17,-3381.752,3635.601,284.2187,0,0,0,0,100,0), -- 00:16:03 +(@PATH,18,-3379.75,3638.496,285.585,0,0,0,0,100,0), -- 00:16:08 +(@PATH,19,-3376.617,3642.928,285.1052,0,0,0,0,100,0), -- 00:16:12 +(@PATH,20,-3372.458,3645.933,284.7447,0,0,0,0,100,0); -- 00:16:13 +-- 0x1C011842401672C000002500008BC617 .go -3376.641 3642.897 285.1084 diff --git a/sql/updates/world/2016_01_08_03_world.sql b/sql/updates/world/2016_01_08_03_world.sql new file mode 100644 index 00000000000..2899c6e06eb --- /dev/null +++ b/sql/updates/world/2016_01_08_03_world.sql @@ -0,0 +1,3 @@ +-- +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=25968; +DELETE FROM `creature` WHERE `id`=25801; diff --git a/sql/updates/world/2016_01_09_00_world.sql b/sql/updates/world/2016_01_09_00_world.sql new file mode 100644 index 00000000000..534e17ccb00 --- /dev/null +++ b/sql/updates/world/2016_01_09_00_world.sql @@ -0,0 +1,16 @@ +-- +-- Enable Landmine Knockback Achievement by removing it from disables +DELETE FROM `disables` WHERE `sourceType`= 4 AND `entry`= 5258; + +-- Insert missing Landmine Knockback Achievement criteria data +DELETE FROM `achievement_criteria_data` WHERE `criteria_id`= 5258; +INSERT INTO `achievement_criteria_data` (`criteria_id`, `type`, `value1`, `value2`, `ScriptName`) VALUES +(5258,0,57064,0,''); + +-- Update description for the linked spells 54355 and 54402 +UPDATE `spell_linked_spell` SET `comment`= 'Trigger Detonation with Land Mine Knockback' WHERE `spell_trigger` = 54355; + +-- Insert spell script name for spell 57099 +DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_gen_landmine_knockback_achievement'; +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(57099,'spell_gen_landmine_knockback_achievement'); diff --git a/sql/updates/world/2016_01_10_00_world.sql b/sql/updates/world/2016_01_10_00_world.sql new file mode 100644 index 00000000000..83ed21c8489 --- /dev/null +++ b/sql/updates/world/2016_01_10_00_world.sql @@ -0,0 +1,3 @@ +-- +UPDATE `creature_text` SET `text`='Windroc Matriarch lets loose a terrifying shriek.', `BroadcastTextId`=16149 WHERE `entry`=19055; +UPDATE `smart_scripts` SET `action_type`=49, `action_param1`=0 WHERE `entryorguid`=1905500 AND `id`=3; diff --git a/sql/updates/world/2016_01_10_01_world.sql b/sql/updates/world/2016_01_10_01_world.sql new file mode 100644 index 00000000000..c79c157a1a1 --- /dev/null +++ b/sql/updates/world/2016_01_10_01_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `creature_template` SET `unit_flags`=32832 WHERE `entry`= 18689; diff --git a/sql/updates/world/2016_01_10_02_world.sql b/sql/updates/world/2016_01_10_02_world.sql new file mode 100644 index 00000000000..eca8ef07849 --- /dev/null +++ b/sql/updates/world/2016_01_10_02_world.sql @@ -0,0 +1,6 @@ +-- +UPDATE `creature_template` SET `AIName`='SmartAI', `ScriptName`='' WHERE `entry`=25623; +DELETE FROM `smart_scripts` WHERE `entryorguid`=25623 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 +(25623, 0, 0, 0, 0, 0, 100, 0, 3000, 5000, 4000, 6000, 11, 54185, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Harvest Collector - IC - Cast Claw Slash'), +(25623, 0, 1, 0, 8, 0, 100, 0, 47166, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Harvest Collector - On spell hit - Despawn'); diff --git a/sql/updates/world/2016_01_10_03_world.sql b/sql/updates/world/2016_01_10_03_world.sql new file mode 100644 index 00000000000..5ac352ffe10 --- /dev/null +++ b/sql/updates/world/2016_01_10_03_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `smart_scripts` SET `action_param6`=2 WHERE `entryorguid`=-96556 AND `id`=0 AND `source_type`=0; diff --git a/sql/updates/world/2016_01_10_04_world.sql b/sql/updates/world/2016_01_10_04_world.sql new file mode 100644 index 00000000000..da6eed191ad --- /dev/null +++ b/sql/updates/world/2016_01_10_04_world.sql @@ -0,0 +1,11 @@ +-- +DELETE FROM `instance_template` WHERE `map` = 169; +INSERT INTO `instance_template` (`map`, `parent`, `script`, `allowMount`) VALUES +(169, 0, '', 0); + +DELETE FROM `game_tele` WHERE `id` IN (1425, 1426, 1427, 1428); +INSERT INTO `game_tele` (`id`, `position_x`, `position_y`, `position_z`, `orientation`, `map`, `name`) VALUES +(1425, -366.091, 3097.86, 92.317, 0.0487625, 169, 'EmeraldDream'), +(1426, 2781.566406, 3006.763184, 23.221882, 0.5, 169, 'EmeraldStatue'), +(1427, -2128.12, -1005.89, 132.213, 0.5, 169, 'VerdantFields'), +(1428, 2732.93, -3319.63, 101.284, 0.5, 169, 'EmeraldForest'); diff --git a/sql/updates/world/2016_01_10_05_world335.sql b/sql/updates/world/2016_01_10_05_world335.sql new file mode 100644 index 00000000000..468e9c6dc17 --- /dev/null +++ b/sql/updates/world/2016_01_10_05_world335.sql @@ -0,0 +1,21 @@ +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` in(19,20) AND `SourceId` in(5066,5090,5091,5093,5094,5095,10373,10374); + +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(19, 0, 5066, 0, 0, 14, 0, 5092, 0, 0, 0, 0, 0, '', 'Call to Arms: The Plaguelands (Breadcrumb)'), +(20, 0, 5066, 0, 0, 14, 0, 5092, 0, 0, 0, 0, 0, '', 'Call to Arms: The Plaguelands (Breadcrumb)'), +(19, 0, 5090, 0, 0, 14, 0, 5092, 0, 0, 0, 0, 0, '', 'Call to Arms: The Plaguelands (Breadcrumb)'), +(20, 0, 5090, 0, 0, 14, 0, 5092, 0, 0, 0, 0, 0, '', 'Call to Arms: The Plaguelands (Breadcrumb)'), +(19, 0, 5091, 0, 0, 14, 0, 5092, 0, 0, 0, 0, 0, '', 'Call to Arms: The Plaguelands (Breadcrumb)'), +(20, 0, 5091, 0, 0, 14, 0, 5092, 0, 0, 0, 0, 0, '', 'Call to Arms: The Plaguelands (Breadcrumb)'), +(19, 0, 5093, 0, 0, 14, 0, 5096, 0, 0, 0, 0, 0, '', 'Call to Arms: The Plaguelands (Breadcrumb)'), +(20, 0, 5093, 0, 0, 14, 0, 5096, 0, 0, 0, 0, 0, '', 'Call to Arms: The Plaguelands (Breadcrumb)'), +(19, 0, 5094, 0, 0, 14, 0, 5096, 0, 0, 0, 0, 0, '', 'Call to Arms: The Plaguelands (Breadcrumb)'), +(20, 0, 5094, 0, 0, 14, 0, 5096, 0, 0, 0, 0, 0, '', 'Call to Arms: The Plaguelands (Breadcrumb)'), +(19, 0, 5095, 0, 0, 14, 0, 5096, 0, 0, 0, 0, 0, '', 'Call to Arms: The Plaguelands (Breadcrumb)'), +(20, 0, 5095, 0, 0, 14, 0, 5096, 0, 0, 0, 0, 0, '', 'Call to Arms: The Plaguelands (Breadcrumb)'), +(19, 0, 10373, 0, 0, 14, 0, 5092, 0, 0, 0, 0, 0, '', 'Call to Arms: The Plaguelands (Breadcrumb)'), +(20, 0, 10373, 0, 0, 14, 0, 5092, 0, 0, 0, 0, 0, '', 'Call to Arms: The Plaguelands (Breadcrumb)'), +(19, 0, 10374, 0, 0, 14, 0, 5096, 0, 0, 0, 0, 0, '', 'Call to Arms: The Plaguelands (Breadcrumb)'), +(20, 0, 10374, 0, 0, 14, 0, 5096, 0, 0, 0, 0, 0, '', 'Call to Arms: The Plaguelands (Breadcrumb)'); + +UPDATE `quest_template_addon` SET `NextQuestID`=0 WHERE `ID` in(5066,5090,5091,5093,5094,5095,10373,10374); diff --git a/sql/updates/world/2016_01_07_npc_taxi.sql b/sql/updates/world/2016_01_12_00_world.sql index 8ed4099450b..8ed4099450b 100644 --- a/sql/updates/world/2016_01_07_npc_taxi.sql +++ b/sql/updates/world/2016_01_12_00_world.sql diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h index 11fbc2f77b6..e8b89a813b5 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.h +++ b/src/server/game/AI/SmartScripts/SmartScript.h @@ -209,7 +209,7 @@ class SmartScript if (lookupRoot) { - if (!meOrigGUID) + if (!meOrigGUID.IsEmpty()) { if (Creature* m = ObjectAccessor::GetCreature(*lookupRoot, meOrigGUID)) { @@ -217,7 +217,8 @@ class SmartScript go = NULL; } } - if (!goOrigGUID) + + if (!goOrigGUID.IsEmpty()) { if (GameObject* o = ObjectAccessor::GetGameObject(*lookupRoot, goOrigGUID)) { diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBot.cpp b/src/server/game/AuctionHouseBot/AuctionHouseBot.cpp index 4c4a3d8028f..e1ba9a64191 100644 --- a/src/server/game/AuctionHouseBot/AuctionHouseBot.cpp +++ b/src/server/game/AuctionHouseBot/AuctionHouseBot.cpp @@ -242,6 +242,22 @@ void AuctionBotConfig::GetConfigFromFile() SetConfig(CONFIG_AHBOT_CLASS_TRADEGOOD_MAX_ITEM_LEVEL, "AuctionHouseBot.Class.TradeGood.ItemLevel.Max", 0); SetConfig(CONFIG_AHBOT_CLASS_CONTAINER_MIN_ITEM_LEVEL, "AuctionHouseBot.Class.Container.ItemLevel.Min", 0); SetConfig(CONFIG_AHBOT_CLASS_CONTAINER_MAX_ITEM_LEVEL, "AuctionHouseBot.Class.Container.ItemLevel.Max", 0); + + SetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_CONSUMABLE, "AuctionHouseBot.Class.RandomStackRatio.Consumable", 20); + SetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_CONTAINER, "AuctionHouseBot.Class.RandomStackRatio.Container", 0); + SetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_WEAPON, "AuctionHouseBot.Class.RandomStackRatio.Weapon", 0); + SetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_GEM, "AuctionHouseBot.Class.RandomStackRatio.Gem", 20); + SetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_ARMOR, "AuctionHouseBot.Class.RandomStackRatio.Armor", 0); + SetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_REAGENT, "AuctionHouseBot.Class.RandomStackRatio.Reagent", 100); + SetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_PROJECTILE, "AuctionHouseBot.Class.RandomStackRatio.Projectile", 100); + SetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_TRADEGOOD, "AuctionHouseBot.Class.RandomStackRatio.TradeGood", 50); + SetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_GENERIC, "AuctionHouseBot.Class.RandomStackRatio.Generic", 100); + SetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_RECIPE, "AuctionHouseBot.Class.RandomStackRatio.Recipe", 0); + SetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_QUIVER, "AuctionHouseBot.Class.RandomStackRatio.Quiver", 0); + SetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_QUEST, "AuctionHouseBot.Class.RandomStackRatio.Quest", 100); + SetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_KEY, "AuctionHouseBot.Class.RandomStackRatio.Key", 100); + SetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_MISC, "AuctionHouseBot.Class.RandomStackRatio.Misc", 100); + SetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_GLYPH, "AuctionHouseBot.Class.RandomStackRatio.Glyph", 0); } char const* AuctionBotConfig::GetHouseTypeName(AuctionHouseType houseType) diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBot.h b/src/server/game/AuctionHouseBot/AuctionHouseBot.h index 63641fc7da2..87f76a17dcc 100644 --- a/src/server/game/AuctionHouseBot/AuctionHouseBot.h +++ b/src/server/game/AuctionHouseBot/AuctionHouseBot.h @@ -137,6 +137,21 @@ enum AuctionBotConfigUInt32Values CONFIG_AHBOT_CLASS_TRADEGOOD_MAX_ITEM_LEVEL, CONFIG_AHBOT_CLASS_CONTAINER_MIN_ITEM_LEVEL, CONFIG_AHBOT_CLASS_CONTAINER_MAX_ITEM_LEVEL, + CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_CONSUMABLE, + CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_CONTAINER, + CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_WEAPON, + CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_GEM, + CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_ARMOR, + CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_REAGENT, + CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_PROJECTILE, + CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_TRADEGOOD, + CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_GENERIC, + CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_RECIPE, + CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_QUIVER, + CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_QUEST, + CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_KEY, + CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_MISC, + CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_GLYPH, CONFIG_UINT32_AHBOT_UINT32_COUNT }; diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp index bcecc20c41a..5acb56b5173 100644 --- a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp +++ b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp @@ -533,6 +533,23 @@ void AuctionBotSeller::LoadItemsQuantity(SellerConfiguration& config) config.SetItemsQuantityPerClass(AUCTION_QUALITY_YELLOW, ITEM_CLASS_GLYPH, 0); // ============================================================================================ + // Set Stack Quantities + config.SetRandomStackRatioPerClass(ITEM_CLASS_CONSUMABLE, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_CONSUMABLE)); + config.SetRandomStackRatioPerClass(ITEM_CLASS_CONTAINER, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_CONTAINER)); + config.SetRandomStackRatioPerClass(ITEM_CLASS_WEAPON, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_WEAPON)); + config.SetRandomStackRatioPerClass(ITEM_CLASS_GEM, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_GEM)); + config.SetRandomStackRatioPerClass(ITEM_CLASS_ARMOR, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_ARMOR)); + config.SetRandomStackRatioPerClass(ITEM_CLASS_REAGENT, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_REAGENT)); + config.SetRandomStackRatioPerClass(ITEM_CLASS_PROJECTILE, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_PROJECTILE)); + config.SetRandomStackRatioPerClass(ITEM_CLASS_TRADE_GOODS, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_TRADEGOOD)); + config.SetRandomStackRatioPerClass(ITEM_CLASS_GENERIC, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_GENERIC)); + config.SetRandomStackRatioPerClass(ITEM_CLASS_RECIPE, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_RECIPE)); + config.SetRandomStackRatioPerClass(ITEM_CLASS_QUIVER, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_QUIVER)); + config.SetRandomStackRatioPerClass(ITEM_CLASS_QUEST, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_QUEST)); + config.SetRandomStackRatioPerClass(ITEM_CLASS_KEY, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_KEY)); + config.SetRandomStackRatioPerClass(ITEM_CLASS_MISC, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_MISC)); + config.SetRandomStackRatioPerClass(ITEM_CLASS_GLYPH, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_GLYPH)); + // Set the best value to get nearest amount of items wanted for (uint32 j = 0; j < MAX_AUCTION_QUALITY; ++j) { @@ -719,6 +736,15 @@ void AuctionBotSeller::SetPricesOfItem(ItemTemplate const* itemProto, SellerConf bidp = urand(basePrice - range, basePrice + range) + 1; } +// Determines the stack size to use for the item +uint32 AuctionBotSeller::GetStackSizeForItem(ItemTemplate const* itemProto, SellerConfiguration& config) const +{ + if (config.GetRandomStackRatioPerClass(ItemClass(itemProto->Class)) > urand(0, 99)) + return urand(1, itemProto->GetMaxStackSize()); + else + return 1; +} + // Determine the multiplier for the sell price of any weapon without a buy price. uint32 AuctionBotSeller::GetSellModifier(ItemTemplate const* prototype) { @@ -952,7 +978,7 @@ void AuctionBotSeller::AddNewAuctions(SellerConfiguration& config) continue; } - uint32 stackCount = urand(1, prototype->GetMaxStackSize()); + uint32 stackCount = GetStackSizeForItem(prototype, config); Item* item = Item::CreateItem(itemId, stackCount); if (!item) diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.h b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.h index 4f293e03d9a..dd82b0f3dda 100644 --- a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.h +++ b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.h @@ -33,12 +33,13 @@ typedef std::vector<std::vector<uint32>> AllItemsArray; struct SellerItemClassInfo { - SellerItemClassInfo(): AmountOfItems(0), MissItems(0), Quantity(0), PriceRatio(0) {} + SellerItemClassInfo(): AmountOfItems(0), MissItems(0), Quantity(0), PriceRatio(0), RandomStackRatio(100) {} uint32 AmountOfItems; uint32 MissItems; uint32 Quantity; uint32 PriceRatio; + uint32 RandomStackRatio; }; struct SellerItemInfo @@ -102,6 +103,8 @@ public: uint32 GetPriceRatioPerQuality(AuctionQuality quality) const { return _ItemInfo[quality].PriceRatio; } void SetPriceRatioPerClass(ItemClass item, uint32 value) { _ItemInfo[0].ItemClassInfos[item].PriceRatio = value; } uint32 GetPriceRatioPerClass(ItemClass item) const { return _ItemInfo[0].ItemClassInfos[item].PriceRatio; } + void SetRandomStackRatioPerClass(ItemClass item, uint32 value) { _ItemInfo[0].ItemClassInfos[item].RandomStackRatio = value; } + uint32 GetRandomStackRatioPerClass(ItemClass item) const { return _ItemInfo[0].ItemClassInfos[item].RandomStackRatio; } private: AuctionHouseType _houseType; @@ -139,6 +142,7 @@ private: uint32 SetStat(SellerConfiguration& config); bool GetItemsToSell(SellerConfiguration& config, ItemsToSellArray& itemsToSellArray, AllItemsArray const& addedItem); void SetPricesOfItem(ItemTemplate const* itemProto, SellerConfiguration& config, uint32& buyp, uint32& bidp, uint32 stackcnt); + uint32 GetStackSizeForItem(ItemTemplate const* itemProto, SellerConfiguration& config) const; void LoadItemsQuantity(SellerConfiguration& config); static uint32 GetBuyModifier(ItemTemplate const* prototype); static uint32 GetSellModifier(ItemTemplate const* itemProto); diff --git a/src/server/game/Entities/Creature/TemporarySummon.h b/src/server/game/Entities/Creature/TemporarySummon.h index afca851974a..6d058f405a8 100644 --- a/src/server/game/Entities/Creature/TemporarySummon.h +++ b/src/server/game/Entities/Creature/TemporarySummon.h @@ -72,9 +72,10 @@ class Minion : public TempSummon Unit* GetOwner() const { return m_owner; } float GetFollowAngle() const override { return m_followAngle; } void SetFollowAngle(float angle) { m_followAngle = angle; } - bool IsPetGhoul() const {return GetEntry() == 26125;} // Ghoul may be guardian or pet - bool IsSpiritWolf() const {return GetEntry() == 29264;} // Spirit wolf from feral spirits + bool IsPetGhoul() const { return GetEntry() == 26125; } // Ghoul may be guardian or pet + bool IsSpiritWolf() const { return GetEntry() == 29264; } // Spirit wolf from feral spirits bool IsGuardianPet() const; + bool IsRisenAlly() const { return GetEntry() == 30230; } protected: Unit* const m_owner; float m_followAngle; diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 9aabed67243..6f0b9f89e44 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -1803,6 +1803,8 @@ void GameObject::CastSpell(Unit* target, uint32 spellId, bool triggered /*= true if (Unit* owner = GetOwner()) { trigger->setFaction(owner->getFaction()); + if (owner->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE)) + trigger->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); // needed for GO casts for proper target validation checks trigger->SetOwnerGUID(owner->GetGUID()); trigger->CastSpell(target ? target : trigger, spellInfo, triggered, nullptr, nullptr, owner->GetGUID()); diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 52291cb6bf5..4fdf25e41c3 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -1242,6 +1242,9 @@ void Player::Update(uint32 p_time) if (charmer->GetTypeId() == TYPEID_UNIT && charmer->IsAlive()) UpdateCharmedAI(); + if (GetAI() && IsAIEnabled) + GetAI()->UpdateAI(p_time); + // Update items that have just a limited lifetime if (now > m_Last_tick) UpdateItemDuration(uint32(now - m_Last_tick)); @@ -1476,8 +1479,8 @@ void Player::Update(uint32 p_time) _pendingBindTimer -= p_time; } - // not auto-free ghost from body in instances - if (m_deathTimer > 0 && !GetBaseMap()->Instanceable() && !HasAuraType(SPELL_AURA_PREVENT_RESURRECTION)) + // not auto-free ghost from body in instances or if its affected by risen ally + if (m_deathTimer > 0 && !GetBaseMap()->Instanceable() && !HasAuraType(SPELL_AURA_PREVENT_RESURRECTION) && !IsGhouled()) { if (p_time >= m_deathTimer) { @@ -2157,7 +2160,7 @@ bool Player::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) co return true; if (spellInfo->Effects[index].IsEffect(SPELL_EFFECT_ATTACK_ME)) return true; - + return Unit::IsImmunedToSpellEffect(spellInfo, index); } @@ -4731,6 +4734,32 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness) } } +void Player::SendGhoulResurrectRequest(Player* target) +{ + target->m_ghoulResurrectPlayerGUID = GetGUID(); + + WorldPacket data(SMSG_RESURRECT_REQUEST, 8 + 4 + 1 + 1); + data << uint64(GetGUID()); + data << uint32(0); + data << uint8(0); + data << uint8(0); + target->GetSession()->SendPacket(&data); +} + +void Player::GhoulResurrect() +{ + CastSpell(this, 46619 /*SPELL_DK_RAISE_ALLY*/, true, nullptr, nullptr, m_ghoulResurrectPlayerGUID); + + m_ghoulResurrectPlayerGUID = ObjectGuid::Empty; +} + +void Player::RemoveGhoul() +{ + if (IsGhouled()) + if (Creature* ghoul = ObjectAccessor::GetCreature(*this, m_ghoulResurrectGhoulGUID)) + ghoul->DespawnOrUnsummon(); // Raise Ally aura will handle unauras +} + void Player::KillPlayer() { if (IsFlying() && !GetTransport()) @@ -18682,7 +18711,7 @@ bool Player::CheckInstanceValidity(bool /*isLogin*/) // game masters' instances are always valid if (IsGameMaster()) return true; - + // non-instances are always valid Map* map = GetMap(); if (!map || !map->IsDungeon()) @@ -20156,6 +20185,12 @@ void Player::RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent) void Player::StopCastingCharm() { + if (IsGhouled()) + { + RemoveGhoul(); + return; + } + Unit* charm = GetCharm(); if (!charm) return; @@ -21508,6 +21543,14 @@ void Player::setResurrectRequestData(ObjectGuid guid, uint32 mapId, float X, flo m_resurrectHealth = health; m_resurrectMana = mana; } + +void Player::clearResurrectRequestData() +{ + setResurrectRequestData(ObjectGuid::Empty, 0, 0.0f, 0.0f, 0.0f, 0, 0); + + m_ghoulResurrectPlayerGUID = ObjectGuid::Empty; + m_ghoulResurrectGhoulGUID = ObjectGuid::Empty; +} //slot to be excluded while counting bool Player::EnchantmentFitsRequirements(uint32 enchantmentcondition, int8 slot) { @@ -23410,6 +23453,8 @@ uint32 Player::GetBaseWeaponSkillValue(WeaponAttackType attType) const void Player::ResurrectUsingRequestData() { + RemoveGhoul(); + /// Teleport before resurrecting by player, otherwise the player might get attacked from creatures near his corpse TeleportTo(m_resurrectMap, m_resurrectX, m_resurrectY, m_resurrectZ, GetOrientation()); @@ -23854,6 +23899,31 @@ void Player::SetViewpoint(WorldObject* target, bool apply) //WorldPacket data(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, 0); //GetSession()->SendPacket(&data); } + + // HACK: Make sure update for PLAYER_FARSIGHT is received before SMSG_PET_SPELLS to properly hide "Release spirit" dialog + if (target->GetTypeId() == TYPEID_UNIT && static_cast<Unit*>(target)->HasUnitTypeMask(UNIT_MASK_MINION) && static_cast<Minion*>(target)->IsRisenAlly()) + { + if (apply) + { + UpdateDataMapType update_players; + BuildUpdate(update_players); + WorldPacket packet; + for (UpdateDataMapType::iterator iter = update_players.begin(); iter != update_players.end(); ++iter) + { + iter->second.BuildPacket(&packet); + iter->first->GetSession()->SendPacket(&packet); + packet.clear(); + } + } + else + { + m_deathTimer = 6 * MINUTE * IN_MILLISECONDS; + + // Reset "Release spirit" timer clientside + WorldPacket data(SMSG_FORCED_DEATH_UPDATE); + SendDirectMessage(&data); + } + } } WorldObject* Player::GetViewpoint() const diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 32a4fec27f2..e7af827e9c7 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1576,7 +1576,7 @@ class Player : public Unit, public GridObject<Player> void UpdatePotionCooldown(Spell* spell = NULL); void setResurrectRequestData(ObjectGuid guid, uint32 mapId, float X, float Y, float Z, uint32 health, uint32 mana); - void clearResurrectRequestData() { setResurrectRequestData(ObjectGuid::Empty, 0, 0.0f, 0.0f, 0.0f, 0, 0); } + void clearResurrectRequestData(); bool isResurrectRequestedBy(ObjectGuid guid) const { return !m_resurrectGUID.IsEmpty() && m_resurrectGUID == guid; } bool isResurrectRequested() const { return !m_resurrectGUID.IsEmpty(); } void ResurrectUsingRequestData(); @@ -1770,6 +1770,15 @@ class Player : public Unit, public GridObject<Player> void ResurrectPlayer(float restore_percent, bool applySickness = false); void BuildPlayerRepop(); void RepopAtGraveyard(); + void SendGhoulResurrectRequest(Player* target); + bool IsValidGhoulResurrectRequest(ObjectGuid guid) + { + return !m_ghoulResurrectPlayerGUID.IsEmpty() && m_ghoulResurrectPlayerGUID == guid; + } + void GhoulResurrect(); + void SetGhoulResurrectGhoulGUID(ObjectGuid guid) { m_ghoulResurrectGhoulGUID = guid; } + ObjectGuid GetGhoulResurrectGhoulGUID() { return m_ghoulResurrectGhoulGUID; } + void RemoveGhoul(); void DurabilityLossAll(double percent, bool inventory); void DurabilityLoss(Item* item, double percent); @@ -2403,6 +2412,9 @@ class Player : public Unit, public GridObject<Player> float m_resurrectX, m_resurrectY, m_resurrectZ; uint32 m_resurrectHealth, m_resurrectMana; + ObjectGuid m_ghoulResurrectPlayerGUID; + ObjectGuid m_ghoulResurrectGhoulGUID; + WorldSession* m_session; typedef std::list<Channel*> JoinedChannelsList; @@ -2502,7 +2514,7 @@ class Player : public Unit, public GridObject<Player> bool IsHasDelayedTeleport() const { return m_bHasDelayedTeleport; } void SetDelayedTeleportFlag(bool setting) { m_bHasDelayedTeleport = setting; } void ScheduleDelayedOperation(uint32 operation) { if (operation < DELAYED_END) m_DelayedOperations |= operation; } - + bool IsInstanceLoginGameMasterException() const; MapReference m_mapRef; diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp index 775a3c96c46..a8e13a9f7db 100644 --- a/src/server/game/Entities/Unit/StatSystem.cpp +++ b/src/server/game/Entities/Unit/StatSystem.cpp @@ -499,7 +499,7 @@ void Player::UpdateAttackPowerAndDamage(bool ranged) if (getClass() == CLASS_SHAMAN || getClass() == CLASS_PALADIN) // mental quickness UpdateSpellDamageAndHealingBonus(); - if (pet && pet->IsPetGhoul()) // At melee attack power change for DK pet + if (pet && (pet->IsPetGhoul() || pet->IsRisenAlly())) // At melee attack power change for DK pet pet->UpdateAttackPowerAndDamage(); if (guardian && guardian->IsSpiritWolf()) // At melee attack power change for Shaman feral spirit @@ -1113,7 +1113,7 @@ bool Guardian::UpdateStats(Stats stat) Unit* owner = GetOwner(); // Handle Death Knight Glyphs and Talents float mod = 0.75f; - if (IsPetGhoul() && (stat == STAT_STAMINA || stat == STAT_STRENGTH)) + if ((IsPetGhoul() || IsRisenAlly()) && (stat == STAT_STAMINA || stat == STAT_STRENGTH)) { if (stat == STAT_STAMINA) mod = 0.3f; // Default Owner's Stamina scale @@ -1329,7 +1329,7 @@ void Guardian::UpdateAttackPowerAndDamage(bool ranged) bonusAP = owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.22f * mod; SetBonusDamage(int32(owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.1287f * mod)); } - else if (IsPetGhoul()) //ghouls benefit from deathknight's attack power (may be summon pet or not) + else if (IsPetGhoul() || IsRisenAlly()) //ghouls benefit from deathknight's attack power (may be summon pet or not) { bonusAP = owner->GetTotalAttackPowerValue(BASE_ATTACK) * 0.22f; SetBonusDamage(int32(owner->GetTotalAttackPowerValue(BASE_ATTACK) * 0.1287f)); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index fcd2535dad9..261f4faf1a8 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -9395,7 +9395,7 @@ void Unit::SetMinion(Minion *minion, bool apply) minion->SetSpeed(UnitMoveType(i), m_speed_rate[i], true); // Ghoul pets have energy instead of mana (is anywhere better place for this code?) - if (minion->IsPetGhoul()) + if (minion->IsPetGhoul() || minion->IsRisenAlly()) minion->setPowerType(POWER_ENERGY); // Send infinity cooldown - client does that automatically but after relog cooldown needs to be set again @@ -13625,6 +13625,9 @@ void Unit::RemoveFromWorld() RemoveAreaAurasDueToLeaveWorld(); + if (IsCharmed()) + RemoveCharmedBy(nullptr); + if (GetCharmerGUID()) { TC_LOG_FATAL("entities.unit", "Unit %u has charmer guid when removed from world", GetEntry()); diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 8fc93f24351..90d312f422a 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1598,6 +1598,7 @@ class Unit : public WorldObject bool IsAlive() const { return (m_deathState == ALIVE); } bool isDying() const { return (m_deathState == JUST_DIED); } bool isDead() const { return (m_deathState == DEAD || m_deathState == CORPSE); } + bool IsGhouled() const { return HasAura(46619 /*SPELL_DK_RAISE_ALLY*/); } DeathState getDeathState() const { return m_deathState; } virtual void setDeathState(DeathState s); // overwrited in Creature/Player/Pet diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index e4ee057d6ea..758d5af83f7 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -71,6 +71,7 @@ void WorldSession::HandleRepopRequestOpcode(WorldPacket& recvData) } //this is spirit release confirm? + GetPlayer()->RemoveGhoul(); GetPlayer()->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true); GetPlayer()->BuildPlayerRepop(); GetPlayer()->RepopAtGraveyard(); @@ -776,6 +777,12 @@ void WorldSession::HandleResurrectResponseOpcode(WorldPacket& recvData) return; } + if (GetPlayer()->IsValidGhoulResurrectRequest(guid)) + { + GetPlayer()->GhoulResurrect(); + return; + } + if (!GetPlayer()->isResurrectRequestedBy(guid)) return; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index cb573f4ec3d..aed7c0db043 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2359,7 +2359,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) // Do healing and triggers if (m_healing > 0) { - bool crit = caster->IsSpellCrit(unitTarget, m_spellInfo, m_spellSchoolMask); + bool crit = target->crit; uint32 addhealth = m_healing; if (crit) { @@ -2384,7 +2384,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) SpellNonMeleeDamage damageInfo(caster, unitTarget, m_spellInfo->Id, m_spellSchoolMask); // Add bonuses and fill damageInfo struct - caster->CalculateSpellDamageTaken(&damageInfo, m_damage, m_spellInfo, m_attackType, target->crit); + caster->CalculateSpellDamageTaken(&damageInfo, m_damage, m_spellInfo, m_attackType, target->crit); caster->DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb); // Send log damage message to client @@ -4207,21 +4207,16 @@ void Spell::SendResurrectRequest(Player* target) { // get resurrector name for creature resurrections, otherwise packet will be not accepted // for player resurrections the name is looked up by guid - std::string const sentName(m_caster->GetTypeId() == TYPEID_PLAYER - ? "" - : m_caster->GetNameForLocaleIdx(target->GetSession()->GetSessionDbLocaleIndex())); + std::string const sentName(m_caster->GetTypeId() == TYPEID_PLAYER ? + "" : m_caster->GetNameForLocaleIdx(target->GetSession()->GetSessionDbLocaleIndex())); - WorldPacket data(SMSG_RESURRECT_REQUEST, (8+4+sentName.size()+1+1+1+4)); + WorldPacket data(SMSG_RESURRECT_REQUEST, 8 + 4 + sentName.size() + 1 + 1 + 1); data << uint64(m_caster->GetGUID()); data << uint32(sentName.size() + 1); - data << sentName; - data << uint8(0); // null terminator - - data << uint8(m_caster->GetTypeId() == TYPEID_PLAYER ? 0 : 1); // "you'll be afflicted with resurrection sickness" + data << uint8(m_caster->IsSpiritHealer()); // "you'll be afflicted with resurrection sickness" // override delay sent with SMSG_CORPSE_RECLAIM_DELAY, set instant resurrection for spells with this attribute - if (m_spellInfo->HasAttribute(SPELL_ATTR3_IGNORE_RESURRECTION_TIMER)) - data << uint32(0); + data << uint8(!m_spellInfo->HasAttribute(SPELL_ATTR3_IGNORE_RESURRECTION_TIMER)); target->GetSession()->SendPacket(&data); } @@ -5512,7 +5507,7 @@ SpellCastResult Spell::CheckPetCast(Unit* target) // dead owner (pets still alive when owners ressed?) if (Unit* owner = m_caster->GetCharmerOrOwner()) - if (!owner->IsAlive()) + if (!owner->IsAlive() && !owner->IsGhouled()) return SPELL_FAILED_CASTER_DEAD; if (!target && m_targets.GetUnitTarget()) diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index fd9247bd778..6ae509af443 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -1362,7 +1362,7 @@ public: int32 level = atol(levelStr); - Player* target = handler->getSelectedPlayer(); + Player* target = handler->getSelectedPlayerOrSelf(); if (!target) { handler->SendSysMessage(LANG_NO_CHAR_SELECTED); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp index 1de3884664b..66806920e77 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp @@ -135,6 +135,7 @@ class boss_lord_marrowgar : public CreatureScript _boneStormDuration = RAID_MODE<uint32>(20000, 30000, 20000, 30000); _baseSpeed = creature->GetSpeedRate(MOVE_RUN); _coldflameLastPos.Relocate(creature); + _introDone = false; _boneSlice = false; } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp index 31dd7de96ca..fafe3113835 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp @@ -236,6 +236,7 @@ class boss_professor_putricide : public CreatureScript summons.DespawnAll(); SetPhase(PHASE_COMBAT_1); _experimentState = EXPERIMENT_STATE_OOZE; + me->SetReactState(REACT_DEFENSIVE); me->SetWalk(false); if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE) me->GetMotionMaster()->MovementExpired(); diff --git a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp index 7f5d2b95dc0..7ea87a3c0c4 100644 --- a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp +++ b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp @@ -560,6 +560,10 @@ public: me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); } else PoisonTimer -= diff; } + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); } }; }; diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp index 59caf4b7f7b..3cea620559a 100644 --- a/src/server/scripts/Spells/spell_dk.cpp +++ b/src/server/scripts/Spells/spell_dk.cpp @@ -22,6 +22,7 @@ */ #include "Player.h" +#include "UnitAI.h" #include "ScriptMgr.h" #include "SpellScript.h" #include "SpellAuraEffects.h" @@ -63,7 +64,10 @@ enum DeathKnightSpells SPELL_DK_UNHOLY_PRESENCE = 48265, SPELL_DK_UNHOLY_PRESENCE_TRIGGERED = 49772, SPELL_DK_WILL_OF_THE_NECROPOLIS_TALENT_R1 = 49189, - SPELL_DK_WILL_OF_THE_NECROPOLIS_AURA_R1 = 52284 + SPELL_DK_WILL_OF_THE_NECROPOLIS_AURA_R1 = 52284, + SPELL_DK_RAISE_ALLY_INITIAL = 61999, + SPELL_DK_RAISE_ALLY = 46619, + SPELL_DK_GHOUL_THRASH = 47480 }; enum DeathKnightSpellIcons @@ -1699,6 +1703,303 @@ public: } }; +enum RaiseAllyMisc +{ + TEXT_RISE_ALLY = 33055, + + SPELL_DK_RISEN_GHOUL_SELF_STUN = 47466, + SPELL_DK_RISEN_GHOUL_SPAWN__IN = 47448, + SPELL_DK_SUMMON_HEAL = 36492, + SPELL_DK_DEATH_KNIGHT_RUNE_WEAPON_SCALING_02 = 51906, + SPELL_DK_DEATH_KNIGHT_PET_SCALING_01 = 54566, + SPELL_DK_DEATH_KNIGHT_PET_SCALING_03 = 61697, + SPELL_DK_MIRROR_NAME = 62224, + SPELL_DK_MIRROR_NAME_TRIGGERED = 62214, + SPELL_DK_PET_SCALING___MASTER_SPELL_03___INTELLECT_SPIRIT_RESILIENCE = 67557, + SPELL_DK_PET_SCALING___MASTER_SPELL_06___SPELL_HIT_EXPERTISE_SPELL_PENETRATION = 67561, + + SPELL_GHOUL_FRENZY = 62218, + + NPC_RISEN_ALLY = 30230 +}; + +// 61999 - Raise Ally Initial +class spell_dk_raise_ally_initial : public SpellScriptLoader +{ +public: + spell_dk_raise_ally_initial() : SpellScriptLoader("spell_dk_raise_ally_initial") { } + + class spell_dk_raise_ally_initial_SpellScript : public SpellScript + { + PrepareSpellScript(spell_dk_raise_ally_initial_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_DK_RAISE_ALLY_INITIAL)) + return false; + return true; + } + + SpellCastResult CheckCast() + { + // Raise Ally cannot be casted on alive players + Unit* target = GetExplTargetUnit(); + if (!target) + return SPELL_FAILED_NO_VALID_TARGETS; + if (target->IsAlive()) + return SPELL_FAILED_TARGET_NOT_DEAD; + if (Player* playerCaster = GetCaster()->ToPlayer()) + if (playerCaster->InArena()) + return SPELL_FAILED_NOT_IN_ARENA; + if (target->IsGhouled()) + return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW; + + return SPELL_CAST_OK; + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + Player* caster = GetCaster()->ToPlayer(); + Player* target = GetHitPlayer(); + if (caster && target) + caster->SendGhoulResurrectRequest(target); + } + + void Register() override + { + OnCheckCast += SpellCheckCastFn(spell_dk_raise_ally_initial_SpellScript::CheckCast); + OnEffectHitTarget += SpellEffectFn(spell_dk_raise_ally_initial_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_dk_raise_ally_initial_SpellScript(); + } +}; + +class player_ghoulAI : public PlayerAI +{ + public: + player_ghoulAI(Player* player, ObjectGuid ghoulGUID) : PlayerAI(player), _ghoulGUID(ghoulGUID) { } + + void UpdateAI(uint32 /*diff*/) override + { + if (Creature* ghoul = ObjectAccessor::GetCreature(*me, _ghoulGUID)) + { + if (!ghoul->IsAlive()) + me->RemoveAura(SPELL_DK_RAISE_ALLY); + } + else + me->RemoveAura(SPELL_DK_RAISE_ALLY); + } + + private: + ObjectGuid _ghoulGUID; +}; + +// 46619 - Raise Ally +class spell_dk_raise_ally : public SpellScriptLoader +{ +public: + spell_dk_raise_ally() : SpellScriptLoader("spell_dk_raise_ally") { } + + class spell_dk_raise_ally_SpellScript : public SpellScript + { + PrepareSpellScript(spell_dk_raise_ally_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_DK_RAISE_ALLY)) + return false; + return true; + } + + void SendText() + { + Player* caster = GetCaster()->ToPlayer(); + Unit* original = GetOriginalCaster(); + if (caster && original) + original->Whisper(TEXT_RISE_ALLY, caster, true); + } + + void HandleSummon(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + + Unit* caster = GetCaster(); + Unit* originalCaster = GetOriginalCaster(); + if (!originalCaster) + return; + + uint32 entry = uint32(GetSpellInfo()->Effects[effIndex].MiscValue); + + //! HACK - StatSystem needs further develop to enable update on Puppet stats + // Using same summon properties as Raise Dead 46585 (Guardian) - EffectMiscValueB = 829 + SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(829); + + uint32 duration = uint32(GetSpellInfo()->GetDuration()); + Position pos = caster->GetPosition(); + + TempSummon* summon = originalCaster->GetMap()->SummonCreature(entry, pos, properties, duration, originalCaster, GetSpellInfo()->Id); + if (!summon) + return; + + //! Leaving this here as it's necessary if statsystem problem is solved + /* + Default SUMMON_CATEGORY_PUPPET behaviour sets possesor as originalCaster, + in this case we need caster as possesor and originalCaster as owner + */ + //summon->RemoveCharmedBy(NULL); + + summon->SetCharmedBy(caster, CHARM_TYPE_POSSESS); + + summon->CastSpell(summon, SPELL_DK_RISEN_GHOUL_SELF_STUN, true); + summon->CastSpell(summon, SPELL_DK_RISEN_GHOUL_SPAWN__IN, true); + summon->CastSpell(summon, SPELL_DK_SUMMON_HEAL, true); + summon->CastSpell(caster, SPELL_DK_MIRROR_NAME, true); + caster->CastSpell(summon, SPELL_DK_MIRROR_NAME_TRIGGERED, true); + summon->CastSpell(summon, SPELL_DK_DEATH_KNIGHT_RUNE_WEAPON_SCALING_02, true); + summon->CastSpell(summon, SPELL_DK_DEATH_KNIGHT_PET_SCALING_01, true); + summon->CastSpell(summon, SPELL_DK_DEATH_KNIGHT_PET_SCALING_03, true); + summon->CastSpell(summon, SPELL_DK_PET_SCALING___MASTER_SPELL_03___INTELLECT_SPIRIT_RESILIENCE, true); + summon->CastSpell(summon, SPELL_DK_PET_SCALING___MASTER_SPELL_06___SPELL_HIT_EXPERTISE_SPELL_PENETRATION, true); + + // SMSG_POWER_UPDATE is sent + summon->SetMaxPower(POWER_ENERGY, 100); + + if (Player* player = GetCaster()->ToPlayer()) + player->SetGhoulResurrectGhoulGUID(summon->GetGUID()); + } + + void Register() override + { + AfterHit += SpellHitFn(spell_dk_raise_ally_SpellScript::SendText); + OnEffectHit += SpellEffectFn(spell_dk_raise_ally_SpellScript::HandleSummon, EFFECT_0, SPELL_EFFECT_SUMMON); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_dk_raise_ally_SpellScript(); + } + + class spell_dk_raise_ally_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dk_raise_ally_AuraScript); + + public: + spell_dk_raise_ally_AuraScript() + { + oldAI = nullptr; + oldAIState = false; + } + + private: + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_DK_RAISE_ALLY)) + return false; + return true; + } + + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Player* player = GetTarget()->ToPlayer(); + if (!player || player->GetGhoulResurrectGhoulGUID().IsEmpty()) + return; + + oldAI = player->GetAI(); + oldAIState = player->IsAIEnabled; + player->SetAI(new player_ghoulAI(player, player->GetGhoulResurrectGhoulGUID())); + player->IsAIEnabled = true; + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Player* player = GetTarget()->ToPlayer(); + if (!player) + return; + + player->IsAIEnabled = oldAIState; + UnitAI* thisAI = player->GetAI(); + player->SetAI(oldAI); + delete thisAI; + + // Dismiss ghoul if necessary + if (Creature* ghoul = ObjectAccessor::GetCreature(*player, player->GetGhoulResurrectGhoulGUID())) + { + ghoul->RemoveCharmedBy(nullptr); + ghoul->DespawnOrUnsummon(1000); + } + + player->SetGhoulResurrectGhoulGUID(ObjectGuid::Empty); + player->RemoveAura(SPELL_GHOUL_FRENZY); + } + + void Register() override + { + AfterEffectApply += AuraEffectApplyFn(spell_dk_raise_ally_AuraScript::OnApply, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_dk_raise_ally_AuraScript::OnRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + + UnitAI* oldAI; + bool oldAIState; + }; + + AuraScript* GetAuraScript() const override + { + return new spell_dk_raise_ally_AuraScript(); + } +}; + +// 47480 - Thrash +class spell_dk_ghoul_thrash : public SpellScriptLoader +{ +public: + spell_dk_ghoul_thrash() : SpellScriptLoader("spell_dk_ghoul_thrash") { } + + class spell_dk_ghoul_thrash_SpellScript : public SpellScript + { + PrepareSpellScript(spell_dk_ghoul_thrash_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_DK_GHOUL_THRASH)) + return false; + return true; + } + + void CalcDamage() + { + if (Aura* aur = GetCaster()->GetAura(SPELL_GHOUL_FRENZY)) + { + int32 damage = GetHitDamage(); + damage += int32(GetCaster()->GetTotalAttackPowerValue(BASE_ATTACK) * 0.05f * aur->GetStackAmount()); + aur->Remove(); + SetHitDamage(damage); + } + + /* + Also remove aura from charmer + SPELL_GHOUL_FRENZY (62218) - Targets (1, 27) (TARGET_UNIT_CASTER, TARGET_UNIT_MASTER) + */ + if (Unit* charmer = GetCaster()->GetCharmer()) + charmer->RemoveAura(SPELL_GHOUL_FRENZY); + } + + void Register() override + { + OnHit += SpellHitFn(spell_dk_ghoul_thrash_SpellScript::CalcDamage); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_dk_ghoul_thrash_SpellScript(); + } +}; + void AddSC_deathknight_spell_scripts() { new spell_dk_anti_magic_shell_raid(); @@ -1729,4 +2030,7 @@ void AddSC_deathknight_spell_scripts() new spell_dk_vampiric_blood(); new spell_dk_will_of_the_necropolis(); new spell_dk_death_grip_initial(); + new spell_dk_raise_ally_initial(); + new spell_dk_raise_ally(); + new spell_dk_ghoul_thrash(); } diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index c66abf72528..5c3ee1d7f4a 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -4120,6 +4120,44 @@ public: } }; +enum LandmineKnockbackAchievement +{ + SPELL_LANDMINE_KNOCKBACK_ACHIEVEMENT = 57064 +}; + +class spell_gen_landmine_knockback_achievement : public SpellScriptLoader +{ +public: + spell_gen_landmine_knockback_achievement() : SpellScriptLoader("spell_gen_landmine_knockback_achievement") { } + + class spell_gen_landmine_knockback_achievement_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gen_landmine_knockback_achievement_SpellScript); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Player* target = GetHitPlayer()) + { + Aura const* aura = GetHitAura(); + if (!aura || aura->GetStackAmount() < 10) + return; + + target->CastSpell(target, SPELL_LANDMINE_KNOCKBACK_ACHIEVEMENT, true); + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_gen_landmine_knockback_achievement_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_gen_landmine_knockback_achievement_SpellScript(); + } +}; + void AddSC_generic_spell_scripts() { new spell_gen_absorb0_hitlimit1(); @@ -4205,4 +4243,5 @@ void AddSC_generic_spell_scripts() new spell_gen_gm_freeze(); new spell_gen_stand(); new spell_gen_mixology_bonus(); + new spell_gen_landmine_knockback_achievement(); } diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 840b819fe99..5b07dde22bb 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -3190,6 +3190,46 @@ AuctionHouseBot.forceIncludeItems = "" AuctionHouseBot.forceExcludeItems = "" # +# AuctionHouseBot.Class.RandomStackRatio.* +# Description: Used to determine how often a stack of the class will be single or randomly-size stacked when posted +# Value needs to be between 0 and 100, no decimal. Anything higher than 100 will be treated as 100 +# Examples: 100 = stacks will always be random in size +# 50 = half the time the stacks are random, the other half being single stack +# 0 = stacks will always single size +# Default: Consumable: 20 (20% random stack size, 80% single stack size) +# Container: 0 (100% single stack size) +# Weapon: 0 (100% single stack size) +# Gem: 20 (20% random stack size, 80% single stack size) +# Armor: 0 (100% single stack size) +# Reagent: 100 (100% random stack size) +# Projectile: 100 (100% random stack size) +# TradeGood: 50 (50% random stack size, 50% single stack size) +# Generic: 100 (100% random stack size) +# Recipe: 0 (100% single stack size) +# Quiver: 0 (100% single stack size) +# Quest: 100 (100% random stack size) +# Key: 100 (100% random stack size) +# Misc: 100 (100% random stack size) +# Glyph: 0 (100% single stack size) +# + +AuctionHouseBot.Class.RandomStackRatio.Consumable = 20 +AuctionHouseBot.Class.RandomStackRatio.Container = 0 +AuctionHouseBot.Class.RandomStackRatio.Weapon = 0 +AuctionHouseBot.Class.RandomStackRatio.Gem = 20 +AuctionHouseBot.Class.RandomStackRatio.Armor = 0 +AuctionHouseBot.Class.RandomStackRatio.Reagent = 100 +AuctionHouseBot.Class.RandomStackRatio.Projectile = 100 +AuctionHouseBot.Class.RandomStackRatio.TradeGood = 50 +AuctionHouseBot.Class.RandomStackRatio.Generic = 100 +AuctionHouseBot.Class.RandomStackRatio.Recipe = 0 +AuctionHouseBot.Class.RandomStackRatio.Quiver = 0 +AuctionHouseBot.Class.RandomStackRatio.Quest = 100 +AuctionHouseBot.Class.RandomStackRatio.Key = 100 +AuctionHouseBot.Class.RandomStackRatio.Misc = 100 +AuctionHouseBot.Class.RandomStackRatio.Glyph = 0 + +# ################################################################################################### ################################################################################################### |