Scripts/SFK: implement all bosses

This commit is contained in:
Ovalord
2017-12-18 22:38:38 +01:00
parent e43a015b83
commit bad49ddb83
11 changed files with 2732 additions and 538 deletions

View File

@@ -0,0 +1,268 @@
-- Template Updates
UPDATE `creature_template` SET `scriptname`= 'boss_baron_ashbury', `flags_extra`= 1 WHERE `entry`= 46962;
UPDATE `creature_template` SET `AIName`= '', `flags_extra`= 1, `scriptname`= 'boss_lord_godfrey' WHERE `entry`= 46964;
UPDATE `creature_template` SET `AIName`= '', `scriptname`= 'npc_sfk_bloodthirsty_ghoul' WHERE `entry`= 50561;
UPDATE `creature_template` SET `flags_extra`= 130, `InhabitType`= 4 WHERE `entry`= 52065;
UPDATE `creature_template` SET `scriptname`= 'boss_baron_silverlaine', `flags_extra`= 1 WHERE `entry`= 3887;
UPDATE `creature_template` SET `flags_extra`= 130 WHERE `entry` IN (51047, 51080, 51085, 50934);
UPDATE `creature_template` SET `scriptname`= 'npc_wolf_master_nandos' WHERE `entry`= 50851;
UPDATE `creature_template` SET `scriptname`= 'npc_razorclaw_the_butcher' WHERE `entry`= 50869;
UPDATE `creature_template` SET `scriptname`= 'npc_odo_the_blindwatcher' WHERE `entry`= 50857;
UPDATE `creature_template` SET `scriptname`= 'npc_rethilgore' WHERE `entry`= 50834;
UPDATE `creature_template` SET `scriptname`= 'boss_commander_springvale', `AIName`= '', `flags_extra`= 1 WHERE `entry`= 4278;
UPDATE `creature_template` SET `flags_extra`= 130, `unit_flags`= 33554688 WHERE `entry`= 50547;
UPDATE `creature_template` SET `faction`= 14, `minlevel`= 87, `maxlevel`= 87, `flags_extra`= 130, `unit_flags`= 33554432 WHERE `entry` IN (50503, 51258);
UPDATE `creature_template` SET `AIName`= '', `scriptname`= 'boss_lord_walden', `flags_extra`= 1 WHERE `entry`= 46963;
UPDATE `creature_template` SET `minlevel`= 85, `maxlevel`= 85, `faction`= 14, `flags_extra`= 130, `modelid1`= 1126, `modelid2`= 23767, `InhabitType`= 4, `unit_flags`= unit_flags | 256 | 512 WHERE `entry`= 50522;
UPDATE `creature_template` SET `scriptname`= 'npc_wailing_guardsman' WHERE `entry`= 50613;
UPDATE `creature_template` SET `scriptname`= 'npc_tormented_officer' WHERE `entry`= 50615;
UPDATE `creature_template` SET `minlevel`= 87, `maxlevel`= 87, `faction`= 14, `unit_flags`= 33554432, `flags_extra`= 130 WHERE `entry`= 50503;
UPDATE `creature_template` SET `flags_extra`= 130 WHERE `entry` IN (50611, 50604, 51085, 51080, 50934, 51047);
UPDATE `creature_template` SET `unit_flags`= 768, `unit_flags2`= 33556480 WHERE `entry`= 47031;
-- Creature Texts
DELETE FROM `creature_text` WHERE `CreatureID` IN (46964, 46962, 3887, 4278, 46963, 47293, 47006, 47027, 48124, 47862, 47294);
INSERT INTO `creature_text` (`CreatureID`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `comment`) VALUES
(46964, 0, 0, 'Ivar''s pack failed horribly, so now he sends mercenaries. No matter, your journey ends in agony.', 14, 0, 100, 0, 0, 0, 'Lord Godfrey - Aggro Alliance'),
(46964, 1, 0, 'That bitch Sylvanas sent you too, did she? No matter, your journey ends in agony.', 14, 0, 100, 0, 0, 0, 'Lord Godfrey - Aggro Horde'),
(46964, 2, 0, 'Murder never gets old.', 14, 0, 100, 0, 0, 0, 'Lord Godfrey - Aggro Horde'),
(46964, 2, 1, 'This is the quality of assassin sent to kill me? Laughable.', 14, 0, 100, 0, 0, 0, 'Lord Godfrey - Aggro Horde'),
(46964, 3, 0, '|TInterface\\Icons\\INV_FIREARM_2H_RIFLE_CATACLYSM_B_01.BLP:20|t%s begins to cast |cFFFF0000|Hspell:93520|h[Pistol Barrage]|h|r!', 41, 0, 100, 0, 0, 0, 'Lord Godfrey Pistol Barrage'),
(46964, 4, 0, 'I thank you for the clean death. I would not have done the same...', 14, 0, 100, 0, 0, 0, 'Lord Godfrey'),
(46962, 1, 0, 'Tally ho! The hunt begins!', 14, 0, 100, 0, 0, 0, 'Baron Ashbury'),
(46962, 2, 0, 'This is just too easy...', 14, 0, 100, 0, 0, 0, 'Baron Ashbury'),
(46962, 3, 0, '|TInterface\\Icons\\spell_holy_healingaura.blp:20|tBaron Ashbury begins to channel |cFFFF0000|Hspell:93468|h''Stay of Execution''|h|r !', 41, 0, 100, 0, 0, 0, 'Baron Ashbury'),
(46962, 4, 0, 'HA! Let''s at least keep it interesting.', 14, 0, 100, 0, 0, 0, 'Baron Ashbury'),
(46962, 5, 0, 'I grow tired of this hunt... Time to die!', 14, 0, 100, 0, 0, 0, 'Baron Ashbury'),
(46962, 6, 0, 'Killed by lowly commoners, how droll...', 14, 0, 100, 0, 0, 0, 'Baron Ashbury'),
(3887, 0, 0, 'Leave this accursed place at once!', 14, 0, 100, 0, 0, 0, 'Baron Silverlaine - Aggro'),
(3887, 1, 0, 'This death is only a temporary respite from my curse.', 14, 0, 100, 0, 0, 0, 'Baron Silverlaine - Death'),
(3887, 2, 0, 'I hope your spirit finds solace.', 14, 0, 100, 0, 0, 0, 'Baron Silverlaine - Slay 1'),
(3887, 2, 1, 'May you rest in peace.', 14, 0, 100, 0, 0, 0, 'Baron Silverlaine - Slay 2'),
(4278, 0, 0, 'Intruders in the keep! To arms!', 14, 0, 100, 0, 0, 0, 'Commander Springvale - Aggro'),
(4278, 1, 0, 'Repel the intruders!', 14, 0, 100, 0, 0, 0, 'Commander Springvale - Summon Adds'),
(4278, 2, 0, 'The attackers weaken!', 14, 0, 100, 0, 0, 0, 'Commander Springvale - Slay 1'),
(4278, 2, 1, 'One step closer to victory!', 14, 0, 100, 0, 0, 0, 'Commander Springvale - Slay 2'),
(4278, 3, 0, 'Our vigilance is eternal...', 14, 0, 100, 0, 0, 0, 'Commander Springvale - Death'),
(46963, 0, 0, 'Even here I find myself beset by fools!', 14, 0, 100, 0, 0, 0, 'Lord Walden - Aggro'),
(46963, 1, 0, 'This childish effort ends now!', 14, 0, 100, 0, 0, 0, 'Lord Walden - Slay 1'),
(46963, 1, 1, 'You shall annoy me no longer!', 14, 0, 100, 0, 0, 0, 'Lord Walden - Slay 2'),
(46963, 2, 0, 'My new life was just beginning...', 14, 0, 100, 0, 0, 0, 'Lord Walden - Death'),
-- Belmont
(47293, 0, 0, 'You''re more skilled in combat than I thought.', 12, 0, 100, 1, 0, 0, 'Deathstalker Commander Belmont to Player'),
(47293, 1, 0, 'Very well then. Let''s get the courtyard door open so we can continue our mission!', 12, 0, 100, 1, 0, 0, 'Deathstalker Commander Belmont to Player'),
(47293, 2, 0, 'This lock should be easy enough to pick.', 12, 0, 100, 1, 0, 0, 'Deathstalker Commander Belmont to Player'),
(47293, 3, 0, 'There we go!', 12, 0, 100, 0, 0, 0, 'Deathstalker Commander Belmont to Player'),
(47293, 4, 0, 'Excellent. Now, to plague this area and move on to-', 12, 0, 100, 396, 0, 0, 'Deathstalker Commander Belmont to Player'),
(47293, 5, 0, 'Cromush! What''re you doing here? This is a covert operation!', 12, 0, 100, 5, 0, 0, 'Deathstalker Commander Belmont to Player'),
(47293, 6, 0, 'My apologies, Cromush, but I assure you there is no problem. We are using an extremely dilute plague.', 12, 0, 100, 396, 0, 0, 'Deathstalker Commander Belmont to Player'),
(47293, 7, 0, 'In fact, it really only serves to scare off the worgen from trying to follow us in here. It''s completely harmless.', 12, 0, 100, 396, 0, 0, 'Deathstalker Commander Belmont to Player'),
(47293, 8, 0, 'The time has come, soldiers! Godfrey lies just ahead! Have no mercy! We fight-', 12, 0, 100, 396, 0, 0, 'Deathstalker Commander Belmont to Player'),
(47293, 9, 0, 'You''d better hurry up if you want in on all the fun.', 12, 0, 100, 153, 0, 0, 'Deathstalker Commander Belmont to Player'),
(47293, 10, 0, 'Why is the door shut? What in Sylvanas'' name is going on here...', 12, 0, 100, 396, 0, 0, 'Deathstalker Commander Belmont to Player'),
(47293, 11, 0, 'Cromush! What happened?', 12, 0, 100, 396, 0, 0, 'Deathstalker Commander Belmont to Player'),
(47293, 12, 0, 'You''ll pay for this Godfrey!', 12, 0, 100, 397, 0, 0, 'Deathstalker Commander Belmont to Player'),
-- Cromush
(47294, 0, 0, 'Unless I''m mistaken, the Warchief explicity forbids using the full plague, no matter the circumstance.', 12, 0, 100, 396, 0, 0, 'High Warlord Cromush to Player'),
(47294, 1, 0, 'Then I''m sure you won''t mind if I accompany you on your mission.', 12, 0, 100, 396, 0, 0, 'High Warlord Cromush to Player'),
(47294, 2, 0, 'FOR THE HORDE!!!', 14, 0, 100, 71, 0, 0, 'High Warlord Cromush to Player'),
(47294, 3, 0, 'The coward...killed them...poisoned...me...', 12, 0, 100, 0, 0, 0, 'High Warlord Cromush to Player'),
-- Ivar
(47006, 0, 0, 'Pathetic.', 12, 0, 100, 1, 0, 0, 'Packleader Ivar Bloodfang to Player'),
(47006, 1, 0, 'Keep moving forward. My men will dispose of this sorry bag of bones.', 12, 0, 100, 1, 0, 0, 'Packleader Ivar Bloodfang to Player'),
(47006, 2, 0, 'Control yourselves! We''re here for Godfrey''s head above all else. Relish in the spoils of war later!', 12, 0, 100, 5, 0, 0, 'Packleader Ivar Bloodfang to Player'),
(47006, 3, 0, 'We have to push forward if we''re to put an end to him. Follow me, I''ll open the courtyard so that you can spearhead our assault.', 12, 0, 100, 0, 0, 0, 'Packleader Ivar Bloodfang to Player'),
(47006, 4, 0, 'What a pathetic lock! Godfrey is going to have to try harder than this if he wants to defeat us.', 12, 0, 100, 0, 0, 0, 'Packleader Ivar Bloodfang to Player'),
(47006, 5, 0, 'The Bloodfang Berserkers begin to salivate heavily.', 16, 0, 100, 0, 0, 0, 'Packleader Ivar Bloodfang to Player'),
(47006, 6, 0, 'The Bloodfang come for you, worgen hunters!', 14, 0, 100, 15, 0, 0, 'Packleader Ivar Bloodfang to Player'),
(47006, 7, 0, 'I''ve picked up Walden''s foul scent. Fill the air with his blood!', 12, 0, 100, 1, 0, 0, 'Packleader Ivar Bloodfang to Player'),
(47006, 8, 0, 'Your time has finally come, Godfrey!', 14, 0, 100, 53, 0, 0, 'Packleader Ivar Bloodfang to Player'),
(47006, 9, 0, 'Attack, my brothers! Make him feel the fury of the pack!', 14, 0, 100, 25, 0, 0, 'Packleader Ivar Bloodfang to Player'),
(47006, 10, 0, 'You''d best hurry if you want any of the spoils.', 12, 0, 100, 0, 0, 0, 'Packleader Ivar Bloodfang to Player'),
(47006, 11, 0, 'I don''t know why the door is closed, heroes. My pack should have already taken care of Godfrey by now...', 12, 0, 100, 1, 0, 0, 'Packleader Ivar Bloodfang to Player'),
(47006, 12, 0, 'We will stand idle no longer! The time to act is now!', 12, 0, 100, 1, 0, 0, 'Packleader Ivar Bloodfang to Player'),
(47006, 13, 0, 'I''ll make sure nothing interferes. Go now heroes! Kill Godfrey!', 12, 0, 100, 0, 0, 0, 'Packleader Ivar Bloodfang to Player'),
(47006, 14, 0, 'Crowley is a disgrace to our kind for giving in to the Forsaken. My pack will show them the true face of the worgen and the relentless fury that comes with our presence!', 12, 0, 100, 5, 0, 0, 'Packleader Ivar Bloodfang to Player'),
-- Bloodfang Berserker
(47027, 0, 0, 'Bones?', 12, 0, 100, 1, 0, 0, 'Bloodfang Berserker'),
-- Rabid Mastiff
(48124, 0, 0, 'The Rabid Mastiff slobbers all over the floor...', 16, 0, 100, 0, 0, 0, 'Rabid Mastiff'),
(48124, 0, 1, 'The dog stares blankly at the wall...', 16, 0, 100, 0, 0, 0, 'Rabid Mastiff'),
(48124, 0, 2, 'A Rabid Mastiff growls...', 16, 0, 100, 0, 0, 0, 'Rabid Mastiff'),
-- Hentry Maleb
(47862, 0, 0, 'Better to rot in this cell than live as a dishonorable traitor.', 12, 0, 100, 1, 0, 0, 'Magistrate Henry Maleb');
-- Creature Template Addon
DELETE FROM `creature_template_addon` WHERE `entry` IN (46964, 49712, 50604, 47030, 93424, 50503,50851, 50923, 50834, 50857, 50869, 50547, 47006, 47031, 47293, 47294);
INSERT INTO `creature_template_addon` (`entry`, `Auras`) VALUES
(46964, '93597'),
(49712, '93597'),
(50503, '93690 67803'),
(50851 , '93853'),
(50923 , '93853'),
(50857 , '93853'),
(50869 , '93853'),
(50834 , '50834');
-- Spell Script Names
DELETE FROM `spell_script_names` WHERE `ScriptName` IN (
'spell_sfk_summon_bloodthirsty_ghouls',
'spell_sfk_pistol_barrage',
'spell_sfk_pain_and_suffering',
'spell_sfk_summon_worgen_spirit',
'spell_sfk_forsaken_ability',
'spell_sfk_asphyxiate',
'spell_sfk_unholy_power',
'spell_sfk_unholy_empowerment',
'spell_sfk_toxic_coagulant',
'spell_sfk_pistol_barrage_summon',
'spell_sfk_conjure_poisonous_mixture',
'spell_sfk_cursed_bullets');
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
(93707, 'spell_sfk_summon_bloodthirsty_ghouls'),
(93520, 'spell_sfk_pistol_barrage'),
(93581, 'spell_sfk_pain_and_suffering'),
(93712, 'spell_sfk_pain_and_suffering'),
(93857, 'spell_sfk_summon_worgen_spirit'),
(7054, 'spell_sfk_forsaken_ability'),
(93423, 'spell_sfk_asphyxiate'),
(93710, 'spell_sfk_asphyxiate'),
(93686, 'spell_sfk_unholy_power'),
(93735, 'spell_sfk_unholy_power'),
(93844, 'spell_sfk_unholy_empowerment'),
(93617, 'spell_sfk_toxic_coagulant'),
(96344, 'spell_sfk_pistol_barrage_summon'),
(93697, 'spell_sfk_conjure_poisonous_mixture'),
(93704, 'spell_sfk_conjure_poisonous_mixture'),
(93629, 'spell_sfk_cursed_bullets'),
(93761, 'spell_sfk_cursed_bullets');
-- Conditions
DELETE FROM `conditions` WHERE `SourceEntry` IN (93564, 93784, 93766, 93599, 93594);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ScriptName`, `Comment`) VALUES
(13, 2, 93564, 0, 0, 31, 0, 3, 50561, 0, 0, 0, '', 'Pistol Barrage - Target Bloodthirsty Ghoul'),
(13, 2, 93784, 0, 0, 31, 0, 3, 50561, 0, 0, 0, '', 'Pistol Barrage HC - Target Bloodthirsty Ghoul'),
(13, 1, 93766, 0, 0, 31, 0, 3, 50604, 0, 0, 0, '', 'Dark Archangel - Wings Aura'),
(13, 1, 93599, 0, 0, 31, 0, 3, 46963, 0, 0, 0, '', 'Toxic Coagulant - Target Lord Walden'),
(13, 1, 93594, 0, 0, 31, 0, 3, 46963, 0, 0, 0, '', 'Toxic Cataclyst - Target Lord Walden');
DELETE FROM `spell_linked_spell` WHERE `spell_trigger`= 93757;
INSERT INTO `spell_linked_spell` (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES
('93757', '93766', '0', 'Baron Ashbury Wings - Apply Aura'),
('93757', '93812', '0', 'Baron Ashbury - Archangel Damage Aura');
DELETE FROM `achievement_criteria_data` WHERE `criteria_id` IN (16081, 16085, 16544, 16086, 16544);
INSERT INTO `achievement_criteria_data` (`criteria_id`, `type`, `value1`, `value2`, `ScriptName`) VALUES
(16081, 11, 0, 0, 'achievement_pardon_denied'),
(16085, 11, 0, 0, 'achievement_to_the_ground'),
(16086, 11, 0, 0, 'achievement_bullet_time');
DELETE FROM `spell_dbc` WHERE `Id`= 93716;
INSERT INTO `spell_dbc` (`Id`, `CastingTimeIndex`, `DurationIndex`, `Comment`) VALUES
(93716, 0, 27, 'Shield of the Perfidious');
DELETE FROM `spelleffect_dbc` WHERE `Id`= 155915;
INSERT INTO `spelleffect_dbc` (`Id`, `Effect`, `EffectMiscValue`, `EffectMiscValueB`, `EffectRadiusIndex`, `EffectRadiusIndexMax`, `EffectImplicitTargetA`, `EffectImplicitTargetB`, `EffectSpellId`, `EffectIndex`) VALUES
(155915, 28, 50547, 64, 7,7, 18, 18, 93716, 0);
-- Boss Loot
-- Baron Ashbury
UPDATE `creature_template` SET `difficulty_entry_1`= 49708, `lootid`= 46962 WHERE `entry` = 46962;
DELETE FROM `creature_loot_template` WHERE `entry` IN (46962, 49708);
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Chance`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`) VALUES
(46962, 6314, 0, 1, 1, 1, 1),
(46962, 6324, 0, 1, 1, 1, 1),
(46962, 6323, 0, 1, 1, 1, 1);
UPDATE `creature_template` SET `lootid`= 49708 WHERE `entry`= 49708;
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Chance`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`) VALUES
(49708, 63433, 0, 1, 1, 1, 1),
(49708, 63437, 0, 1, 1, 1, 1),
(49708, 63435, 0, 1, 1, 1, 1),
(49708, 63436, 0, 1, 1, 1, 1),
(49708, 63434, 0, 1, 1, 1, 1);
-- Baron Silverlaine
UPDATE creature_template SET `difficulty_entry_1`= 49709, `lootid`= 3887 WHERE `entry`= 3887;
DELETE FROM `creature_loot_template` WHERE `entry` IN (3887, 49709);
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Chance`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`) VALUES
(3887, 6321, 0, 1, 1, 1, 1),
(3887, 6323, 0, 1, 1, 1, 1),
(3887, 60885, -100, 1, 2, 1, 1),
(3887, 60878, -100, 1, 3, 1, 1);
UPDATE `creature_template` SET `lootid`= 49709 WHERE `entry`= 49709;
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Chance`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`) VALUES
(49709, 63440, 0, 1, 1, 1, 1),
(49709, 63439, 0, 1, 1, 1, 1),
(49709, 63444, 0, 1, 1, 1, 1),
(49709, 63438, 0, 1, 1, 1, 1),
(49709, 63441, 0, 1, 1, 1, 1);
-- Commander Springvale
UPDATE creature_template SET `difficulty_entry_1`= 49710, `lootid`= 4278 WHERE `entry`= 4278;
DELETE FROM `creature_loot_template` WHERE `entry` IN (4278, 49710);
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Chance`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`) VALUES
(4278, 3191, 0, 1, 1, 1, 1),
(4278, 6320, 0, 1, 1, 1, 1),
(4278, 60879, -100, 1, 2, 1, 1),
(4278, 60880, -100, 1, 3, 1, 1);
UPDATE `creature_template` SET `lootid`= 49710 WHERE `entry`= 49710;
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Chance`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`) VALUES
(49710, 63448, 0, 1, 1, 1, 1),
(49710, 63449, 0, 1, 1, 1, 1),
(49710, 63447, 0, 1, 1, 1, 1),
(49710, 63446, 0, 1, 1, 1, 1),
(49710, 63445, 0, 1, 1, 1, 1);
-- Lord Walden
UPDATE creature_template SET `difficulty_entry_1`= 49711, `lootid`= 46962 WHERE `entry`= 46962;
DELETE FROM `creature_loot_template` WHERE `entry` IN (46962, 49711);
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Chance`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`) VALUES
(46962, 3230, 0, 1, 1, 1, 1),
(46962, 6642, 0, 1, 1, 1, 1),
(46962, 6341, 0, 1, 1, 1, 1),
(46962, 1292, 0, 1, 1, 1, 1),
(46962, 60876, -100, 1, 2, 1, 1),
(46962, 60881, -100, 1, 3, 1, 1);
UPDATE `creature_template` SET `lootid`= 49711 WHERE `entry`= 49711;
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Chance`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`) VALUES
(49711, 63455, 0, 1, 1, 1, 1),
(49711, 63454, 0, 1, 1, 1, 1),
(49711, 63452, 0, 1, 1, 1, 1),
(49711, 63450, 0, 1, 1, 1, 1),
(49711, 63453, 0, 1, 1, 1, 1);
-- Lord Godfrey
UPDATE `creature_template` SET `difficulty_entry_1`= 49712, `lootid`= 46964 WHERE `entry`= 46964;
UPDATE `creature_template` SET `lootid`= 49712 WHERE `entry`= 49712;
DELETE FROM `creature_loot_template` WHERE `Entry` IN (46964, 49712);
DELETE FROM `reference_loot_template` WHERE `Entry` IN (469640, 497120, 497121);
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Chance`, `LootMode`, `Reference`, `MaxCount`) VALUES
(46964, 469640, 100, 1, 469640, 2),
(49712, 497120, 100, 1, 497120, 2),
(49712, 497121, 100, 1, 497121, 1); -- Chaos Orb
INSERT INTO `reference_loot_template` (`Entry`, `Item`, `Chance`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`) VALUES
(469640, 3748, 0, 1, 1, 1, 1),
(469640, 6220, 0, 1, 1, 1, 1),
(469640, 6641, 0, 1, 1, 1, 1),
(469640, 6318, 0, 1, 1, 1, 1),
(469640, 60877, -100, 1, 2, 1, 1),
(469640, 60882, -100, 1, 3, 1, 1),
(497120, 63465, 0, 1, 1, 1, 1),
(497120, 63463, 0, 1, 1, 1, 1),
(497120, 63459, 0, 1, 1, 1, 1),
(497120, 63462, 0, 1, 1, 1, 1),
(497120, 63458, 0, 1, 1, 1, 1),
(497120, 63457, 0, 1, 1, 1, 1),
(497120, 63464, 0, 1, 1, 1, 1),
(497120, 63460, 0, 1, 1, 1, 1),
(497120, 63456, 0, 1, 1, 1, 1),
(497120, 63461, 0, 1, 1, 1, 1),
(497121, 52078, 100, 1, 1, 1, 1);

View File

@@ -4177,9 +4177,40 @@ void SpellMgr::LoadSpellInfoCorrections()
{
spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_3_YARDS);
});
// END OF THE LOST CITY OF THE TOL'VIR SPELLS
//
// SHADOWFANG KEEP SPELLS
//
// Summon Spirit of Wolf Master Nandos
// Summon Spirit of Odo the Blindwatcher
// Summon Spirit of Razorclaw the Butcher
// Summon Spirit of Rethilgore
ApplySpellFix({ 93896, 93859, 93921, 93925 }, [](SpellInfo* spellInfo)
{
spellInfo->Effects[EFFECT_0].MaxRadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_15_YARDS);
});
// Desecration Arm
ApplySpellFix({ 67802 }, [](SpellInfo* spellInfo)
{
spellInfo->Effects[EFFECT_0].MaxRadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_7_YARDS);
});
// Desecration
ApplySpellFix({ 93691, 94370 }, [](SpellInfo* spellInfo)
{
spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_6_YARDS);
spellInfo->Effects[EFFECT_1].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_6_YARDS);
});
// Toxic Coagulant
ApplySpellFix({ 93617 }, [](SpellInfo* spellInfo)
{
spellInfo->AuraInterruptFlags = AURA_INTERRUPT_FLAG_MOVE;
});
// END OF SHADOWFANG KEEP SPELLS
// Threatening Gaze
ApplySpellFix({ 24314 }, [](SpellInfo* spellInfo)
{

View File

@@ -0,0 +1,350 @@
/*
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "shadowfang_keep.h"
#include "ObjectMgr.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "Spell.h"
#include "SpellAuras.h"
#include "SpellAuraEffects.h"
#include "Player.h"
enum Spells
{
// Baron Ashbury
SPELL_ASPHYXIATE = 93423,
SPELL_ASPHYXIATE_ROOT = 93422,
SPELL_ASPHYXIATE_DAMAGE = 93424,
SPELL_STAY_OF_EXECUTION = 93468,
SPELL_STAY_OF_EXECUTION_HC = 93705,
SPELL_PAIN_AND_SUFFERING = 93581,
SPELL_PAIN_AND_SUFFERING_DUMMY = 93605,
SPELL_WRACKING_PAIN = 93720,
SPELL_DARK_ARCHANGEL = 93757,
SPELL_CALAMITY_CHANNEL = 93812,
// Wings
SPELL_RIDE_VEHICLE_HARDCODED = 46598,
SPELL_CALAMITY_AURA = 93766,
};
enum Texts
{
SAY_AGGRO = 1,
SAY_ASPHYXIATE = 2,
SAY_ANNOUNCE_STAY = 3,
SAY_STAY_EXECUTION = 4,
SAY_ARCHANGEL = 5,
SAY_DEATH = 6,
};
enum Events
{
EVENT_ASPHYXIATE = 1,
EVENT_STAY_OF_EXECUTION,
EVENT_PAIN_AND_SUFFERING,
EVENT_WRACKING_PAIN,
EVENT_DARK_ARCHANGEL,
EVENT_APPLY_IMMUNITY,
EVENT_DISABLE_ACHIEVEMENT,
};
enum AchievementData
{
DATA_PARDON_DENIED = 1,
};
class boss_baron_ashbury : public CreatureScript
{
public:
boss_baron_ashbury() : CreatureScript("boss_baron_ashbury") { }
struct boss_baron_ashburyAI : public BossAI
{
boss_baron_ashburyAI(Creature* creature) : BossAI(creature, DATA_BARON_ASHBURY)
{
}
void Reset() override
{
_Reset();
_isArchangel = false;
_canAttack = true;
_pardonDenied = true;
me->SetReactState(REACT_PASSIVE);
MakeInterruptable(false);
}
void EnterCombat(Unit* /*who*/) override
{
_EnterCombat();
Talk(SAY_AGGRO);
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me);
me->SetReactState(REACT_AGGRESSIVE);
events.ScheduleEvent(EVENT_ASPHYXIATE, Seconds(20));
events.ScheduleEvent(EVENT_PAIN_AND_SUFFERING, Seconds(5) + Milliseconds(500));
if (IsHeroic())
events.ScheduleEvent(EVENT_WRACKING_PAIN, Seconds(14));
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_WRACKING_PAIN);
Talk(SAY_DEATH);
}
void EnterEvadeMode(EvadeReason /*why*/) override
{
_EnterEvadeMode();
summons.DespawnAll();
instance->SetBossState(DATA_BARON_ASHBURY, FAIL);
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_WRACKING_PAIN);
MakeInterruptable(false);
me->SetReactState(REACT_PASSIVE);
_DespawnAtEvade();
}
void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/) override
{
if (me->HealthBelowPct(25) && !_isArchangel && IsHeroic())
{
events.Reset();
events.ScheduleEvent(EVENT_DARK_ARCHANGEL, Milliseconds(1));
_isArchangel = true;
}
}
void OnSpellCastInterrupt(SpellInfo const* spell) override
{
MakeInterruptable(false);
events.CancelEvent(EVENT_APPLY_IMMUNITY);
if (spell->Id == SPELL_STAY_OF_EXECUTION_HC && _pardonDenied)
events.CancelEvent(EVENT_DISABLE_ACHIEVEMENT);
}
void MakeInterruptable(bool apply)
{
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_INTERRUPT, !apply);
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, !apply);
}
uint32 GetData(uint32 type) const override
{
switch (type)
{
case DATA_PARDON_DENIED:
return _pardonDenied;
default:
break;
}
return 0;
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while(uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_ASPHYXIATE:
Talk(SAY_ASPHYXIATE);
DoCastAOE(SPELL_ASPHYXIATE);
events.ScheduleEvent(EVENT_STAY_OF_EXECUTION, Seconds(7));
_canAttack = false;
break;
case EVENT_STAY_OF_EXECUTION:
if (IsHeroic())
{
MakeInterruptable(true);
events.ScheduleEvent(EVENT_APPLY_IMMUNITY, Seconds(8));
events.ScheduleEvent(EVENT_DISABLE_ACHIEVEMENT, Seconds(8));
}
Talk(SAY_STAY_EXECUTION);
Talk(SAY_ANNOUNCE_STAY);
DoCastAOE(SPELL_STAY_OF_EXECUTION);
events.ScheduleEvent(EVENT_ASPHYXIATE, Seconds(45));
_canAttack = true;
break;
case EVENT_PAIN_AND_SUFFERING:
MakeInterruptable(true);
me->StopMoving();
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
DoCast(target, SPELL_PAIN_AND_SUFFERING);
events.ScheduleEvent(EVENT_APPLY_IMMUNITY, IsHeroic() ? Seconds(6) : Seconds(8));
events.Repeat(Seconds(26) + Milliseconds(500));
break;
case EVENT_WRACKING_PAIN:
DoCastAOE(SPELL_WRACKING_PAIN);
events.Repeat(Seconds(26) + Milliseconds(500));
break;
case EVENT_DARK_ARCHANGEL:
Talk(SAY_ARCHANGEL);
me->CastStop();
DoCastAOE(SPELL_DARK_ARCHANGEL);
me->AttackStop();
me->SetReactState(REACT_PASSIVE);
MakeInterruptable(false);
if (Creature* wings = DoSummon(NPC_ASHBURY_WINGS, me->GetPosition(), 0, TEMPSUMMON_MANUAL_DESPAWN))
wings->CastSpell(me, SPELL_RIDE_VEHICLE_HARDCODED);
break;
case EVENT_APPLY_IMMUNITY:
MakeInterruptable(true);
break;
case EVENT_DISABLE_ACHIEVEMENT:
_pardonDenied = false;
break;
default:
break;
}
}
if (_canAttack)
DoMeleeAttackIfReady();
}
private:
bool _isArchangel;
bool _canAttack;
bool _pardonDenied;
};
CreatureAI* GetAI(Creature *creature) const override
{
return GetShadowfangKeepAI<boss_baron_ashburyAI>(creature);
}
};
class spell_sfk_asphyxiate : public SpellScriptLoader
{
public:
spell_sfk_asphyxiate() : SpellScriptLoader("spell_sfk_asphyxiate") { }
class spell_sfk_asphyxiate_AuraScript : public AuraScript
{
PrepareAuraScript(spell_sfk_asphyxiate_AuraScript);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_ASPHYXIATE_ROOT });
}
void HandleTriggerSpell(AuraEffect const* aurEff)
{
PreventDefaultAction();
if (Unit* caster = GetCaster())
{
if (Unit* target = GetTarget())
{
uint32 triggerSpell = GetSpellInfo()->Effects[EFFECT_2].TriggerSpell;
uint64 damage = target->GetMaxHealth() / GetSpellInfo()->GetMaxTicks();
if (damage > target->GetHealth())
damage = target->GetHealth() - 1;
if (!target->HasAura(SPELL_ASPHYXIATE_ROOT))
target->CastSpell(target, SPELL_ASPHYXIATE_ROOT, true);
target->CastCustomSpell(triggerSpell, SPELLVALUE_BASE_POINT0, damage, target, true, nullptr, aurEff, caster->GetGUID());
}
}
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_sfk_asphyxiate_AuraScript::HandleTriggerSpell, EFFECT_2, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_sfk_asphyxiate_AuraScript();
}
};
class spell_sfk_pain_and_suffering : public SpellScriptLoader
{
public:
spell_sfk_pain_and_suffering() : SpellScriptLoader("spell_sfk_pain_and_suffering") { }
class spell_sfk_pain_and_suffering_AuraScript : public AuraScript
{
PrepareAuraScript(spell_sfk_pain_and_suffering_AuraScript);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PAIN_AND_SUFFERING_DUMMY });
}
void OnPeriodic(AuraEffect const* aurEff)
{
if (Unit* owner = GetOwner()->ToUnit())
if (InstanceScript* instance = owner->GetInstanceScript())
if (Creature* ashbury = instance->GetCreature(DATA_BARON_ASHBURY))
owner->CastSpell(ashbury, SPELL_PAIN_AND_SUFFERING_DUMMY, true);
uint64 damage = aurEff->GetBaseAmount() * aurEff->GetTickNumber();
GetEffect(EFFECT_0)->ChangeAmount(damage);
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_sfk_pain_and_suffering_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_sfk_pain_and_suffering_AuraScript();
}
};
class achievement_pardon_denied : public AchievementCriteriaScript
{
public:
achievement_pardon_denied() : AchievementCriteriaScript("achievement_pardon_denied") { }
bool OnCheck(Player* /*source*/, Unit* target)
{
if (!target)
return false;
if (target->GetMap()->IsHeroic())
return target->GetAI()->GetData(DATA_PARDON_DENIED);
return false;
}
};
void AddSC_boss_baron_ashbury()
{
new boss_baron_ashbury();
new spell_sfk_asphyxiate();
new spell_sfk_pain_and_suffering();
new achievement_pardon_denied();
}

View File

@@ -0,0 +1,606 @@
/*
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "shadowfang_keep.h"
#include "ObjectMgr.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "Spell.h"
#include "SpellAuras.h"
#include "SpellAuraEffects.h"
#include "Player.h"
enum Texts
{
SAY_AGGRO = 0,
SAY_DEATH = 1,
SAY_SLAY = 2,
};
enum Events
{
// Baron Silverlaine
EVENT_VEIL_OF_SHADOW = 1,
EVENT_CURSED_VEIL,
EVENT_SUMMON_WORGEN_SPIRIT,
// Odo the Blindwatcher
EVENT_HOWLING_RAGE,
// Wolf Master Nandos
EVENT_CLAW,
// Razorclaw the Butcher
EVENT_SPECTRAL_RUSH,
EVENT_SPECTRAL_RAVAGING,
EVENT_BUTCHER_DRAIN,
// Rethilgore
EVENT_SOUL_DRAIN
};
enum Actions
{
ACTION_DESPAWN = 1
};
enum Spells
{
SPELL_VEIL_OF_SHADOWS = 23224,
SPELL_CURSED_VEIL = 93956,
SPELL_SUMMON_WORGEN_SPIRIT = 93857,
SPELL_SUMMON_WORGEN_SPIRIT_NANDOS_DUMMY = 93896, // Dummy Summon
SPELL_SUMMON_WORGEN_SPIRIT_NANDOS_SUMMON = 93899,
SPELL_SUMMON_WORGEN_SPIRIT_ODO_DUMMY = 93859, // Dummy Summon
SPELL_SUMMON_WORGEN_SPIRIT_ODO_SUMMON = 93899,
SPELL_SUMMON_WORGEN_SPIRIT_RAZORCLAW_DUMMY = 93921, // Dummy Summon
SPELL_SUMMON_WORGEN_SPIRIT_RAZORCLAW_SUMMON = 93924,
SPELL_SUMMON_WORGEN_SPIRIT_RETHILGORE_DUMMY = 93925, // Dummy Summon
SPELL_SUMMON_WORGEN_SPIRIT_RETHILGORE_SUMMON = 93927,
// Odo the Blindwatcher
SPELL_HOWLING_RAGE = 93931,
SPELL_BLINDING_SHADOWS = 93952,
// Wolf Master Nandos
SPELL_CLAW = 16827,
SPELL_SUMMON_LUPINE_SPECTRE = 94199,
// Razorclaw the Butcher
SPELL_SPECTRAL_RAVAGING = 93930,
SPELL_SPECTRAL_RUSH = 93914,
SPELL_BUTCHER_DRAIN = 7485,
// Rethilgore
SPELL_SOUL_DRAIN = 93863
};
class boss_baron_silverlaine : public CreatureScript
{
public:
boss_baron_silverlaine() : CreatureScript("boss_baron_silverlaine") { }
struct boss_baron_silverlaineAI : public BossAI
{
boss_baron_silverlaineAI(Creature* creature) : BossAI(creature, DATA_BARON_SILVERLAINE) { }
void Reset() override
{
_Reset();
_worgenCounter = 0;
}
void EnterCombat(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
_EnterCombat();
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me);
if (IsHeroic())
events.ScheduleEvent(EVENT_CURSED_VEIL, Seconds(6));
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DEATH);
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
DespawnWorgenSpirits();
_JustDied();
}
void KilledUnit(Unit* target) override
{
if (target->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_SLAY);
}
void EnterEvadeMode(EvadeReason /*why*/) override
{
_EnterEvadeMode();
summons.DespawnAll();
instance->SetBossState(DATA_BARON_SILVERLAINE, FAIL);
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
DespawnWorgenSpirits();
_DespawnAtEvade();
}
void DespawnWorgenSpirits()
{
EntryCheckPredicate nandos(NPC_WOLF_MASTER_NANDOS);
summons.DoAction(ACTION_DESPAWN, nandos);
EntryCheckPredicate odo(NPC_ODO_THE_BLINDWATCHER);
summons.DoAction(ACTION_DESPAWN, odo);
EntryCheckPredicate razorclaw(NPC_RAZORCLAW_THE_BUTCHER);
summons.DoAction(ACTION_DESPAWN, razorclaw);
EntryCheckPredicate rethilgore(NPC_RETHILGORE);
summons.DoAction(ACTION_DESPAWN, rethilgore);
}
void JustSummoned(Creature* summon) override
{
summons.Summon(summon);
switch (summon->GetEntry())
{
case NPC_ODO_DUMMY:
summon->CastSpell(summon, SPELL_SUMMON_WORGEN_SPIRIT_ODO_SUMMON);
break;
case NPC_NANDOS_DUMMY:
summon->CastSpell(summon, SPELL_SUMMON_WORGEN_SPIRIT_NANDOS_SUMMON);
break;
case NPC_RAZORCLAW_DUMMY:
summon->CastSpell(summon, SPELL_SUMMON_WORGEN_SPIRIT_RAZORCLAW_SUMMON);
break;
case NPC_RETHILGORE_DUMMY:
summon->CastSpell(summon, SPELL_SUMMON_WORGEN_SPIRIT_RETHILGORE_SUMMON);
break;
default:
break;
}
}
void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/) override
{
switch (IsHeroic())
{
case true:
{
if (me->HealthBelowPct(90) && _worgenCounter == 0)
{
events.ScheduleEvent(EVENT_SUMMON_WORGEN_SPIRIT, (Milliseconds(1)));
_worgenCounter++;
}
else if (me->HealthBelowPct(60) && _worgenCounter == 1)
{
events.ScheduleEvent(EVENT_SUMMON_WORGEN_SPIRIT, (Milliseconds(1)));
_worgenCounter++;
}
else if (me->HealthBelowPct(30) && _worgenCounter == 2)
{
events.ScheduleEvent(EVENT_SUMMON_WORGEN_SPIRIT, (Milliseconds(1)));
_worgenCounter++;
}
break;
}
case false:
{
if (me->HealthBelowPct(75) && _worgenCounter == 0)
{
events.ScheduleEvent(EVENT_SUMMON_WORGEN_SPIRIT, (Milliseconds(1)));
_worgenCounter++;
}
else if (me->HealthBelowPct(35) && _worgenCounter == 1)
{
events.ScheduleEvent(EVENT_SUMMON_WORGEN_SPIRIT, (Milliseconds(1)));
_worgenCounter++;
}
break;
}
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while(uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_CURSED_VEIL:
DoCastAOE(SPELL_CURSED_VEIL);
events.Repeat(Seconds(26) + Milliseconds(500));
break;
case EVENT_SUMMON_WORGEN_SPIRIT:
DoCastAOE(SPELL_SUMMON_WORGEN_SPIRIT);
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
private:
uint8 _worgenCounter;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetShadowfangKeepAI<boss_baron_silverlaineAI>(creature);
}
};
class npc_wolf_master_nandos : public CreatureScript
{
public:
npc_wolf_master_nandos() : CreatureScript("npc_wolf_master_nandos") { }
struct npc_wolf_master_nandosAI : public ScriptedAI
{
npc_wolf_master_nandosAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
void IsSummonedBy(Unit* /*summoner*/) override
{
if (Creature* silverlaine = _instance->GetCreature(DATA_BARON_SILVERLAINE))
silverlaine->AI()->JustSummoned(me);
_instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me);
DoZoneInCombat();
events.ScheduleEvent(EVENT_CLAW, Seconds(1) + Milliseconds(600));
for (uint8 i = 0; i < 3; i++);
DoCast(me, SPELL_SUMMON_LUPINE_SPECTRE, true);
}
void JustDied(Unit* /*killer*/) override
{
_instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
me->DespawnOrUnsummon(Seconds(5));
}
void DoAction(int32 action) override
{
switch (action)
{
case ACTION_DESPAWN:
_instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
me->DespawnOrUnsummon(Milliseconds(1));
break;
default:
break;
}
}
void UpdateAI(uint32 diff) override
{
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_CLAW:
DoCastVictim(SPELL_CLAW);
events.Repeat(Seconds(3));
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
private:
InstanceScript* _instance;
EventMap events;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetShadowfangKeepAI<npc_wolf_master_nandosAI>(creature);
}
};
class npc_odo_the_blindwatcher : public CreatureScript
{
public:
npc_odo_the_blindwatcher() : CreatureScript("npc_odo_the_blindwatcher") { }
struct npc_odo_the_blindwatcherAI : public ScriptedAI
{
npc_odo_the_blindwatcherAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
void IsSummonedBy(Unit* /*summoner*/) override
{
if (Creature* silverlaine = _instance->GetCreature(DATA_BARON_SILVERLAINE))
silverlaine->AI()->JustSummoned(me);
_instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me);
DoZoneInCombat();
_events.ScheduleEvent(EVENT_HOWLING_RAGE, Seconds(5) + Milliseconds(500));
}
void JustDied(Unit* /*killer*/) override
{
_instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
me->DespawnOrUnsummon(Seconds(5));
}
void DoAction(int32 action) override
{
switch (action)
{
case ACTION_DESPAWN:
_instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
me->DespawnOrUnsummon(Milliseconds(1));
break;
default:
break;
}
}
void UpdateAI(uint32 diff) override
{
_events.Update(diff);
while (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_HOWLING_RAGE:
DoCastVictim(SPELL_BLINDING_SHADOWS);
DoCastAOE(SPELL_HOWLING_RAGE);
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
private:
InstanceScript* _instance;
EventMap _events;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetShadowfangKeepAI<npc_odo_the_blindwatcherAI>(creature);
}
};
class npc_razorclaw_the_butcher : public CreatureScript
{
public:
npc_razorclaw_the_butcher() : CreatureScript("npc_razorclaw_the_butcher") { }
struct npc_razorclaw_the_butcherAI : public ScriptedAI
{
npc_razorclaw_the_butcherAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
void IsSummonedBy(Unit* /*summoner*/) override
{
_player = ObjectGuid::Empty;
if (Creature* silverlaine = _instance->GetCreature(DATA_BARON_SILVERLAINE))
silverlaine->AI()->JustSummoned(me);
_instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me);
DoZoneInCombat();
_events.ScheduleEvent(EVENT_SPECTRAL_RUSH, Seconds(16));
_events.ScheduleEvent(EVENT_BUTCHER_DRAIN, Seconds(2) + Milliseconds(500));
}
void JustDied(Unit* /*killer*/) override
{
_instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
me->DespawnOrUnsummon(Seconds(5));
}
void DoAction(int32 action) override
{
switch (action)
{
case ACTION_DESPAWN:
_instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
me->DespawnOrUnsummon(Milliseconds(1));
break;
default:
break;
}
}
void UpdateAI(uint32 diff) override
{
_events.Update(diff);
while (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_SPECTRAL_RUSH:
if (Unit* target = SelectTarget(SELECT_TARGET_FARTHEST, 0, 0.0f, true))
{
_events.ScheduleEvent(EVENT_SPECTRAL_RAVAGING, Milliseconds(500));
DoCast(target, SPELL_SPECTRAL_RUSH);
_player = target->GetGUID();
}
break;
case EVENT_SPECTRAL_RAVAGING:
if (Unit* target = ObjectAccessor::GetPlayer(*me, _player))
DoCast(target, SPELL_SPECTRAL_RAVAGING);
break;
case EVENT_BUTCHER_DRAIN:
DoCastVictim(SPELL_BUTCHER_DRAIN);
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
private:
InstanceScript* _instance;
EventMap _events;
ObjectGuid _player;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetShadowfangKeepAI<npc_razorclaw_the_butcherAI>(creature);
}
};
class npc_rethilgore : public CreatureScript
{
public:
npc_rethilgore() : CreatureScript("npc_rethilgore") { }
struct npc_rethilgoreAI : public ScriptedAI
{
npc_rethilgoreAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
void IsSummonedBy(Unit* /*summoner*/) override
{
if (Creature* silverlaine = _instance->GetCreature(DATA_BARON_SILVERLAINE))
silverlaine->AI()->JustSummoned(me);
_instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me);
DoZoneInCombat();
_events.ScheduleEvent(EVENT_SOUL_DRAIN, Seconds(10));
}
void JustDied(Unit* /*killer*/) override
{
_instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
me->DespawnOrUnsummon(Seconds(5));
}
void DoAction(int32 action) override
{
switch (action)
{
case ACTION_DESPAWN:
_instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
me->DespawnOrUnsummon(Milliseconds(1));
break;
default:
break;
}
}
void UpdateAI(uint32 diff) override
{
_events.Update(diff);
while (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_SOUL_DRAIN:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
DoCast(target, SPELL_SOUL_DRAIN);
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
private:
InstanceScript* _instance;
EventMap _events;
};
CreatureAI* GetAI(Creature* creature) const
{
return GetShadowfangKeepAI<npc_rethilgoreAI>(creature);
}
};
class spell_sfk_summon_worgen_spirit : public SpellScriptLoader
{
public:
spell_sfk_summon_worgen_spirit() : SpellScriptLoader("spell_sfk_summon_worgen_spirit") { }
class spell_sfk_summon_worgen_spirit_SpellScript : public SpellScript
{
PrepareSpellScript(spell_sfk_summon_worgen_spirit_SpellScript);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo(
{
SPELL_SUMMON_WORGEN_SPIRIT_NANDOS_DUMMY,
SPELL_SUMMON_WORGEN_SPIRIT_ODO_DUMMY,
SPELL_SUMMON_WORGEN_SPIRIT_RAZORCLAW_DUMMY,
SPELL_SUMMON_WORGEN_SPIRIT_RETHILGORE_DUMMY
});
}
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
{
if (Unit* caster = GetCaster())
{
switch (RAND(0, 3))
{
case 0: // Nandos
caster->CastSpell((Unit*)NULL, SPELL_SUMMON_WORGEN_SPIRIT_NANDOS_DUMMY, true);
break;
case 1: // Odo
caster->CastSpell((Unit*)NULL, SPELL_SUMMON_WORGEN_SPIRIT_ODO_DUMMY, true);
break;
case 2: // Razorclaw
caster->CastSpell((Unit*)NULL, SPELL_SUMMON_WORGEN_SPIRIT_RAZORCLAW_DUMMY, true);
break;
case 3: // Rethilgore
caster->CastSpell((Unit*)NULL, SPELL_SUMMON_WORGEN_SPIRIT_RETHILGORE_DUMMY, true);
break;
}
}
}
void Register() override
{
OnEffectLaunch += SpellEffectFn(spell_sfk_summon_worgen_spirit_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_sfk_summon_worgen_spirit_SpellScript();
}
};
void AddSC_boss_baron_silverlaine()
{
new boss_baron_silverlaine();
new npc_wolf_master_nandos();
new npc_odo_the_blindwatcher();
new npc_razorclaw_the_butcher();
new npc_rethilgore();
new spell_sfk_summon_worgen_spirit();
}

View File

@@ -0,0 +1,583 @@
/*
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "shadowfang_keep.h"
#include "ObjectMgr.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "Spell.h"
#include "SpellAuras.h"
#include "SpellAuraEffects.h"
#include "Player.h"
enum Spells
{
// Commander Springvale
SPELL_MALEFIC_STRIKE = 93685,
SPELL_UNHOLY_POWER = 93686,
SPELL_UNHOLY_POWER_HC = 93735,
SPELL_SHIELD_OF_THE_PERFIDIOUS_DUMMY = 93716,
SPELL_SHIELD_OF_THE_PERFIDIOUS = 93693,
SPELL_DESECRATION_DUMMY = 93688,
SPELL_DESECRATION = 93687,
SPELL_DESECRATION_ARM_AURA = 67803,
SPELL_WORD_OF_SHAME = 93852,
// Wailing Guardsman
SPELL_UNHOLY_EMPOWERMENT = 93844,
SPELL_SCREAMS_OF_THE_PAST = 7074,
SPELL_MORTAL_STRIKE = 91801,
//Tormented Officer
SPELL_FORSAKEN_ABILITY = 7054,
SPELL_FORSAKEN_ABILITY_DAMAGE = 7038,
SPELL_FORSAKEN_ABILITY_ARMOR = 7039,
SPELL_FORSAKEN_ABILITY_HEAL = 7041,
SPELL_FORSAKEN_ABILITY_SPEED = 7042,
SPELL_FORSAKEN_ABILITY_HEALTH = 7040,
SPELL_SHIELD_WALL = 91463
};
enum Texts
{
SAY_AGGRO = 0,
SAY_ADDS = 1,
SAY_SLAY = 2,
SAY_DEATH = 3
};
enum Events
{
// Commander Springvale
EVENT_MALEFIC_STRIKE = 1,
EVENT_SHIELD_OF_THE_PERFIDIOUS,
EVENT_DESECRATION,
EVENT_SUMMON_ADDS,
EVENT_WORD_OF_SHAME,
// Wailing Guardsman
EVENT_UNHOLY_EMPOWERMENT,
EVENT_SCREAMS_OF_THE_PAST,
EVENT_MORTAL_STRIKE,
// Tormented Officer
EVENT_FORSAKEN_ABILITY
};
enum Actions
{
ACTION_UNHOLY_POWER = 1,
ACTION_TO_THE_GROUND
};
enum AchievementData
{
DATA_TO_THE_GROUND = 1
};
// Heroic additional adds
Position const OfficerPos = {-229.681f, 2260.03f, 102.84f, 3.45575f};
Position const GuardsmanPos = {-228.33f, 2254.39f, 102.84f, 3.36848f};
// Encounter spawn positions
Position const SpawnPos[] =
{
{-235.5069f, 2230.76f, 93.70721f, 0.0f}, // Wailing Guardsman
{-266.2257f, 2270.207f, 96.51828f, 0.0f} // Tormented Officer
};
class boss_commander_springvale : public CreatureScript
{
public:
boss_commander_springvale() : CreatureScript("boss_commander_springvale") { }
struct boss_commander_springvaleAI : public BossAI
{
boss_commander_springvaleAI(Creature* creature) : BossAI(creature, DATA_COMMANDER_SPRINGVALE) { }
void Reset() override
{
_Reset();
_toTheGround = true;
if (IsHeroic())
{
DoSummon(NPC_WAILING_GUARDSMAN, GuardsmanPos, 4000, TEMPSUMMON_CORPSE_TIMED_DESPAWN);
DoSummon(NPC_TORMENTED_OFFICER, OfficerPos, 4000, TEMPSUMMON_CORPSE_TIMED_DESPAWN);
}
/*
else
{
// Fill this case with the path that Commander Springvale is walking in normal mode
}
*/
}
void EnterCombat(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
_EnterCombat();
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me);
events.ScheduleEvent(EVENT_MALEFIC_STRIKE, Seconds(5));
events.ScheduleEvent(EVENT_DESECRATION, Seconds(9) + Milliseconds(500));
if (IsHeroic())
events.ScheduleEvent(EVENT_SUMMON_ADDS, Seconds(41));
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DEATH);
_JustDied();
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_WORD_OF_SHAME);
}
void KilledUnit(Unit* target) override
{
if (target->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_SLAY);
}
void EnterEvadeMode(EvadeReason /*why*/) override
{
_EnterEvadeMode();
summons.DespawnAll();
instance->SetBossState(DATA_COMMANDER_SPRINGVALE, FAIL);
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_WORD_OF_SHAME);
_DespawnAtEvade();
}
void JustSummoned(Creature* summon) override
{
summons.Summon(summon);
switch (summon->GetEntry())
{
case NPC_TORMENTED_OFFICER:
case NPC_WAILING_GUARDSMAN:
if (me->IsInCombat())
summon->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), true);
break;
case NPC_SHIELD_FOCUS:
me->StopMoving();
me->SetFacingToObject(summon);
DoCast(summon, SPELL_SHIELD_OF_THE_PERFIDIOUS);
default:
break;
}
}
uint32 GetData(uint32 type) const override
{
switch (type)
{
case DATA_TO_THE_GROUND:
return _toTheGround;
default:
break;
}
return 0;
}
void DoAction(int32 action) override
{
switch (action)
{
case ACTION_UNHOLY_POWER:
if (IsHeroic())
{
switch (RAND(0, 1))
{
case 0:
events.ScheduleEvent(EVENT_SHIELD_OF_THE_PERFIDIOUS, Seconds(1));
break;
case 1:
events.ScheduleEvent(EVENT_WORD_OF_SHAME, Seconds(1));
break;
default:
break;
}
}
else
events.ScheduleEvent(EVENT_SHIELD_OF_THE_PERFIDIOUS, Seconds(1));
break;
case ACTION_TO_THE_GROUND:
_toTheGround = false;
break;
default:
break;
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while(uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_MALEFIC_STRIKE:
if (!me->HasAura(SPELL_SHIELD_OF_THE_PERFIDIOUS))
DoCastVictim(SPELL_MALEFIC_STRIKE);
events.Repeat(Seconds(5), Seconds(6));
break;
case EVENT_SHIELD_OF_THE_PERFIDIOUS:
me->RemoveAurasDueToSpell(SPELL_UNHOLY_POWER);
me->RemoveAurasDueToSpell(SPELL_UNHOLY_POWER_HC);
DoCast(SPELL_SHIELD_OF_THE_PERFIDIOUS_DUMMY);
break;
case EVENT_DESECRATION:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
DoCast(target, SPELL_DESECRATION);
events.Repeat(Seconds(28));
break;
case EVENT_SUMMON_ADDS:
Talk(SAY_ADDS);
DoSummon(NPC_WAILING_GUARDSMAN, SpawnPos[0], 4000, TEMPSUMMON_CORPSE_TIMED_DESPAWN);
DoSummon(NPC_TORMENTED_OFFICER, SpawnPos[1], 4000, TEMPSUMMON_CORPSE_TIMED_DESPAWN);
events.Repeat(Seconds(41));
break;
case EVENT_WORD_OF_SHAME:
me->RemoveAurasDueToSpell(SPELL_UNHOLY_POWER);
me->RemoveAurasDueToSpell(SPELL_UNHOLY_POWER_HC);
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true, -SPELL_WORD_OF_SHAME))
DoCast(target, SPELL_WORD_OF_SHAME, true);
else
events.ScheduleEvent(EVENT_SHIELD_OF_THE_PERFIDIOUS, Milliseconds(1));
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
private:
bool _toTheGround;
};
CreatureAI* GetAI(Creature *creature) const override
{
return GetShadowfangKeepAI<boss_commander_springvaleAI>(creature);
}
};
class npc_wailing_guardsman : public CreatureScript
{
public:
npc_wailing_guardsman() : CreatureScript("npc_wailing_guardsman") { }
struct npc_wailing_guardsmanAI : public ScriptedAI
{
npc_wailing_guardsmanAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
void EnterCombat(Unit* who) override
{
if (Creature* tormentedOfficer = me->FindNearestCreature(NPC_TORMENTED_OFFICER, 20.0f))
tormentedOfficer->AI()->AttackStart(who);
_events.ScheduleEvent(EVENT_MORTAL_STRIKE, Seconds(11));
_events.ScheduleEvent(EVENT_SCREAMS_OF_THE_PAST, Seconds(14));
_events.ScheduleEvent(EVENT_UNHOLY_EMPOWERMENT, Seconds(28), Seconds(30));
}
void UpdateAI(uint32 diff) override
{
_events.Update(diff);
while (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_MORTAL_STRIKE:
DoCastVictim(SPELL_MORTAL_STRIKE);
_events.Repeat(Seconds(12));
break;
case EVENT_SCREAMS_OF_THE_PAST:
DoCastAOE(SPELL_SCREAMS_OF_THE_PAST);
break;
case EVENT_UNHOLY_EMPOWERMENT:
if (Creature* springvale = _instance->GetCreature(DATA_COMMANDER_SPRINGVALE))
DoCast(springvale, SPELL_UNHOLY_EMPOWERMENT);
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
private:
InstanceScript* _instance;
EventMap _events;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetShadowfangKeepAI<npc_wailing_guardsmanAI>(creature);
}
};
class npc_tormented_officer : public CreatureScript
{
public:
npc_tormented_officer() : CreatureScript("npc_tormented_officer") { }
struct npc_tormented_officerAI : public ScriptedAI
{
npc_tormented_officerAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
void EnterCombat(Unit* who) override
{
if (Creature* wailingGuardsman = me->FindNearestCreature(NPC_WAILING_GUARDSMAN, 20.0f))
wailingGuardsman->AI()->AttackStart(who);
_shielded = false;
_events.ScheduleEvent(EVENT_UNHOLY_EMPOWERMENT, Seconds(28), Seconds(30));
_events.ScheduleEvent(EVENT_FORSAKEN_ABILITY, Seconds(17));
}
void DamageTaken(Unit* /*attacker*/, uint32& damage) override
{
if (me->HealthBelowPct(20) && !_shielded)
{
DoCast(me, SPELL_SHIELD_WALL);
_shielded = true;
}
}
void UpdateAI(uint32 diff) override
{
_events.Update(diff);
while (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_FORSAKEN_ABILITY:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
DoCast(target, SPELL_FORSAKEN_ABILITY);
break;
case EVENT_UNHOLY_EMPOWERMENT:
if (Creature* springvale = _instance->GetCreature(DATA_COMMANDER_SPRINGVALE))
DoCast(springvale, SPELL_UNHOLY_EMPOWERMENT);
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
private:
InstanceScript* _instance;
EventMap _events;
bool _shielded;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetShadowfangKeepAI<npc_tormented_officerAI>(creature);
}
};
class spell_sfk_forsaken_ability : public SpellScriptLoader
{
public:
spell_sfk_forsaken_ability() : SpellScriptLoader("spell_sfk_forsaken_ability") { }
class spell_sfk_forsaken_ability_AuraScript : public AuraScript
{
PrepareAuraScript(spell_sfk_forsaken_ability_AuraScript);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo(
{
SPELL_FORSAKEN_ABILITY_DAMAGE,
SPELL_FORSAKEN_ABILITY_ARMOR,
SPELL_FORSAKEN_ABILITY_SPEED,
SPELL_FORSAKEN_ABILITY_HEAL,
SPELL_FORSAKEN_ABILITY_HEALTH
});
}
void OnPeriodic(AuraEffect const* /*aurEff*/)
{
if (Unit* owner = GetOwner()->ToUnit())
{
switch (RAND(0, 4))
{
case 0: // Damage
owner->CastSpell(owner, SPELL_FORSAKEN_ABILITY_DAMAGE, true);
break;
case 1: // Armor
owner->CastSpell(owner, SPELL_FORSAKEN_ABILITY_ARMOR, true);
break;
case 2: // Speed
owner->CastSpell(owner, SPELL_FORSAKEN_ABILITY_SPEED, true);
break;
case 3: // Heal
owner->CastSpell(owner, SPELL_FORSAKEN_ABILITY_HEAL, true);
break;
case 4: // Health
owner->CastSpell(owner, SPELL_FORSAKEN_ABILITY_HEALTH, true);
break;
}
}
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_sfk_forsaken_ability_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_sfk_forsaken_ability_AuraScript();
}
};
class spell_sfk_unholy_power : public SpellScriptLoader
{
public:
spell_sfk_unholy_power() : SpellScriptLoader("spell_sfk_unholy_power") { }
class spell_sfk_unholy_power_SpellScript : public SpellScript
{
PrepareSpellScript(spell_sfk_unholy_power_SpellScript);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo(
{
SPELL_UNHOLY_POWER_HC,
SPELL_UNHOLY_POWER
});
}
void HandleStacks()
{
if (Unit* target = GetHitUnit())
{
Aura* aura = nullptr;
aura = target->GetAura(SPELL_UNHOLY_POWER_HC);
if (!aura)
target->GetAura(SPELL_UNHOLY_POWER);
if (aura)
if (aura->GetStackAmount() == 3)
if (target->GetTypeId() == TYPEID_UNIT && target->IsAIEnabled)
target->ToCreature()->AI()->DoAction(ACTION_UNHOLY_POWER);
}
}
void Register() override
{
AfterHit += SpellHitFn(spell_sfk_unholy_power_SpellScript::HandleStacks);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_sfk_unholy_power_SpellScript();
}
};
class spell_sfk_unholy_empowerment : public SpellScriptLoader
{
public:
spell_sfk_unholy_empowerment() : SpellScriptLoader("spell_sfk_unholy_empowerment") { }
class spell_sfk_unholy_empowerment_SpellScript : public SpellScript
{
PrepareSpellScript(spell_sfk_unholy_empowerment_SpellScript);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo(
{
SPELL_UNHOLY_POWER_HC,
SPELL_UNHOLY_POWER
});
return true;
}
void HandleStacks()
{
if (Unit* target = GetHitUnit())
{
Aura* aura = nullptr;
aura = target->GetAura(SPELL_UNHOLY_POWER_HC);
if (!aura)
target->GetAura(SPELL_UNHOLY_POWER);
if (aura)
if (aura->GetStackAmount() == 3)
if (target->GetTypeId() == TYPEID_UNIT && target->IsAIEnabled)
target->ToCreature()->AI()->DoAction(ACTION_UNHOLY_POWER);
if (target->GetTypeId() == TYPEID_UNIT && target->IsAIEnabled)
target->ToCreature()->AI()->DoAction(ACTION_TO_THE_GROUND);
}
}
void Register() override
{
AfterHit += SpellHitFn(spell_sfk_unholy_empowerment_SpellScript::HandleStacks);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_sfk_unholy_empowerment_SpellScript();
}
};
class achievement_to_the_ground : public AchievementCriteriaScript
{
public:
achievement_to_the_ground() : AchievementCriteriaScript("achievement_to_the_ground") { }
bool OnCheck(Player* /*source*/, Unit* target)
{
if (!target)
return false;
if (target->GetMap()->IsHeroic())
return target->GetAI()->GetData(DATA_TO_THE_GROUND);
return false;
}
};
void AddSC_boss_commander_springvale()
{
new boss_commander_springvale();
new npc_wailing_guardsman();
new npc_tormented_officer();
new spell_sfk_forsaken_ability();
new spell_sfk_unholy_power();
new spell_sfk_unholy_empowerment();
new achievement_to_the_ground();
}

View File

@@ -0,0 +1,485 @@
/*
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "shadowfang_keep.h"
#include "ObjectMgr.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "Spell.h"
#include "SpellAuras.h"
#include "SpellAuraEffects.h"
#include "Player.h"
enum Texts
{
SAY_AGGRO_ALLIANCE = 0,
SAY_AGGRO_HORDE = 1,
SAY_SLAY = 2,
SAY_ANNOUNCE_PISTOL_BARRAGE = 3,
SAY_DEATH = 4
};
enum Events
{
// Lord Godfrey
EVENT_CURSED_BULLETS = 1,
EVENT_MORTAL_WOUND,
EVENT_SUMMON_BLOODTHIRSTY_GHOULS,
EVENT_PISTOL_BARRAGE,
EVENT_PISTOL_BARRAGE_CAST,
EVENT_APPLY_IMMUNITY,
// Bloodthirsty Ghoul
EVENT_ATTACK
};
enum Spells
{
SPELL_CURSED_BULLETS = 93629,
SPELL_CURSED_BULLETS_HC = 93761,
SPELL_MORTAL_WOUND = 93675,
SPELL_SUMMON_BLOODTHIRSTY_GHOULS_AURA = 93707,
SPELL_SUMMON_BLOODTHIRSTY_GHOULS_TRIGGERED_1 = 93709,
SPELL_SUMMON_BLOODTHIRSTY_GHOULS_TRIGGERED_2 = 93714,
SPELL_PISTOL_BARRAGE_FORCE_CAST = 96344,
SPELL_PISTOL_BARRAGE_CAST = 93520,
SPELL_BULLET_TIME_CREDIT = 95929,
SPELL_PISTOL_BARRAGE_TRIGGER_1 = 93566,
SPELL_PISTOL_BARRAGE_TRIGGER_2 = 93558
};
enum AchievementData
{
DATA_BULLET_TIME = 1,
};
class boss_lord_godfrey : public CreatureScript
{
public:
boss_lord_godfrey() : CreatureScript("boss_lord_godfrey") { }
struct boss_lord_godfreyAI : public BossAI
{
boss_lord_godfreyAI(Creature* creature) : BossAI(creature, DATA_LORD_GODFREY)
{
}
void Reset() override
{
_Reset();
_killedGhoulCounter = 0;
MakeInterruptable(false);
}
void EnterCombat(Unit* /*who*/) override
{
if (instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
Talk(SAY_AGGRO_ALLIANCE);
else
Talk(SAY_AGGRO_HORDE);
_EnterCombat();
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me);
events.ScheduleEvent(EVENT_CURSED_BULLETS, Seconds(10) + Milliseconds(800));
events.ScheduleEvent(EVENT_MORTAL_WOUND, Seconds(3) + Milliseconds(500));
events.ScheduleEvent(EVENT_SUMMON_BLOODTHIRSTY_GHOULS, Seconds(6));
if (IsHeroic())
events.ScheduleEvent(EVENT_PISTOL_BARRAGE, Seconds(12) + Milliseconds(500));
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DEATH);
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
_JustDied();
}
void SummonedCreatureDies(Creature* summon, Unit* killer) override
{
switch (summon->GetEntry())
{
case NPC_BLOODTHIRSTY_GHOUL:
if (killer->GetEntry() == BOSS_LORD_GODFREY && IsHeroic())
{
DoCastAOE(SPELL_BULLET_TIME_CREDIT, true);
_killedGhoulCounter++;
}
break;
default:
break;
}
}
void KilledUnit(Unit* target) override
{
if (target->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_SLAY);
}
void EnterEvadeMode(EvadeReason /*why*/) override
{
_EnterEvadeMode();
summons.DespawnAll();
me->SetReactState(REACT_AGGRESSIVE);
instance->SetBossState(DATA_LORD_GODFREY, FAIL);
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
_DespawnAtEvade();
}
void JustSummoned(Creature* summon) override
{
summons.Summon(summon);
}
uint32 GetData(uint32 type) const override
{
switch (type)
{
case DATA_BULLET_TIME:
return _killedGhoulCounter;;
default:
break;
}
return 0;
}
void MakeInterruptable(bool apply)
{
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_INTERRUPT, !apply);
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, !apply);
}
void OnSpellCastInterrupt(SpellInfo const* spell) override
{
switch (spell->Id)
{
case SPELL_CURSED_BULLETS:
case SPELL_CURSED_BULLETS_HC:
events.CancelEvent(EVENT_APPLY_IMMUNITY);
MakeInterruptable(false);
break;
default:
break;
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_CURSED_BULLETS:
MakeInterruptable(true);
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
DoCast(target, SPELL_CURSED_BULLETS);
events.ScheduleEvent(EVENT_CURSED_BULLETS, Seconds(12));
events.ScheduleEvent(EVENT_APPLY_IMMUNITY, Seconds(1) + Milliseconds(500));
break;
case EVENT_MORTAL_WOUND:
DoCastVictim(SPELL_MORTAL_WOUND);
events.Repeat(Seconds(6));
break;
case EVENT_SUMMON_BLOODTHIRSTY_GHOULS:
DoCastAOE(SPELL_SUMMON_BLOODTHIRSTY_GHOULS_AURA, true);
events.Repeat(Seconds(30));
break;
case EVENT_PISTOL_BARRAGE:
me->AttackStop();
me->SetReactState(REACT_PASSIVE);
DoCastAOE(SPELL_PISTOL_BARRAGE_FORCE_CAST);
events.ScheduleEvent(EVENT_PISTOL_BARRAGE_CAST, Milliseconds(500));
break;
case EVENT_PISTOL_BARRAGE_CAST:
if (Creature* target = me->FindNearestCreature(NPC_PISTOL_BARRAGE_DUMMY, 500.0f, true))
{
Talk(SAY_ANNOUNCE_PISTOL_BARRAGE);
me->SetFacingToObject(target);
DoCastAOE(SPELL_PISTOL_BARRAGE_CAST);
}
events.ScheduleEvent(EVENT_PISTOL_BARRAGE, Seconds(30) + Milliseconds(100));
break;
case EVENT_APPLY_IMMUNITY:
MakeInterruptable(false);
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
private:
uint8 _killedGhoulCounter;
};
CreatureAI* GetAI(Creature *creature) const override
{
return GetShadowfangKeepAI<boss_lord_godfreyAI>(creature);
}
};
class npc_sfk_bloodthirsty_ghoul : public CreatureScript
{
public:
npc_sfk_bloodthirsty_ghoul() : CreatureScript("npc_sfk_bloodthirsty_ghoul") { }
struct npc_sfk_bloodthirsty_ghoulAI : public ScriptedAI
{
npc_sfk_bloodthirsty_ghoulAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
void IsSummonedBy(Unit* summoner) override
{
if (!summoner->IsInCombat())
me->DespawnOrUnsummon();
me->SetReactState(REACT_PASSIVE);
me->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE);
DoZoneInCombat();
_events.ScheduleEvent(EVENT_ATTACK, Seconds(4));
}
void JustDied(Unit* /*killer*/) override
{
me->DespawnOrUnsummon(Seconds(5));
}
void UpdateAI(uint32 diff) override
{
_events.Update(diff);
while (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_ATTACK:
me->SetReactState(REACT_AGGRESSIVE);
if (Unit* target = me->SelectNearestPlayer(100.0f))
me->AI()->AttackStart(target);
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
private:
InstanceScript* _instance;
EventMap _events;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetShadowfangKeepAI<npc_sfk_bloodthirsty_ghoulAI>(creature);
}
};
class spell_sfk_summon_bloodthirsty_ghouls : public SpellScriptLoader
{
public:
spell_sfk_summon_bloodthirsty_ghouls() : SpellScriptLoader("spell_sfk_summon_bloodthirsty_ghouls") { }
class spell_sfk_summon_bloodthirsty_ghouls_AuraScript : public AuraScript
{
PrepareAuraScript(spell_sfk_summon_bloodthirsty_ghouls_AuraScript);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo(
{
SPELL_SUMMON_BLOODTHIRSTY_GHOULS_TRIGGERED_1,
SPELL_SUMMON_BLOODTHIRSTY_GHOULS_TRIGGERED_2
});
}
void OnPeriodic(AuraEffect const* /*aurEff*/)
{
switch (RAND(0, 1))
{
case 0:
GetCaster()->CastSpell((Unit*)NULL, SPELL_SUMMON_BLOODTHIRSTY_GHOULS_TRIGGERED_1, true);
break;
case 1:
GetCaster()->CastSpell((Unit*)NULL, SPELL_SUMMON_BLOODTHIRSTY_GHOULS_TRIGGERED_2, true);
break;
}
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_sfk_summon_bloodthirsty_ghouls_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
}
};
AuraScript* GetAuraScript() const
{
return new spell_sfk_summon_bloodthirsty_ghouls_AuraScript();
}
};
class spell_sfk_pistol_barrage : public SpellScriptLoader
{
public:
spell_sfk_pistol_barrage() : SpellScriptLoader("spell_sfk_pistol_barrage") { }
class spell_sfk_pistol_barrage_AuraScript : public AuraScript
{
PrepareAuraScript(spell_sfk_pistol_barrage_AuraScript);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo(
{
SPELL_PISTOL_BARRAGE_TRIGGER_1,
SPELL_PISTOL_BARRAGE_TRIGGER_2
});
}
void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (Unit* caster = GetCaster())
caster->CastSpell(caster, SPELL_PISTOL_BARRAGE_TRIGGER_1, true);
}
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (Unit* caster = GetCaster())
{
if (caster->ToCreature())
caster->ToCreature()->SetReactState(REACT_AGGRESSIVE);
caster->RemoveAurasDueToSpell(SPELL_PISTOL_BARRAGE_TRIGGER_1);
}
}
void OnPeriodic(AuraEffect const* /*aurEff*/)
{
if (Unit* caster = GetCaster())
{
float ori = caster->GetOrientation() + frand(-0.5236f, 0.5236f);
float posX = caster->GetPositionX() + cos(ori) * 60;
float posY = caster->GetPositionY() + sin(ori) * 60;
float posZ = caster->GetPositionZ();
GetCaster()->CastSpell(posX, posY, posZ, SPELL_PISTOL_BARRAGE_TRIGGER_2, true);
}
}
void Register() override
{
OnEffectApply += AuraEffectApplyFn(spell_sfk_pistol_barrage_AuraScript::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
OnEffectRemove += AuraEffectRemoveFn(spell_sfk_pistol_barrage_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
OnEffectPeriodic += AuraEffectPeriodicFn(spell_sfk_pistol_barrage_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
}
};
AuraScript* GetAuraScript() const
{
return new spell_sfk_pistol_barrage_AuraScript();
}
};
class spell_sfk_pistol_barrage_summon : public SpellScriptLoader
{
public:
spell_sfk_pistol_barrage_summon() : SpellScriptLoader("spell_sfk_pistol_barrage_summon") { }
class spell_sfk_pistol_barrage_summon_SpellScript : public SpellScript
{
PrepareSpellScript(spell_sfk_pistol_barrage_summon_SpellScript);
void FilterTargets(std::list<WorldObject*>& targets)
{
Trinity::Containers::RandomResize(targets, 1);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sfk_pistol_barrage_summon_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_sfk_pistol_barrage_summon_SpellScript();
}
};
class spell_sfk_cursed_bullets : public SpellScriptLoader
{
public:
spell_sfk_cursed_bullets() : SpellScriptLoader("spell_sfk_cursed_bullets") { }
class spell_sfk_cursed_bullets_AuraScript : public AuraScript
{
PrepareAuraScript(spell_sfk_cursed_bullets_AuraScript);
void OnPeriodic(AuraEffect const* aurEff)
{
uint64 damage;
damage = aurEff->GetBaseAmount() * aurEff->GetTickNumber();
GetEffect(EFFECT_1)->ChangeAmount(damage);
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_sfk_cursed_bullets_AuraScript::OnPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_DAMAGE);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_sfk_cursed_bullets_AuraScript();
}
};
class achievement_bullet_time : public AchievementCriteriaScript
{
public:
achievement_bullet_time() : AchievementCriteriaScript("achievement_bullet_time") { }
bool OnCheck(Player* /*source*/, Unit* target)
{
if (!target)
return false;
if (target->GetMap()->IsHeroic())
return target->GetAI()->GetData(DATA_BULLET_TIME) >= 12;
return false;
}
};
void AddSC_boss_lord_godfrey()
{
new boss_lord_godfrey();
new npc_sfk_bloodthirsty_ghoul();
new spell_sfk_summon_bloodthirsty_ghouls();
new spell_sfk_pistol_barrage();
new spell_sfk_pistol_barrage_summon();
new spell_sfk_cursed_bullets();
new achievement_bullet_time();
}

View File

@@ -0,0 +1,257 @@
/*
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "shadowfang_keep.h"
#include "ObjectMgr.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "Spell.h"
#include "SpellAuras.h"
#include "SpellAuraEffects.h"
#include "Player.h"
enum Texts
{
SAY_AGGRO = 0,
SAY_SLAY = 1,
SAY_DEATH = 2
};
enum Spells
{
// Lord Walden
SPELL_ICE_SHARDS = 93527,
SPELL_CONJURE_FROST_MIXTURE = 93505,
SPELL_CONJURE_POISONOUS_MIXTURE = 93697,
SPELL_CONJURE_MYSTERY_MIXTURE = 93695,
SPELL_CONJURE_MYSTERY_MIXTURE_CHANNEL = 93562,
SPELL_FULLY_COAGULATED = 93660,
// Mystery Toxine
SPELL_TOXIC_COAGULANT = 93572,
SPELL_TOXIC_COAGULANT_SLOW = 93617,
SPELL_TOXIC_CATALYST = 93573,
SPELL_TOXIC_CATALYST_AURA = 93689
};
enum Events
{
EVENT_ICE_SHARDS = 1,
EVENT_CONJURE_FROST_MIXTURE,
EVENT_CONJURE_POISONOUS_MIXTURE,
EVENT_CONJURE_MYSTERY_TOXINE,
EVENT_ADD_CATALYST
};
class boss_lord_walden : public CreatureScript
{
public:
boss_lord_walden() : CreatureScript("boss_lord_walden") { }
struct boss_lord_waldenAI : public BossAI
{
boss_lord_waldenAI(Creature* creature) : BossAI(creature, DATA_LORD_WALDEN) { }
void EnterCombat(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
_EnterCombat();
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me);
events.ScheduleEvent(EVENT_ICE_SHARDS, Seconds(23));
events.ScheduleEvent(EVENT_CONJURE_FROST_MIXTURE, Seconds(8));
events.ScheduleEvent(EVENT_CONJURE_POISONOUS_MIXTURE, Seconds(21));
if (IsHeroic())
events.ScheduleEvent(EVENT_CONJURE_MYSTERY_TOXINE, Seconds(10) + Milliseconds(500));
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DEATH);
_JustDied();
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
}
void KilledUnit(Unit* target) override
{
if (target->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_SLAY);
}
void EnterEvadeMode(EvadeReason /*why*/) override
{
_EnterEvadeMode();
summons.DespawnAll();
instance->SetBossState(DATA_LORD_WALDEN, FAIL);
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
_DespawnAtEvade();
}
void JustSummoned(Creature* summon) override
{
summons.Summon(summon);
switch (summon->GetEntry())
{
case NPC_MYSTERY_MIXTURE:
if (!me->HealthBelowPct(35))
summon->CastSpell((Unit*)NULL, SPELL_TOXIC_COAGULANT, true);
else
{
summon->CastSpell((Unit*)NULL, SPELL_TOXIC_CATALYST, true);
events.ScheduleEvent(EVENT_ADD_CATALYST, Seconds(2));
}
// Since summon above caster is not implemented yet
summon->NearTeleportTo(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 4.5f, me->GetOrientation());
break;
default:
break;
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while(uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_ICE_SHARDS:
me->StopMoving();
DoCastAOE(SPELL_ICE_SHARDS);
events.Repeat(Seconds(21) + Milliseconds(500));
break;
case EVENT_CONJURE_FROST_MIXTURE:
me->StopMoving();
DoCastAOE(SPELL_CONJURE_FROST_MIXTURE);
events.Repeat(Seconds(21) + Milliseconds(500));
break;
case EVENT_CONJURE_POISONOUS_MIXTURE:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
DoCast(target, SPELL_CONJURE_POISONOUS_MIXTURE);
events.Repeat(Seconds(21) + Milliseconds(500));
break;
case EVENT_CONJURE_MYSTERY_TOXINE:
DoCast(SPELL_CONJURE_MYSTERY_MIXTURE);
DoCast(SPELL_CONJURE_MYSTERY_MIXTURE_CHANNEL);
events.Repeat(Seconds(21) + Milliseconds(500));
break;
case EVENT_ADD_CATALYST:
if (Unit* mixture = me->FindNearestCreature(NPC_MYSTERY_MIXTURE, 20.0f, true))
mixture->CastSpell(mixture, SPELL_TOXIC_CATALYST_AURA, false);
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature *creature) const override
{
return GetShadowfangKeepAI<boss_lord_waldenAI>(creature);
}
};
class spell_sfk_toxic_coagulant : public SpellScriptLoader
{
public:
spell_sfk_toxic_coagulant() : SpellScriptLoader("spell_sfk_toxic_coagulant") { }
class spell_sfk_toxic_coagulant_SpellScript : public SpellScript
{
PrepareSpellScript(spell_sfk_toxic_coagulant_SpellScript);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo(
{
SPELL_FULLY_COAGULATED,
SPELL_TOXIC_COAGULANT_SLOW
});
}
void HandleStacks()
{
if (Unit* target = GetHitUnit())
{
Aura* aura = nullptr;
aura = target->GetAura(SPELL_TOXIC_COAGULANT_SLOW);
if (aura)
{
if (aura->GetStackAmount() == 3)
{
target->RemoveAurasDueToSpell(SPELL_TOXIC_COAGULANT_SLOW);
target->CastSpell(target, SPELL_FULLY_COAGULATED, true);
}
}
}
}
void Register() override
{
AfterHit += SpellHitFn(spell_sfk_toxic_coagulant_SpellScript::HandleStacks);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_sfk_toxic_coagulant_SpellScript();
}
};
class spell_sfk_conjure_poisonous_mixture : public SpellScriptLoader
{
public:
spell_sfk_conjure_poisonous_mixture() : SpellScriptLoader("spell_sfk_conjure_poisonous_mixture") { }
class spell_sfk_conjure_poisonous_mixture_SpellScript : public SpellScript
{
PrepareSpellScript(spell_sfk_conjure_poisonous_mixture_SpellScript);
void FilterTargets(std::list<WorldObject*>& targets)
{
Trinity::Containers::RandomResize(targets, 1);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sfk_conjure_poisonous_mixture_SpellScript::FilterTargets, EFFECT_ALL, TARGET_UNIT_DEST_AREA_ENEMY);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_sfk_conjure_poisonous_mixture_SpellScript();
}
};
void AddSC_boss_lord_walden()
{
new boss_lord_walden();
new spell_sfk_toxic_coagulant();
new spell_sfk_conjure_poisonous_mixture();
}

View File

@@ -1,6 +1,5 @@
/*
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
* Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -16,269 +15,119 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* ScriptData
SDName: Instance_Shadowfang_Keep
SD%Complete: 90
SDComment:
SDCategory: Shadowfang Keep
EndScriptData */
#include "ScriptedCreature.h"
#include "ScriptMgr.h"
#include "InstanceScript.h"
#include "shadowfang_keep.h"
#include "TemporarySummon.h"
#include "Player.h"
#define MAX_ENCOUNTER 4
enum Yells
ObjectData const creatureData[] =
{
SAY_BOSS_DIE_AD = 4,
SAY_BOSS_DIE_AS = 3,
SAY_ARCHMAGE = 0
{ BOSS_BARON_ASHBURY, DATA_BARON_ASHBURY },
{ BOSS_BARON_SILVERLAINE, DATA_BARON_SILVERLAINE },
{ BOSS_COMMANDER_SPRINGVALE, DATA_COMMANDER_SPRINGVALE },
{ BOSS_LORD_WALDEN, DATA_LORD_WALDEN },
{ BOSS_LORD_GODFREY, DATA_LORD_GODFREY },
};
enum Creatures
DoorData const doorData[] =
{
NPC_ASH = 3850,
NPC_ADA = 3849,
NPC_ARCHMAGE_ARUGAL = 4275,
NPC_ARUGAL_VOIDWALKER = 4627
{ GO_ARUGAL_DOOR, DATA_LORD_GODFREY, DOOR_TYPE_ROOM },
{ 0, 0, DOOR_TYPE_ROOM }, // END
};
enum GameObjects
BossBoundaryData const boundaries =
{
GO_COURTYARD_DOOR = 18895, //door to open when talking to NPC's
GO_SORCERER_DOOR = 18972, //door to open when Fenrus the Devourer
GO_ARUGAL_DOOR = 18971 //door to open when Wolf Master Nandos
{ DATA_COMMANDER_SPRINGVALE, new ParallelogramBoundary(Position(-222.75f, 2269.03f), Position(-217.60f, 2249.65f), Position(-267.47f, 2256.10f)) },
{ DATA_LORD_WALDEN, new CircleBoundary(Position(-146.58f, 2173.037f), 17.0) },
};
enum Spells
{
SPELL_ASHCROMBE_TELEPORT = 15742
};
const Position SpawnLocation[] =
{
{-148.199f, 2165.647f, 128.448f, 1.026f},
{-153.110f, 2168.620f, 128.448f, 1.026f},
{-145.905f, 2180.520f, 128.448f, 4.183f},
{-140.794f, 2178.037f, 128.448f, 4.090f},
{-138.640f, 2170.159f, 136.577f, 2.737f}
};
class instance_shadowfang_keep : public InstanceMapScript
{
public:
instance_shadowfang_keep() : InstanceMapScript("instance_shadowfang_keep", 33) { }
InstanceScript* GetInstanceScript(InstanceMap* map) const override
{
return new instance_shadowfang_keep_InstanceMapScript(map);
}
instance_shadowfang_keep() : InstanceMapScript(SKScriptName, 33) { }
struct instance_shadowfang_keep_InstanceMapScript : public InstanceScript
{
instance_shadowfang_keep_InstanceMapScript(Map* map) : InstanceScript(map)
{
SetHeaders(DataHeader);
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
uiPhase = 0;
uiTimer = 0;
SetBossNumber(EncounterCount);
LoadDoorData(doorData);
LoadBossBoundaries(boundaries);
LoadObjectData(creatureData, nullptr);
_teamInInstance = 0;
}
uint32 m_auiEncounter[MAX_ENCOUNTER];
std::string str_data;
ObjectGuid uiAshGUID;
ObjectGuid uiAdaGUID;
ObjectGuid uiArchmageArugalGUID;
ObjectGuid DoorCourtyardGUID;
ObjectGuid DoorSorcererGUID;
ObjectGuid DoorArugalGUID;
uint8 uiPhase;
uint16 uiTimer;
void OnCreatureCreate(Creature* creature) override
void OnPlayerEnter(Player* player) override
{
switch (creature->GetEntry())
if (!_teamInInstance)
{
case NPC_ASH: uiAshGUID = creature->GetGUID(); break;
case NPC_ADA: uiAdaGUID = creature->GetGUID(); break;
case NPC_ARCHMAGE_ARUGAL: uiArchmageArugalGUID = creature->GetGUID(); break;
_teamInInstance = player->GetTeam();
SetData(DATA_TEAM_IN_INSTANCE, _teamInInstance);
}
}
void OnGameObjectCreate(GameObject* go) override
bool SetBossState(uint32 type, EncounterState state) override
{
switch (go->GetEntry())
{
case GO_COURTYARD_DOOR:
DoorCourtyardGUID = go->GetGUID();
if (m_auiEncounter[0] == DONE)
HandleGameObject(ObjectGuid::Empty, true, go);
break;
case GO_SORCERER_DOOR:
DoorSorcererGUID = go->GetGUID();
if (m_auiEncounter[2] == DONE)
HandleGameObject(ObjectGuid::Empty, true, go);
break;
case GO_ARUGAL_DOOR:
DoorArugalGUID = go->GetGUID();
if (m_auiEncounter[3] == DONE)
HandleGameObject(ObjectGuid::Empty, true, go);
break;
}
}
if (!InstanceScript::SetBossState(type, state))
return false;
void DoSpeech()
{
Creature* pAda = instance->GetCreature(uiAdaGUID);
Creature* pAsh = instance->GetCreature(uiAshGUID);
if (pAda && pAda->IsAlive() && pAsh && pAsh->IsAlive())
{
pAda->AI()->Talk(SAY_BOSS_DIE_AD);
pAsh->AI()->Talk(SAY_BOSS_DIE_AS);
}
}
void SetData(uint32 type, uint32 data) override
{
switch (type)
{
case TYPE_FREE_NPC:
if (data == DONE)
DoUseDoorOrButton(DoorCourtyardGUID);
m_auiEncounter[0] = data;
break;
case TYPE_RETHILGORE:
if (data == DONE)
DoSpeech();
m_auiEncounter[1] = data;
break;
case TYPE_FENRUS:
switch (data)
{
case DONE:
uiTimer = 1000;
uiPhase = 1;
break;
case 7:
DoUseDoorOrButton(DoorSorcererGUID);
break;
}
m_auiEncounter[2] = data;
break;
case TYPE_NANDOS:
if (data == DONE)
DoUseDoorOrButton(DoorArugalGUID);
m_auiEncounter[3] = data;
break;
}
if (data == DONE)
{
OUT_SAVE_INST_DATA;
std::ostringstream saveStream;
saveStream << m_auiEncounter[0] << ' ' << m_auiEncounter[1] << ' ' << m_auiEncounter[2] << ' ' << m_auiEncounter[3];
str_data = saveStream.str();
SaveToDB();
OUT_SAVE_INST_DATA_COMPLETE;
}
return true;
}
uint32 GetData(uint32 type) const override
{
switch (type)
{
case TYPE_FREE_NPC:
return m_auiEncounter[0];
case TYPE_RETHILGORE:
return m_auiEncounter[1];
case TYPE_FENRUS:
return m_auiEncounter[2];
case TYPE_NANDOS:
return m_auiEncounter[3];
case DATA_TEAM_IN_INSTANCE:
return _teamInInstance;
default:
break;
}
return 0;
}
std::string GetSaveData() override
void SetData(uint32 type, uint32 data) override
{
return str_data;
}
void Load(const char* in) override
{
if (!in)
switch (type)
{
OUT_LOAD_INST_DATA_FAIL;
return;
}
OUT_LOAD_INST_DATA(in);
std::istringstream loadStream(in);
loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3];
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
{
if (m_auiEncounter[i] == IN_PROGRESS)
m_auiEncounter[i] = NOT_STARTED;
}
OUT_LOAD_INST_DATA_COMPLETE;
}
void Update(uint32 uiDiff) override
{
if (GetData(TYPE_FENRUS) != DONE)
return;
Creature* pArchmage = instance->GetCreature(uiArchmageArugalGUID);
if (!pArchmage || !pArchmage->IsAlive())
return;
if (uiPhase)
{
if (uiTimer <= uiDiff)
{
switch (uiPhase)
{
case 1:
{
Creature* summon = pArchmage->SummonCreature(pArchmage->GetEntry(), SpawnLocation[4], TEMPSUMMON_TIMED_DESPAWN, 10000);
summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
summon->SetReactState(REACT_DEFENSIVE);
summon->CastSpell(summon, SPELL_ASHCROMBE_TELEPORT, true);
summon->AI()->Talk(SAY_ARCHMAGE);
uiTimer = 2000;
uiPhase = 2;
break;
}
case 2:
{
pArchmage->SummonCreature(NPC_ARUGAL_VOIDWALKER, SpawnLocation[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
pArchmage->SummonCreature(NPC_ARUGAL_VOIDWALKER, SpawnLocation[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
pArchmage->SummonCreature(NPC_ARUGAL_VOIDWALKER, SpawnLocation[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
pArchmage->SummonCreature(NPC_ARUGAL_VOIDWALKER, SpawnLocation[3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
uiPhase = 0;
break;
}
}
} else uiTimer -= uiDiff;
case DATA_TEAM_IN_INSTANCE:
_teamInInstance = data;
SaveToDB();
break;
default:
break;
}
}
void WriteSaveDataMore(std::ostringstream& data) override
{
data << _teamInInstance;
}
void ReadSaveDataMore(std::istringstream& data) override
{
data >> _teamInInstance;
uint32 temp = 0;
data >> temp;
if (temp)
SetData(DATA_TEAM_IN_INSTANCE, temp);
}
protected:
EventMap events;
uint32 _teamInInstance;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override
{
return new instance_shadowfang_keep_InstanceMapScript(map);
}
};
void AddSC_instance_shadowfang_keep()

View File

@@ -16,17 +16,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* ScriptData
SDName: Shadowfang_Keep
SD%Complete: 75
SDComment: npc_shadowfang_prisoner using escortAI for movement to door. Might need additional code in case being attacked. Add proper texts/say().
SDCategory: Shadowfang Keep
EndScriptData */
/* ContentData
npc_shadowfang_prisoner
EndContentData */
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "ScriptedGossip.h"
@@ -36,334 +25,45 @@ EndContentData */
#include "shadowfang_keep.h"
#include "Player.h"
/*######
## npc_shadowfang_prisoner
######*/
enum Yells
enum SKShieldOfBones
{
SAY_FREE_AS = 0,
SAY_OPEN_DOOR_AS = 1,
SAY_POST_DOOR_AS = 2,
SAY_FREE_AD = 0,
SAY_OPEN_DOOR_AD = 1,
SAY_POST1_DOOR_AD = 2,
SAY_POST2_DOOR_AD = 3
SPELL_SHIELD_OF_BONES_TRIGGERED = 91631,
};
enum Spells
{
SPELL_UNLOCK = 6421,
SPELL_DARK_OFFERING = 7154
};
enum Creatures
{
NPC_ASH = 3850
};
class npc_shadowfang_prisoner : public CreatureScript
{
public:
npc_shadowfang_prisoner() : CreatureScript("npc_shadowfang_prisoner") { }
CreatureAI* GetAI(Creature* creature) const override
{
return GetInstanceAI<npc_shadowfang_prisonerAI>(creature);
}
struct npc_shadowfang_prisonerAI : public npc_escortAI
{
npc_shadowfang_prisonerAI(Creature* creature) : npc_escortAI(creature)
{
instance = creature->GetInstanceScript();
}
InstanceScript* instance;
bool GossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
{
uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
ClearGossipMenuFor(player);
if (action == GOSSIP_ACTION_INFO_DEF + 1)
{
CloseGossipMenuFor(player);
Start(false, false);
}
return true;
}
bool GossipHello(Player* player) override
{
InstanceScript* instance = me->GetInstanceScript();
if (instance && instance->GetData(TYPE_FREE_NPC) != DONE && instance->GetData(TYPE_RETHILGORE) == DONE)
AddGossipItemFor(player, Player::GetDefaultGossipMenuForSource(me), 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
SendGossipMenuFor(player, player->GetGossipTextId(me), me->GetGUID());
return true;
}
void WaypointReached(uint32 waypointId) override
{
switch (waypointId)
{
case 0:
if (me->GetEntry() == NPC_ASH)
Talk(SAY_FREE_AS);
else
Talk(SAY_FREE_AD);
break;
case 10:
if (me->GetEntry() == NPC_ASH)
Talk(SAY_OPEN_DOOR_AS);
else
Talk(SAY_OPEN_DOOR_AD);
break;
case 11:
if (me->GetEntry() == NPC_ASH)
DoCast(me, SPELL_UNLOCK);
break;
case 12:
if (me->GetEntry() == NPC_ASH)
Talk(SAY_POST_DOOR_AS);
else
Talk(SAY_POST1_DOOR_AD);
instance->SetData(TYPE_FREE_NPC, DONE);
break;
case 13:
if (me->GetEntry() != NPC_ASH)
Talk(SAY_POST2_DOOR_AD);
break;
}
}
void Reset() override { }
void EnterCombat(Unit* /*who*/) override { }
};
};
class npc_arugal_voidwalker : public CreatureScript
{
public:
npc_arugal_voidwalker() : CreatureScript("npc_arugal_voidwalker") { }
CreatureAI* GetAI(Creature* creature) const override
{
return GetInstanceAI<npc_arugal_voidwalkerAI>(creature);
}
struct npc_arugal_voidwalkerAI : public ScriptedAI
{
npc_arugal_voidwalkerAI(Creature* creature) : ScriptedAI(creature)
{
Initialize();
instance = creature->GetInstanceScript();
}
void Initialize()
{
uiDarkOffering = urand(200, 1000);
}
InstanceScript* instance;
uint32 uiDarkOffering;
void Reset() override
{
Initialize();
}
void UpdateAI(uint32 uiDiff) override
{
if (!UpdateVictim())
return;
if (uiDarkOffering <= uiDiff)
{
if (Creature* pFriend = me->FindNearestCreature(me->GetEntry(), 25.0f, true))
DoCast(pFriend, SPELL_DARK_OFFERING);
else
DoCast(me, SPELL_DARK_OFFERING);
uiDarkOffering = urand(4400, 12500);
} else uiDarkOffering -= uiDiff;
DoMeleeAttackIfReady();
}
void JustDied(Unit* /*killer*/) override
{
instance->SetData(TYPE_FENRUS, instance->GetData(TYPE_FENRUS) + 1);
}
};
};
enum ArugalSpells
{
SPELL_TELE_UPPER = 7587,
SPELL_TELE_SPAWN = 7586,
SPELL_TELE_STAIRS = 7136,
NUM_TELEPORT_SPELLS = 3,
SPELL_ARUGAL_CURSE = 7621,
SPELL_THUNDERSHOCK = 7803,
SPELL_VOIDBOLT = 7588
};
enum ArugalTexts
{
SAY_AGGRO = 1, // You, too, shall serve!
SAY_TRANSFORM = 2, // Release your rage!
SAY_SLAY = 3 // Another falls!
};
enum ArugalEvents
{
EVENT_VOID_BOLT = 1,
EVENT_TELEPORT,
EVENT_THUNDERSHOCK,
EVENT_CURSE
};
class boss_archmage_arugal : public CreatureScript
class spell_sfk_shield_of_bones: public SpellScriptLoader
{
public:
boss_archmage_arugal() : CreatureScript("boss_archmage_arugal") { }
spell_sfk_shield_of_bones() : SpellScriptLoader("spell_sfk_shield_of_bones") { }
struct boss_archmage_arugalAI : public BossAI
class spell_sfk_shield_of_bones_AuraScript : public AuraScript
{
boss_archmage_arugalAI(Creature* creature) : BossAI(creature, BOSS_ARUGAL) { }
PrepareAuraScript(spell_sfk_shield_of_bones_AuraScript);
uint32 teleportSpells[NUM_TELEPORT_SPELLS] =
bool Validate(SpellInfo const* /*spellInfo*/) override
{
SPELL_TELE_SPAWN,
SPELL_TELE_UPPER,
SPELL_TELE_STAIRS
};
void KilledUnit(Unit* who) override
{
if (who->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_SLAY);
return ValidateSpellInfo({ SPELL_SHIELD_OF_BONES_TRIGGERED });
}
void SpellHitTarget(Unit* /*target*/, SpellInfo const* spell) override
void OnAuraRemoveHandler(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
if (spell->Id == SPELL_ARUGAL_CURSE)
Talk(SAY_TRANSFORM);
}
void EnterCombat(Unit* /*who*/) override
{
_EnterCombat();
Talk(SAY_AGGRO);
events.ScheduleEvent(EVENT_CURSE, Seconds(7));
events.ScheduleEvent(EVENT_TELEPORT, Seconds(15));
events.ScheduleEvent(EVENT_VOID_BOLT, Seconds(1));
events.ScheduleEvent(EVENT_THUNDERSHOCK, Seconds(10));
}
void AttackStart(Unit* who) override
{
AttackStartCaster(who, 100.0f); // void bolt range is 100.f
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_CURSE:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 30.0f, true))
DoCast(target, SPELL_ARUGAL_CURSE);
events.Repeat(Seconds(15));
break;
case EVENT_TELEPORT:
{
// ensure we never cast the same teleport twice in a row
uint8 spellIndex = urand(1, NUM_TELEPORT_SPELLS-1);
std::swap(teleportSpells[0], teleportSpells[spellIndex]);
DoCast(teleportSpells[0]);
events.Repeat(Seconds(20));
break;
}
case EVENT_THUNDERSHOCK:
DoCastAOE(SPELL_THUNDERSHOCK);
events.Repeat(Seconds(30));
break;
case EVENT_VOID_BOLT:
DoCastVictim(SPELL_VOIDBOLT);
events.Repeat(Seconds(5));
break;
}
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetInstanceAI<boss_archmage_arugalAI>(creature);
}
};
class spell_shadowfang_keep_haunting_spirits : public SpellScriptLoader
{
public:
spell_shadowfang_keep_haunting_spirits() : SpellScriptLoader("spell_shadowfang_keep_haunting_spirits") { }
class spell_shadowfang_keep_haunting_spirits_AuraScript : public AuraScript
{
PrepareAuraScript(spell_shadowfang_keep_haunting_spirits_AuraScript);
void CalcPeriodic(AuraEffect const* /*aurEff*/, bool& isPeriodic, int32& amplitude)
{
isPeriodic = true;
amplitude = (irand(0, 60) + 30) * IN_MILLISECONDS;
}
void HandleDummyTick(AuraEffect const* aurEff)
{
GetTarget()->CastSpell((Unit*)NULL, aurEff->GetAmount(), true);
}
void HandleUpdatePeriodic(AuraEffect* aurEff)
{
aurEff->CalculatePeriodic(GetCaster());
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_ENEMY_SPELL)
if (Unit* caster = GetCaster())
caster->CastSpell(caster, SPELL_SHIELD_OF_BONES_TRIGGERED, true);
}
void Register() override
{
DoEffectCalcPeriodic += AuraEffectCalcPeriodicFn(spell_shadowfang_keep_haunting_spirits_AuraScript::CalcPeriodic, EFFECT_0, SPELL_AURA_DUMMY);
OnEffectPeriodic += AuraEffectPeriodicFn(spell_shadowfang_keep_haunting_spirits_AuraScript::HandleDummyTick, EFFECT_0, SPELL_AURA_DUMMY);
OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_shadowfang_keep_haunting_spirits_AuraScript::HandleUpdatePeriodic, EFFECT_0, SPELL_AURA_DUMMY);
AfterEffectRemove += AuraEffectRemoveFn(spell_sfk_shield_of_bones_AuraScript::OnAuraRemoveHandler, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_shadowfang_keep_haunting_spirits_AuraScript();
return new spell_sfk_shield_of_bones_AuraScript();
}
};
void AddSC_shadowfang_keep()
{
new npc_shadowfang_prisoner();
new npc_arugal_voidwalker();
new boss_archmage_arugal();
new spell_shadowfang_keep_haunting_spirits();
new spell_sfk_shield_of_bones();
}

View File

@@ -1,6 +1,5 @@
/*
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
* Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -19,16 +18,72 @@
#ifndef DEF_SHADOWFANG_H
#define DEF_SHADOWFANG_H
#include "SpellScript.h"
#define DataHeader "SK"
#define SKScriptName "instance_shadowfang_keep"
uint32 const EncounterCount = 7;
enum SKCreatures
{
// Baron Ashbury
BOSS_BARON_ASHBURY = 46962,
NPC_ASHBURY_WINGS = 50604,
// Baron Silverlaine
BOSS_BARON_SILVERLAINE = 3887,
NPC_NANDOS_DUMMY = 51047,
NPC_WOLF_MASTER_NANDOS = 50851,
NPC_LUPINE_SPECTRE = 50923,
NPC_ODO_DUMMY = 50934,
NPC_ODO_THE_BLINDWATCHER = 50857,
NPC_RAZORCLAW_DUMMY = 51080,
NPC_RAZORCLAW_THE_BUTCHER = 50869,
NPC_RETHILGORE_DUMMY = 51085,
NPC_RETHILGORE = 50834,
// Commander Springvale
BOSS_COMMANDER_SPRINGVALE = 4278,
NPC_TORMENTED_OFFICER = 50615,
NPC_WAILING_GUARDSMAN = 50613,
NPC_SHIELD_FOCUS = 50547,
NPC_DESECRATION_STALKER = 50503,
// Lord Walden
BOSS_LORD_WALDEN = 46963,
NPC_MYSTERY_MIXTURE = 50522,
// Lord Godfrey
BOSS_LORD_GODFREY = 46964,
NPC_BLOODTHIRSTY_GHOUL = 50561,
NPC_PISTOL_BARRAGE_DUMMY = 52065,
};
enum SKGameObjectIds
{
GO_COURTYARD_DOOR = 18895,
GO_SORCERER_DOOR = 18972,
GO_ARUGAL_DOOR = 18971
};
enum SKDataTypes
{
TYPE_FREE_NPC = 1,
TYPE_RETHILGORE = 2,
TYPE_FENRUS = 3,
TYPE_NANDOS = 4,
BOSS_ARUGAL = 5,
DATA_APOTHECARY_HUMMEL = 6
DATA_BARON_ASHBURY = 1,
DATA_BARON_SILVERLAINE = 2,
DATA_COMMANDER_SPRINGVALE = 3,
DATA_LORD_WALDEN = 4,
DATA_LORD_GODFREY = 5,
DATA_APOTHECARY_HUMMEL = 6,
DATA_TEAM_IN_INSTANCE = 7
};
template<class AI>
AI* GetShadowfangKeepAI(Creature* creature)
{
return GetInstanceAI<AI>(creature, SKScriptName);
}
#endif

View File

@@ -131,6 +131,11 @@ void AddSC_boss_vectus();
void AddSC_boss_kirtonos_the_herald();
void AddSC_instance_scholomance();
void AddSC_shadowfang_keep(); //Shadowfang keep
void AddSC_boss_baron_ashbury();
void AddSC_boss_baron_silverlaine();
void AddSC_boss_commander_springvale();
void AddSC_boss_lord_walden();
void AddSC_boss_lord_godfrey();
void AddSC_instance_shadowfang_keep();
void AddSC_boss_apothecary_hummel();
void AddSC_boss_magistrate_barthilas(); //Stratholme
@@ -321,6 +326,11 @@ void AddEasternKingdomsScripts()
AddSC_boss_kirtonos_the_herald();
AddSC_instance_scholomance();
AddSC_shadowfang_keep(); //Shadowfang keep
AddSC_boss_baron_ashbury();
AddSC_boss_baron_silverlaine();
AddSC_boss_commander_springvale();
AddSC_boss_lord_walden();
AddSC_boss_lord_godfrey();
AddSC_instance_shadowfang_keep();
AddSC_boss_apothecary_hummel();
AddSC_boss_magistrate_barthilas(); //Stratholme