From 332a4ef45a21fc17ba1f9bbf64def66d2bbb7e54 Mon Sep 17 00:00:00 2001 From: Ovahlord Date: Tue, 21 Aug 2018 19:04:51 +0200 Subject: [PATCH] Scripts/TotT: implement Ozumat encounter --- .../custom/custom_2018_08_21_00_world.sql | 156 ++++ src/server/game/Spells/SpellMgr.cpp | 44 + .../ThroneOfTheTides/boss_ozumat.cpp | 874 ++++++++++++++++++ .../instance_throne_of_the_todes.cpp | 49 +- .../ThroneOfTheTides/throne_of_the_tides.cpp | 19 +- .../ThroneOfTheTides/throne_of_the_tides.h | 66 +- 6 files changed, 1179 insertions(+), 29 deletions(-) create mode 100644 sql/updates/world/custom/custom_2018_08_21_00_world.sql diff --git a/sql/updates/world/custom/custom_2018_08_21_00_world.sql b/sql/updates/world/custom/custom_2018_08_21_00_world.sql new file mode 100644 index 00000000000..bab3a185e68 --- /dev/null +++ b/sql/updates/world/custom/custom_2018_08_21_00_world.sql @@ -0,0 +1,156 @@ +-- Template Updates +-- Ozumat +UPDATE `creature_template` SET `InhabitType`= 4, `ScriptName`= 'boss_ozumat', `mechanic_immune_mask`= 617299839 WHERE `entry`= 44566; +UPDATE `creature_template` SET `minlevel`= 87, `maxlevel`= 87, `InhabitType`= 4, `VehicleId`= 1438, `mechanic_immune_mask`= 617299839, `flags_extra`= 1 WHERE `entry`= 49097; +-- Neptulon +UPDATE `creature_template` SET `difficulty_entry_1`= 49094, `ScriptName`= 'npc_ozumat_neptulon' WHERE `entry`= 40792; +UPDATE `creature_template` SET `minlevel`= 86, `maxlevel`= 86, `exp`= 3, `gossip_menu_id`= 11469, `faction`= 2263, `npcflag`= 1, `unit_flags`= 32768 WHERE `entry`= 49094; +-- Ozumat Combat Trigger +UPDATE `creature_template` SET `unit_flags`= 34080768, `InhabitType`= 12, `flags_extra`= 128 WHERE `entry` IN (44864, 49099); +-- Ozumat Add Spawner +UPDATE `creature_template` SET `unit_flags`= 33554432, `InhabitType`= 4, `flags_extra`= 128 WHERE `entry`= 44656; +-- Deep Murloc Invader +UPDATE `creature_template` SET `exp`= 3, `difficulty_entry_1`= 49068, `InhabitType`= 1, `flags_extra`= 512, `DamageModifier`= 4, `BaseVariance`= 0.5 WHERE `entry`= 44658; +UPDATE `creature_template` SET `minlevel`= 86, `maxlevel`= 86, `exp`= 3, `faction`= 1771, `InhabitType`= 1, `flags_extra`= 512, `DamageModifier`= 8, `BaseVariance`= 0.5 WHERE `entry`= 49068; +-- Vicious Mindlasher +UPDATE `creature_template` SET `difficulty_entry_1`= 49107, `unit_class`= 2, `InhabitType`= 1, `flags_extra`= 512, `ScriptName`= 'npc_ozumat_vicious_mindlasher' WHERE `entry`= 44715; +UPDATE `creature_template` SET `minlevel`= 86, `maxlevel`= 86, `exp`= 3, `faction`= 1771, `unit_class`= 2, `InhabitType`= 1, `flags_extra`= 512 WHERE `entry`= 49107; +-- Unyielding Behemoth +UPDATE `creature_template` SET `difficulty_entry_1`= 49104, `InhabitType`= 1, `flags_extra`= 512 | 0x40000000, `VehicleId`= 1066, `DamageModifier`= 15, `BaseVariance`= 0.5, `mechanic_immune_mask`= 617299839, `ScriptName`= 'npc_ozumat_unyielding_behemoth' WHERE `entry`= 44648; +UPDATE `creature_template` SET `minlevel`= 86, `maxlevel`= 86, `exp`= 3, `faction`= 1771, `InhabitType`= 1, `flags_extra`= 512 | 0x40000000, `VehicleId`= 1066, `DamageModifier`= 30, `BaseVariance`= 0.5,`mechanic_immune_mask`= 617299839 WHERE `entry`= 49104; +-- Unyielding Behemoth (Hand Visual) +UPDATE `creature_template` SET `unit_flags`= 33554496, `flags_extra`= 128 WHERE `entry`= 44950; +-- Unyielding Behemoth (Leap Vehicle) +UPDATE `creature_template` SET `unit_flags`= 33554496, `unit_flags2`= 2099200, `InhabitType`= 4, `flags_extra`= 128, `VehicleId`= 1065 WHERE `entry`= 44949; +-- Faceless Sapper +UPDATE `creature_template` SET `difficulty_entry_1`= 49073, `InhabitType`= 1, `flags_extra`= 512 | 0x40000000, `mechanic_immune_mask`= 617299839 WHERE `entry`= 44752; +UPDATE `creature_template` SET `minlevel`= 86, `maxlevel`= 86, `exp`= 3, `faction`= 1771, `unit_flags2`= 32, `InhabitType`= 1, `flags_extra`= 512 | 0x40000000, `mechanic_immune_mask`= 617299839 WHERE `entry`= 49073; +-- Blight Beast +UPDATE `creature_template` SET `difficulty_entry_1`= 49061, `InhabitType`= 1, `flags_extra`= 512, `speed_run`= 0.57142, `DamageModifier`= 15, `BaseVariance`= 0.5 WHERE `entry`= 44841; +UPDATE `creature_template` SET `minlevel`= 86, `maxlevel`= 86, `exp`= 3, `faction`= 1771, `InhabitType`= 1, `flags_extra`= 512, `speed_run`= 0.57142, `DamageModifier`= 30, `BaseVariance`= 0.5 WHERE `entry`= 49061; +-- Blight of Ozumat +UPDATE `creature_template` SET `unit_flags`= 33554432, `flags_extra`= 128 WHERE `entry` IN (44801, 49062); +-- Blight of Ozumat 2 +UPDATE `creature_template` SET `unit_flags`= 33554432, `flags_extra`= 128 WHERE `entry` IN (44834, 49063); + +-- Template Addons +DELETE FROM `creature_template_addon` WHERE `entry` IN (44841, 44801, 49062, 44834, 49063); +INSERT INTO `creature_template_addon` (`entry`, `auras`) VALUES +(44841, '83665'), +(44801, '83525'), +(49062, '83525'), +(44834, '83607'), +(49063, '83607'); + +-- Spells +DELETE FROM `spell_script_names` WHERE `ScriptName` IN +('spell_ozumat_charge_to_window', +'spell_ozumat_jump_to_ground', +'spell_ozumat_shadow_blast', +'spell_ozumat_shadow_blast_missile', +'spell_ozumat_blight_of_ozumat'); +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(83240, 'spell_ozumat_charge_to_window'), +(83241, 'spell_ozumat_jump_to_ground'), +(83653, 'spell_ozumat_charge_to_window'), +(83652, 'spell_ozumat_jump_to_ground'), +(83929, 'spell_ozumat_shadow_blast'), +(83931, 'spell_ozumat_shadow_blast_missile'), +(83518, 'spell_ozumat_blight_of_ozumat'); + +-- Gossips +DELETE FROM `gossip_menu_option` WHERE (`MenuID`=11469 AND `OptionID`=0); +INSERT INTO `gossip_menu_option` (`MenuID`, `OptionID`, `OptionIcon`, `OptionText`, `OptionType`, `OptionNpcFlag`, `OptionBroadcastTextId`) VALUES +(11469, 0, 0, 'We are ready!', 1, 1, 41133); + +-- Spellclicks +DELETE FROM `npc_spellclick_spells` WHERE `npc_entry` IN (44648); +INSERT INTO `npc_spellclick_spells` (`npc_entry`, `spell_id`, `cast_flags`, `user_type`) VALUES +(44648, 46598, 1, 1); + +-- Vehicle Accessories +DELETE FROM `vehicle_template_accessory` WHERE `entry` IN (44648); +INSERT INTO `vehicle_template_accessory` (`entry`, `accessory_entry`, `seat_id`, `minion`, `description`, `summontype`, `summontimer`) VALUES +(44648, 44950, 0, 1, 'Unyielding Behemoth - Hand Visual', 8, 0); + +-- Texts +DELETE FROM `creature_text` WHERE `CreatureID`= 40792; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `comment`) VALUES +(40792, 0, 0, 'Ahh - my fearless assistants, I assume.', 14, 0, 100, 0, 0, 19469, 44263, 'Neptulon - Intro 1'), +(40792, 1, 0, 'You may yet regret your presence here.', 14, 0, 100, 0, 0, 19470, 44264, 'Neptulon - Intro 2'), +(40792, 2, 0, 'As I purify these waters, the servants of filth will surely be stirred. Beware!', 14, 0, 100, 0, 0, 19471, 44265, 'Neptulon - Purify Waters 1'), +(40792, 3, 0, 'Patience, guests. The waters are nearly cleansed.', 14, 0, 100, 0, 0, 19475, 44269, 'Neptulon - Purify Waters 2'), +(40792, 4, 0, 'The beast has returned! It must not pollute my waters!', 14, 0, 100, 0, 0, 19476, 44270, 'Neptulon to Player'), +(40792, 5, 0, 'Augh... Their filthiness stains me!', 14, 0, 100, 0, 0, 19472, 44266, 'Neptulon to Player'), +(40792, 6, 0, 'My waters are cleansed! Drink in their power!', 14, 0, 100, 0, 0, 19478, 44272, 'Neptulon to Player'), +(40792, 7, 0, 'Behold the power of pure water!', 14, 0, 100, 0, 0, 19477, 44271, 'Neptulon to Player'), +(40792, 8, 0, 'Ozumat is vulnerable, strike now!', 41, 0, 100, 0, 0, 19477, 50863, 'Neptulon to Player'); + +-- Conditions +DELETE FROM `conditions` WHERE `SourceEntry` IN (76953, 83360, 83441, 83240, 83241, 83437, 83977, 83463, 83648, 83653, 83652, 83606, 84037, 94171, 94170) AND `SourceTypeOrReferenceId`= 13; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ScriptName`, `Comment`) VALUES +(13, 1, 76953, 0, 0, 31, 0, 3, 36171, 0, 0, 0, '', 'Purify - Target World Trigger'), +(13, 1, 83360, 0, 0, 31, 0, 3, 44656, 0, 0, 0, '', 'Summon Murloc Add Trigger - Target Ozumat Add Spawner'), +(13, 1, 83441, 0, 0, 31, 0, 3, 44656, 0, 0, 0, '', 'Summon Caster Add Trigger - Target Ozumat Add Spawner'), +(13, 1, 83648, 0, 0, 31, 0, 3, 44656, 0, 0, 0, '', 'Summon Kite Add Trigger - Target Ozumat Add Spawner'), +(13, 1, 83437, 0, 0, 31, 0, 3, 44656, 0, 0, 0, '', 'Summon Öt Add Trigger - Target Ozumat Add Spawner'), +(13, 1, 83240, 0, 0, 31, 0, 3, 40792, 0, 0, 0, '', 'Charge to window - Target Neptulon'), +(13, 1, 83241, 0, 0, 31, 0, 3, 40792, 0, 0, 0, '', 'Jump to ground - Target Neptulon'), +(13, 1, 83653, 0, 0, 31, 0, 3, 40792, 0, 0, 0, '', 'Charge to window - Target Neptulon'), +(13, 1, 83652, 0, 0, 31, 0, 3, 40792, 0, 0, 0, '', 'Jump to ground - Target Neptulon'), +(13, 1, 83463, 0, 0, 31, 0, 3, 40792, 0, 0, 0, '', 'Entangling Grasp - Target Neptulon'), +(13, 1, 94170, 0, 0, 31, 0, 3, 40792, 0, 0, 0, '', 'Grab Neptulon - Target Neptulon'), +(13, 1, 83977, 0, 0, 31, 0, 3, 44950, 0, 0, 0, '', 'Shadow Blast - Target Unyielding Behemoth (Hand Visual)'), +(13, 1, 83606, 0, 0, 31, 0, 3, 36171, 254898, 0, 0, '', 'Purify - Target World Trigger'), +(13, 1, 84037, 0, 0, 31, 0, 3, 44566, 0, 0, 0, '', 'Pure Water - Target Ozumat'), +(13, 1, 94171, 0, 0, 31, 0, 3, 44566, 0, 0, 0, '', 'Grab Neptulon - Target Ozumat'); + +-- Areatriggers +DELETE FROM `areatrigger_scripts` WHERE `entry`= 6646; +INSERT INTO `areatrigger_scripts` (`entry`, `ScriptName`) VALUES +(6646, 'at_tott_neptulon_intro'); + +-- Delete Encounter Related Creatures +DELETE FROM `creature` WHERE `guid` IN (255404, 254949, 255407, 254956); +DELETE FROM `creature_addon` WHERE `guid` IN (255404, 254949, 255407, 254956); + +-- Currency Loot +DELETE FROM `creature_onkill_reward` WHERE `creature_id`= 49097; +INSERT INTO `creature_onkill_reward` (`creature_id`, `CurrencyId1`, `CurrencyCount1`) VALUES +(49097, 395, 7000); + +-- Loot +UPDATE `gameobject_template_addon`SET `flags`= 16,`mingold`= 19800, `maxgold`= 20000 WHERE `entry` IN (205216, 207973); + +DELETE FROM `gameobject_loot_template` WHERE `Entry` IN (29711, 36142); +DELETE FROM `reference_loot_template` WHERE `Entry` IN (297110, 361420); +INSERT INTO `gameobject_loot_template` (`Entry`, `Chance`, `LootMode`, `Reference`, `MinCount`, `MaxCount`) VALUES +(29711, 100, 1, 448190, 2, 2); + +INSERT INTO `gameobject_loot_template` (`Entry`, `Item`, `Chance`, `LootMode`, `Reference`, `MinCount`, `MaxCount`) VALUES +(36142, 52078, 100, 1, 0, 1, 1), -- Chaos Orb +(36142, 361420, 100, 1, 361420, 2, 2); + +INSERT INTO `reference_loot_template` (`Entry`, `Item`, `Chance`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`) VALUES +(297110, 55252, 0, 1, 1, 1, 1), +(297110, 55259, 0, 1, 1, 1, 1), +(297110, 55258, 0, 1, 1, 1, 1), +(297110, 55254, 0, 1, 1, 1, 1), +(297110, 55253, 0, 1, 1, 1, 1), +(297110, 55255, 0, 1, 1, 1, 1), +(297110, 55249, 0, 1, 1, 1, 1), +(297110, 55250, 0, 1, 1, 1, 1), +(297110, 55251, 0, 1, 1, 1, 1), +(297110, 55256, 0, 1, 1, 1, 1); + +INSERT INTO `reference_loot_template` (`Entry`, `Item`, `Chance`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`) VALUES +(361420, 56284, 0, 1, 1, 1, 1), +(361420, 56289, 0, 1, 1, 1, 1), +(361420, 56288, 0, 1, 1, 1, 1), +(361420, 56291, 0, 1, 1, 1, 1), +(361420, 56281, 0, 1, 1, 1, 1), +(361420, 56286, 0, 1, 1, 1, 1), +(361420, 56283, 0, 1, 1, 1, 1), +(361420, 56282, 0, 1, 1, 1, 1), +(361420, 56285, 0, 1, 1, 1, 1), +(361420, 56290, 0, 1, 1, 1, 1); diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 81b0cdeea8f..e14b867f49f 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -4384,6 +4384,50 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_1_YARD); }); + // Ozumat + // Purify + ApplySpellFix({ 76953 }, [](SpellInfo* spellInfo) + { + spellInfo->MaxAffectedTargets = 5; + spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_100_YARDS); + }); + + // Summon Murloc Add Trigger + ApplySpellFix({ 83360 }, [](SpellInfo* spellInfo) + { + spellInfo->MaxAffectedTargets = 1; + }); + + // Summon Caster Add Trigger + ApplySpellFix({ 83441 }, [](SpellInfo* spellInfo) + { + spellInfo->MaxAffectedTargets = 1; + }); + + // Summon Lt Add Trigger + ApplySpellFix({ 83437 }, [](SpellInfo* spellInfo) + { + spellInfo->MaxAffectedTargets = 1; + }); + + // Summon Kite Add Trigger + ApplySpellFix({ 83648 }, [](SpellInfo* spellInfo) + { + spellInfo->MaxAffectedTargets = 1; + }); + + // Blight of Ozumat + ApplySpellFix({ 83518 }, [](SpellInfo* spellInfo) + { + spellInfo->MaxAffectedTargets = 1; + }); + + // Grab Neptulon + ApplySpellFix({ 94171 }, [](SpellInfo* spellInfo) + { + spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(6); // 100yd + }); + // END OF THRONE OF THE TIDES SPELLS // diff --git a/src/server/scripts/EasternKingdoms/ThroneOfTheTides/boss_ozumat.cpp b/src/server/scripts/EasternKingdoms/ThroneOfTheTides/boss_ozumat.cpp index 1cf5b951a1a..15df8b3216e 100644 --- a/src/server/scripts/EasternKingdoms/ThroneOfTheTides/boss_ozumat.cpp +++ b/src/server/scripts/EasternKingdoms/ThroneOfTheTides/boss_ozumat.cpp @@ -15,6 +15,880 @@ * with this program. If not, see . */ +#include "ScriptMgr.h" +#include "throne_of_the_tides.h" +#include "GameObject.h" +#include "MoveSpline.h" +#include "ObjectMgr.h" +#include "PassiveAI.h" +#include "ScriptedCreature.h" +#include "Spell.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" +#include "SpellMgr.h" +#include "Vehicle.h" + +enum Texts +{ + // Neptulon + SAY_INTRO_1 = 0, + SAY_INTRO_2 = 1, + SAY_PURIFY_WATERS_1 = 2, + SAY_PURIFY_WATERS_2 = 3, + SAY_OZUMAT_RETURNED = 4, + SAY_STUNNED = 5, + SAY_WATERS_CLEANSED_1 = 6, + SAY_WATERS_CLEANSED_2 = 7, + SAY_ANNOUNCE_OZUMAT_VULNERABLE = 8 +}; + +enum Spells +{ + // Neptulon + SPELL_PURIFY = 76952, + SPELL_PURE_WATER = 84037, + SPELL_TIDAL_SURGE_1 = 76133, + SPELL_TIDAL_SURGE_2 = 76155, + SPELL_CLEAR_TIDAL_SURGE = 83909, + + // Ozumat + SPELL_OZUMAT_GLOBE_IMPACT_PERIODIC = 83126, + SPELL_OZUMAT_RIDE_AURA = 83119, + SPELL_BLIGHT_OF_OZUMAT = 83585, + SPELL_BLIGHT_OF_OZUMAT_CHANNEL = 83672, + SPELL_SUMMON_BLIGHT_OF_OZUMAT = 83606, + SPELL_SUMMON_CHEST_VISUAL = 84074, + SPELL_GRAB_NEPTULON = 94170, + + // Phase 1 Adds + SPELL_CHARGE_TO_WINDOW = 83240, + + // Vicious Mindlasher + SPELL_SHADOW_BOLT = 83914, + SPELL_BRAIN_SPIKE = 83915, + SPELL_VEIL_OF_SHADOW = 83926, + + // Unyielding Behemoth + SPELL_SHADOW_BLAST = 83929, + SPELL_SHADOW_BLAST_RIDE_VEHICLE = 83975, + SPELL_SHADOW_BLAST_VISUAL = 83977, + SPELL_SHADOW_BLAST_MISSILE = 83931, + SPELL_SHRINK = 83976, + SPELL_BLIGHT_SPRAY = 83985, + + // Faceless Sapper + SPELL_WATER_EXPLOSION_DOWN = 83479, + SPELL_ENTANGLING_GRASP = 83463, + + // World Trigger (Friendly + Invis Man) + SPELL_SUMMON_MURLOC_ADD_PERIODIC = 83357, + SPELL_SUMMON_CASTER_ADD_PERIODIC = 83440, + SPELL_SUMMON_KITE_ADD_PERIODIC = 83649, + SPELL_SUMMON_LT_ADD_EFFECT = 83436 +}; + +enum Events +{ + // Neptulon + EVENT_TALK_INTRO = 1, + EVENT_PURIFY, + EVENT_APPLY_CASTER_PERIODIC, + EVENT_CAST_LT_EFFECT, + EVENT_TALK_PURIFY_2, + EVENT_SUMMON_OZUMAT, + EVENT_TALK_OZUMAT_RETURNED, + EVENT_SUMMON_FACELESS_SAPPERS, + EVENT_TALK_STUNNED, + EVENT_APPLY_KITE_PERIODIC, + EVENT_TIDAL_SURGE_1, + EVENT_TIDAL_SURGE_2, + EVENT_MAKE_OZUMAT_ATTACKABLE, + EVENT_PURE_WATER, + + // Ozumat + EVENT_GLOBE_IMPACT, + EVENT_BLIGHT_OF_OZUMAT, + EVENT_CHANGE_SEAT, + EVENT_SWIM_AWAY, + EVENT_COMPLETE_ENCOUNTER, + + // Vicious Mindlasher + EVENT_BRAIN_SPIKE, + EVENT_VEIL_OF_SHADOW, + + // Unyielding Behemoth + EVENT_BLIGHT_SPRAY, + EVENT_SHADOW_BLAST, + EVENT_SHADOW_BLAST_VISUAL, + EVENT_DISABLE_HOVER_ANIM, + EVENT_FINISH_SHADOW_BLAST +}; + +enum Actions +{ + ACTION_FACELESS_DIED = 0, + // ACTION_CORAL_GARDEN_ENTERED = 1, + ACTION_COMPLETE_ENCOUNTER = 2 +}; + +enum MovePoints +{ + POINT_NONE = 0 +}; + +enum GossipMenu +{ + GOSSIP_OPTION_START_ENCOUNTER = 0 +}; + +enum VehicleSeats +{ + SEAT_0 = 0, + SEAT_1 = 1 +}; + +class ChargeToWindowEvent : public BasicEvent +{ + public: + ChargeToWindowEvent(Creature* owner) : _owner(owner) { } + + bool Execute(uint64 /*time*/, uint32 /*diff*/) override + { + _owner->CastSpell(_owner, SPELL_CHARGE_TO_WINDOW); + return true; + } + + private: + Creature* _owner; +}; + +class EntanglingGraspEvent : public BasicEvent +{ + public: + EntanglingGraspEvent(Creature* owner) : _owner(owner) { } + + bool Execute(uint64 /*time*/, uint32 /*diff*/) override + { + _owner->CastSpell(_owner, SPELL_ENTANGLING_GRASP); + return true; + } + + private: + Creature* _owner; +}; + +class AttackNeptulonEvent : public BasicEvent +{ + public: + AttackNeptulonEvent(Creature* owner) : _owner(owner) { } + + bool Execute(uint64 /*time*/, uint32 /*diff*/) override + { + if (InstanceScript* instance = _owner->GetInstanceScript()) + { + if (Creature* neptulon = instance->GetCreature(DATA_NEPTULON)) + { + _owner->SetReactState(REACT_AGGRESSIVE); + if (_owner->IsAIEnabled) + { + if (_owner->GetEntry() == NPC_UNYIELDING_BEHEMOTH + || _owner->GetEntry() == NPC_VICIOUS_MINDLASHER + || _owner->GetEntry() == NPC_BLIGHT_BEAST) + _owner->AI()->DoZoneInCombat(); + else + _owner->AI()->AttackStart(neptulon); + } + } + } + return true; + } + private: + Creature* _owner; +}; + +Position const OzumatCombatTriggerPos = { -153.333f, 982.807f, 229.5483f, 2.792527f }; +Position const WorldTriggerFriendlyPos = { -147.439f, 981.911f, 230.3853f, 0.0f }; +Position const OzumatPos = { -64.0677f, 845.455f, 310.6913f, 2.181662f }; +Position const AddSpawnerPosLeft = { -65.9722f, 1031.8f, 257.2863f }; +Position const WindowChargePos1 = { -95.2135f, 1014.13f, 253.908f }; +Position const WindowChargePos2 = { -127.332f, 930.429f, 253.371f }; +Position const GroundJumpPos1 = { -122.5607f, 1001.56f, 230.2997f }; +Position const GroundJumpPos2 = { -137.7711f, 952.5314f, 231.0441f }; +Position const OzumatVehicleEscapePos = { 69.08652f, 746.204f, 423.8753f }; +Position const NeptulonsCachePos = { -157.986f, 982.238f, 229.131f, 2.984498f }; +QuaternionData const NeptulonsCacheRot = QuaternionData(0.0f, 0.0f, 0.9969168f, 0.07846643f); + +Position const OzumatAddSpawnerPositions[] = +{ + { -103.066f, 910.313f, 263.1674f, 2.164208f }, + { -65.9722f, 1031.8f, 257.2863f, 3.926991f } +}; + +Position const FacelessSapperPositions[] = +{ + { -168.227f, 963.314f, 306.8248f, 0.4886922f }, + { -125.307f, 1004.49f, 306.9727f, 3.892084f }, + { -166.064f, 1005.38f, 307.5078f, 5.393067f } +}; + +struct boss_ozumat : public BossAI +{ + boss_ozumat(Creature* creature) : BossAI(creature, DATA_OZUMAT) + { + Initialize(); + } + + void Initialize() + { + _dead = false; + me->SetReactState(REACT_PASSIVE); + } + + void Reset() override + { + events.ScheduleEvent(EVENT_GLOBE_IMPACT, 2s + 500ms); + events.ScheduleEvent(EVENT_BLIGHT_OF_OZUMAT, 3s + 500ms); + } + + void DamageTaken(Unit* /*attacker*/, uint32 &damage) override + { + if (damage >= me->GetHealth()) + { + damage = me->GetHealth() - 1; + if (!_dead) + { + me->InterruptNonMeleeSpells(false); + DoCastSelf(SPELL_GRAB_NEPTULON); + if (Creature* neptulon = instance->GetCreature(DATA_NEPTULON)) + neptulon->AI()->DoAction(ACTION_COMPLETE_ENCOUNTER); + + if (GameObject* cache = me->SummonGameObject(IsHeroic() ? GO_NEPTULONS_CACHE_HEROIC : GO_NEPTULONS_CACHE_NORMAL, NeptulonsCachePos, NeptulonsCacheRot, WEEK, GO_SUMMON_TIMED_DESPAWN)) + cache->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + + events.ScheduleEvent(EVENT_CHANGE_SEAT, 3s + 500ms); + _dead = true; + } + } + } + + void UpdateAI(uint32 diff) override + { + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_GLOBE_IMPACT: + DoCastSelf(SPELL_OZUMAT_GLOBE_IMPACT_PERIODIC); + if (Creature* vehicle = instance->GetCreature(DATA_OZUMAT_VEHICLE)) + DoCast(vehicle, SPELL_OZUMAT_RIDE_AURA); + break; + case EVENT_BLIGHT_OF_OZUMAT: + DoZoneInCombat(); + DoCastSelf(SPELL_BLIGHT_OF_OZUMAT); + break; + case EVENT_CHANGE_SEAT: + DoCastAOE(SPELL_SUMMON_CHEST_VISUAL); + if (Creature* vehicle = instance->GetCreature(DATA_OZUMAT_VEHICLE)) + me->EnterVehicle(vehicle, SEAT_1); + + events.ScheduleEvent(EVENT_SWIM_AWAY, 1s); + break; + case EVENT_SWIM_AWAY: + if (Creature* vehicle = me->GetVehicleCreatureBase()) + vehicle->GetMotionMaster()->MovePoint(0, OzumatVehicleEscapePos, false); + events.ScheduleEvent(EVENT_COMPLETE_ENCOUNTER, 5s); + break; + case EVENT_COMPLETE_ENCOUNTER: + DoCastAOE(SPELL_CLEAR_TIDAL_SURGE, true); + if (Creature* neptulon = instance->GetCreature(DATA_NEPTULON)) + { + instance->SetBossState(DATA_OZUMAT, DONE); + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, neptulon); + + if (IsHeroic()) + instance->instance->PermBindAllPlayers(); + + neptulon->DespawnOrUnsummon(); + + if (Player* player = me->SelectNearestPlayer(500.0f)) + player->RewardPlayerAndGroupAtKill(me, false); + + me->DespawnOrUnsummon(); + } + break; + default: + break; + } + } + } +private: + bool _dead; +}; + +struct npc_ozumat_neptulon : public ScriptedAI +{ + npc_ozumat_neptulon(Creature* creature) : ScriptedAI(creature), _instance(me->GetInstanceScript()), _summons(me) + { + Initialize(); + } + + void Initialize() + { + _deadAddsCount = 0; + _friendlyTriggerGUID = ObjectGuid::Empty; + } + + void AttackStart(Unit* /*who*/) override { } + + void Reset() override + { + Initialize(); + _instance->SetBossState(DATA_OZUMAT, NOT_STARTED); + } + + void EnterEvadeMode(EvadeReason why) override + { + if (why != EVADE_REASON_OTHER) + return; + + _EnterEvadeMode(); + _summons.DespawnAll(); + _instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + _instance->SetBossState(DATA_OZUMAT, FAIL); + DoCastAOE(SPELL_CLEAR_TIDAL_SURGE); + me->DespawnOrUnsummon(0, 30s); + } + + void JustDied(Unit* /*killer*/) override + { + _summons.DespawnAll(); + _instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + _instance->SetBossState(DATA_OZUMAT, FAIL); + DoCastAOE(SPELL_CLEAR_TIDAL_SURGE); + me->DespawnOrUnsummon(0, 30s); + } + + bool GossipSelect(Player* /*player*/, uint32 /*menuId*/, uint32 gossipListId) override + { + if (gossipListId == GOSSIP_OPTION_START_ENCOUNTER) + { + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + me->SetFacingTo(0.1396263f); + + _instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1); + _instance->SetBossState(DATA_OZUMAT, IN_PROGRESS); + + DoSummon(NPC_OZUMAT_COMBAT_TRIGGER, OzumatCombatTriggerPos); + + for (uint8 i = 0; i < 2; i++) + DoSummon(NPC_OZUMAT_ADD_SPAWNER, OzumatAddSpawnerPositions[i]); + + if (Creature* friendlyTrigger = DoSummon(NPC_WORLD_TRIGGER_FRIENDLY, WorldTriggerFriendlyPos)) + { + _friendlyTriggerGUID = friendlyTrigger->GetGUID(); + friendlyTrigger->CastSpell(friendlyTrigger, SPELL_SUMMON_MURLOC_ADD_PERIODIC); + } + + _events.CancelEvent(EVENT_TALK_INTRO); + _events.ScheduleEvent(EVENT_PURIFY, 1s); + _events.ScheduleEvent(EVENT_CAST_LT_EFFECT, 20s, 22s); + _events.ScheduleEvent(EVENT_APPLY_CASTER_PERIODIC, 5s); + } + + return false; + } + + void DoAction(int32 action) override + { + switch (action) + { + case ACTION_CORAL_GARDEN_ENTERED: + Talk(SAY_INTRO_1); + _events.ScheduleEvent(EVENT_TALK_INTRO, 7s); + break; + case ACTION_FACELESS_DIED: + _deadAddsCount++; + if (_deadAddsCount == 4) + { + _events.ScheduleEvent(EVENT_SUMMON_OZUMAT, 3s); + _events.ScheduleEvent(EVENT_TALK_OZUMAT_RETURNED, 200ms); + _events.ScheduleEvent(EVENT_SUMMON_FACELESS_SAPPERS, 4s + 500ms); + _events.ScheduleEvent(EVENT_APPLY_KITE_PERIODIC, 9s); + } + break; + case ACTION_COMPLETE_ENCOUNTER: + for (ObjectGuid guid : _summons) + if (Creature* summon = ObjectAccessor::GetCreature(*me, guid)) + if (summon->GetEntry() != BOSS_OZUMAT) + summon->DespawnOrUnsummon(); + + _events.Reset(); + break; + default: + break; + } + + } + + void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override + { + if (summon->GetEntry() == NPC_FACELESS_SAPPER) + { + _deadAddsCount++; + if (_deadAddsCount == 7) + { + if (Creature* friendlyTrigger = ObjectAccessor::GetCreature(*me, _friendlyTriggerGUID)) + friendlyTrigger->RemoveAllAuras(); + + if (Creature* ozumat = _instance->GetCreature(DATA_OZUMAT)) + ozumat->RemoveAurasDueToSpell(SPELL_BLIGHT_OF_OZUMAT); + + _summons.DespawnEntry(NPC_OZUMAT_ADD_SPAWNER); + _events.ScheduleEvent(EVENT_TIDAL_SURGE_1, 2s + 500ms); + } + } + } + + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override + { + if (spell->Id == SPELL_ENTANGLING_GRASP) + { + me->RemoveAurasDueToSpell(SPELL_PURIFY); + _events.RescheduleEvent(EVENT_TALK_STUNNED, 3s); + } + } + + void JustSummoned(Creature* summon) override + { + _summons.Summon(summon); + + switch (summon->GetEntry()) + { + case NPC_DEEP_MURLOC_INVADER: + case NPC_VICIOUS_MINDLASHER: + case NPC_UNYIELDING_BEHEMOTH: + summon->SetReactState(REACT_PASSIVE); + summon->SetDisableGravity(true); + summon->SendSetPlayHoverAnim(true); + summon->SetCorpseDelay(4); + summon->m_Events.AddEvent(new ChargeToWindowEvent(summon), summon->m_Events.CalculateTime(2 * IN_MILLISECONDS)); + break; + case NPC_BLIGHT_BEAST: + summon->SetReactState(REACT_PASSIVE); + summon->SetDisableGravity(true); + summon->SendSetPlayHoverAnim(true); + summon->SetCorpseDelay(4); + summon->m_Events.AddEvent(new ChargeToWindowEvent(summon), summon->m_Events.CalculateTime(2400)); + break; + case NPC_FACELESS_SAPPER: + summon->CastSpell(summon, SPELL_WATER_EXPLOSION_DOWN); + summon->SetReactState(REACT_PASSIVE); + summon->SetCorpseDelay(4); + summon->GetMotionMaster()->MoveFall(); + summon->m_Events.AddEvent(new EntanglingGraspEvent(summon), summon->m_Events.CalculateTime(3 * IN_MILLISECONDS)); + break; + case NPC_OZUMAT_COMBAT_TRIGGER: + summon->SetReactState(REACT_PASSIVE); + summon->SetCombatPulseDelay(1); + summon->AI()->DoZoneInCombat(); + break; + default: + break; + } + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_TALK_INTRO: + Talk(SAY_INTRO_2); + break; + case EVENT_PURIFY: + Talk(SAY_PURIFY_WATERS_1); + DoCastSelf(SPELL_PURIFY); + _events.ScheduleEvent(EVENT_TALK_PURIFY_2, 46s); + break; + case EVENT_APPLY_CASTER_PERIODIC: + if (Creature* friendlyTrigger = ObjectAccessor::GetCreature(*me, _friendlyTriggerGUID)) + friendlyTrigger->CastSpell(friendlyTrigger, SPELL_SUMMON_CASTER_ADD_PERIODIC); + break; + case EVENT_CAST_LT_EFFECT: + if (Creature* friendlyTrigger = ObjectAccessor::GetCreature(*me, _friendlyTriggerGUID)) + friendlyTrigger->CastSpell(friendlyTrigger, SPELL_SUMMON_LT_ADD_EFFECT); + break; + case EVENT_TALK_PURIFY_2: + Talk(SAY_PURIFY_WATERS_2); + break; + case EVENT_SUMMON_OZUMAT: + DoSummon(BOSS_OZUMAT, OzumatPos); + break; + case EVENT_TALK_OZUMAT_RETURNED: + Talk(SAY_OZUMAT_RETURNED); + break; + case EVENT_SUMMON_FACELESS_SAPPERS: + for (uint8 i = 0; i < 3; i++) + DoSummon(NPC_FACELESS_SAPPER, FacelessSapperPositions[i]); + break; + case EVENT_TALK_STUNNED: + Talk(SAY_STUNNED); + break; + case EVENT_APPLY_KITE_PERIODIC: + if (Creature* friendlyTrigger = ObjectAccessor::GetCreature(*me, _friendlyTriggerGUID)) + friendlyTrigger->CastSpell(friendlyTrigger, SPELL_SUMMON_KITE_ADD_PERIODIC); + break; + case EVENT_TIDAL_SURGE_1: + if (Creature* ozumat = _instance->GetCreature(DATA_OZUMAT)) + { + ozumat->CastSpell(ozumat, SPELL_SUMMON_BLIGHT_OF_OZUMAT); + ozumat->CastSpell(ozumat, SPELL_BLIGHT_OF_OZUMAT_CHANNEL); + } + + Talk(SAY_WATERS_CLEANSED_1); + DoCastAOE(SPELL_TIDAL_SURGE_1); + _events.ScheduleEvent(EVENT_TIDAL_SURGE_2, 3s + 200ms); + break; + case EVENT_TIDAL_SURGE_2: + _instance->DoCastSpellOnPlayers(SPELL_TIDAL_SURGE_2); + _events.ScheduleEvent(EVENT_MAKE_OZUMAT_ATTACKABLE, 5s + 500ms); + break; + case EVENT_MAKE_OZUMAT_ATTACKABLE: + Talk(SAY_WATERS_CLEANSED_2); + Talk(SAY_ANNOUNCE_OZUMAT_VULNERABLE); + DoCastAOE(SPELL_PURE_WATER); + _events.ScheduleEvent(EVENT_PURE_WATER, 2s + 500ms); + break; + case EVENT_PURE_WATER: + DoCastAOE(SPELL_PURE_WATER); + _events.Repeat(2s + 500ms); + break; + default: + break; + } + } + } + +private: + InstanceScript* _instance; + SummonList _summons; + EventMap _events; + ObjectGuid _friendlyTriggerGUID; + uint8 _deadAddsCount; +}; + +struct npc_ozumat_vicious_mindlasher : public ScriptedAI +{ + npc_ozumat_vicious_mindlasher(Creature* creature) : ScriptedAI(creature), _instance(me->GetInstanceScript()) { } + + void AttackStart(Unit* who) override + { + if (!who) + return; + + AttackStartCaster(who, 20.0f); + } + + void JustEngagedWith(Unit* /*who*/) override + { + _events.ScheduleEvent(EVENT_BRAIN_SPIKE, 44s, 45s); + _events.ScheduleEvent(SPELL_VEIL_OF_SHADOW, 8s, 9s); + } + + void JustDied(Unit* /*killer*/) override + { + if (Creature* neptulon = _instance->GetCreature(DATA_NEPTULON)) + neptulon->AI()->DoAction(ACTION_FACELESS_DIED); + } + + 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_BRAIN_SPIKE: + DoCastAOE(SPELL_BRAIN_SPIKE); + break; + case SPELL_VEIL_OF_SHADOW: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f, true, 0)) + DoCast(target, SPELL_VEIL_OF_SHADOW); + break; + default: + break; + } + } + + DoSpellAttackIfReady(SPELL_SHADOW_BOLT); + } + +private: + InstanceScript* _instance; + EventMap _events; + +}; + +struct npc_ozumat_unyielding_behemoth : public ScriptedAI +{ + npc_ozumat_unyielding_behemoth(Creature* creature) : ScriptedAI(creature), _instance(me->GetInstanceScript()) { } + + void JustEngagedWith(Unit* /*who*/) override + { + _events.ScheduleEvent(EVENT_SHADOW_BLAST, 10s); + } + + void JustDied(Unit* /*killer*/) override + { + if (Creature* neptulon = _instance->GetCreature(DATA_NEPTULON)) + neptulon->AI()->DoAction(ACTION_FACELESS_DIED); + } + + void PassengerBoarded(Unit* who, int8 /*seatId*/, bool apply) override + { + if (!who || !apply) + return; + + who->CastSpell(who, SPELL_SHRINK); + } + + void JustSummoned(Creature* summon) override + { + if (summon->GetEntry() == NPC_UNYIELDING_BEHEMOTH_LEAP_VEHICLE) + { + me->AttackStop(); + me->SetReactState(REACT_PASSIVE); + me->SetDisableGravity(true); + me->SendSetPlayHoverAnim(true); + DoCast(summon, SPELL_SHADOW_BLAST_RIDE_VEHICLE); + _events.ScheduleEvent(EVENT_DISABLE_HOVER_ANIM, 400ms); + _events.ScheduleEvent(EVENT_SHADOW_BLAST_VISUAL, 1s + 200ms); + _events.ScheduleEvent(EVENT_FINISH_SHADOW_BLAST, 6s); + } + } + + void SpellHitTarget(Unit* target, SpellInfo const* spell) override + { + if (spell->Id == SPELL_SHADOW_BLAST_VISUAL) + target->RemoveAurasDueToSpell(SPELL_SHRINK); + } + + 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_BLIGHT_SPRAY: + DoCastVictim(SPELL_BLIGHT_SPRAY); + break; + case EVENT_SHADOW_BLAST: + DoCastAOE(SPELL_SHADOW_BLAST); + break; + case EVENT_DISABLE_HOVER_ANIM: + me->SendSetPlayHoverAnim(false); + break; + case EVENT_SHADOW_BLAST_VISUAL: + DoCastAOE(SPELL_SHADOW_BLAST_VISUAL); + break; + case EVENT_FINISH_SHADOW_BLAST: + me->SetDisableGravity(false); + me->SendSetPlayHoverAnim(false); + me->SetReactState(REACT_AGGRESSIVE); + if (Unit* victim = me->GetVictim()) + AttackStart(victim); + + _events.ScheduleEvent(EVENT_BLIGHT_SPRAY, 100ms); + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); + } + +private: + InstanceScript* _instance; + EventMap _events; +}; + +class spell_ozumat_charge_to_window : public SpellScript +{ + PrepareSpellScript(spell_ozumat_charge_to_window); + + void SetDest(SpellDestination& dest) + { + if (Unit* caster = GetCaster()) + { + if (caster->GetDistance(AddSpawnerPosLeft) < 1.0f) + dest.Relocate(WindowChargePos1); + else + dest.Relocate(WindowChargePos2); + } + } + + void Register() + { + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_ozumat_charge_to_window::SetDest, EFFECT_0, TARGET_DEST_NEARBY_ENTRY); + } +}; + +class spell_ozumat_jump_to_ground : public SpellScript +{ + PrepareSpellScript(spell_ozumat_jump_to_ground); + + void SetDest(SpellDestination& dest) + { + if (Unit* caster = GetCaster()) + { + if (caster->GetDistance(WindowChargePos1) < 1.0f) + dest.Relocate(GroundJumpPos1); + else + dest.Relocate(GroundJumpPos2); + } + } + + void DisableHoverEffects() + { + if (Unit* caster = GetCaster()) + { + caster->SetDisableGravity(false); + caster->SendSetPlayHoverAnim(false); + } + } + + void PrepareNeptulonAttack() + { + if (Unit* caster = GetCaster()) + { + if (Creature* creature = caster->ToCreature()) + { + if (int32 travelTime = creature->movespline->Duration()) + creature->m_Events.AddEvent(new AttackNeptulonEvent(creature), creature->m_Events.CalculateTime(travelTime + 500)); + } + } + } + + void Register() + { + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_ozumat_jump_to_ground::SetDest, EFFECT_0, TARGET_DEST_NEARBY_ENTRY); + BeforeCast += SpellCastFn(spell_ozumat_jump_to_ground::DisableHoverEffects); + AfterCast += SpellCastFn(spell_ozumat_jump_to_ground::PrepareNeptulonAttack); + } +}; + +class spell_ozumat_shadow_blast : public SpellScript +{ + PrepareSpellScript(spell_ozumat_shadow_blast); + + void SetDest(SpellDestination& dest) + { + dest.RelocateOffset({ 0.0f, 0.0f, 5.0f, 0.0f }); + } + + void Register() + { + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_ozumat_shadow_blast::SetDest, EFFECT_0, TARGET_DEST_CASTER); + } +}; + +class spell_ozumat_shadow_blast_AuraScript : public AuraScript +{ + PrepareAuraScript(spell_ozumat_shadow_blast_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_SHADOW_BLAST_MISSILE }); + } + + void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* target = GetTarget()) + { + target->SendSetPlayHoverAnim(true); + target->CastSpell(target, SPELL_SHADOW_BLAST_MISSILE); + + if (Vehicle* vehicle = target->GetVehicleKit()) + if (Unit* dummy = vehicle->GetPassenger(SEAT_0)) + dummy->CastSpell(dummy, SPELL_SHRINK); + } + } + + void Register() override + { + AfterEffectRemove += AuraEffectRemoveFn(spell_ozumat_shadow_blast_AuraScript::AfterRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } +}; + +class spell_ozumat_shadow_blast_missile : public SpellScript +{ + PrepareSpellScript(spell_ozumat_shadow_blast_missile); + + void SetDest(SpellDestination& dest) + { + Unit* caster = GetCaster(); + if (!caster) + return; + + // Calculation is correct, core needs to support vertical only splines.... + Position pos = GetCaster()->GetPosition(); + pos.m_positionZ = caster->GetMap()->GetHeight(caster->GetPhaseShift(), pos); + dest.Relocate(pos); + } + + void Register() + { + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_ozumat_shadow_blast_missile::SetDest, EFFECT_0, TARGET_DEST_CASTER); + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_ozumat_shadow_blast_missile::SetDest, EFFECT_1, TARGET_DEST_CASTER); + } +}; + +class spell_ozumat_blight_of_ozumat : public SpellScript +{ + PrepareSpellScript(spell_ozumat_blight_of_ozumat); + + void HandleHit(SpellEffIndex effIndex) + { + if (Unit* caster = GetCaster()) + caster->CastSpell(GetHitUnit(), GetSpellInfo()->Effects[effIndex].BasePoints, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_ozumat_blight_of_ozumat::HandleHit, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } +}; + void AddSC_boss_ozumat() { + RegisterThroneOfTheTidesCreatureAI(boss_ozumat); + RegisterThroneOfTheTidesCreatureAI(npc_ozumat_neptulon); + RegisterThroneOfTheTidesCreatureAI(npc_ozumat_vicious_mindlasher); + RegisterThroneOfTheTidesCreatureAI(npc_ozumat_unyielding_behemoth); + RegisterSpellScript(spell_ozumat_charge_to_window); + RegisterSpellScript(spell_ozumat_jump_to_ground); + RegisterSpellAndAuraScriptPair(spell_ozumat_shadow_blast, spell_ozumat_shadow_blast_AuraScript); + RegisterSpellScript(spell_ozumat_shadow_blast_missile); + RegisterSpellScript(spell_ozumat_blight_of_ozumat); } diff --git a/src/server/scripts/EasternKingdoms/ThroneOfTheTides/instance_throne_of_the_todes.cpp b/src/server/scripts/EasternKingdoms/ThroneOfTheTides/instance_throne_of_the_todes.cpp index ac7c16d5e24..c39d78c1d7b 100644 --- a/src/server/scripts/EasternKingdoms/ThroneOfTheTides/instance_throne_of_the_todes.cpp +++ b/src/server/scripts/EasternKingdoms/ThroneOfTheTides/instance_throne_of_the_todes.cpp @@ -17,6 +17,7 @@ #include "ScriptMgr.h" #include "throne_of_the_tides.h" +#include "CreatureAI.h" #include "GameObject.h" #include "InstanceScript.h" #include "Vehicle.h" @@ -30,6 +31,8 @@ ObjectData const creatureData[] = { BOSS_OZUMAT, DATA_OZUMAT }, { NPC_LADY_NAZJAR, DATA_LADY_NAZJAR_GAUNTLET }, { NPC_OZUMAT_VEHICLE_BIG, DATA_OZUMAT_VEHICLE_BIG }, + { NPC_OZUMAT_VEHICLE, DATA_OZUMAT_VEHICLE }, + { NPC_NEPTULON, DATA_NEPTULON }, { 0, 0 } // END }; @@ -51,6 +54,7 @@ DoorData const doorData[] = { GO_DOODAD_ABYSSAL_MAW_DOOR_1, DATA_COMMANDER_ULTHOK, DOOR_TYPE_ROOM }, { GO_DOODAD_ABYSSAL_MAW_DOOR_2, DATA_COMMANDER_ULTHOK, DOOR_TYPE_ROOM }, { GO_DOODAD_ABYSSAL_MAW_DOOR_4, DATA_COMMANDER_ULTHOK, DOOR_TYPE_PASSAGE }, + { GO_DOODAD_ABYSSAL_MAW_DOOR_4, DATA_OZUMAT, DOOR_TYPE_ROOM }, { 0, 0, DOOR_TYPE_ROOM } // END }; @@ -59,7 +63,8 @@ enum Events EVENT_FALLING_ROCKS = 1, EVENT_RESPAWN_COMMANDER_ULTHOK, EVENT_BREAK_CORAL, - EVENT_MOVE_COMMANDER_ULTHOK_TO_HOME_POS + EVENT_MOVE_COMMANDER_ULTHOK_TO_HOME_POS, + EVENT_CHECK_DEAD_PLAYERS, }; Position const fallingRocksDummyPos = { -144.283f, 983.316f, 230.4773f }; @@ -92,7 +97,6 @@ class FaceDirectionEvent : public BasicEvent float _facingAngle; }; - class JumpThroughWindowEvent : public BasicEvent { public: @@ -186,6 +190,7 @@ class instance_throne_of_the_tides : public InstanceMapScript case NPC_OZUMAT_VEHICLE: case NPC_OZUMAT_VEHICLE_BIG: case NPC_LADY_NAZJAR: + case NPC_OZUMAT_ADD_SPAWNER: creature->setActive(true); creature->SetFarVisible(true); break; @@ -209,6 +214,16 @@ class instance_throne_of_the_tides : public InstanceMapScript case NPC_GEYSER_DUMMY: _geyserGUIDs.push_back(creature->GetGUID()); break; + case NPC_DEEP_MURLOC_INVADER: + case NPC_VICIOUS_MINDLASHER: + case NPC_UNYIELDING_BEHEMOTH: + case NPC_UNYIELDING_BEHEMOTH_LEAP_VEHICLE: + case NPC_BLIGHT_BEAST: + case NPC_BLIGHT_OF_OZUMAT: + case NPC_BLIGHT_OF_OZUMAT_2: + if (Creature* neptulon = GetCreature(DATA_NEPTULON)) + neptulon->AI()->JustSummoned(creature); + break; default: break; } @@ -350,6 +365,10 @@ class instance_throne_of_the_tides : public InstanceMapScript events.ScheduleEvent(EVENT_BREAK_CORAL, 2s); break; + case EVENT_INDEX_NEPTULON_INTRO_DONE: + if (Creature* neptulon = GetCreature(DATA_NEPTULON)) + neptulon->AI()->DoAction(ACTION_CORAL_GARDEN_ENTERED); + break; default: break; } @@ -363,6 +382,9 @@ class instance_throne_of_the_tides : public InstanceMapScript void OnUnitDeath(Unit* who) override { + if (who->GetTypeId() == TYPEID_PLAYER && GetBossState(DATA_OZUMAT) == IN_PROGRESS) + events.ScheduleEvent(EVENT_CHECK_DEAD_PLAYERS, 100ms); + if (who->GetTypeId() != TYPEID_UNIT) return; @@ -402,6 +424,29 @@ class instance_throne_of_the_tides : public InstanceMapScript ulthok->GetMotionMaster()->MoveTargetedHome(); } break; + case EVENT_CHECK_DEAD_PLAYERS: + { + uint8 instancePlayersCount = instance->GetPlayersCountExceptGMs(); + uint8 deadPlayersCount = 0; + Map::PlayerList const& players = instance->GetPlayers(); + + for (auto const& i : players) + { + if (Player* player = i.GetSource()) + { + if (player->IsGameMaster()) + continue; + + if (player->isDead()) + deadPlayersCount++; + + if (deadPlayersCount == instancePlayersCount) + if (Creature* neptulon = GetCreature(DATA_NEPTULON)) + neptulon->AI()->EnterEvadeMode(CreatureAI::EVADE_REASON_OTHER); + } + } + break; + } default: break; } diff --git a/src/server/scripts/EasternKingdoms/ThroneOfTheTides/throne_of_the_tides.cpp b/src/server/scripts/EasternKingdoms/ThroneOfTheTides/throne_of_the_tides.cpp index fbc8351302e..8409d2e1ff9 100644 --- a/src/server/scripts/EasternKingdoms/ThroneOfTheTides/throne_of_the_tides.cpp +++ b/src/server/scripts/EasternKingdoms/ThroneOfTheTides/throne_of_the_tides.cpp @@ -58,9 +58,6 @@ struct npc_tott_ozumat_vehicle_big : public ScriptedAI { if (!who) return; - - if (apply) - who->SetFacingTo(3.141593f, true); } void UpdateAI(uint32 diff) override @@ -482,6 +479,21 @@ class at_tott_commander_ulthok_summon : public AreaTriggerScript } }; +class at_tott_neptulon_intro : public AreaTriggerScript +{ + public: + at_tott_neptulon_intro() : AreaTriggerScript("at_tott_neptulon_intro") { } + + bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) + { + if (InstanceScript* instance = player->GetInstanceScript()) + if (instance->GetData(DATA_CURRENT_EVENT_PROGRESS) <= EVENT_INDEX_ULTHOK_ARRIVED) + instance->SetData(DATA_CURRENT_EVENT_PROGRESS, EVENT_INDEX_NEPTULON_INTRO_DONE); + + return true; + } +}; + void AddSC_throne_of_the_tides() { RegisterThroneOfTheTidesCreatureAI(npc_tott_ozumat_vehicle_big); @@ -495,4 +507,5 @@ void AddSC_throne_of_the_tides() new at_tott_tentacle_knockback(); new at_tott_lady_nazjar_gauntlet(); new at_tott_commander_ulthok_summon(); + new at_tott_neptulon_intro(); } diff --git a/src/server/scripts/EasternKingdoms/ThroneOfTheTides/throne_of_the_tides.h b/src/server/scripts/EasternKingdoms/ThroneOfTheTides/throne_of_the_tides.h index 1bfde3d5923..4acc5f9630d 100644 --- a/src/server/scripts/EasternKingdoms/ThroneOfTheTides/throne_of_the_tides.h +++ b/src/server/scripts/EasternKingdoms/ThroneOfTheTides/throne_of_the_tides.h @@ -45,38 +45,53 @@ enum TotTDataTypes DATA_LEVIATHAN_TENTACLE_1 = 12, DATA_LEVIATHAN_TENTACLE_2 = 13, DATA_ABYSSAL_CORAL_CHUNK = 14, - + DATA_NEPTULON = 15, + DATA_OZUMAT_VEHICLE = 16 }; enum TotTCreatureIds { // Bosses - BOSS_LADY_NAZJAR = 40586, - BOSS_COMMANDER_ULTHOK = 40765, - BOSS_MINDBENDER_GURSHA = 40788, - BOSS_OZUMAT = 44566, + BOSS_LADY_NAZJAR = 40586, + BOSS_COMMANDER_ULTHOK = 40765, + BOSS_MINDBENDER_GURSHA = 40788, + BOSS_OZUMAT = 44566, // Encounter Related /*Lady Naz'jar*/ - NPC_GEYSER = 40597, - NPC_NAZJAR_HONOR_GUARD = 40633, - NPC_NAZJAR_TEMPEST_WITCH = 44404, - NPC_WATERSPOUT = 48571, + NPC_GEYSER = 40597, + NPC_NAZJAR_HONOR_GUARD = 40633, + NPC_NAZJAR_TEMPEST_WITCH = 44404, + NPC_WATERSPOUT = 48571, + + /*Ozumat*/ + NPC_NEPTULON = 40792, + NPC_OZUMAT_COMBAT_TRIGGER = 44864, + NPC_WORLD_TRIGGER_FRIENDLY = 18721, + NPC_DEEP_MURLOC_INVADER = 44658, + NPC_VICIOUS_MINDLASHER = 44715, + NPC_UNYIELDING_BEHEMOTH = 44648, + NPC_UNYIELDING_BEHEMOTH_LEAP_VEHICLE = 44949, + NPC_OZUMAT_ADD_SPAWNER = 44656, + NPC_OZUMAT_VEHICLE = 44581, + NPC_FACELESS_SAPPER = 44752, + NPC_BLIGHT_BEAST = 44841, + NPC_BLIGHT_OF_OZUMAT = 44801, + NPC_BLIGHT_OF_OZUMAT_2 = 44834, // Event Creatures - NPC_OZUMAT_VEHICLE_BIG = 45030, - NPC_OZUMAT_VEHICLE = 44581, - NPC_WORLD_TRIGGER_INFINITE_AOI = 36171, - NPC_NAZJAR_SPIRITMENDER_1 = 41096, - NPC_NAZJAR_SPIRITMENDER_2 = 41139, - NPC_NAZJAR_INVADER_1 = 39616, - NPC_NAZJAR_INVADER_2 = 40584, - NPC_OZUMAT = 40655, - NPC_WORLD_TRIGGER_NOT_IMMUNE_PC = 21252, - NPC_LADY_NAZJAR = 39959, + NPC_OZUMAT_VEHICLE_BIG = 45030, + NPC_WORLD_TRIGGER_INFINITE_AOI = 36171, + NPC_NAZJAR_SPIRITMENDER_1 = 41096, + NPC_NAZJAR_SPIRITMENDER_2 = 41139, + NPC_NAZJAR_INVADER_1 = 39616, + NPC_NAZJAR_INVADER_2 = 40584, + NPC_OZUMAT = 40655, + NPC_WORLD_TRIGGER_NOT_IMMUNE_PC = 21252, + NPC_LADY_NAZJAR = 39959, // Generic Creatures - NPC_GEYSER_DUMMY = 48983, + NPC_GEYSER_DUMMY = 48983 }; enum TotTGameObjectIds @@ -85,13 +100,14 @@ enum TotTGameObjectIds GO_DOODAD_ABYSSAL_MAW_DOOR_1 = 204338, GO_DOODAD_ABYSSAL_MAW_DOOR_2 = 204339, GO_DOODAD_ABYSSAL_MAW_DOOR_4 = 204341, - GO_THRONE_OF_THE_TIDES_DEFENSE_SYSTEM = 203199, GO_DOODAD_INVISIBLE_DOOR_1 = 207997, GO_DOODAD_INVISIBLE_DOOR_2 = 207998, GO_DOODAD_ABYSSAL_LEVIATHAN_TENTACLE_1 = 208302, GO_DOODAD_ABYSSAL_LEVIATHAN_TENTACLE_2 = 208301, GO_DOODAD_ABYSSAL_CORAL_CHUNK_CEILING = 205542, + GO_NEPTULONS_CACHE_NORMAL = 205216, + GO_NEPTULONS_CACHE_HEROIC = 207973 }; enum TotTSpells @@ -105,7 +121,7 @@ enum TotTSpells SPELL_SHOCK_DEFENSE_OZUMAT = 86635, SPELL_ULTHOK_INTRO_VISUAL_CEILING_IMPACT = 76021, SPELL_ULTHOK_INTRO_JUMP = 82960, - SPELL_ULTHOK_INTRO_VISUAL_STATE = 76017, + SPELL_ULTHOK_INTRO_VISUAL_STATE = 76017 }; enum TotTCinematic @@ -119,12 +135,14 @@ enum TotTEventIndex EVENT_INDEX_FIRST_INVADERS, EVENT_INDEX_LADY_NAZJAR_GAUNTLET, EVENT_INDEX_DEFENSE_SYSTEM_ACTIVATED, - EVENT_INDEX_ULTHOK_ARRIVED + EVENT_INDEX_ULTHOK_ARRIVED, + EVENT_INDEX_NEPTULON_INTRO_DONE }; enum TotTActions { - ACTION_DEFENSE_SYSTEM_ACTIVATED = 1 + ACTION_DEFENSE_SYSTEM_ACTIVATED = 1, + ACTION_CORAL_GARDEN_ENTERED = 1 }; enum TotTSounds