From f55b034f4c022583234c93ce0fdf083ff7af9232 Mon Sep 17 00:00:00 2001 From: Ovahlord Date: Fri, 13 Jul 2018 22:01:47 +0200 Subject: [PATCH] Scripts/BoT: implement Ascendant Council encounter --- .../custom/custom_2018_07_13_01_world.sql | 309 ++ src/server/game/Spells/SpellMgr.cpp | 13 + .../BastionOfTwilight/bastion_of_twilight.h | 13 +- .../boss_ascendant_council.cpp | 2798 +++++++++++++++++ .../instance_bastion_of_twilight.cpp | 32 +- .../eastern_kingdoms_script_loader.cpp | 2 + 6 files changed, 3152 insertions(+), 15 deletions(-) create mode 100644 sql/updates/world/custom/custom_2018_07_13_01_world.sql create mode 100644 src/server/scripts/EasternKingdoms/BastionOfTwilight/boss_ascendant_council.cpp diff --git a/sql/updates/world/custom/custom_2018_07_13_01_world.sql b/sql/updates/world/custom/custom_2018_07_13_01_world.sql new file mode 100644 index 00000000000..1694d618683 --- /dev/null +++ b/sql/updates/world/custom/custom_2018_07_13_01_world.sql @@ -0,0 +1,309 @@ +-- Template Updates +-- Ascendant Council Controller +UPDATE `creature_template` SET `unit_flags`= 33554432, `flags_extra`= 128, `ScriptName`= 'boss_ascendant_council_controller' WHERE `entry`= 43691; +-- Feludius +UPDATE `creature_template` SET `difficulty_entry_1`= 49612, `difficulty_entry_2`= 49613, `difficulty_entry_3`= 49614, `ScriptName`= 'npc_feludius' WHERE `entry`= 43687; +UPDATE `creature_template` SET `flags_extra`= 0, `movementId`= 187, `BaseAttackTime`= 1500, `speed_walk`= 3.2, `speed_run`= 2, `unit_class`= 2, `minlevel`= 88, `maxlevel`= 88, `exp`= 3,`faction`= 16, `DamageModifier`= 35, `BaseVariance`= 5, `mechanic_immune_mask`= 80297855, `unit_flags`= 64 WHERE `entry` IN (43687, 49612, 49613, 49614); +-- Ignacious +UPDATE `creature_template` SET `difficulty_entry_1`= 49615, `difficulty_entry_2`= 49616, `difficulty_entry_3`= 49617, `ScriptName`= 'npc_ignacious' WHERE `entry`= 43686; +UPDATE `creature_template` SET `flags_extra`= 0, `movementId`= 187, `BaseAttackTime`= 1500, `speed_walk`= 3.2, `speed_run`= 2, `unit_class`= 2, `minlevel`= 88, `maxlevel`= 88, `exp`= 3,`faction`= 16, `DamageModifier`= 35, `BaseVariance`= 5, `mechanic_immune_mask`= 80297855 WHERE `entry` IN (43686, 49615, 49616, 49617); +-- Arion +UPDATE `creature_template` SET `difficulty_entry_1`= 49606, `difficulty_entry_2`= 49607, `difficulty_entry_3`= 49608, `ScriptName`= 'npc_arion' WHERE `entry`= 43688; +UPDATE `creature_template` SET `flags_extra`= 0, `movementId`= 187, `BaseAttackTime`= 1500, `speed_walk`= 3.2, `speed_run`= 2, `unit_class`= 2, `minlevel`= 88, `maxlevel`= 88, `exp`= 3,`faction`= 16, `DamageModifier`= 35, `BaseVariance`= 5, `mechanic_immune_mask`= 80297855 WHERE `entry` IN (43688, 49606, 49607, 49608); +-- Terrastra +UPDATE `creature_template` SET `difficulty_entry_1`= 49609, `difficulty_entry_2`= 49610, `difficulty_entry_3`= 49611, `ScriptName`= 'npc_terrastra' WHERE `entry`= 43689; +UPDATE `creature_template` SET `flags_extra`= 0, `movementId`= 187, `BaseAttackTime`= 1500, `speed_walk`= 3.2, `speed_run`= 2, `unit_class`= 2, `minlevel`= 88, `maxlevel`= 88, `exp`= 3,`faction`= 16, `DamageModifier`= 35, `BaseVariance`= 5, `mechanic_immune_mask`= 617299839 WHERE `entry` IN (43689, 49609, 49610, 49611); +-- Elementium Monstrosity +UPDATE `creature_template` SET `difficulty_entry_1`= 49619, `difficulty_entry_2`= 49620, `difficulty_entry_3`= 49621, `ScriptName`= 'npc_elementium_monstrosity' WHERE `entry`= 43735; +UPDATE `creature_template` SET `flags_extra`= 0, `movementId`= 187, `BaseAttackTime`= 1500, `speed_walk`= 3.2, `speed_run`= 2, `unit_class`= 2, `minlevel`= 88, `maxlevel`= 88, `exp`= 3,`faction`= 16, `DamageModifier`= 35, `BaseVariance`= 5, `mechanic_immune_mask`= 617299839 WHERE `entry` IN (43735, 49619, 49620, 49621); +-- Ascendant Council Target Stalker +UPDATE `creature_template` SET `flags_extra`= 128 WHERE `entry`= 44553; +-- Water Bomb +UPDATE `creature_template` SET `unit_flags`= 33554432, `flags_extra`= 128 WHERE `entry`= 44201; +-- Inferno Rush +UPDATE `creature_template` SET `unit_flags`= 33554432, `flags_extra`= 128 WHERE `entry`= 47501; +-- Violent Cyclone +UPDATE `creature_template` SET `unit_flags`= 33554432, `flags_extra`= 128, `ScriptName`= 'npc_ascendant_council_violent_cyclone' WHERE `entry`= 44747; +-- Gravity Well +UPDATE `creature_template` SET `unit_flags`= 33554432, `unit_flags2`= 2099200, `flags_extra`= 128, `ScriptName`= 'npc_ascendant_council_gravity_well' WHERE `entry`= 44824; +-- Eruption Target +UPDATE `creature_template` SET `unit_flags`= 33554432, `flags_extra`= 128, `ScriptName`= 'npc_ascendant_council_eruption_target' WHERE `entry`= 44845; +-- Ascendant Council Plume Stalker +UPDATE `creature_template` SET `ScriptName`= 'npc_ascendant_council_plume_stalker' WHERE `entry`= 45420; +-- Liquid Ice +UPDATE `creature_template` SET `unit_flags`= 33554432, `flags_extra`= 128 WHERE `entry`= 45452; +-- Gravity Crush +UPDATE `creature_template` SET `unit_flags`= 34079232, `flags_extra`= 128, `VehicleId`= 1110, `InhabitType`= 4, `ScriptName`= 'npc_ascendant_council_gravity_crush' WHERE `entry`= 45476; +-- Frozen Orb Spawner +UPDATE `creature_template` SET `unit_flags`= 33554688, `flags_extra`= 128 WHERE `entry`= 49517; +-- Frozen Orb +UPDATE `creature_template` SET `unit_flags`= 34080768, `speed_run`= 0.714, `ScriptName`= 'npc_ascendant_council_frozen_orb' WHERE `entry`= 49518; +-- Flame Strike +UPDATE `creature_template` SET `unit_flags`= 33554432, `flags_extra`= 128, `ScriptName`= 'npc_ascendant_council_flame_strike' WHERE `entry`= 49432; + +-- Spells +DELETE FROM `spell_script_names` WHERE `ScriptName` IN +('spell_feludius_water_bomb_targeting', +'spell_feludius_water_bomb', +'spell_feludius_glaciate', +'spell_feludius_fire_proc_check', +'spell_feludius_heart_of_ice', +'spell_feludius_frost_imbued', +'spell_feludius_frozen_orb_targeting', +'spell_ignacious_rising_flames', +'spell_ignacious_burning_blood', +'spell_ignacious_flame_imbued', +'spell_ignacious_inferno_rush', +'spell_ignacious_flame_strike', +'spell_arion_lashing_winds', +'spell_arion_thundershock', +'spell_arion_lightning_rod', +'spell_arion_chain_lightning_targeting', +'spell_arion_disperse', +'spell_arion_lightning_blast', +'spell_arion_static_overload', +'spell_arion_static_overload_triggered', +'spell_terrastra_gravity_well', +'spell_terrastra_harden_skin', +'spell_terrastra_quake', +'spell_terrastra_eruption', +'spell_terrastra_gravity_core', +'spell_terrastra_gravity_core_triggered', +'spell_elementium_monstrosity_lava_seed', +'spell_elementium_monstrosity_cryogenic_aura', +'spell_elementium_monstrosity_liquid_ice', +'spell_elementium_monstrosity_electric_instability', +'spell_elementium_monstrosity_gravity_crush'); + +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +-- Feludius +(82697, 'spell_feludius_water_bomb_targeting'), +(82699, 'spell_feludius_water_bomb'), +(82746, 'spell_feludius_glaciate'), +(92506, 'spell_feludius_glaciate'), +(92507, 'spell_feludius_glaciate'), +(92508, 'spell_feludius_glaciate'), +(82772, 'spell_feludius_fire_proc_check'), +(92503, 'spell_feludius_fire_proc_check'), +(92504, 'spell_feludius_fire_proc_check'), +(92505, 'spell_feludius_fire_proc_check'), +(82762, 'spell_feludius_fire_proc_check'), +(82665, 'spell_feludius_heart_of_ice'), +(82666, 'spell_feludius_frost_imbued'), +(95883, 'spell_feludius_frozen_orb_targeting'), +-- Ignacious +(82636, 'spell_ignacious_rising_flames'), +(82660, 'spell_ignacious_burning_blood'), +(82663, 'spell_ignacious_flame_imbued'), +(82856, 'spell_ignacious_inferno_rush'), +(92520, 'spell_ignacious_inferno_rush'), +(92521, 'spell_ignacious_inferno_rush'), +(92522, 'spell_ignacious_inferno_rush'), +(92080, 'spell_ignacious_flame_strike'), +-- Arion +(83498, 'spell_arion_lashing_winds'), +(92476, 'spell_arion_lashing_winds'), +(92477, 'spell_arion_lashing_winds'), +(92478, 'spell_arion_lashing_winds'), +(83067, 'spell_arion_thundershock'), +(92469, 'spell_arion_thundershock'), +(92470, 'spell_arion_thundershock'), +(92471, 'spell_arion_thundershock'), +(83099, 'spell_arion_lightning_rod'), +(83300, 'spell_arion_chain_lightning_targeting'), +(83087, 'spell_arion_disperse'), +(83070, 'spell_arion_lightning_blast'), +(92454, 'spell_arion_lightning_blast'), +(92455, 'spell_arion_lightning_blast'), +(92456, 'spell_arion_lightning_blast'), +(92067, 'spell_arion_static_overload'), +(92068, 'spell_arion_static_overload_triggered'), +(92466, 'spell_arion_static_overload_triggered'), +(92467, 'spell_arion_static_overload_triggered'), +(92468, 'spell_arion_static_overload_triggered'), +-- Terrastra +(83578, 'spell_terrastra_gravity_well'), +(83718, 'spell_terrastra_harden_skin'), +(92541, 'spell_terrastra_harden_skin'), +(92542, 'spell_terrastra_harden_skin'), +(92543, 'spell_terrastra_harden_skin'), +(83565, 'spell_terrastra_quake'), +(92544, 'spell_terrastra_quake'), +(92545, 'spell_terrastra_quake'), +(92546, 'spell_terrastra_quake'), +(83675, 'spell_terrastra_eruption'), +(92075, 'spell_terrastra_gravity_core'), +(92076, 'spell_terrastra_gravity_core_triggered'), +(92537, 'spell_terrastra_gravity_core_triggered'), +(92538, 'spell_terrastra_gravity_core_triggered'), +(92539, 'spell_terrastra_gravity_core_triggered'), +-- Elementium Monstrosity +(84913, 'spell_elementium_monstrosity_lava_seed'), +(84918, 'spell_elementium_monstrosity_cryogenic_aura'), +(84914, 'spell_elementium_monstrosity_liquid_ice'), +(84527, 'spell_elementium_monstrosity_electric_instability'), +(84948, 'spell_elementium_monstrosity_gravity_crush'), +(92486, 'spell_elementium_monstrosity_gravity_crush'), +(92487, 'spell_elementium_monstrosity_gravity_crush'), +(92488, 'spell_elementium_monstrosity_gravity_crush'); + +DELETE FROM `conditions` WHERE `SourceEntry` IN (82699, 83475, 83087, 82344, 84913, 84915, 92497, 92498, 92499, 92214) AND `SourceTypeOrReferenceId`= 13; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ScriptName`, `Comment`) VALUES +(13, 1, 82699, 0, 0, 31, 0, 3, 44201, 0, 0, 0, '', 'Water Bomb - Target Water Bomb'), +(13, 1, 83475, 0, 0, 31, 0, 3, 44553, 0, 0, 0, '', 'Cyclone Aggro - Target Ascendant Council Target Stalker'), +(13, 1, 83087, 0, 0, 31, 0, 3, 44553, 0, 0, 0, '', 'Disperse - Target Ascendant Council Target Stalker'), +(13, 1, 82344, 0, 0, 31, 0, 3, 43687, 0, 0, 0, '', 'Merge Health - Target Feludius'), +(13, 1, 82344, 0, 1, 31, 0, 3, 43686, 0, 0, 0, '', 'Merge Health - Target Ignacious'), +(13, 1, 82344, 0, 2, 31, 0, 3, 43688, 0, 0, 0, '', 'Merge Health - Target Arion'), +(13, 1, 82344, 0, 3, 31, 0, 3, 43689, 0, 0, 0, '', 'Merge Health - Target Terrastra'), +(13, 1, 84913, 0, 0, 31, 0, 3, 45420, 0, 0, 0, '', 'Lava Seed - Target Ascendant Council Plume Stalker'), +(13, 2, 84915, 0, 0, 31, 0, 3, 43735, 0, 0, 0, '', 'Liquid Ice - Target Elementium Monstrosity'), +(13, 2, 92497, 0, 0, 31, 0, 3, 43735, 0, 0, 0, '', 'Liquid Ice - Target Elementium Monstrosity'), +(13, 2, 92498, 0, 0, 31, 0, 3, 43735, 0, 0, 0, '', 'Liquid Ice - Target Elementium Monstrosity'), +(13, 2, 92499, 0, 0, 31, 0, 3, 43735, 0, 0, 0, '', 'Liquid Ice - Target Elementium Monstrosity'), +(13, 2, 92214, 0, 0, 31, 0, 3, 49518, 0, 0, 0, '', 'Flame Strike - Target Frozen Orb'); + +-- Texts +DELETE FROM `creature_text` WHERE `CreatureId` IN (43687, 43686, 43688, 43689, 43691, 43735, 49518); +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `comment`) VALUES +-- Feludius +(43687, 0, 0, 'You dare invade our lord''s sanctum?', 14, 0, 100, 0, 0, 20162, 47725, 'Feludius - Engage'), +(43687, 1, 0, 'I will freeze the blood in your veins!', 14, 0, 100, 0, 0, 20164, 47671, 'Feludius - Say Glaciate'), +(43687, 2, 0, '%s begins to cast Glaciate!', 41, 0, 100, 0, 0, 0, 47672, 'Feludius - Announce Glaciate'), +(43687, 3, 0, 'Perish!', 14, 0, 100, 0, 0, 20163, 47717, 'Feludius - Slay'), +(43687, 4, 0, 'But now, witness true power...', 14, 0, 100, 0, 0, 20165, 44322, 'Feludius - Merge'), +-- Ignacious +(43686, 0, 0, 'You will die for your insolence!', 14, 0, 100, 0, 0, 20285, 47724, 'Ignacious - Engage'), +(43686, 1, 0, 'BURN!', 14, 0, 100, 0, 0, 20287, 47715, 'Ignacious - Say Aegis of Flame'), +(43686, 2, 0, '%s begins to cast Rising Flames!', 41, 0, 100, 0, 0, 0, 49844, 'Ignacious - Announce Rising Flames'), +(43686, 3, 0, 'More fuel for the fire!', 14, 0, 100, 0, 0, 20286, 47716, 'Ignacious - Slay'), +(43686, 4, 0, '...the fury of the elements!', 14, 0, 100, 0, 0, 20288, 44323, 'Ignacious - Merge'), +-- Arion +(43688, 0, 0, 'Enough of this foolishness!', 14, 0, 100, 0, 0, 20237, 44307, 'Arion - Engage'), +(43688, 1, 0, 'Wind, hear my call!', 14, 0, 100, 0, 0, 20239, 47718, 'Arion - Call Winds'), +(43688, 2, 0, '%s begins to cast Thundershock!', 41, 0, 100, 0, 0, 0, 47719, 'Arion - Announce Thundershock'), +(43688, 3, 0, 'Merely a whisper in the wind....', 14, 0, 100, 0, 0, 20238, 47720, 'Arion - Slay'), +(43688, 4, 0, 'An impressive display...', 14, 0, 100, 0, 0, 20240, 44320, 'Arion - Merge'), +-- Terrastra +(43689, 0, 0, 'We will handle them!', 14, 0, 100, 0, 0, 21843, 44308, 'Terrastra - Engage'), +(43689, 1, 0, 'The earth will devour you!', 14, 0, 100, 0, 0, 21844, 47722, 'Terrastra - Say Quake'), +(43689, 2, 0, '%s begins to cast Quake!', 41, 0, 100, 0, 0, 21844, 47723, 'Terrastra - Say Anounce Quake'), +(43689, 3, 0, 'The soil welcomes your bones!', 14, 0, 100, 0, 0, 21842, 47721, 'Terrastra - Slay'), +(43689, 4, 0, '...to have made it this far.', 14, 0, 100, 0, 0, 21845, 44321, 'Terrastra - Merge'), +-- Ascendant Council Controller +(43691, 0, 0, 'The ground beneath you rumbles ominously....', 41, 0, 100, 0, 0, 0, 47728, 'Ascendant Council Controller - Warn Quake'), +(43691, 1, 0, 'The surrounding air crackles with energy....', 41, 0, 100, 0, 0, 0, 47727, 'Ascendant Council Controller - Warn Thunderstorm'), +-- Elementium Monstrosity +(43735, 0, 0, 'BEHOLD YOUR DOOM!', 14, 0, 100, 0, 0, 20396, 44336, 'Elementium Monstrosity - Merged'), +(43735, 1, 0, 'FEEL THE POWER!', 14, 0, 100, 0, 0, 20400, 47726, 'Elementium Monstrosity - Lava Seed'), +(43735, 2, 0, 'Impossible....', 14, 0, 100, 0, 0, 20399, 44339, 'Elementium Monstrosity - Death'), +(43735, 3, 0, 'Eradicate....', 14, 0, 100, 0, 0, 20398, 44337, 'Elementium Monstrosity - Slay 1'), +(43735, 3, 1, 'Annihilate....', 14, 0, 100, 0, 0, 20397, 44338, 'Elementium Monstrosity - Slay 2'), +-- Frozen Orb +(49518, 0, 0, '%s begins to pursue $n!', 41, 0, 100, 0, 0, 0, 49578, 'Frozen Orb - Pursue Player'); + +-- Addons +-- Remove auras from bosses +UPDATE `creature_template_addon` SET `auras`= '' WHERE `entry` IN (43686, 43689, 43688); +UPDATE `creature_addon` SET `auras`= '' WHERE `guid` IN (254144, 254133, 254134, 254148); + +DELETE FROM `creature_template_addon` WHERE `entry` IN (44747, 45452, 49517, 49518); +INSERT INTO `creature_template_addon` (`entry`, `auras`) VALUES +(44747, '83472'), +(45452, '84914'), +(49517, '92269'), +(49518, '92302'); + +-- Serverside spells +-- Difficulty spell entries +DELETE FROM `spell_dbc` WHERE `Id` IN (82675, 82697, 88578, 84916, 84947, 92080, 92081); +INSERT INTO `spell_dbc`(`Id`, `Attributes`, `AttributesEx`, `AttributesEx2`, `AttributesEx3`, `AttributesEx4`, `AttributesEx5`, `AttributesEx6`, `AttributesEx7`, `AttributesEx8`, `AttributesEx9`, `AttributesEx10`, `CastingTimeIndex`, `DurationIndex`, `RangeIndex`, `SchoolMask`, `SpellAuraOptionsId`, `SpellCastingRequirementsId`, `SpellCategoriesId`, `SpellClassOptionsId`, `SpellEquippedItemsId`, `SpellInterruptsId`, `SpellLevelsId`, `SpellTargetRestrictionsId`, `Comment`) VALUES +(82675, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, '(Serverside/Non-DB2) Water Bomb'), +(82697, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '(Serverside/Non-DB2) Water Bomb'), +(88578, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, '(Serverside/Non-DB2) Inferno Rush'), +(84916, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '(Serverside/Non-DB2) Liquid Ice'), +(84947, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 589, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '(Serverside/Non-DB2) Gravity Crush'), +(92080, 0, 0, 4, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, '(Serverside/Non-DB2) Flame Strike'), +(92081, 0, 0, 4, 256, 0, 0, 0, 0, 0, 0, 0, 0, 21, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, '(Serverside/Non-DB2) Flame Strike'); + +DELETE FROM `spelleffect_dbc` WHERE `Id` IN (160084, 160085, 160086, 160087, 160088, 160089, 160090); +INSERT INTO `spelleffect_dbc` (`Id`, `Effect`, `EffectBasePoints`, `EffectMiscValue`, `EffectMiscValueB`, `EffectRadiusIndex`, `EffectRadiusIndexMax`, `EffectImplicitTargetA`, `EffectImplicitTargetB`, `EffectSpellId`, `EffectIndex`, `Comment`) VALUES +(160084, 28, 1, 44201, 64, 8, 8, 53, 91, 82675, 0, 'Water Bomb - Summon'), +(160085, 3, 82675, 0, 0 , 12, 12, 22, 15, 82697, 0, 'Water Bomb - Dummy'), +(160086, 28, 1, 47501, 64, 0, 0, 87, 87, 88578, 0, 'Inferno Rush - Summon'), +(160087, 28, 1, 45452, 64, 0, 0, 18, 0, 84916, 0, 'Liquid Ice - Summon'), +(160088, 28, 1, 45476, 64, 0, 0, 18, 0, 84947, 0, 'Gravity Crush - Summon'), +(160089, 3, 92081, 0, 0 , 30, 30, 22, 15, 92080, 0, 'Flame Strike - Dummy'), +(160090, 28, 1, 49432, 64, 0, 0, 53, 0, 92081, 0, 'Flame Strike - Summon'); + +DELETE FROM `spell_target_position` WHERE `ID` IN (82329, 82330, 82331, 82332); +INSERT INTO `spell_target_position` (`ID`, `EffectIndex`, `MapID`, `PositionX`, `PositionY`, `PositionZ`) VALUES +(82329, 0, 671, -1029.45, -603.773, 831.901), +(82330, 0, 671, -987.599, -561.885, 831.901), +(82331, 0, 671, -1029.41, -561.885, 831.901), +(82332, 0, 671, -987.599, -603.773, 831.901); + +-- Achievement +DELETE FROM `achievement_criteria_data` WHERE `criteria_id`= 15471; +INSERT INTO `achievement_criteria_data` (`criteria_id`, `type`, `value1`, `value2`, `ScriptName`) VALUES +(15471, 11, 0, 0, 'achievement_elementary'); + +-- Delete Elementium Monstrosity +DELETE FROM `creature` WHERE `guid`= 254260; +DELETE FROM `creature_addon` WHERE `guid`= 254260; + +-- Loot +DELETE FROM `creature_loot_template` WHERE `entry` IN (43735, 49619, 49620, 49621); +UPDATE `creature_template` SET `lootid`= `entry` WHERE `entry` IN (43735, 49619, 49620, 49621); +DELETE FROM `reference_loot_template` WHERE `Entry` IN (437350, 437351); +INSERT INTO `reference_loot_template` (`Entry`, `Item`, `Chance`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`) VALUES +-- Normal Mode +(437350, 59513, 0, 1, 1, 1, 1), -- Scepter of Ice +(437350, 59504, 0, 1, 1, 1, 1), -- Arion's Crown +(437350, 59509, 0, 1, 1, 1, 1), -- Glaciated Helm +(437350, 59510, 0, 1, 1, 1, 1), -- Feludius' Mantle +(437350, 59507, 0, 1, 1, 1, 1), -- Glittering Epidermis +(437350, 59505, 0, 1, 1, 1, 1), -- Gravitational Pull +(437350, 59511, 0, 1, 1, 1, 1), -- Hydrolance Gloves +(437350, 59502, 0, 1, 1, 1, 1), -- Dispersing Belt +(437350, 59503, 0, 1, 1, 1, 1), -- Terrastra's Legguards +(437350, 59508, 0, 1, 1, 1, 1), -- Treads of Liquid Ice +(437350, 59506, 0, 1, 1, 1, 1), -- Crushing Weight +(437350, 59514, 0, 1, 1, 1, 1), -- Heart of Ignacious +-- Heroic Mode +(437351, 65111, 0, 1, 1, 1, 1), -- Scepter of Ice +(437351, 65120, 0, 1, 1, 1, 1), -- Arion's Crown +(437351, 65115, 0, 1, 1, 1, 1), -- Glaciated Helm +(437351, 65114, 0, 1, 1, 1, 1), -- Feludius' Mantle +(437351, 65117, 0, 1, 1, 1, 1), -- Glittering Epidermis +(437351, 65119, 0, 1, 1, 1, 1), -- Gravitational Pull +(437351, 65113, 0, 1, 1, 1, 1), -- Hydrolance Gloves +(437351, 65122, 0, 1, 1, 1, 1), -- Dispersing Belt +(437351, 65121, 0, 1, 1, 1, 1), -- Terrastra's Legguards +(437351, 65116, 0, 1, 1, 1, 1), -- Treads of Liquid Ice +(437351, 65118, 0, 1, 1, 1, 1), -- Crushing Weight +(437351, 65110, 0, 1, 1, 1, 1); -- Heart of Ignacious + +INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Chance`, `LootMode`, `Reference`, `MaxCount`) VALUES +-- 10 Player Normal +(43735, 437350, 100, 1, 437350, 2), +-- 25 Player Normal +(49619, 437350, 100, 1, 437350, 6), +-- 10 Player Heroic +(49620, 437351, 100, 1, 437351, 2), +-- 25 Player Heroic +(49621, 437351, 100, 1, 437351, 6); + +-- Gold Loot +-- 10 Player +UPDATE `creature_template` SET `mingold`= 2200000, `maxgold`= 2400000 WHERE `entry` IN (43735, 49620); +-- 25 Player +UPDATE `creature_template` SET `mingold`= 4900000, `maxgold`= 5100000 WHERE `entry` IN (49619, 49621); + +-- Currency Loot +DELETE FROM `creature_onkill_reward` WHERE `creature_id` IN (43735, 49619, 49620, 49621); +INSERT INTO `creature_onkill_reward` (`creature_id`, `CurrencyId1`, `CurrencyCount1`) VALUES +(43735, 396, 11500), +(49619, 396, 13500), +(49620, 396, 11500), +(49621, 396, 13500); diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index da4d1a7c986..4faa328a8c2 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -4271,6 +4271,19 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->MaxAffectedTargets = 1; }); + // Ascendant Council + // Disperse + ApplySpellFix({ 83087 }, [](SpellInfo* spellInfo) + { + spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); + }); + + // Frozen Orb + ApplySpellFix({ 92267 }, [](SpellInfo* spellInfo) + { + spellInfo->AttributesEx2 |= SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS; + }); + // ENDOF BASTION OF TWILIGHT // diff --git a/src/server/scripts/EasternKingdoms/BastionOfTwilight/bastion_of_twilight.h b/src/server/scripts/EasternKingdoms/BastionOfTwilight/bastion_of_twilight.h index d796c92202c..e3a1ad0dffa 100644 --- a/src/server/scripts/EasternKingdoms/BastionOfTwilight/bastion_of_twilight.h +++ b/src/server/scripts/EasternKingdoms/BastionOfTwilight/bastion_of_twilight.h @@ -42,13 +42,14 @@ enum BoTDataTypes DATA_TERRASTRA = 10, DATA_ARION = 11, DATA_ELEMENTIUM_MONSTROSITY = 12, + DATA_ASCENDANT_COUNCIL_CONTROLLER = 13, // GameObject Types - DATA_WHELP_CAGE = 13, + DATA_WHELP_CAGE = 14, // Areatriggers - DATA_AT_HALFUS_INTRO = 14, - DATA_AT_THERALION_AND_VALIONA_INTRO = 15, + DATA_AT_HALFUS_INTRO = 15, + DATA_AT_THERALION_AND_VALIONA_INTRO = 16, // Encounter Related /*Halfus Wyrmbreaker*/ @@ -114,6 +115,12 @@ enum BoTCreatures NPC_TWILIGHT_SENTRY = 50008, NPC_TWILIGHT_RIFT = 50014, + /*Ascendant Council*/ + NPC_ASCENDANT_COUNCIL_CONTROLLER = 43691, + NPC_WATER_BOMB = 44201, + NPC_INFERNO_RUSH = 47501, + NPC_FROZEN_ORB = 49518, + // Generic Creatures NPC_INVISIBLE_STALKER = 42098 }; diff --git a/src/server/scripts/EasternKingdoms/BastionOfTwilight/boss_ascendant_council.cpp b/src/server/scripts/EasternKingdoms/BastionOfTwilight/boss_ascendant_council.cpp new file mode 100644 index 00000000000..fabab5571d6 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BastionOfTwilight/boss_ascendant_council.cpp @@ -0,0 +1,2798 @@ +/* +* Copyright (C) 2008-2018 TrinityCore +* +* 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 . +*/ + +#include "GridNotifiers.h" +#include "ObjectMgr.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" +#include "SpellMgr.h" +#include "Player.h" +#include "DataStores\DBCStores.h" +#include "bastion_of_twilight.h" + +enum Texts +{ + // Ascendant Council + SAY_ENGAGE = 0, + SAY_ABILITY = 1, + SAY_ANNOUNCE_ABILITY = 2, + SAY_SLAY = 3, + SAY_FUSION = 4, + + // Elementium Monstrosity + SAY_SUMMONED = 0, + SAY_LAVA_SEED = 1, + SAY_DEATH = 2, + + // Ascendant Council Controller + SAY_ANNOUNCE_QUAKE_WARNING = 0, + SAY_ANNOUNCE_THUNDERSHOCK_WARNING = 1, + + // Frozen Orb + SAY_ANNOUNCE_PURSUE_PLAYER = 0 +}; + +enum Spells +{ + // Ascendant Council + SPELL_CLEAR_ALL_DEBUFFS = 34098, + + // Feludius + SPELL_GLACIATE = 82746, + SPELL_FROZEN = 82772, + SPELL_WATER_BOMB_AOE = 82697, // Serverside spell + SPELL_WATER_BOMB_SUMMON = 82675, // Serverside spell + SPELL_WATER_BOMB = 82699, + SPELL_WATERLOGGED = 82762, + SPELL_HYDRO_LANCE = 82752, + SPELL_HEART_OF_ICE = 82665, + SPELL_FROST_IMBUED = 82666, + SPELL_FROST_EXPLOSION_DND = 94739, + SPELL_TELEPORT_RIGHT_BALCONY = 81799, + SPELL_TELEPORT_WATER = 82332, + SPELL_FROZEN_ORB = 92267, + + // Ignacious + SPELL_AEGIS_OF_FLAME = 82631, + SPELL_FLAME_IMBUED = 82663, + SPELL_RISING_FLAMES = 82636, + SPELL_RISING_FLAMES_BUFF = 82639, + SPELL_FLAME_TORRENT = 82777, + SPELL_BURNING_BLOOD = 82660, + SPELL_INFERNO_LEAP = 82856, + SPELL_INFERNO_RUSH = 82859, + SPELL_INFERNO_RUSH_SUMMON = 88578, // Serverside spell + SPELL_FIRE_EXPLOSION_DND = 94738, + SPELL_TELEPORT_LEFT_BALCONY = 81800, + SPELL_TELEPORT_FIRE = 82331, + SPELL_FLAME_STRIKE_TARGETING = 92080, // Serverside spell + SPELL_FLAME_STRIKE = 92212, + + // Arion + SPELL_TELEPORT_LEFT_FLOOR = 81796, + SPELL_CALL_WINDS = 83491, + SPELL_THUNDERSHOCK = 83067, + SPELL_LIGHTNING_ROD = 83099, + SPELL_CHAIN_LIGHTNING_TARGETING = 83300, + SPELL_DISPERSE = 83087, + SPELL_TELEPORT_AIR = 82330, + SPELL_STATIC_OVERLOAD = 92067, + + // Terrastra + SPELL_TELEPORT_RIGHT_FLOOR = 81798, + SPELL_GROUNDED = 83581, + SPELL_GRAVITY_WELL = 83572, + SPELL_HARDEN_SKIN = 83718, + SPELL_SHATTER = 83760, + SPELL_QUAKE = 83565, + SPELL_ERUPTION_DUMMY = 83675, + SPELL_ERUPTION_SUMMON = 83661, + SPELL_ERUPTION_DAMAGE = 83692, + SPELL_ELEMENTAL_STASIS = 82285, + SPELL_TELEPORT_EARTH = 82329, + + // Elementium Monstrosity + SPELL_TWILIGHT_EXPLOSION_DND = 95789, + SPELL_MERGE_HEALTH = 82344, + SPELL_ELECTRIC_INSTABILITY = 84526, + SPELL_ELECTRIC_INSTABILITY_DAMAGE = 84529, + SPELL_CRYOGENIC_AURA = 84918, + SPELL_LAVA_SEED = 84913, + SPELL_LIQUID_ICE_SUMMON = 84916, // Serverside spell + SPELL_LIQUID_ICE_MOD_SCALE = 84917, + SPELL_GRAVITY_CRUSH = 84948, + SPELL_GRAVITY_CRUSH_SUMMON = 84947, // Serverside spell + SPELL_GRAVITY_CORE = 92075, + + // Water Bomb + SPELL_WATER_BOMB_TRIGGERED = 82700, + + // Inferno Rush + SPELL_INFERNO_RUSH_AURA = 88579, + SPELL_INFERNO_RUSH_TRIGGERED = 82860, + + // Violent Cyclone + SPELL_CYCLONE_AGGRO = 83475, + SPELL_SWIRLING_WINDS = 83500, + + // Gravity Well + SPELL_GRAVITY_WELL_PRE_VISUAL = 95760, + SPELL_MAGNETIC_PULL_PERIODIC = 83579, + SPELL_MAGNETIC_PULL_SLOW = 83587, + SPELL_MAGNETIC_PULL_PULL = 83583, + + // Eruption + SPELL_ERUPTION_PRE_VISUAL = 83662, + + // Ascendant Council Plume Stalker + SPELL_LAVA_SEED_DUMMY = 84911, + SPELL_LAVA_PLUME = 84912, + + // Liquid Ice + SPELL_LIQUID_ICE_TRIGGERED = 84915, + + // Gravity Crush + SPELL_GRAVITY_CRUSH_RIDE_VEHICLE = 84952, + + // Frozen Orb + SPELL_FROZEN_ORB_TARGETING = 95883, + SPELL_FROZEN_ORB_INCREASE_SPEED = 99250, + SPELL_FROZEN_ORB_DUMMY = 92303, + SPELL_FROST_BEACON = 92307, + SPELL_GLACIATE_FROST_ORB = 92548, + + // Flame Strike + SPELL_FLAME_STRIKE_PRE_VISUAL = 92211, + SPELL_FLAME_STRIKE_PERIODIC = 92215 +}; + +#define SPELL_HYDRO_LANCE RAID_MODE(82752, 92509, 92510, 92511) +#define SPELL_AEGIS_OF_FLAME RAID_MODE(82631, 92512, 92513, 92514) +#define SPELL_LIGHTNING_BLAST RAID_MODE(83070, 92454, 92455, 92456) + +enum Events +{ + // Ascendant Council + EVENT_TALK_ENGAGE = 1, + EVENT_EXPLOSION_DND, + EVENT_SWITCH_POSITIONS, + EVENT_ATTACK_PLAYERS, + EVENT_TELEPORT_PREPARE_FUSION, + EVENT_FACE_CONTROLLER, + EVENT_MOVE_TO_MIDDLE, + + // Feludius + EVENT_GLACIATE, + EVENT_HEART_OF_ICE, + EVENT_WATER_BOMB, + EVENT_HYDRO_LANCE, + EVENT_FROZEN_ORB, + + // Ignacious + EVENT_AEGIS_OF_FLAME, + EVENT_RISING_FLAMES, + EVENT_FLAME_TORRENT, + EVENT_BURNING_BLOOD, + EVENT_INFERNO_LEAP, + EVENT_IGNITE_INFERNO_RUSH, + EVENT_FLAME_STRIKE, + + // Arion + EVENT_CALL_WINDS, + EVENT_THUNDERSHOCK, + EVENT_THUNDERSHOCK_PRE_WARNING, + EVENT_LIGHTNING_ROD, + EVENT_CHAIN_LIGHTNING, + EVENT_DISPERSE, + EVENT_LIGHTNING_BLAST, + EVENT_STATIC_OVERLOAD, + + // Terrastra + EVENT_GRAVITY_WELL, + EVENT_HARDEN_SKIN, + EVENT_QUAKE, + EVENT_QUAKE_PRE_WARNING, + EVENT_ERUPTION, + EVENT_GRAVITY_CORE, + + // Elementium Monstrosity + EVENT_APPLY_PERIODIC_EFFECTS, + EVENT_LAVA_SEED, + EVENT_GRAVITY_CRUSH, + + // Ascendant Council Controller + EVENT_RESET_BOSS_STATE, + EVENT_SUMMON_ELEMENTIUM_MONSTROSITY, + + // Violent Cyclone + EVENT_CYCLONE_AGGRO, + EVENT_MOVE_CYCLONE, + + // Gravity Well + EVENT_MAGNETIC_PULL, + + // Eruption Target + EVENT_ERUPTION_DAMAGE, + + // Ascendant Council Plume Stalker + EVENT_LAVA_PLUME, + EVENT_CLEAR_LAVA_SEED_DUMMY_AURA, + EVENT_MOVE_PLUME, + + // Gravity Crush + EVENT_MOVE_UP, + + // Frozen Orb + EVENT_PURSUE_TARGET, + EVENT_INCREASE_SPEED +}; + +enum Phases +{ + // Ascendant Council Controller + PHASE_FELUDIUS_IGNACIOUS = 0, + PHASE_ARION_TERRASTRA = 1, + PHASE_ELEMENTIUM_MONSTROSITY = 2, + + PHASE_INTRO = 0, + PHASE_COMBAT = 1 +}; + +enum Actions +{ + // Ascendant Council Controller + ACTION_START_ENCOUNTER = 1, + ACTION_STOP_ENCOUNTER, + ACTION_SWITCH_COUNCILLORS, + ACTION_UNITE_COUNCILLORS, + ACTION_FINISH_ENCOUNTER, + + // Ascendant Council + ACTION_CHANGE_PLACES, + ACTION_TELEPORT_DOWN, + ACTION_PREPARE_FUSION, + ACTION_SCHEDULE_HEROIC_ABILITY, + + // Ignacious + ACTION_CAST_INFERNO_RUSH, + + // Arion + ACTION_CAST_LIGHTNING_BLAST, + + // Elementium Monstrosity + ACTION_FAIL_ACHIEVEMENT, +}; + +enum MovePoints +{ + POINT_NONE = 0 +}; + +enum AchievementData +{ + DATA_ELEMENTARY = 0 +}; + +enum SummonProperties +{ + PROPERTY_DEFAULT = 64 +}; + +Position const arionMiddlePosition = { -1007.961f, -582.0203f, 831.9003f }; +Position const terrastraMiddlePosition = { -1009.37f, -583.4302f, 831.901f }; +Position const feludiusMiddlePosition = { -1007.965f, -583.4254f, 831.901f }; +Position const ingaciousMiddlePosition = { -1009.373f, -582.0148f, 831.9003f }; + +class boss_ascendant_council_controller : public CreatureScript +{ + public: + boss_ascendant_council_controller() : CreatureScript("boss_ascendant_council_controller") { } + + struct boss_ascendant_council_controllerAI : public BossAI + { + boss_ascendant_council_controllerAI(Creature* creature) : BossAI(creature, DATA_ASCENDANT_COUNCIL) { } + + void Reset() override + { + if (instance->GetBossState(DATA_ASCENDANT_COUNCIL) != DONE) + instance->SetData(DATA_ASCENDANT_COUNCIL, NOT_STARTED); + + events.SetPhase(PHASE_FELUDIUS_IGNACIOUS); + } + + void DoAction(int32 action) override + { + switch (action) + { + case ACTION_START_ENCOUNTER: + instance->SetBossState(DATA_ASCENDANT_COUNCIL, IN_PROGRESS); + + if (Creature* feludius = instance->GetCreature(DATA_FELUDIUS)) + instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, feludius, 3); + + if (Creature* ignacious = instance->GetCreature(DATA_IGNACIOUS)) + instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, ignacious, 4); + + if (IsHeroic()) + { + if (Creature* arion = instance->GetCreature(DATA_ARION)) + arion->AI()->DoAction(ACTION_SCHEDULE_HEROIC_ABILITY); + + if (Creature* terrastra = instance->GetCreature(DATA_TERRASTRA)) + terrastra->AI()->DoAction(ACTION_SCHEDULE_HEROIC_ABILITY); + } + break; + case ACTION_STOP_ENCOUNTER: + if (Creature* feludius = instance->GetCreature(DATA_FELUDIUS)) + { + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, feludius); + feludius->AI()->EnterEvadeMode(); + } + + if (Creature* ignacious = instance->GetCreature(DATA_IGNACIOUS)) + { + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, ignacious); + ignacious->AI()->EnterEvadeMode(); + } + + if (Creature* arion = instance->GetCreature(DATA_ARION)) + { + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, arion); + arion->AI()->EnterEvadeMode(); + } + + if (Creature* terrastra = instance->GetCreature(DATA_TERRASTRA)) + { + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, terrastra); + terrastra->AI()->EnterEvadeMode(); + } + + if (Creature* elementiumMonstrosity = instance->GetCreature(DATA_ELEMENTIUM_MONSTROSITY)) + { + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, elementiumMonstrosity); + elementiumMonstrosity->DespawnOrUnsummon(); + } + + RemoveAurasFromPlayers(); + instance->SetBossState(DATA_ASCENDANT_COUNCIL, FAIL); + events.SetPhase(PHASE_FELUDIUS_IGNACIOUS); + events.ScheduleEvent(EVENT_RESET_BOSS_STATE, Seconds(30)); + break; + case ACTION_SWITCH_COUNCILLORS: + if (!events.IsInPhase(PHASE_ARION_TERRASTRA)) + { + if (Creature* feludius = instance->GetCreature(DATA_FELUDIUS)) + { + feludius->AI()->DoAction(ACTION_CHANGE_PLACES); + if (IsHeroic()) + feludius->AI()->DoAction(ACTION_SCHEDULE_HEROIC_ABILITY); + } + + if (Creature* ignacious = instance->GetCreature(DATA_IGNACIOUS)) + { + ignacious->AI()->DoAction(ACTION_CHANGE_PLACES); + if (IsHeroic()) + ignacious->AI()->DoAction(ACTION_SCHEDULE_HEROIC_ABILITY); + } + + if (Creature* arion = instance->GetCreature(DATA_ARION)) + arion->AI()->DoAction(ACTION_CHANGE_PLACES); + + if (Creature* terrastra = instance->GetCreature(DATA_TERRASTRA)) + terrastra->AI()->DoAction(ACTION_CHANGE_PLACES); + + events.SetPhase(PHASE_ARION_TERRASTRA); + } + break; + case ACTION_UNITE_COUNCILLORS: + if (!events.IsInPhase(PHASE_ELEMENTIUM_MONSTROSITY)) + { + if (Creature* feludius = instance->GetCreature(DATA_FELUDIUS)) + feludius->AI()->DoAction(ACTION_PREPARE_FUSION); + + if (Creature* ignacious = instance->GetCreature(DATA_IGNACIOUS)) + ignacious->AI()->DoAction(ACTION_PREPARE_FUSION); + + if (Creature* arion = instance->GetCreature(DATA_ARION)) + arion->AI()->DoAction(ACTION_PREPARE_FUSION); + + if (Creature* terrastra = instance->GetCreature(DATA_TERRASTRA)) + terrastra->AI()->DoAction(ACTION_PREPARE_FUSION); + + events.ScheduleEvent(EVENT_SUMMON_ELEMENTIUM_MONSTROSITY, Seconds(14) + Milliseconds(500)); + events.SetPhase(PHASE_ELEMENTIUM_MONSTROSITY); + } + case ACTION_FINISH_ENCOUNTER: + if (Creature* elementiumMonstrosity = instance->GetCreature(DATA_ELEMENTIUM_MONSTROSITY)) + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, elementiumMonstrosity); + + RemoveAurasFromPlayers(); + instance->SetBossState(DATA_ASCENDANT_COUNCIL, DONE); + break; + default: + break; + } + } + + void UpdateAI(uint32 diff) override + { + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_RESET_BOSS_STATE: + instance->SetBossState(DATA_ASCENDANT_COUNCIL, NOT_STARTED); + break; + case EVENT_SUMMON_ELEMENTIUM_MONSTROSITY: + if (Creature* feludius = instance->GetCreature(DATA_FELUDIUS)) + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, feludius); + + if (Creature* ignacious = instance->GetCreature(DATA_IGNACIOUS)) + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, ignacious); + + if (Creature* arion = instance->GetCreature(DATA_ARION)) + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, arion); + + if (Creature* terrastra = instance->GetCreature(DATA_TERRASTRA)) + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, terrastra); + + if (SummonPropertiesEntry const* entry = sSummonPropertiesStore.LookupEntry(PROPERTY_DEFAULT)) + me->GetMap()->SummonCreature(BOSS_ELEMENTIUM_MONSTROSITY, me->GetPosition(), entry, 0, me); + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); + } + + private: + void RemoveAurasFromPlayers() + { + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_STATIC_OVERLOAD); + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_GRAVITY_CORE); + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_SWIRLING_WINDS); + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_GROUNDED); + } + + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetBastionOfTwilightAI(creature); + } +}; + +class npc_feludius : public CreatureScript +{ + public: + npc_feludius() : CreatureScript("npc_feludius") { } + + struct npc_feludiusAI : public ScriptedAI + { + npc_feludiusAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _summons(me) { } + + void Reset() override + { + me->MakeInterruptable(false); + _events.Reset(); + } + + void JustEngagedWith(Unit* who) override + { + if (Creature* controller = _instance->GetCreature(DATA_ASCENDANT_COUNCIL_CONTROLLER)) + controller->AI()->DoAction(ACTION_START_ENCOUNTER); + + if (Creature* ignacious = _instance->GetCreature(DATA_IGNACIOUS)) + ignacious->AI()->AttackStart(who); + + Talk(SAY_ENGAGE); + _events.ScheduleEvent(EVENT_GLACIATE, Seconds(31) + Milliseconds(500)); + _events.ScheduleEvent(EVENT_HEART_OF_ICE, Seconds(15) + Milliseconds(500)); + _events.ScheduleEvent(EVENT_WATER_BOMB, Seconds(15) + Milliseconds(500)); + _events.ScheduleEvent(EVENT_HYDRO_LANCE, Seconds(8) + Milliseconds(500)); + } + + void EnterEvadeMode(EvadeReason why) override + { + if (why == EVADE_REASON_NO_HOSTILES) + { + if (Creature* controller = _instance->GetCreature(DATA_ASCENDANT_COUNCIL_CONTROLLER)) + controller->AI()->DoAction(ACTION_STOP_ENCOUNTER); + } + else + { + _EnterEvadeMode(); + _summons.DespawnAll(); + me->DespawnOrUnsummon(0, Seconds(30)); + } + } + + void KilledUnit(Unit* who) override + { + if (who->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); + } + + void JustSummoned(Creature* summon) override + { + _summons.Summon(summon); + } + + void DamageTaken(Unit* attacker, uint32& damage) override + { + if (attacker->HasAura(SPELL_FLAME_IMBUED)) + damage *= 2; + + if (me->HealthBelowPctDamaged(25, damage)) + if (Creature* controller = _instance->GetCreature(DATA_ASCENDANT_COUNCIL_CONTROLLER)) + controller->AI()->DoAction(ACTION_SWITCH_COUNCILLORS); + + // Do not allow to kill any of the councillors + if (damage >= me->GetHealth()) + damage = me->GetHealth() - 1; + } + + void DoAction(int32 action) override + { + switch (action) + { + case ACTION_CHANGE_PLACES: + _events.Reset(); + me->AttackStop(); + me->SetReactState(REACT_PASSIVE); + me->CastStop(); + _events.ScheduleEvent(EVENT_EXPLOSION_DND, Seconds(2) + Milliseconds(700)); + break; + case ACTION_PREPARE_FUSION: + _events.Reset(); + me->SetWalk(true); + me->CastStop(); + _events.ScheduleEvent(EVENT_TELEPORT_PREPARE_FUSION, Seconds(1) + Milliseconds(200)); + break; + case ACTION_SCHEDULE_HEROIC_ABILITY: + _events.ScheduleEvent(EVENT_FROZEN_ORB, Seconds(23) + Milliseconds(900)); + break; + default: + break; + } + } + + void OnSuccessfulSpellCast(SpellInfo const* spell) override + { + if (spell->Id == SPELL_HYDRO_LANCE) + me->MakeInterruptable(false); + } + + void OnSpellCastInterrupt(SpellInfo const* spell) override + { + if (spell->Id == SPELL_HYDRO_LANCE) + me->MakeInterruptable(false); + } + + 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_GLACIATE: + Talk(SAY_ABILITY); + Talk(SAY_ANNOUNCE_ABILITY); + DoCastAOE(SPELL_GLACIATE); + _events.Repeat(Seconds(34)); + break; + case EVENT_HEART_OF_ICE: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, NonTankTargetSelector(me))) + DoCast(target, SPELL_HEART_OF_ICE); + _events.Repeat(Seconds(24)); + break; + case EVENT_WATER_BOMB: + DoCastAOE(SPELL_WATER_BOMB_AOE, true); + DoCastAOE(SPELL_WATER_BOMB); + _events.Repeat(Seconds(34)); + break; + case EVENT_HYDRO_LANCE: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, NonTankTargetSelector(me))) + { + me->MakeInterruptable(true); + DoCast(target, SPELL_HYDRO_LANCE); + } + _events.Repeat(Seconds(23)); + break; + case EVENT_EXPLOSION_DND: + DoCastSelf(SPELL_FROST_EXPLOSION_DND); + _events.ScheduleEvent(EVENT_SWITCH_POSITIONS, Seconds(1) + Milliseconds(200)); + break; + case EVENT_SWITCH_POSITIONS: + DoCastSelf(SPELL_TELEPORT_RIGHT_BALCONY); + DoCastSelf(SPELL_CLEAR_ALL_DEBUFFS); + break; + case EVENT_TELEPORT_PREPARE_FUSION: + DoCastSelf(SPELL_TELEPORT_WATER); + _events.ScheduleEvent(EVENT_FACE_CONTROLLER, Milliseconds(100)); + _events.ScheduleEvent(EVENT_MOVE_TO_MIDDLE, Seconds(6) + Milliseconds(300)); + break; + case EVENT_FACE_CONTROLLER: + if (Creature* controller = _instance->GetCreature(DATA_ASCENDANT_COUNCIL_CONTROLLER)) + me->SetFacingToObject(controller); + break; + case EVENT_MOVE_TO_MIDDLE: + Talk(SAY_FUSION); + me->GetMotionMaster()->MovePoint(POINT_NONE, feludiusMiddlePosition, true); + break; + case EVENT_FROZEN_ORB: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true, 0)) + DoCast(target, SPELL_FROZEN_ORB); + _events.Repeat(Seconds(20)); + break; + default: + break; + } + } + DoMeleeAttackIfReady(); + } + + private: + EventMap _events; + InstanceScript* _instance; + SummonList _summons; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetBastionOfTwilightAI(creature); + } +}; + +class npc_ignacious : public CreatureScript +{ + public: + npc_ignacious() : CreatureScript("npc_ignacious") { } + + struct npc_ignaciousAI : public ScriptedAI + { + npc_ignaciousAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _summons(me) + { + Initialize(); + } + + void Initialize() + { + _lastVictimGuid = ObjectGuid::Empty; + _infernoRushGUIDs.clear(); + } + + void Reset() override + { + Initialize(); + _events.Reset(); + me->MakeInterruptable(false); + } + + void JustEngagedWith(Unit* who) override + { + if (Creature* feludius = _instance->GetCreature(DATA_FELUDIUS)) + feludius->AI()->AttackStart(who); + + _events.ScheduleEvent(EVENT_TALK_ENGAGE, Seconds(5)); + _events.ScheduleEvent(EVENT_FLAME_TORRENT, Seconds(8) + Milliseconds(300)); + _events.ScheduleEvent(EVENT_AEGIS_OF_FLAME, Seconds(31) + Milliseconds(500)); + _events.ScheduleEvent(EVENT_BURNING_BLOOD, Seconds(30)); + _events.ScheduleEvent(EVENT_INFERNO_LEAP, Seconds(15) + Milliseconds(500)); + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + _EnterEvadeMode(); + _summons.DespawnAll(); + me->DespawnOrUnsummon(0, Seconds(30)); + } + + void KilledUnit(Unit* who) override + { + if (who->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); + } + + void JustSummoned(Creature* summon) override + { + _summons.Summon(summon); + + if (summon->GetEntry() == NPC_INFERNO_RUSH) + _infernoRushGUIDs.push_back(summon->GetGUID()); + } + + void DamageTaken(Unit* attacker, uint32& damage) override + { + if (attacker->HasAura(SPELL_FROST_IMBUED)) + damage *= 2; + + if (me->HealthBelowPctDamaged(25, damage)) + if (Creature* controller = _instance->GetCreature(DATA_ASCENDANT_COUNCIL_CONTROLLER)) + controller->AI()->DoAction(ACTION_SWITCH_COUNCILLORS); + + // Do not allow to kill any of the councillors + if (damage >= me->GetHealth()) + damage = me->GetHealth() - 1; + } + + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override + { + if (spell->Id == SPELL_AEGIS_OF_FLAME) + Talk(SAY_ABILITY); + } + + void OnSpellCastInterrupt(SpellInfo const* spell) override + { + if (spell->Id == SPELL_RISING_FLAMES) + me->MakeInterruptable(false); + } + + void DoAction(int32 action) override + { + switch (action) + { + case ACTION_CAST_INFERNO_RUSH: + { + Unit* target = me->GetVictim(); + + if (Unit* previousVictim = ObjectAccessor::GetUnit(*me, _lastVictimGuid)) + if (me->GetDistance(previousVictim) <= 100.0f) + target = previousVictim; + + if (target) + { + _infernoRushGUIDs.clear(); + float distance = me->GetDistance(target); + float angle = me->GetAngle(target); + Position pos = me->GetPosition(); + + if (distance > 6.0f) + { + for (uint32 i = 6; i < uint32(distance); i += 6) + { + float x = pos.GetPositionX() + cos(angle) * i; + float y = pos.GetPositionY() + sin(angle) * i; + float z = pos.GetPositionZ(); + float floor = me->GetMap()->GetHeight(me->GetPhaseShift(), x, y, z, true); + me->CastSpell(x, y, z, SPELL_INFERNO_RUSH_SUMMON, true); + } + } + + DoCast(target, SPELL_INFERNO_RUSH, true); + _events.ScheduleEvent(EVENT_IGNITE_INFERNO_RUSH, Seconds(2)); + } + break; + } + case ACTION_CHANGE_PLACES: + _events.Reset(); + me->AttackStop(); + me->SetReactState(REACT_PASSIVE); + me->CastStop(); + _events.ScheduleEvent(EVENT_EXPLOSION_DND, Seconds(2) + Milliseconds(700)); + break; + case ACTION_PREPARE_FUSION: + _events.Reset(); + me->SetWalk(true); + me->CastStop(); + _events.ScheduleEvent(EVENT_TELEPORT_PREPARE_FUSION, Seconds(1) + Milliseconds(200)); + break; + case ACTION_SCHEDULE_HEROIC_ABILITY: + _events.ScheduleEvent(EVENT_FLAME_STRIKE, Seconds(32)); + 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_TALK_ENGAGE: + Talk(SAY_ENGAGE); + break; + case EVENT_AEGIS_OF_FLAME: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, NonTankTargetSelector(me))) + { + me->MakeInterruptable(true); + DoCastSelf(SPELL_AEGIS_OF_FLAME); + _events.ScheduleEvent(EVENT_RISING_FLAMES, Seconds(4) + Milliseconds(400)); + } + _events.Repeat(Seconds(34)); + break; + case EVENT_RISING_FLAMES: + Talk(SAY_ANNOUNCE_ABILITY); + me->StopMoving(); + DoCastSelf(SPELL_RISING_FLAMES); + break; + case EVENT_FLAME_TORRENT: + DoCastSelf(SPELL_FLAME_TORRENT); + _events.Repeat(Seconds(12)); + break; + case EVENT_BURNING_BLOOD: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, NonTankTargetSelector(me))) + DoCast(target, SPELL_BURNING_BLOOD); + _events.Repeat(Seconds(24)); + break; + case EVENT_INFERNO_LEAP: + if (Unit* target = SelectTarget(SELECT_TARGET_FARTHEST, 0, 60.0f, true, 0)) + { + if (Unit* victim = me->GetVictim()) + _lastVictimGuid = victim->GetGUID(); + + DoCast(target, SPELL_INFERNO_LEAP); + } + _events.Repeat(Seconds(31) + Milliseconds(500)); + break; + case EVENT_IGNITE_INFERNO_RUSH: + for (ObjectGuid guid : _infernoRushGUIDs) + if (Creature* infernoRush = ObjectAccessor::GetCreature(*me, guid)) + infernoRush->CastSpell(infernoRush, SPELL_INFERNO_RUSH_AURA); + break; + case EVENT_EXPLOSION_DND: + DoCastSelf(SPELL_FIRE_EXPLOSION_DND); + _events.ScheduleEvent(EVENT_SWITCH_POSITIONS, Seconds(1) + Milliseconds(200)); + break; + case EVENT_SWITCH_POSITIONS: + DoCastSelf(SPELL_TELEPORT_LEFT_BALCONY); + DoCastSelf(SPELL_CLEAR_ALL_DEBUFFS); + break; + case EVENT_TELEPORT_PREPARE_FUSION: + DoCastSelf(SPELL_TELEPORT_FIRE); + _events.ScheduleEvent(EVENT_FACE_CONTROLLER, Milliseconds(100)); + _events.ScheduleEvent(EVENT_MOVE_TO_MIDDLE, Seconds(9) + Milliseconds(900)); + break; + case EVENT_FACE_CONTROLLER: + if (Creature* controller = _instance->GetCreature(DATA_ASCENDANT_COUNCIL_CONTROLLER)) + me->SetFacingToObject(controller); + break; + case EVENT_MOVE_TO_MIDDLE: + Talk(SAY_FUSION); + me->GetMotionMaster()->MovePoint(POINT_NONE, feludiusMiddlePosition, true); + break; + case EVENT_FLAME_STRIKE: + DoCastAOE(SPELL_FLAME_STRIKE_TARGETING, true); + _events.Repeat(Seconds(20)); + default: + break; + } + } + DoMeleeAttackIfReady(); + } + + private: + EventMap _events; + InstanceScript* _instance; + SummonList _summons; + ObjectGuid _lastVictimGuid; + GuidVector _infernoRushGUIDs; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetBastionOfTwilightAI(creature); + } +}; + +class npc_arion : public CreatureScript +{ + public: + npc_arion() : CreatureScript("npc_arion") { } + + struct npc_arionAI : public ScriptedAI + { + npc_arionAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _summons(me) { } + + void Reset() override + { + me->SetReactState(REACT_PASSIVE); + me->MakeInterruptable(false); + _events.Reset(); + _events.SetPhase(PHASE_FELUDIUS_IGNACIOUS); + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + _EnterEvadeMode(); + _summons.DespawnAll(); + me->DespawnOrUnsummon(0, Seconds(30)); + } + + void KilledUnit(Unit* who) override + { + if (who->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); + } + + void JustSummoned(Creature* summon) override + { + _summons.Summon(summon); + } + + void DamageTaken(Unit* attacker, uint32& damage) override + { + if (me->HealthBelowPctDamaged(25, damage)) + if (Creature* controller = _instance->GetCreature(DATA_ASCENDANT_COUNCIL_CONTROLLER)) + controller->AI()->DoAction(ACTION_UNITE_COUNCILLORS); + + // Do not allow to kill any of the councillors + if (damage >= me->GetHealth()) + damage = me->GetHealth() - 1; + } + + void DoAction(int32 action) override + { + switch (action) + { + case ACTION_CHANGE_PLACES: + _events.CancelEvent(EVENT_STATIC_OVERLOAD); + _events.ScheduleEvent(EVENT_TALK_ENGAGE, Milliseconds(1)); + _events.ScheduleEvent(EVENT_SWITCH_POSITIONS, Seconds(3)); + break; + case ACTION_CAST_LIGHTNING_BLAST: + _events.ScheduleEvent(EVENT_LIGHTNING_BLAST, Seconds(2)); + break; + case ACTION_PREPARE_FUSION: + _events.Reset(); + me->AttackStop(); + me->SetReactState(REACT_PASSIVE); + me->CastStop(); + me->SetWalk(true); + DoCastSelf(SPELL_CLEAR_ALL_DEBUFFS); + _events.ScheduleEvent(EVENT_TELEPORT_PREPARE_FUSION, Seconds(1) + Milliseconds(200)); + break; + case ACTION_SCHEDULE_HEROIC_ABILITY: + _events.ScheduleEvent(EVENT_STATIC_OVERLOAD, Seconds(19) + Milliseconds(700)); + break; + default: + break; + } + } + + void OnSuccessfulSpellCast(SpellInfo const* spell) override + { + if (spell->Id == SPELL_LIGHTNING_BLAST) + me->MakeInterruptable(false); + } + + void OnSpellCastInterrupt(SpellInfo const* spell) override + { + if (spell->Id == SPELL_LIGHTNING_BLAST) + me->MakeInterruptable(false); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim() && !_events.IsInPhase(PHASE_FELUDIUS_IGNACIOUS)) + return; + + _events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_TALK_ENGAGE: + Talk(SAY_ENGAGE); + break; + case EVENT_SWITCH_POSITIONS: + _instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 2); + DoCastSelf(SPELL_TELEPORT_LEFT_FLOOR); + _events.ScheduleEvent(EVENT_ATTACK_PLAYERS, Milliseconds(100)); + break; + case EVENT_ATTACK_PLAYERS: + _events.SetPhase(PHASE_ARION_TERRASTRA); + _events.ScheduleEvent(EVENT_CALL_WINDS, Seconds(9) + Milliseconds(300)); + _events.ScheduleEvent(EVENT_THUNDERSHOCK, Minutes(1) + Seconds(4)); + _events.ScheduleEvent(EVENT_THUNDERSHOCK_PRE_WARNING, Seconds(55) + Milliseconds(700)); + _events.ScheduleEvent(EVENT_LIGHTNING_ROD, Seconds(17) + Milliseconds(900)); + _events.ScheduleEvent(EVENT_DISPERSE, Seconds(20) + Milliseconds(500)); + me->SetReactState(REACT_AGGRESSIVE); + DoZoneInCombat(); + break; + case EVENT_CALL_WINDS: + Talk(SAY_ABILITY); + DoCastSelf(SPELL_CALL_WINDS); + _events.Repeat(Seconds(31) + Milliseconds(500)); + break; + case EVENT_THUNDERSHOCK: + Talk(SAY_ANNOUNCE_ABILITY); + DoCastAOE(SPELL_THUNDERSHOCK); + _events.Repeat(Minutes(1) + Seconds(8)); + _events.ScheduleEvent(EVENT_THUNDERSHOCK_PRE_WARNING, Seconds(59) + Milliseconds(700)); + break; + case EVENT_THUNDERSHOCK_PRE_WARNING: + if (Creature* controller = _instance->GetCreature(DATA_ASCENDANT_COUNCIL_CONTROLLER)) + controller->AI()->Talk(SAY_ANNOUNCE_THUNDERSHOCK_WARNING); + break; + case EVENT_LIGHTNING_ROD: + DoCastAOE(SPELL_LIGHTNING_ROD); + _events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, Seconds(8), Seconds(10)); + _events.Repeat(Seconds(19) + Milliseconds(400)); + break; + case EVENT_CHAIN_LIGHTNING: + DoCastAOE(SPELL_CHAIN_LIGHTNING_TARGETING); + break; + case EVENT_DISPERSE: + me->AttackStop(); + me->SetReactState(REACT_PASSIVE); + DoCastAOE(SPELL_DISPERSE); + _events.Repeat(Seconds(24)); + break; + case EVENT_LIGHTNING_BLAST: + me->SetReactState(REACT_AGGRESSIVE); + if (Unit* victim = me->GetVictim()) + me->AI()->AttackStart(victim); + + me->MakeInterruptable(true); + DoCastAOE(SPELL_LIGHTNING_BLAST); + break; + case EVENT_TELEPORT_PREPARE_FUSION: + DoCastSelf(SPELL_TELEPORT_AIR); + _events.ScheduleEvent(EVENT_FACE_CONTROLLER, Milliseconds(100)); + _events.ScheduleEvent(EVENT_MOVE_TO_MIDDLE, Milliseconds(200)); + break; + case EVENT_FACE_CONTROLLER: + if (Creature* controller = _instance->GetCreature(DATA_ASCENDANT_COUNCIL_CONTROLLER)) + me->SetFacingToObject(controller); + break; + case EVENT_MOVE_TO_MIDDLE: + Talk(SAY_FUSION); + me->GetMotionMaster()->MovePoint(POINT_NONE, feludiusMiddlePosition, true); + break; + case EVENT_STATIC_OVERLOAD: + DoCastAOE(SPELL_STATIC_OVERLOAD, true); + _events.Repeat(Seconds(20)); + break; + default: + break; + } + } + DoMeleeAttackIfReady(); + } + + private: + EventMap _events; + InstanceScript* _instance; + SummonList _summons; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetBastionOfTwilightAI(creature); + } +}; + +class npc_terrastra : public CreatureScript +{ + public: + npc_terrastra() : CreatureScript("npc_terrastra") { } + + struct npc_terrastraAI : public ScriptedAI + { + npc_terrastraAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _summons(me) { } + + void Reset() override + { + me->SetReactState(REACT_PASSIVE); + _events.Reset(); + _events.SetPhase(PHASE_FELUDIUS_IGNACIOUS); + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + _EnterEvadeMode(); + _summons.DespawnAll(); + me->DespawnOrUnsummon(0, Seconds(30)); + } + + void KilledUnit(Unit* who) override + { + if (who->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); + } + + void JustSummoned(Creature* summon) override + { + _summons.Summon(summon); + } + + void DamageTaken(Unit* attacker, uint32& damage) override + { + if (me->HealthBelowPctDamaged(25, damage)) + if (Creature* controller = _instance->GetCreature(DATA_ASCENDANT_COUNCIL_CONTROLLER)) + controller->AI()->DoAction(ACTION_UNITE_COUNCILLORS); + + // Do not allow to kill any of the councillors + if (damage >= me->GetHealth()) + damage = me->GetHealth() - 1; + } + + void DoAction(int32 action) override + { + switch (action) + { + case ACTION_CHANGE_PLACES: + _events.CancelEvent(EVENT_GRAVITY_CORE); + _events.ScheduleEvent(EVENT_TALK_ENGAGE, Seconds(3) + Milliseconds(100)); + _events.ScheduleEvent(EVENT_SWITCH_POSITIONS, Seconds(3)); + break; + case ACTION_PREPARE_FUSION: + _events.Reset(); + me->AttackStop(); + me->SetReactState(REACT_PASSIVE); + me->CastStop(); + me->SetWalk(true); + DoCastAOE(SPELL_ELEMENTAL_STASIS); + DoCastSelf(SPELL_CLEAR_ALL_DEBUFFS); + _events.ScheduleEvent(EVENT_TELEPORT_PREPARE_FUSION, Seconds(1) + Milliseconds(200)); + break; + case ACTION_SCHEDULE_HEROIC_ABILITY: + _events.ScheduleEvent(EVENT_GRAVITY_CORE, Seconds(22) + Milliseconds(700)); + break; + default: + break; + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim() && !_events.IsInPhase(PHASE_FELUDIUS_IGNACIOUS)) + return; + + _events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_TALK_ENGAGE: + Talk(SAY_ENGAGE); + break; + case EVENT_SWITCH_POSITIONS: + _instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 2); + DoCastSelf(SPELL_TELEPORT_RIGHT_FLOOR); + _events.ScheduleEvent(EVENT_ATTACK_PLAYERS, Milliseconds(100)); + break; + case EVENT_ATTACK_PLAYERS: + _events.SetPhase(PHASE_ARION_TERRASTRA); + _events.ScheduleEvent(EVENT_GRAVITY_WELL, Seconds(6) + Milliseconds(900)); + _events.ScheduleEvent(EVENT_HARDEN_SKIN, Seconds(22) + Milliseconds(700)); + _events.ScheduleEvent(EVENT_QUAKE_PRE_WARNING, Seconds(19) + Milliseconds(200)); + _events.ScheduleEvent(EVENT_QUAKE, Seconds(27) + Milliseconds(500)); + _events.ScheduleEvent(EVENT_ERUPTION, Seconds(9) + Milliseconds(300)); + me->SetReactState(REACT_AGGRESSIVE); + DoZoneInCombat(); + break; + case EVENT_GRAVITY_WELL: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true, 0)) + DoCast(target, SPELL_GRAVITY_WELL); + _events.Repeat(Seconds(17)); + break; + case EVENT_HARDEN_SKIN: + DoCastSelf(SPELL_HARDEN_SKIN); + _events.Repeat(Seconds(43) + Milliseconds(800)); + break; + case EVENT_QUAKE: + Talk(SAY_ANNOUNCE_ABILITY); + Talk(SAY_ABILITY); + DoCastAOE(SPELL_QUAKE); + _events.Repeat(Minutes(1) + Seconds(8)); + _events.ScheduleEvent(EVENT_QUAKE_PRE_WARNING, Seconds(59) + Milliseconds(700)); + break; + case EVENT_QUAKE_PRE_WARNING: + if (Creature* controller = _instance->GetCreature(DATA_ASCENDANT_COUNCIL_CONTROLLER)) + controller->AI()->Talk(SAY_ANNOUNCE_QUAKE_WARNING); + break; + case EVENT_ERUPTION: + DoCastSelf(SPELL_ERUPTION_DUMMY); + _events.Repeat(Seconds(17)); + break; + case EVENT_TELEPORT_PREPARE_FUSION: + DoCastSelf(SPELL_TELEPORT_EARTH); + _events.ScheduleEvent(EVENT_FACE_CONTROLLER, Milliseconds(200)); + _events.ScheduleEvent(EVENT_MOVE_TO_MIDDLE, Seconds(3) + Milliseconds(900)); + break; + case EVENT_FACE_CONTROLLER: + if (Creature* controller = _instance->GetCreature(DATA_ASCENDANT_COUNCIL_CONTROLLER)) + me->SetFacingToObject(controller); + break; + case EVENT_MOVE_TO_MIDDLE: + Talk(SAY_FUSION); + me->GetMotionMaster()->MovePoint(POINT_NONE, feludiusMiddlePosition, true); + break; + case EVENT_GRAVITY_CORE: + DoCastAOE(SPELL_GRAVITY_CORE, true); + _events.Repeat(Seconds(20)); + break; + default: + break; + } + } + DoMeleeAttackIfReady(); + } + + private: + EventMap _events; + InstanceScript* _instance; + SummonList _summons; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetBastionOfTwilightAI(creature); + } +}; + +class npc_elementium_monstrosity : public CreatureScript +{ + public: + npc_elementium_monstrosity() : CreatureScript("npc_elementium_monstrosity") { } + + struct npc_elementium_monstrosityAI : public ScriptedAI + { + npc_elementium_monstrosityAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _summons(me) + { + Initialize(); + } + + void Initialize() + { + _mergedHealth = 0; + _mergedTargets = 0; + _achievementEnligible = true; + me->SetReactState(REACT_PASSIVE); + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + _EnterEvadeMode(); + _summons.DespawnAll(); + if (Creature* controller = _instance->GetCreature(DATA_ASCENDANT_COUNCIL_CONTROLLER)) + controller->AI()->DoAction(ACTION_STOP_ENCOUNTER); + } + + void IsSummonedBy(Unit* /*summoner*/) override + { + DoZoneInCombat(); + DoCastSelf(SPELL_TWILIGHT_EXPLOSION_DND); + DoCastSelf(SPELL_MERGE_HEALTH); + Talk(SAY_SUMMONED); + _events.SetPhase(PHASE_INTRO); + _events.ScheduleEvent(EVENT_APPLY_PERIODIC_EFFECTS, Seconds(1) + Milliseconds(500)); + _events.ScheduleEvent(EVENT_ATTACK_PLAYERS, Seconds(3) + Milliseconds(800)); + _events.ScheduleEvent(EVENT_LAVA_SEED, Seconds(19) + Milliseconds(700)); + _events.ScheduleEvent(EVENT_GRAVITY_CRUSH, Seconds(32) + Milliseconds(900)); + } + + void JustDied(Unit* /*killer*/) override + { + if (Creature* controller = _instance->GetCreature(DATA_ASCENDANT_COUNCIL_CONTROLLER)) + controller->AI()->DoAction(ACTION_FINISH_ENCOUNTER); + + _summons.DespawnAll(); + Talk(SAY_DEATH); + } + + void KilledUnit(Unit* who) override + { + if (who->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); + } + + void JustSummoned(Creature* summon) override + { + _summons.Summon(summon); + } + + void SpellHitTarget(Unit* target, SpellInfo const* spell) override + { + if (spell->Id == SPELL_MERGE_HEALTH) + { + _mergedHealth += target->GetHealth(); + _mergedTargets++; + + if (Creature* creature = target->ToCreature()) + creature->DespawnOrUnsummon(); + + if (_mergedTargets == 4) + { + me->SetHealth(_mergedHealth); + _instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1); + } + } + } + + void DoAction(int32 action) override + { + if (action == ACTION_FAIL_ACHIEVEMENT) + _achievementEnligible = false; + } + + uint32 GetData(uint32 type) const override + { + if (type == DATA_ELEMENTARY) + return _achievementEnligible; + + return 0; + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim() && !_events.IsInPhase(PHASE_INTRO)) + return; + + _events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_ATTACK_PLAYERS: + me->SetReactState(REACT_AGGRESSIVE); + break; + case EVENT_APPLY_PERIODIC_EFFECTS: + DoCastSelf(SPELL_ELECTRIC_INSTABILITY); + DoCastSelf(SPELL_CRYOGENIC_AURA); + break; + case EVENT_LAVA_SEED: + Talk(SAY_LAVA_SEED); + DoCastAOE(SPELL_LAVA_SEED); + _events.Repeat(Seconds(21) + Milliseconds(700)); + break; + case EVENT_GRAVITY_CRUSH: + DoCastAOE(SPELL_GRAVITY_CRUSH); + _events.Repeat(Seconds(24), Seconds(28)); + break; + default: + break; + } + } + DoMeleeAttackIfReady(); + } + + private: + EventMap _events; + InstanceScript* _instance; + SummonList _summons; + uint32 _mergedHealth; + uint8 _mergedTargets; + bool _achievementEnligible; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetBastionOfTwilightAI(creature); + } +}; + +class npc_ascendant_council_violent_cyclone : public CreatureScript +{ + public: + npc_ascendant_council_violent_cyclone() : CreatureScript("npc_ascendant_council_violent_cyclone") { } + + struct npc_ascendant_council_violent_cycloneAI : public ScriptedAI + { + npc_ascendant_council_violent_cycloneAI(Creature* creature) : ScriptedAI(creature) + { + Initialize(); + } + + void Initialize() + { + _targetPositions.clear(); + } + + void IsSummonedBy(Unit* /*summoner*/) override + { + me->SetWalk(true); + _events.ScheduleEvent(EVENT_CYCLONE_AGGRO, Seconds(2) + Milliseconds(300)); + } + + void SpellHitTarget(Unit* target, SpellInfo const* spell) override + { + // According to sniffs the cyclone uses the positions of the Ascendant Council Target Stalkers + // as potential waypoints so he stays within a certain area rather than moving arround the room + if (spell->Id == SPELL_CYCLONE_AGGRO) + { + _targetPositions.push_back(target->GetPosition()); + _events.RescheduleEvent(EVENT_MOVE_CYCLONE, Milliseconds(100)); + } + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_CYCLONE_AGGRO: + DoCastAOE(SPELL_CYCLONE_AGGRO); + break; + case EVENT_MOVE_CYCLONE: + { + std::vector potentialDestinations; + for (Position pos : _targetPositions) + { + if (me->GetDistance(pos) > 30.0f) + potentialDestinations.push_back(pos); + } + + if (!potentialDestinations.empty()) + { + Position destination = Trinity::Containers::SelectRandomContainerElement(potentialDestinations); + me->GetMotionMaster()->MovePoint(POINT_NONE, destination, true); + } + + _events.Repeat(Seconds(10), Seconds(14)); + break; + } + default: + break; + } + } + } + + private: + EventMap _events; + std::vector _targetPositions; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetBastionOfTwilightAI(creature); + } +}; + +class npc_ascendant_council_gravity_well : public CreatureScript +{ + public: + npc_ascendant_council_gravity_well() : CreatureScript("npc_ascendant_council_gravity_well") { } + + struct npc_ascendant_council_gravity_wellAI : public ScriptedAI + { + npc_ascendant_council_gravity_wellAI(Creature* creature) : ScriptedAI(creature) { } + + void IsSummonedBy(Unit* /*summoner*/) override + { + DoCastSelf(SPELL_GRAVITY_WELL_PRE_VISUAL); + _events.ScheduleEvent(EVENT_MAGNETIC_PULL, Seconds(3) + Milliseconds(400)); + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_MAGNETIC_PULL: + me->RemoveAurasDueToSpell(SPELL_GRAVITY_WELL_PRE_VISUAL); + DoCastSelf(SPELL_MAGNETIC_PULL_PERIODIC); + DoCastSelf(SPELL_MAGNETIC_PULL_SLOW); + break; + default: + break; + } + } + } + + private: + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetBastionOfTwilightAI(creature); + } +}; + +class npc_ascendant_council_eruption_target : public CreatureScript +{ + public: + npc_ascendant_council_eruption_target() : CreatureScript("npc_ascendant_council_eruption_target") { } + + struct npc_ascendant_council_eruption_targetAI : public ScriptedAI + { + npc_ascendant_council_eruption_targetAI(Creature* creature) : ScriptedAI(creature) { } + + void IsSummonedBy(Unit* /*summoner*/) override + { + DoCastSelf(SPELL_ERUPTION_PRE_VISUAL); + _events.ScheduleEvent(EVENT_ERUPTION_DAMAGE, Seconds(3) + Milliseconds(900)); + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_ERUPTION_DAMAGE: + me->RemoveAurasDueToSpell(SPELL_ERUPTION_PRE_VISUAL); + me->DespawnOrUnsummon(Seconds(6) + Milliseconds(400)); + if (TempSummon* summon = me->ToTempSummon()) + if (Unit* summoner = summon->GetSummoner()) + summoner->CastSpell(me, SPELL_ERUPTION_DAMAGE, true); + break; + default: + break; + } + } + } + + private: + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetBastionOfTwilightAI(creature); + } +}; + +class npc_ascendant_council_plume_stalker : public CreatureScript +{ + public: + npc_ascendant_council_plume_stalker() : CreatureScript("npc_ascendant_council_plume_stalker") { } + + struct npc_ascendant_council_plume_stalkerAI : public ScriptedAI + { + npc_ascendant_council_plume_stalkerAI(Creature* creature) : ScriptedAI(creature) { } + + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override + { + if (spell->Id == SPELL_LAVA_SEED_DUMMY) + { + me->StopMoving(); + _events.ScheduleEvent(EVENT_LAVA_PLUME, Seconds(1) + Milliseconds(100)); + } + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_LAVA_PLUME: + DoCastAOE(SPELL_LAVA_PLUME); + _events.ScheduleEvent(EVENT_CLEAR_LAVA_SEED_DUMMY_AURA, Seconds(1) + Milliseconds(100)); + _events.ScheduleEvent(EVENT_MOVE_PLUME, Seconds(2) + Milliseconds(300)); + break; + case EVENT_CLEAR_LAVA_SEED_DUMMY_AURA: + me->RemoveAurasDueToSpell(SPELL_LAVA_SEED_DUMMY); + break; + case EVENT_MOVE_PLUME: + { + Position pos = me->GetHomePosition(); + me->MovePosition(pos, 5.0f, frand(0.0f, float(M_PI * 2))); + me->GetMotionMaster()->MovePoint(POINT_NONE, pos, true); + break; + } + default: + break; + } + } + } + + private: + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetBastionOfTwilightAI(creature); + } +}; + +class npc_ascendant_council_gravity_crush : public CreatureScript +{ + public: + npc_ascendant_council_gravity_crush() : CreatureScript("npc_ascendant_council_gravity_crush") { } + + struct npc_ascendant_council_gravity_crushAI : public ScriptedAI + { + npc_ascendant_council_gravity_crushAI(Creature* creature) : ScriptedAI(creature), _instance(me->GetInstanceScript()) { } + + void IsSummonedBy(Unit* summoner) override + { + if (!summoner) + return; + + summoner->CastSpell(me, SPELL_GRAVITY_CRUSH_RIDE_VEHICLE, true); + _events.ScheduleEvent(EVENT_MOVE_UP, Seconds(1) + Milliseconds(200)); + + if (Creature* elementiumMonstrosity = _instance->GetCreature(DATA_ELEMENTIUM_MONSTROSITY)) + elementiumMonstrosity->AI()->JustSummoned(me); + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_MOVE_UP: + { + Position pos = me->GetPosition(); + pos.m_positionZ += 30.0f; + me->GetMotionMaster()->MovePoint(POINT_NONE, pos, false); + break; + } + default: + break; + } + } + } + + private: + EventMap _events; + InstanceScript* _instance; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetBastionOfTwilightAI(creature); + } +}; + +class npc_ascendant_council_frozen_orb : public CreatureScript +{ + public: + npc_ascendant_council_frozen_orb() : CreatureScript("npc_ascendant_council_frozen_orb") { } + + struct npc_ascendant_council_frozen_orbAI : public ScriptedAI + { + npc_ascendant_council_frozen_orbAI(Creature* creature) : ScriptedAI(creature), _instance(me->GetInstanceScript()) + { + Initialize(); + } + + void Initialize() + { + _targetGUID = ObjectGuid::Empty; + me->SetReactState(REACT_PASSIVE); + } + + void IsSummonedBy(Unit* /*summoner*/) override + { + DoCastAOE(SPELL_FROZEN_ORB_TARGETING); + if (Creature* feludius = _instance->GetCreature(DATA_FELUDIUS)) + feludius->AI()->JustSummoned(me); + } + + void SpellHitTarget(Unit* target, SpellInfo const* spell) override + { + switch (spell->Id) + { + case SPELL_FROZEN_ORB_TARGETING: + _targetGUID = target->GetGUID(); + _events.ScheduleEvent(EVENT_PURSUE_TARGET, Seconds(2)); + break; + case SPELL_FROZEN_ORB_DUMMY: + if (target->GetGUID() == _targetGUID) + { + me->GetMotionMaster()->Clear(); + me->RemoveAllAuras(); + DoCastAOE(SPELL_GLACIATE_FROST_ORB); + me->DespawnOrUnsummon(Seconds(1) + Milliseconds(900)); + } + break; + default: + break; + } + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_PURSUE_TARGET: + if (Unit* target = ObjectAccessor::GetUnit(*me, _targetGUID)) + { + Talk(SAY_ANNOUNCE_PURSUE_PLAYER, target); + DoCast(target, SPELL_FROST_BEACON); + me->ClearUnitState(UNIT_STATE_CASTING); + me->GetMotionMaster()->MoveFollow(target, 0.0f, 0.0f); + _events.ScheduleEvent(EVENT_INCREASE_SPEED, Seconds(1)); + } + break; + case EVENT_INCREASE_SPEED: + DoCastSelf(SPELL_FROZEN_ORB_INCREASE_SPEED, true); + _events.Repeat(Seconds(1)); + break; + default: + break; + } + } + } + + private: + EventMap _events; + InstanceScript* _instance; + ObjectGuid _targetGUID; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetBastionOfTwilightAI(creature); + } +}; + +class npc_ascendant_council_flame_strike : public CreatureScript +{ + public: + npc_ascendant_council_flame_strike() : CreatureScript("npc_ascendant_council_flame_strike") { } + + struct npc_ascendant_council_flame_strikeAI : public ScriptedAI + { + npc_ascendant_council_flame_strikeAI(Creature* creature) : ScriptedAI(creature) { } + + void IsSummonedBy(Unit* summoner) override + { + DoCastAOE(SPELL_FLAME_STRIKE_PRE_VISUAL); + summoner->CastSpell(me, SPELL_FLAME_STRIKE); + } + + void SpellHit(Unit* /*caste*/r, SpellInfo const* spell) override + { + if (spell->Id == SPELL_FLAME_STRIKE) + { + me->RemoveAurasDueToSpell(SPELL_FLAME_STRIKE_PRE_VISUAL); + DoCastAOE(SPELL_FLAME_STRIKE_PERIODIC); + } + } + + void SpellHitTarget(Unit* target, SpellInfo const* spell) override + { + if (target->GetEntry() == NPC_FROZEN_ORB) + { + target->GetMotionMaster()->Clear(); + target->RemoveAllAuras(); + target->ToCreature()->DespawnOrUnsummon(Seconds(2) + Milliseconds(300)); + me->RemoveAllAuras(); + me->DespawnOrUnsummon(Seconds(2) + Milliseconds(300)); + } + } + + private: + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetBastionOfTwilightAI(creature); + } +}; + +class spell_feludius_water_bomb_targeting : public SpellScript +{ + PrepareSpellScript(spell_feludius_water_bomb_targeting); + + void HandleHit(SpellEffIndex effIndex) + { + if (Unit* caster = GetCaster()) + for (uint8 i = 0; i < 2; i++) + caster->CastSpell(GetHitUnit(), GetSpellInfo()->Effects[effIndex].BasePoints, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_feludius_water_bomb_targeting::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY); + } +}; + +class spell_feludius_water_bomb : public SpellScript +{ + PrepareSpellScript(spell_feludius_water_bomb); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_WATER_BOMB_TRIGGERED }); + } + + void HandleHit(SpellEffIndex /*effIndex*/) + { + if (Creature* target = GetHitCreature()) + { + target->CastSpell(target, SPELL_WATER_BOMB_TRIGGERED, true); + target->DespawnOrUnsummon(Seconds(2)); + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_feludius_water_bomb::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY); + } +}; + +class spell_feludius_glaciate : public SpellScript +{ + PrepareSpellScript(spell_feludius_glaciate); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo( + { + SPELL_WATERLOGGED, + SPELL_FROZEN + }); + } + + void ChangeDamage(SpellEffIndex /*effIndex*/) + { + if (Unit* caster = GetCaster()) + { + float distance = GetHitUnit()->GetDistance(caster); + uint32 damageLossPerYard = caster->GetMap()->IsHeroic() ? 25000 : 20000; + int32 damage = std::max(int32(10000), int32(GetHitDamage() - (damageLossPerYard * distance))); + SetHitDamage(damage); + } + } + + void FreezeTarget(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + { + if (Unit* caster = GetCaster()) + { + if (target->HasAura(SPELL_WATERLOGGED)) + { + caster->CastSpell(target, SPELL_FROZEN, true); + target->RemoveAurasDueToSpell(SPELL_WATERLOGGED); + } + } + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_feludius_glaciate::ChangeDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); + OnEffectHitTarget += SpellEffectFn(spell_feludius_glaciate::FreezeTarget, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); + } +}; + +class spell_feludius_fire_proc_check : public AuraScript +{ + PrepareAuraScript(spell_feludius_fire_proc_check); + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (SpellInfo const* spell = eventInfo.GetSpellInfo()) + if (uint32 spellId = sSpellMgr->GetSpellIdForDifficulty(SPELL_INFERNO_RUSH_TRIGGERED, eventInfo.GetActor())) + return (spell->Id == spellId); + + return false; + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_feludius_fire_proc_check::CheckProc); + } +}; + +class spell_feludius_heart_of_ice : public AuraScript +{ + PrepareAuraScript(spell_feludius_heart_of_ice); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo( + { + SPELL_FROST_IMBUED, + SPELL_BURNING_BLOOD + }); + } + + void AfterApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + if (Unit* target = GetTarget()) + target->RemoveAurasDueToSpell(SPELL_BURNING_BLOOD); + } + + void HandlePeriodic(AuraEffect const* aurEff) + { + GetTarget()->CastSpell(GetTarget(), SPELL_FROST_IMBUED, true, nullptr, aurEff); + + if (AuraEffect* aurEff = GetEffect(EFFECT_0)) + { + int32 damage = aurEff->GetAmount() + CalculatePct(aurEff->GetAmount(), 10); + aurEff->SetAmount(damage); + } + } + + void Register() override + { + AfterEffectApply += AuraEffectApplyFn(spell_feludius_heart_of_ice::AfterApply, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE, AURA_EFFECT_HANDLE_REAL); + OnEffectPeriodic += AuraEffectPeriodicFn(spell_feludius_heart_of_ice::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE); + } +}; + +class spell_feludius_frost_imbued : public SpellScript +{ + PrepareSpellScript(spell_feludius_frost_imbued); + + void FilterTargets(std::list& targets) + { + if (targets.empty()) + return; + + targets.remove_if(Trinity::UnitAuraCheck(true, GetSpellInfo()->Id)); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_feludius_frost_imbued::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); + } +}; + +class spell_feludius_frost_imbued_AuraScript : public AuraScript +{ + PrepareAuraScript(spell_feludius_frost_imbued_AuraScript); + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (Unit* caster = GetCaster()) + return (GetTarget()->GetDistance(caster) > 10.0f); + + return true; + } + + void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& /*eventInfo*/) + { + PreventDefaultAction(); + Remove(); + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_feludius_frost_imbued_AuraScript::CheckProc); + } +}; + +class spell_feludius_frozen_orb_targeting : public SpellScript +{ + PrepareSpellScript(spell_feludius_frozen_orb_targeting); + + void FilterTargets(std::list& targets) + { + if (targets.empty()) + return; + + Trinity::Containers::RandomResize(targets, 1); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_feludius_frozen_orb_targeting::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + } +}; + +class spell_ignacious_rising_flames : public AuraScript +{ + PrepareAuraScript(spell_ignacious_rising_flames); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_RISING_FLAMES_BUFF }); + } + + void HandlePeriodic(AuraEffect const* aurEff) + { + GetTarget()->CastSpell(GetTarget(), SPELL_RISING_FLAMES_BUFF, true, nullptr, aurEff); + } + + void HandleAuraRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* target = GetTarget()) + { + target->RemoveAurasDueToSpell(SPELL_RISING_FLAMES_BUFF); + if (Creature* creature = target->ToCreature()) + creature->MakeInterruptable(false); + } + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_ignacious_rising_flames::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + AfterEffectRemove += AuraEffectRemoveFn(spell_ignacious_rising_flames::HandleAuraRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); + } +}; + +class spell_ignacious_burning_blood : public AuraScript +{ + PrepareAuraScript(spell_ignacious_burning_blood); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo( + { + SPELL_FLAME_IMBUED, + SPELL_HEART_OF_ICE + }); + } + + void AfterApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + if (Unit* target = GetTarget()) + target->RemoveAurasDueToSpell(SPELL_HEART_OF_ICE); + } + + void HandlePeriodic(AuraEffect const* aurEff) + { + GetTarget()->CastSpell(GetTarget(), SPELL_FLAME_IMBUED, true, nullptr, aurEff); + + if (AuraEffect* aurEff = GetEffect(EFFECT_0)) + { + int32 damage = aurEff->GetAmount() + CalculatePct(aurEff->GetAmount(), 10); + aurEff->SetAmount(damage); + } + } + + void Register() override + { + AfterEffectApply += AuraEffectApplyFn(spell_ignacious_burning_blood::AfterApply, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE, AURA_EFFECT_HANDLE_REAL); + OnEffectPeriodic += AuraEffectPeriodicFn(spell_ignacious_burning_blood::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE); + } +}; + +class spell_ignacious_flame_imbued : public SpellScript +{ + PrepareSpellScript(spell_ignacious_flame_imbued); + + void FilterTargets(std::list& targets) + { + if (targets.empty()) + return; + + targets.remove_if(Trinity::UnitAuraCheck(true, GetSpellInfo()->Id)); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_ignacious_flame_imbued::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); + } +}; + +class spell_ignacious_flame_imbued_AuraScript : public AuraScript +{ + PrepareAuraScript(spell_ignacious_flame_imbued_AuraScript); + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (Unit* caster = GetCaster()) + return (GetTarget()->GetDistance(caster) > 10.0f); + + return true; + } + + void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& /*eventInfo*/) + { + PreventDefaultAction(); + Remove(); + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_ignacious_flame_imbued_AuraScript::CheckProc); + } +}; + +class spell_ignacious_inferno_rush : public SpellScript +{ + PrepareSpellScript(spell_ignacious_inferno_rush); + + void HandleInfernoRush() + { + if (Unit* caster = GetCaster()) + if (Creature* creature = caster->ToCreature()) + if (creature->IsAIEnabled) + creature->AI()->DoAction(ACTION_CAST_INFERNO_RUSH); + } + + void Register() + { + AfterCast += SpellCastFn(spell_ignacious_inferno_rush::HandleInfernoRush); + } +}; + +class spell_ignacious_flame_strike : public SpellScript +{ + PrepareSpellScript(spell_ignacious_flame_strike); + + void FilterTargets(std::list& targets) + { + if (targets.empty()) + return; + + Trinity::Containers::RandomResize(targets, 1); + } + + void HandleHit(SpellEffIndex effIndex) + { + if (Unit* caster = GetCaster()) + caster->CastSpell(GetHitUnit(), GetSpellInfo()->Effects[effIndex].BasePoints, true); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_ignacious_flame_strike::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnEffectHitTarget += SpellEffectFn(spell_ignacious_flame_strike::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY); + } +}; + +class spell_arion_lashing_winds : public SpellScript +{ + PrepareSpellScript(spell_arion_lashing_winds); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo( + { + SPELL_SWIRLING_WINDS, + SPELL_GROUNDED + }); + } + + void HandleHit(SpellEffIndex effIndex) + { + if (Unit* caster = GetCaster()) + { + if (Unit* target = GetHitUnit()) + { + caster->CastSpell(target, SPELL_SWIRLING_WINDS, true); + target->RemoveAurasDueToSpell(SPELL_GROUNDED); + } + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_arion_lashing_winds::HandleHit, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); + } +}; + +class spell_arion_thundershock : public SpellScript +{ + PrepareSpellScript(spell_arion_thundershock); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_GROUNDED }); + } + + void ChangeDamage(SpellEffIndex /*effIndex*/) + { + if (GetHitUnit()->HasAura(SPELL_GROUNDED)) + SetHitDamage(CalculatePct(GetHitDamage(), 1)); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_arion_thundershock::ChangeDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); + } +}; + +class spell_arion_lightning_rod : public SpellScript +{ + PrepareSpellScript(spell_arion_lightning_rod); + + void FilterTargets(std::list& targets) + { + if (targets.size() < 3) + return; + + uint8 size = GetCaster()->GetMap()->Is25ManRaid() ? 3 : 1; + Trinity::Containers::RandomResize(targets, size); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_arion_lightning_rod::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + } +}; + +class spell_arion_chain_lightning_targeting : public SpellScript +{ + PrepareSpellScript(spell_arion_chain_lightning_targeting); + + void HandleHit(SpellEffIndex effIndex) + { + if (Unit* caster = GetCaster()) + { + if (Unit* target = GetHitUnit()) + { + if (target->HasAura(SPELL_LIGHTNING_ROD)) + { + caster->CastSpell(target, GetSpellInfo()->Effects[effIndex].BasePoints, true); + target->RemoveAurasDueToSpell(SPELL_LIGHTNING_ROD); + } + } + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_arion_chain_lightning_targeting::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY); + } +}; + +class ArionDisperseDistanceCheck +{ + public: + ArionDisperseDistanceCheck(Unit* _arion) : arion(_arion) { } + + bool operator()(WorldObject* object) + { + return (arion->GetDistance(object) < 10.0f); + } + + private: + Unit* arion; +}; + +class spell_arion_disperse : public SpellScript +{ + PrepareSpellScript(spell_arion_disperse); + + void FilterTargets(std::list& targets) + { + if (targets.empty()) + return; + + targets.remove_if(ArionDisperseDistanceCheck(GetCaster())); + + if (targets.empty()) + return; + + Trinity::Containers::RandomResize(targets, 1); + } + + void HandleHit(SpellEffIndex effIndex) + { + if (Unit* caster = GetCaster()) + { + caster->CastSpell(GetHitUnit(), GetSpellInfo()->Effects[effIndex].BasePoints, true); + + if (Creature* creature = caster->ToCreature()) + if (creature->IsAIEnabled) + creature->AI()->DoAction(ACTION_CAST_LIGHTNING_BLAST); + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_arion_disperse::HandleHit, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_arion_disperse::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + } +}; + +class AttackerVictimCheck +{ + public: + AttackerVictimCheck(Unit* _attacker) : attacker(_attacker) { } + + bool operator()(WorldObject* object) + { + return (attacker->GetVictim() && attacker->GetVictim() == object->ToUnit()); + } + private: + Unit* attacker; +}; + +class spell_arion_lightning_blast : public SpellScript +{ + PrepareSpellScript(spell_arion_lightning_blast); + + void FilterTargets(std::list& targets) + { + if (targets.empty()) + return; + + targets.remove_if(AttackerVictimCheck(GetCaster())); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_arion_lightning_blast::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_arion_lightning_blast::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + } +}; + +class spell_arion_static_overload : public SpellScript +{ + PrepareSpellScript(spell_arion_static_overload); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_GRAVITY_CORE }); + } + + void FilterTargets(std::list& targets) + { + if (targets.empty()) + return; + + targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_GRAVITY_CORE)); + + if (targets.empty()) + return; + + Trinity::Containers::RandomResize(targets, 1); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_arion_static_overload::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY); + } +}; + +class spell_arion_static_overload_triggered : public SpellScript +{ + PrepareSpellScript(spell_arion_static_overload_triggered); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo( + { + SPELL_GRAVITY_CORE, + SPELL_STATIC_OVERLOAD + }); + } + + void HandleHit(SpellEffIndex /*effIndex*/) + { + if (Unit* caster = GetCaster()) + caster->RemoveAurasDueToSpell(SPELL_STATIC_OVERLOAD); + + GetHitUnit()->RemoveAurasDueToSpell(SPELL_GRAVITY_CORE); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_arion_static_overload_triggered::HandleHit, EFFECT_0, SPELL_EFFECT_APPLY_AURA); + } +}; + +class spell_terrastra_gravity_well : public SpellScript +{ + PrepareSpellScript(spell_terrastra_gravity_well); + + void HandleHit(SpellEffIndex /*effIndex*/) + { + if (Unit* caster = GetCaster()) + { + if (Unit* target = GetHitUnit()) + { + if (!target->HasAura(SPELL_MAGNETIC_PULL_PULL)) + caster->CastSpell(target, SPELL_MAGNETIC_PULL_PULL, true); + + target->RemoveAurasDueToSpell(SPELL_SWIRLING_WINDS); + } + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_terrastra_gravity_well::HandleHit, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); + } +}; + +class spell_terrastra_harden_skin : public AuraScript +{ + PrepareAuraScript(spell_terrastra_harden_skin); + + bool Load() override + { + _absorbedDamage = 0; + return true; + } + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_SHATTER }); + } + + void OnAbsorb(AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount) + { + absorbAmount = CalculatePct(dmgInfo.GetDamage(), GetSpellInfo()->Effects[EFFECT_2].BasePoints); + _absorbedDamage += absorbAmount; + } + + void OnAuraRemoveHandler(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_ENEMY_SPELL) + if (Unit* target = GetTarget()) + target->CastCustomSpell(SPELL_SHATTER, SPELLVALUE_BASE_POINT0, _absorbedDamage, nullptr, true, nullptr, aurEff); + } +private: + uint32 _absorbedDamage; + + void Register() override + { + OnEffectAbsorb += AuraEffectAbsorbFn(spell_terrastra_harden_skin::OnAbsorb, EFFECT_1); + AfterEffectRemove += AuraEffectRemoveFn(spell_terrastra_harden_skin::OnAuraRemoveHandler, EFFECT_1, SPELL_AURA_SCHOOL_ABSORB, AURA_EFFECT_HANDLE_REAL); + } +}; + +class spell_terrastra_quake : public SpellScript +{ + PrepareSpellScript(spell_terrastra_quake); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_SWIRLING_WINDS }); + } + + void FilterTargets(std::list& targets) + { + if (targets.empty()) + return; + + targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_SWIRLING_WINDS)); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_terrastra_quake::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + } +}; + +class spell_terrastra_eruption : public SpellScript +{ + PrepareSpellScript(spell_terrastra_eruption); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_ERUPTION_SUMMON }); + } + + void HandleHit(SpellEffIndex /*effIndex*/) + { + if (Unit* caster = GetCaster()) + { + float angle = caster->GetOrientation(); + float steps = float(M_PI / 2.5f); + float dist = caster->GetFloatValue(UNIT_FIELD_COMBATREACH); + float z = caster->GetPositionZ(); + for (uint8 i = 0; i < 5; i++) + { + float x = caster->GetPositionX() + cos(angle + (i * steps)) * dist; + float y = caster->GetPositionY() + sin(angle + (i * steps)) * dist; + float floor = caster->GetMap()->GetHeight(caster->GetPhaseShift(), x, y, z, true); + caster->CastSpell(x, y, z, SPELL_ERUPTION_SUMMON, true); + } + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_terrastra_eruption::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY); + } +}; + +class spell_terrastra_gravity_core : public SpellScript +{ + PrepareSpellScript(spell_terrastra_gravity_core); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_STATIC_OVERLOAD }); + } + + void FilterTargets(std::list& targets) + { + if (targets.empty()) + return; + + targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_STATIC_OVERLOAD)); + + if (targets.empty()) + return; + + Trinity::Containers::RandomResize(targets, 1); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_terrastra_gravity_core::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY); + } +}; + +class spell_terrastra_gravity_core_triggered : public SpellScript +{ + PrepareSpellScript(spell_terrastra_gravity_core_triggered); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo( + { + SPELL_GRAVITY_CORE, + SPELL_STATIC_OVERLOAD + }); + } + + void HandleHit(SpellEffIndex /*effIndex*/) + { + if (Unit* caster = GetCaster()) + caster->RemoveAurasDueToSpell(SPELL_GRAVITY_CORE); + + GetHitUnit()->RemoveAurasDueToSpell(SPELL_STATIC_OVERLOAD); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_terrastra_gravity_core_triggered::HandleHit, EFFECT_0, SPELL_EFFECT_APPLY_AURA); + } +}; + +class spell_elementium_monstrosity_lava_seed : public SpellScript +{ + PrepareSpellScript(spell_elementium_monstrosity_lava_seed); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_LAVA_SEED_DUMMY }); + } + + void HandleHit(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + target->CastSpell(target, SPELL_LAVA_SEED_DUMMY); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_elementium_monstrosity_lava_seed::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY); + } +}; + +class spell_elementium_monstrosity_cryogenic_aura : public AuraScript +{ + PrepareAuraScript(spell_elementium_monstrosity_cryogenic_aura); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo( + { + SPELL_LIQUID_ICE_SUMMON, + SPELL_LIQUID_ICE_MOD_SCALE, + SPELL_LIQUID_ICE_TRIGGERED + }); + } + + void HandlePeriodic(AuraEffect const* /*aurEff*/) + { + if (Unit* target = GetTarget()) + { + if (Aura* aura = target->GetAura(sSpellMgr->GetSpellIdForDifficulty(SPELL_LIQUID_ICE_TRIGGERED, target))) + { + if (Unit* caster = aura->GetCaster()) + target->CastSpell(caster, SPELL_LIQUID_ICE_MOD_SCALE, true); + } + else + { + target->CastSpell(target, SPELL_LIQUID_ICE_SUMMON, true); + + if (Creature* creature = target->ToCreature()) + if (creature->IsAIEnabled) + creature->AI()->DoAction(ACTION_FAIL_ACHIEVEMENT); + } + } + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_elementium_monstrosity_cryogenic_aura::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } +}; + +class spell_elementium_monstrosity_liquid_ice : public AuraScript +{ + PrepareAuraScript(spell_elementium_monstrosity_liquid_ice); + + void HandlePeriodic(AuraEffect const* aurEff) + { + PreventDefaultAction(); + if (Unit* target = GetTarget()) + { + uint32 triggerSpell = GetSpellInfo()->Effects[EFFECT_0].TriggerSpell; + int32 radius = target->GetObjectScale() * 500; + target->CastCustomSpell(triggerSpell, SPELLVALUE_RADIUS_MOD, radius, nullptr, true, nullptr, aurEff, target->GetGUID()); + } + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_elementium_monstrosity_liquid_ice::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } +}; + +class spell_elementium_monstrosity_electric_instability : public SpellScript +{ + PrepareSpellScript(spell_elementium_monstrosity_electric_instability); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo( + { + SPELL_ELECTRIC_INSTABILITY, + SPELL_ELECTRIC_INSTABILITY_DAMAGE + }); + } + + void FilterTargets(std::list& targets) + { + if (targets.empty()) + return; + + uint8 size = 1; + if (Unit* caster = GetCaster()) + if (AuraEffect* aurEff = caster->GetAuraEffect(SPELL_ELECTRIC_INSTABILITY, EFFECT_0)) + if (uint32 ticks = aurEff->GetTickNumber()) + size += uint8(std::floor(ticks / 20)); + + if (targets.size() > size) + Trinity::Containers::RandomResize(targets, size); + } + + void HandleHit(SpellEffIndex /*effIndex*/) + { + if (Unit* caster = GetCaster()) + caster->CastSpell(GetHitUnit(), SPELL_ELECTRIC_INSTABILITY_DAMAGE, true); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_elementium_monstrosity_electric_instability::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnEffectHitTarget += SpellEffectFn(spell_elementium_monstrosity_electric_instability::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY); + } +}; + +class spell_elementium_monstrosity_gravity_crush : public SpellScript +{ + PrepareSpellScript(spell_elementium_monstrosity_gravity_crush); + + void FilterTargets(std::list& targets) + { + if (targets.empty()) + return; + + targets.remove_if(AttackerVictimCheck(GetCaster())); + + Trinity::Containers::RandomResize(targets, GetCaster()->GetMap()->Is25ManRaid() ? 3 : 1); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_elementium_monstrosity_gravity_crush::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY); + } +}; + +class achievement_elementary : public AchievementCriteriaScript +{ + public: + achievement_elementary() : AchievementCriteriaScript("achievement_elementary") { } + + bool OnCheck(Player* /*source*/, Unit* target) override + { + if (!target) + return false; + + if (target->IsAIEnabled) + return target->GetAI()->GetData(DATA_ELEMENTARY); + + return false; + } +}; + +void AddSC_boss_ascendant_council() +{ + new boss_ascendant_council_controller(); + new npc_feludius(); + new npc_ignacious(); + new npc_arion(); + new npc_terrastra(); + new npc_elementium_monstrosity(); + new npc_ascendant_council_violent_cyclone(); + new npc_ascendant_council_gravity_well(); + new npc_ascendant_council_eruption_target(); + new npc_ascendant_council_plume_stalker(); + new npc_ascendant_council_gravity_crush(); + new npc_ascendant_council_frozen_orb(); + new npc_ascendant_council_flame_strike(); + RegisterSpellScript(spell_feludius_water_bomb_targeting); + RegisterSpellScript(spell_feludius_water_bomb); + RegisterSpellScript(spell_feludius_glaciate); + RegisterAuraScript(spell_feludius_fire_proc_check); + RegisterAuraScript(spell_feludius_heart_of_ice); + RegisterSpellAndAuraScriptPair(spell_feludius_frost_imbued, spell_feludius_frost_imbued_AuraScript); + RegisterSpellScript(spell_feludius_frozen_orb_targeting); + RegisterAuraScript(spell_ignacious_rising_flames); + RegisterAuraScript(spell_ignacious_burning_blood); + RegisterSpellAndAuraScriptPair(spell_ignacious_flame_imbued, spell_ignacious_flame_imbued_AuraScript); + RegisterSpellScript(spell_ignacious_inferno_rush); + RegisterSpellScript(spell_ignacious_flame_strike); + RegisterSpellScript(spell_arion_lashing_winds); + RegisterSpellScript(spell_arion_thundershock); + RegisterSpellScript(spell_arion_lightning_rod); + RegisterSpellScript(spell_arion_chain_lightning_targeting); + RegisterSpellScript(spell_arion_disperse); + RegisterSpellScript(spell_arion_lightning_blast); + RegisterSpellScript(spell_arion_static_overload); + RegisterSpellScript(spell_arion_static_overload_triggered); + RegisterSpellScript(spell_terrastra_gravity_well); + RegisterAuraScript(spell_terrastra_harden_skin); + RegisterSpellScript(spell_terrastra_quake); + RegisterSpellScript(spell_terrastra_eruption); + RegisterSpellScript(spell_terrastra_gravity_core); + RegisterSpellScript(spell_terrastra_gravity_core_triggered); + RegisterSpellScript(spell_elementium_monstrosity_lava_seed); + RegisterAuraScript(spell_elementium_monstrosity_cryogenic_aura); + RegisterAuraScript(spell_elementium_monstrosity_liquid_ice); + RegisterSpellScript(spell_elementium_monstrosity_electric_instability); + RegisterSpellScript(spell_elementium_monstrosity_gravity_crush); + new achievement_elementary(); +} diff --git a/src/server/scripts/EasternKingdoms/BastionOfTwilight/instance_bastion_of_twilight.cpp b/src/server/scripts/EasternKingdoms/BastionOfTwilight/instance_bastion_of_twilight.cpp index fc9ae9a0af8..aedbf01ec69 100644 --- a/src/server/scripts/EasternKingdoms/BastionOfTwilight/instance_bastion_of_twilight.cpp +++ b/src/server/scripts/EasternKingdoms/BastionOfTwilight/instance_bastion_of_twilight.cpp @@ -28,18 +28,19 @@ ObjectData const creatureData[] = { - { BOSS_HALFUS_WYRMBREAKER, DATA_HALFUS_WYRMBREAKER }, - { BOSS_THERALION, DATA_THERALION }, - { BOSS_VALIONA, DATA_VALIONA }, - { BOSS_IGNACIOUS, DATA_IGNACIOUS }, - { BOSS_FELUDIUS, DATA_FELUDIUS }, - { BOSS_TERRASTRA, DATA_TERRASTRA }, - { BOSS_ARION, DATA_ARION }, - { BOSS_ELEMENTIUM_MONSTROSITY, DATA_ELEMENTIUM_MONSTROSITY }, - { BOSS_CHOGALL, DATA_CHOGALL }, - { BOSS_SINESTRA, DATA_SINESTRA }, - { NPC_PROTO_BEHEMOTH, DATA_PROTO_BEHEMOTH }, - { 0, 0 } // END + { BOSS_HALFUS_WYRMBREAKER, DATA_HALFUS_WYRMBREAKER }, + { BOSS_THERALION, DATA_THERALION }, + { BOSS_VALIONA, DATA_VALIONA }, + { BOSS_IGNACIOUS, DATA_IGNACIOUS }, + { BOSS_FELUDIUS, DATA_FELUDIUS }, + { BOSS_TERRASTRA, DATA_TERRASTRA }, + { BOSS_ARION, DATA_ARION }, + { BOSS_ELEMENTIUM_MONSTROSITY, DATA_ELEMENTIUM_MONSTROSITY }, + { BOSS_CHOGALL, DATA_CHOGALL }, + { BOSS_SINESTRA, DATA_SINESTRA }, + { NPC_PROTO_BEHEMOTH, DATA_PROTO_BEHEMOTH }, + { NPC_ASCENDANT_COUNCIL_CONTROLLER, DATA_ASCENDANT_COUNCIL_CONTROLLER }, + { 0, 0 } // END }; ObjectData const gameobjectData[] = @@ -154,6 +155,13 @@ class instance_bastion_of_twilight : public InstanceMapScript case NPC_UNSTABLE_TWILIGHT: _unstableTwilightGUIDs.insert(creature->GetGUID()); break; + case BOSS_FELUDIUS: + case BOSS_IGNACIOUS: + case BOSS_ARION: + case BOSS_TERRASTRA: + if (creature->isDead() && GetBossState(DATA_ASCENDANT_COUNCIL) != DONE) + creature->Respawn(); + break; default: break; } diff --git a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp index 65fe09d8d65..02a6cc3cfb2 100644 --- a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp +++ b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp @@ -28,6 +28,7 @@ void AddSC_instance_baradin_hold(); void AddSC_bastion_of_twilight(); //Bastion of Twilight void AddSC_boss_halfus_wyrmbreaker(); void AddSC_boss_theralion_and_valiona(); +void AddSC_boss_ascendant_council(); void AddSC_instance_bastion_of_twilight(); void AddSC_boss_romogg_bonecrusher(); //Blackrock Caverns void AddSC_boss_corla(); @@ -241,6 +242,7 @@ void AddEasternKingdomsScripts() AddSC_bastion_of_twilight(); //Bastion of Twilight AddSC_boss_halfus_wyrmbreaker(); AddSC_boss_theralion_and_valiona(); + AddSC_boss_ascendant_council(); AddSC_instance_bastion_of_twilight(); AddSC_boss_romogg_bonecrusher(); //Blackrock Caverns AddSC_boss_corla();