diff --git a/sql/updates/world/4.3.4/custom_2018_02_18_00_world.sql b/sql/updates/world/4.3.4/custom_2018_02_18_00_world.sql new file mode 100644 index 00000000000..ab56ac28f04 --- /dev/null +++ b/sql/updates/world/4.3.4/custom_2018_02_18_00_world.sql @@ -0,0 +1,115 @@ +-- Template Updates +-- Foe Reaper 5000 +UPDATE `creature_template` SET `unit_flags2`= 0, `ScriptName`= 'boss_foe_reaper_5000' WHERE `entry`= 43778; +UPDATE `creature_template` SET `minlevel`= 87, `maxlevel`= 87, `unit_flags2`= 0, `flags_extra`= 1 WHERE `entry`= 48941; +-- Prototype Reaper +UPDATE `creature_template` SET `speed_walk`=1, `speed_run`=1.142857, `spell1`= 91734, `spell2`= 91735, `spell3`= 91736, `unit_flags2`= 0 WHERE `entry`= 49208; +UPDATE `npc_spellclick_spells` SET `spell_id`= 43671 WHERE `npc_entry`= 49208; +-- Defias Watcher +UPDATE `creature_template` SET `unit_flags2`= 0, `RegenHealth`= 0, `ScriptName`= 'npc_deadmines_defias_watcher' WHERE `entry`= 47404; +UPDATE `creature_template` SET `unit_flags2`= 0, `RegenHealth`= 0 WHERE `entry`= 48803; +-- Defias Reaper +UPDATE `creature_template` SET `unit_flags2`= 0, `ScriptName`= 'npc_deadmines_defias_watcher' WHERE `entry`= 47403; +UPDATE `creature_template` SET `unit_flags2`= 0 WHERE `entry`= 48804; +-- Deadmines Foe Reaper Targeting Bunny +UPDATE `creature_template` SET `faction`= 35, `unit_flags`= 33554432, `flags_extra`= 128 WHERE `entry`= 47468; +-- Molten Slag +UPDATE `creature_template` SET `DamageModifier`= 30, `ScriptName`= 'npc_foe_reaper_5000_molten_slag' WHERE `entry`= 49229; + + +DELETE FROM `creature_text` WHERE `CreatureID` IN (43778, 45979); +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `Comment`) VALUES +-- Foe Reaper 5000 +(43778, 0, 0, 'Foe Reaper 5000 on-line. All systems nominal.', 14, 0, 100, 0, 0, 22137, 47596, 'Foe Reaper 5000'), +(43778, 1, 0, '|TInterface\\Icons\\ability_whirlwind.blp:20|t Foe Reaper 5000 begins to activate |cFFFF0000|Hspell:88481|h[Overdrive]|h|r!', 41, 0, 100, 0, 0, 0, 48812, 'Foe Reaper 5000'), +(43778, 2, 0, 'Overdrive engine activated.', 14, 0, 100, 0, 0, 22142, 47609, 'Foe Reaper 5000'), +(43778, 3, 0, 'Acquiring target...', 14, 0, 100, 0, 0, 22140, 47628, 'Foe Reaper 5000 to Player'), +(43778, 4, 0, 'Target acquired. Harvesting servos engaged.', 14, 0, 100, 0, 0, 22141, 47629, 'Foe Reaper 5000'), +(43778, 5, 0, 'Safety restrictions off-line. Catastrophic system failure imminent.', 14, 0, 100, 0, 0, 22143, 47642, 'Foe Reaper 5000'), +(43778, 6, 0, '|TInterface\Icons\spell_fire_totemofwrath.blp:20|t Foe Reaper 5000 |cFFFF0000|Hspell:88522|h[Safety Restrictions are Off-line]|h|r!', 41, 0, 100, 0, 0, 0, 50713, 'Foe Reaper 5000'), +(43778, 7, 0, 'Target destroyed.', 14, 0, 100, 0, 0, 22139, 47630, 'Feindschnitter 5000 to Player'), +(43778, 8, 0, 'Overheat threshold exceeded. System failure. Wheat clog in port two. Shutting down.', 14, 0, 100, 0, 0, 22138, 47643, 'Foe Reaper 5000'), +-- General Purpose Bunny +(45979, 0, 0, 'A stray jolt from the Foe Reaper has disrupted the foundry controls!', 41, 0, 100, 0, 0, 0, 49315, 'General Purpose Bunny JMF'), +(45979, 1, 0, 'The molten slag begins to bubble furiously!', 41, 0, 100, 0, 0, 0, 49316, 'General Purpose Bunny JMF'); + +-- Template Addon +DELETE FROM `creature_template_addon` WHERE `entry`= 47468; +INSERT INTO `creature_template_addon` (`entry`, `auras`) VALUES +(47468, 88508); + +-- Conditions +DELETE FROM `conditions` WHERE `SourceEntry` IN (89132, 91839, 91841, 91842, 91843) AND `SourceTypeOrReferenceId`= 13; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ScriptName`, `Comment`) VALUES +(13, 1, 89132, 0, 0, 31, 0, 3, 43778, 0, 0, 0, '', 'Energize - Target Foe Reaper 5000'), +(13, 1, 91839, 0, 0, 31, 0, 5, 123207, 0, 0, 0, '', 'Summon Molten Slag - Target Goblin Smelthing Pot'), +(13, 1, 91841, 0, 0, 31, 0, 5, 123208, 0, 0, 0, '', 'Summon Molten Slag - Target Goblin Smelthing Pot'), +(13, 1, 91842, 0, 0, 31, 0, 5, 123209, 0, 0, 0, '', 'Summon Molten Slag - Target Goblin Smelthing Pot'), +(13, 1, 91843, 0, 0, 31, 0, 5, 123210, 0, 0, 0, '', 'Summon Molten Slag - Target Goblin Smelthing Pot'); + +-- Spells +DELETE FROM `spell_script_names` WHERE `ScriptName` IN +('spell_deadmines_on_fire', +'spell_foe_reaper_5000_acquire_target', +'spell_foe_reaper_5000_fixate_targeting', +'spell_foe_reaper_5000_fixate'); + +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(91737, 'spell_deadmines_on_fire'), +(88492, 'spell_foe_reaper_5000_acquire_target'), +(91831, 'spell_foe_reaper_5000_fixate_targeting'), +(91830, 'spell_foe_reaper_5000_fixate'); + +-- Loot +UPDATE `creature_template` SET `lootid`= 43778 WHERE `entry` = 43778; +DELETE FROM creature_loot_template WHERE `Entry` IN (43778, 48941); +INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Chance`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`) VALUES +(43778, 1937, 0, 1, 1, 1, 1), +(43778, 5187, 0, 1, 1, 1, 1), +(43778, 5201, 0, 1, 1, 1, 1); + +UPDATE `creature_template` SET `lootid` = 48941 WHERE `entry` = 48941; +INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Chance`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`) VALUES +(48941, 65166, 0, 1, 1, 1, 1), +(48941, 65165, 0, 1, 1, 1, 1), +(48941, 65167, 0, 1, 1, 1, 1); + +-- SAI +-- Creature General Purpose Bunny JMF (Look 2) 47242 SAI +SET @ENTRY := 47242; +UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`= @ENTRY; +SET @ENTRY := -375839; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(@ENTRY, 0, 0, 0, 72, 0, 100, 0, 1, 0, 0, 0, 67, 0, 150, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "On DoAction 1 - Trigger timed event #0"), +(@ENTRY, 0, 1, 0, 59, 0, 100, 1, 0, 0, 0, 0, 11, 89202, 2, 0, 0, 0, 0, 10, 375842, 0, 0, 0, 0, 0, 0, "On timed event 0 triggered - Self: Cast spell 89202 on Creature General Purpose Bunny JMF (Look 2)"); + +SET @ENTRY := -375846; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(@ENTRY, 0, 0, 0, 72, 0, 100, 0, 1, 0, 0, 0, 67, 0, 2500, 2500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "On DoAction 1 - Trigger timed event #0"), +(@ENTRY, 0, 1, 0, 59, 0, 100, 1, 0, 0, 0, 0, 11, 89202, 2, 0, 0, 0, 0, 10, 375841, 0, 0, 0, 0, 0, 0, "On timed event 0 triggered - Self: Cast spell 89202 on Creature General Purpose Bunny JMF (Look 2)"); + +SET @ENTRY := -375922; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(@ENTRY, 0, 0, 0, 72, 0, 100, 0, 1, 0, 0, 0, 67, 0, 2500, 2500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "On DoAction 1 - Trigger timed event #0"), +(@ENTRY, 0, 1, 0, 59, 0, 100, 1, 0, 0, 0, 0, 11, 89202, 2, 0, 0, 0, 0, 10, 375840, 0, 0, 0, 0, 0, 0, "On timed event 0 triggered - Self: Cast spell 89202 on Creature General Purpose Bunny JMF (Look 2)"); + +SET @ENTRY := -375844; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(@ENTRY, 0, 0, 0, 72, 0, 100, 0, 1, 0, 0, 0, 67, 0, 5000, 5000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "On DoAction 1 - Trigger timed event #0"), +(@ENTRY, 0, 1, 0, 59, 0, 100, 1, 0, 0, 0, 0, 11, 89202, 2, 0, 0, 0, 0, 10, 375923, 0, 0, 0, 0, 0, 0, "On timed event 0 triggered - Self: Cast spell 89202 on Creature General Purpose Bunny JMF (Look 2)"); + +SET @ENTRY := -375843; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(@ENTRY, 0, 0, 0, 72, 0, 100, 0, 1, 0, 0, 0, 67, 0, 5000, 5000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "On DoAction 1 - Trigger timed event #0"), +(@ENTRY, 0, 1, 0, 59, 0, 100, 1, 0, 0, 0, 0, 11, 89202, 2, 0, 0, 0, 0, 10, 375848, 0, 0, 0, 0, 0, 0, "On timed event 0 triggered - Self: Cast spell 89202 on Creature General Purpose Bunny JMF (Look 2)"); + +SET @ENTRY := -375847; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(@ENTRY, 0, 0, 0, 72, 0, 100, 0, 1, 0, 0, 0, 67, 0, 5000, 5000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "On DoAction 1 - Trigger timed event #0"), +(@ENTRY, 0, 1, 0, 59, 0, 100, 1, 0, 0, 0, 0, 11, 89202, 2, 0, 0, 0, 0, 10, 375921, 0, 0, 0, 0, 0, 0, "On timed event 0 triggered - Self: Cast spell 89202 on Creature General Purpose Bunny JMF (Look 2)"); diff --git a/src/server/scripts/EasternKingdoms/Deadmines/boss_foe_reaper_5000.cpp b/src/server/scripts/EasternKingdoms/Deadmines/boss_foe_reaper_5000.cpp new file mode 100644 index 00000000000..e4d2523478d --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Deadmines/boss_foe_reaper_5000.cpp @@ -0,0 +1,595 @@ +/* +* Copyright (C) 2008-2017 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 "ObjectMgr.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" +#include "Player.h" +#include "deadmines.h" + +enum Texts +{ + // Foe Reaper 5000 + SAY_ON_LINE = 0, + SAY_ANNOUNCE_OVERDRIVE = 1, + SAY_OVERDRIVE = 2, + SAY_HARVEST_ACQUIRING_TARGET = 3, + SAY_HARVEST = 4, + SAY_SAFETY_RESTRICTIONS_OFFLINE = 5, + SAY_ANNOUNCE_RESTRICTIONS_OFFLINE = 6, + SAY_SLAY = 7, + SAY_DEATH = 8, + + // General Purpose Bunny + SAY_ANNOUNCE_FOUNDRY_DISRUPTED = 0, + SAY_ANNOUNCE_MOLTEN_SLAG = 1 +}; + +enum Spells +{ + // Foe Reaper 5000 + SPELL_ENERGIZE = 89132, + SPELL_ON_LINE = 89198, + SPELL_OFF_LINE = 88348, + SPELL_RED_EYES = 24263, + SPELL_ON_LINE_2 = 89121, + SPELL_REAPER_STRIKE = 88490, + SPELL_OVERDRIVE = 88481, + SPELL_ACQUIRING_TARGET = 88492, + SPELL_HARVEST = 88497, + SPELL_HARVEST_SWEEP = 88521, + SPELL_SAFETY_RESTRICTIONS_OFFLINE = 88522, + + // General Purpose Bunny + SPELL_SUMMON_MOLTEN_SLAG_1 = 91839, + SPELL_SUMMON_MOLTEN_SLAG_2 = 91841, + SPELL_SUMMON_MOLTEN_SLAG_3 = 91842, + SPELL_SUMMON_MOLTEN_SLAG_4 = 91843, + + // Molten Slag + SPELL_MOLTEN_SHIELD = 91815, + SPELL_FIXATE_TARGETING = 91831, + + // Player + SPELL_FIXATE_TAUNT = 91829 +}; + +uint32 randomSlagSpells[] = +{ + SPELL_SUMMON_MOLTEN_SLAG_1, + SPELL_SUMMON_MOLTEN_SLAG_2, + SPELL_SUMMON_MOLTEN_SLAG_3, + SPELL_SUMMON_MOLTEN_SLAG_4, +}; + +enum Events +{ + // Foe Reaper 5000 + EVENT_ON_LINE = 1, + EVENT_RED_EYES, + EVENT_ON_LINE_2, + EVENT_ANNOUNCE_DISRUPTING_FOUNDRY, + EVENT_ANNOUNCE_MOLTEN_SLAG, + EVENT_SUMMON_MOLTEN_SLAG, + EVENT_OVERDRIVE, + EVENT_MOVE_OVERDRIVE, + EVENT_END_OVERDRIVE, + EVENT_ACQUIRING_TARGET, + EVENT_HARVEST, + EVENT_HARVEST_SWEEP, + EVENT_ANNOUNCE_SAFETY_RESTRICTIONS_OFFLINE, + + // Molten Slag + EVENT_MOLTEN_SHIELD, + EVENT_FIXATE_PLAYER +}; + +enum Phases +{ + PHASE_INTRO = 1, + PHASE_1 = 2, +}; + +enum Actions +{ + ACTION_ELECTRICAL_CHARGE = 1 +}; + +enum Points +{ + POINT_MOVE_OVERDRIVE = 1, + POINT_MOVE_HARVEST = 2 +}; + +class boss_foe_reaper_5000 : public CreatureScript +{ + public: + boss_foe_reaper_5000() : CreatureScript("boss_foe_reaper_5000") { } + + struct boss_foe_reaper_5000AI : public BossAI + { + boss_foe_reaper_5000AI(Creature* creature) : BossAI(creature, DATA_HELIX_GEARBREAKER) + { + me->setPowerType(POWER_ENERGY); + me->SetMaxPower(POWER_ENERGY, 100); + Initialize(); + } + + void Initialize() + { + _safetyRestrictionsOffline = false; + } + + void Reset() override + { + _Reset(); + Initialize(); + if (!instance->GetData(DATA_FOE_REAPER_INTRO)) + events.SetPhase(PHASE_INTRO); + else + { + me->RemoveAurasDueToSpell(SPELL_OFF_LINE); + { + DoCast(me, SPELL_RED_EYES, true); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED | UNIT_FLAG_IMMUNE_TO_PC); + } + } + } + + void JustEngagedWith(Unit* /*who*/) override + { + _JustEngagedWith(); + events.SetPhase(PHASE_1); + instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me); + events.ScheduleEvent(EVENT_OVERDRIVE, Seconds(9)); + events.ScheduleEvent(EVENT_ACQUIRING_TARGET, Seconds(35)); + if (IsHeroic()) + { + events.ScheduleEvent(EVENT_ANNOUNCE_DISRUPTING_FOUNDRY, Seconds(4)); + events.ScheduleEvent(EVENT_ANNOUNCE_MOLTEN_SLAG, Seconds(6) + Milliseconds(400)); + events.ScheduleEvent(EVENT_SUMMON_MOLTEN_SLAG, Seconds(17)); + } + } + + void JustDied(Unit* /*killer*/) override + { + _JustDied(); + Talk(SAY_DEATH); + summons.DespawnAll(); + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + if (IsHeroic()) + if (Creature* prototypeReaper = instance->GetCreature(DATA_PROTOTYPE_REAPER)) + prototypeReaper->DespawnOrUnsummon(0); + } + + void KilledUnit(Unit* who) override + { + if (who->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + _EnterEvadeMode(); + summons.DespawnAll(); + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + if (IsHeroic()) + if (Creature* prototypeReaper = instance->GetCreature(DATA_PROTOTYPE_REAPER)) + prototypeReaper->DespawnOrUnsummon(0, Seconds(30)); + _DespawnAtEvade(); + } + + void JustSummoned(Creature* summon) override + { + summons.Summon(summon); + + if (summon->GetEntry() == NPC_FOE_REAPER_TARGETING_BUNNY) + { + me->StopMoving(); + me->AttackStop(); + me->SetReactState(REACT_PASSIVE); + me->SetFacingToObject(summon); + + } + } + + void MovementInform(uint32 type, uint32 point) override + { + if (type != POINT_MOTION_TYPE && type != EFFECT_MOTION_TYPE) + return; + + switch (point) + { + case POINT_MOVE_OVERDRIVE: + events.ScheduleEvent(EVENT_MOVE_OVERDRIVE, Seconds(1)); + break; + case POINT_MOVE_HARVEST: + me->RemoveAurasDueToSpell(SPELL_HARVEST); + events.ScheduleEvent(EVENT_HARVEST_SWEEP, Seconds(1)); + break; + default: + break; + } + } + + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override + { + switch (spell->Id) + { + case SPELL_ENERGIZE: + if (me->GetPower(POWER_ENERGY) == 100) + { + instance->SetData(DATA_FOE_REAPER_INTRO, DONE); + events.ScheduleEvent(EVENT_ON_LINE, Seconds(3)); + } + break; + case SPELL_OVERDRIVE: + Talk(SAY_OVERDRIVE); + me->AttackStop(); + me->SetReactState(REACT_PASSIVE); + events.ScheduleEvent(EVENT_MOVE_OVERDRIVE, Seconds(2)); + events.ScheduleEvent(EVENT_END_OVERDRIVE, Seconds(10)); + break; + case SPELL_HARVEST: + Talk(SAY_HARVEST); + events.ScheduleEvent(EVENT_HARVEST, Seconds(2)); + break; + default: + break; + } + } + + void DoAction(int32 action) override + { + switch (action) + { + case 0: + break; + default: + break; + } + } + + void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/) override + { + if (me->HealthBelowPct(30) && !_safetyRestrictionsOffline) + { + Talk(SAY_SAFETY_RESTRICTIONS_OFFLINE); + DoCastSelf(SPELL_SAFETY_RESTRICTIONS_OFFLINE, true); + events.ScheduleEvent(EVENT_ANNOUNCE_SAFETY_RESTRICTIONS_OFFLINE, Seconds(3) + Milliseconds(800)); + _safetyRestrictionsOffline = true; + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim() && !events.IsInPhase(PHASE_INTRO)) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_ON_LINE: + { + me->CastSpell(me, SPELL_ON_LINE); + events.ScheduleEvent(EVENT_RED_EYES, Seconds(8) + Milliseconds(400)); + std::list units; + GetCreatureListWithEntryInGrid(units, me, NPC_GENERAL_PURPOSE_BUNNY_L2, 15.0f); + if (!units.empty()) + for (auto itr = units.begin(); itr != units.end(); ++itr) + (*itr)->AI()->DoAction(ACTION_ELECTRICAL_CHARGE); + break; + } + case EVENT_RED_EYES: + DoCastSelf(SPELL_RED_EYES, true); + events.ScheduleEvent(EVENT_ON_LINE_2, Seconds(2) + Milliseconds(400)); + break; + case EVENT_ON_LINE_2: + me->RemoveAurasDueToSpell(SPELL_OFF_LINE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED | UNIT_FLAG_IMMUNE_TO_PC); + DoCastSelf(SPELL_ON_LINE_2, true); + Talk(SAY_ON_LINE); + break; + case EVENT_ANNOUNCE_DISRUPTING_FOUNDRY: + if (Creature* bunny = me->FindNearestCreature(NPC_GENERAL_PURPOSE_DUMMY_JMF, 100.0f, true)) + bunny->AI()->Talk(SAY_ANNOUNCE_FOUNDRY_DISRUPTED); + break; + case EVENT_ANNOUNCE_MOLTEN_SLAG: + if (Creature* bunny = me->FindNearestCreature(NPC_GENERAL_PURPOSE_DUMMY_JMF, 100.0f, true)) + bunny->AI()->Talk(SAY_ANNOUNCE_MOLTEN_SLAG); + break; + case EVENT_SUMMON_MOLTEN_SLAG: + { + uint8 i = RAND(0, 3); + if (Creature* bunny = me->FindNearestCreature(NPC_GENERAL_PURPOSE_DUMMY_JMF, 100.0f, true)) + bunny->CastSpell(bunny, randomSlagSpells[i], true); + events.Repeat(Seconds(21), Seconds(22)); + break; + } + case EVENT_OVERDRIVE: + DoCastSelf(SPELL_OVERDRIVE); + Talk(SAY_ANNOUNCE_OVERDRIVE); + events.Repeat(Seconds(53)); + break; + case EVENT_MOVE_OVERDRIVE: + { + // Let's just copy the random movement generator part here except we are walking + // and use our own position instead of our home position + float respX, respY, respZ, respO, destX, destY, destZ, travelDistZ; + me->GetPosition(respX, respY, respZ, respO); + Map const* map = me->GetBaseMap(); + const float angle = float(rand_norm()) * static_cast(M_PI*2.0f); + const float range = 15.0f; + const float distanceX = range * std::cos(angle); + const float distanceY = range * std::sin(angle); + destX = respX + distanceX; + destY = respY + distanceY; + Trinity::NormalizeMapCoord(destX); + Trinity::NormalizeMapCoord(destY); + travelDistZ = 10.0f; + destZ = map->GetHeight(me->GetPhases(), destX, destY, respZ + travelDistZ - 2.0f, false); + if (std::fabs(destZ - respZ) > travelDistZ) + { + destZ = map->GetHeight(me->GetPhases(), destX, destY, respZ - 2.0f, true); + + if (std::fabs(destZ - respZ) > travelDistZ) + { + destZ = map->GetHeight(me->GetPhases(), destX, destY, respZ + travelDistZ - 2.0f, true); + + if (std::fabs(destZ - respZ) > travelDistZ) + return; + } + } + me->GetMotionMaster()->MovePoint(POINT_MOVE_OVERDRIVE, destX, destY, destZ, true); + break; + } + case EVENT_END_OVERDRIVE: + me->GetMotionMaster()->Clear(); + me->SetReactState(REACT_AGGRESSIVE); + me->AI()->AttackStart(me->GetVictim()); + events.CancelEvent(EVENT_MOVE_OVERDRIVE); + break; + case EVENT_ACQUIRING_TARGET: + Talk(SAY_HARVEST_ACQUIRING_TARGET); + DoCastAOE(SPELL_ACQUIRING_TARGET, true); + events.Repeat(Seconds(55)); + break; + case EVENT_HARVEST: + if (Creature* bunny = instance->GetCreature(DATA_FOE_REAPER_BUNNY)) + me->GetMotionMaster()->MovePoint(POINT_MOVE_HARVEST, bunny->GetPosition(), true); + break; + case EVENT_HARVEST_SWEEP: + DoCastAOE(SPELL_HARVEST_SWEEP); + me->setAttackTimer(BASE_ATTACK, me->GetFloatValue(UNIT_FIELD_BASEATTACKTIME)); + summons.DespawnEntry(NPC_FOE_REAPER_TARGETING_BUNNY); + me->SetReactState(REACT_AGGRESSIVE); + me->AI()->AttackStart(me->GetVictim()); + break; + case EVENT_ANNOUNCE_SAFETY_RESTRICTIONS_OFFLINE: + Talk(SAY_ANNOUNCE_RESTRICTIONS_OFFLINE); + break; + default: + break; + } + } + + DoSpellAttackIfReady(SPELL_REAPER_STRIKE); + } + private: + bool _safetyRestrictionsOffline; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetDeadminesAI(creature); + } +}; + +class npc_foe_reaper_5000_molten_slag : public CreatureScript +{ + public: + npc_foe_reaper_5000_molten_slag() : CreatureScript("npc_foe_reaper_5000_molten_slag") { } + + struct npc_foe_reaper_5000_molten_slagAI : public ScriptedAI + { + npc_foe_reaper_5000_molten_slagAI(Creature* creature) : ScriptedAI(creature) { } + + void InitializeAI() override + { + me->SetReactState(REACT_PASSIVE); + } + + void IsSummonedBy(Unit* /*summoner*/) override + { + DoZoneInCombat(); + _events.ScheduleEvent(EVENT_MOLTEN_SHIELD, Seconds(3)); + _events.ScheduleEvent(EVENT_FIXATE_PLAYER, Seconds(3)); + } + + void JustDied(Unit* /*killer*/) override + { + me->DespawnOrUnsummon(Seconds(5)); + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_MOLTEN_SHIELD: + DoCastSelf(SPELL_MOLTEN_SHIELD, true); + me->SetReactState(REACT_AGGRESSIVE); + me->SetInCombatWithZone(); + break; + case EVENT_FIXATE_PLAYER: + DoCastAOE(SPELL_FIXATE_TARGETING, true); + _events.Repeat(Seconds(12)); + break; + default: + break; + } + } + DoMeleeAttackIfReady(); + } + private: + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetDeadminesAI(creature); + } +}; + +class spell_foe_reaper_5000_acquire_target : public SpellScriptLoader +{ + public: + spell_foe_reaper_5000_acquire_target() : SpellScriptLoader("spell_foe_reaper_5000_acquire_target") { } + + class spell_foe_reaper_5000_acquire_target_SpellScript : public SpellScript + { + PrepareSpellScript(spell_foe_reaper_5000_acquire_target_SpellScript); + + void FilterTargets(std::list& targets) + { + if (targets.empty()) + return; + + Trinity::Containers::RandomResize(targets, 1); + } + + void HandleHit(SpellEffIndex effIndex) + { + GetCaster()->CastSpell(GetHitUnit(), GetSpellInfo()->Effects[effIndex].BasePoints); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_foe_reaper_5000_acquire_target_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnEffectHitTarget += SpellEffectFn(spell_foe_reaper_5000_acquire_target_SpellScript::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_foe_reaper_5000_acquire_target_SpellScript(); + } +}; + +class FixateTargetingCheck +{ + public: + FixateTargetingCheck() { } + + bool operator()(WorldObject* object) + { + if (Unit* unit = object->ToUnit()) + if ((unit->GetEntry() == NPC_PROTOTYPE_REAPER && unit->IsCharmedOwnedByPlayerOrPlayer()) || unit->GetTypeId() == TYPEID_PLAYER) + return false; + + return true; + } +}; + +class spell_foe_reaper_5000_fixate_targeting : public SpellScriptLoader +{ + public: + spell_foe_reaper_5000_fixate_targeting() : SpellScriptLoader("spell_foe_reaper_5000_fixate_targeting") { } + + class spell_foe_reaper_5000_fixate_targeting_SpellScript : public SpellScript + { + PrepareSpellScript(spell_foe_reaper_5000_fixate_targeting_SpellScript); + + void FilterTargets(std::list& targets) + { + if (targets.empty()) + return; + + targets.remove_if(FixateTargetingCheck()); + + if (targets.empty()) + return; + + Trinity::Containers::RandomResize(targets, 1); + } + + void HandleHit(SpellEffIndex effIndex) + { + GetCaster()->CastSpell(GetHitUnit(), GetSpellInfo()->Effects[effIndex].BasePoints, true); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_foe_reaper_5000_fixate_targeting_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnEffectHitTarget += SpellEffectFn(spell_foe_reaper_5000_fixate_targeting_SpellScript::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_foe_reaper_5000_fixate_targeting_SpellScript(); + } +}; + +class spell_foe_reaper_5000_fixate : public SpellScriptLoader +{ + public: + spell_foe_reaper_5000_fixate() : SpellScriptLoader("spell_foe_reaper_5000_fixate") { } + + class spell_foe_reaper_5000_fixate_SpellScript : public SpellScript + { + PrepareSpellScript(spell_foe_reaper_5000_fixate_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_FIXATE_TAUNT }); + } + + void HandleHit(SpellEffIndex effIndex) + { + if (Unit* caster = GetCaster()) + GetHitUnit()->CastSpell(caster, SPELL_FIXATE_TAUNT, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_foe_reaper_5000_fixate_SpellScript::HandleHit, EFFECT_0, SPELL_EFFECT_APPLY_AURA); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_foe_reaper_5000_fixate_SpellScript(); + } +}; + +void AddSC_boss_foe_reaper_5000() +{ + new boss_foe_reaper_5000(); + new npc_foe_reaper_5000_molten_slag(); + new spell_foe_reaper_5000_acquire_target(); + new spell_foe_reaper_5000_fixate_targeting(); + new spell_foe_reaper_5000_fixate(); +} diff --git a/src/server/scripts/EasternKingdoms/Deadmines/deadmines.cpp b/src/server/scripts/EasternKingdoms/Deadmines/deadmines.cpp index 057d572ba39..87e0bdb1236 100644 --- a/src/server/scripts/EasternKingdoms/Deadmines/deadmines.cpp +++ b/src/server/scripts/EasternKingdoms/Deadmines/deadmines.cpp @@ -22,6 +22,130 @@ #include "Player.h" #include "WorldSession.h" +enum DefiasWatcherSpells +{ + SPELL_ON_FIRE = 91737, + SPELL_EXPLOSIVE_SUICIDE = 91738, + SPELL_ENERGIZE = 89132, +}; + +enum DefiasWatcherFaction +{ + FACTION_CONTROLABLE = 1816 +}; + +class npc_deadmines_defias_watcher : public CreatureScript +{ + public: + npc_deadmines_defias_watcher() : CreatureScript("npc_deadmines_defias_watcher") { } + + struct npc_deadmines_defias_watcherAI : public ScriptedAI + { + npc_deadmines_defias_watcherAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) + { + Initialize(); + } + + void Initialize() + { + _suicideStarted = false; + } + + void JustEngagedWith(Unit* who) override + { + } + + void Reset() override + { + me->SetHealth(me->GetMaxHealth()); + } + + void JustDied(Unit* /*killer*/) override + { + if (!_suicideStarted) + DoCastAOE(SPELL_ENERGIZE, true); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + if (me->GetHealthPct() <= 30.0f && !_suicideStarted) + { + DoCastSelf(SPELL_ON_FIRE, true); + DoCastAOE(SPELL_ENERGIZE, true); + me->AttackStop(); + me->SetReactState(REACT_PASSIVE); + me->SetFaction(FACTION_CONTROLABLE); + me->setRegeneratingHealth(false); + _events.Reset(); + _suicideStarted = true; + } + + _events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case 0: + break; + default: + break; + } + } + DoMeleeAttackIfReady(); + } + private: + EventMap _events; + InstanceScript* _instance; + bool _suicideStarted; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetDeadminesAI(creature); + } +}; + +class spell_deadmines_on_fire : public SpellScriptLoader +{ + public: + spell_deadmines_on_fire() : SpellScriptLoader("spell_deadmines_on_fire") { } + + class spell_deadmines_on_fire_AuraScript : public AuraScript + { + PrepareAuraScript(spell_deadmines_on_fire_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_EXPLOSIVE_SUICIDE }); + } + + void AfterRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + if (Unit* owner = GetOwner()->ToUnit()) + owner->CastSpell(owner, SPELL_EXPLOSIVE_SUICIDE, true); + } + + void Register() override + { + AfterEffectRemove += AuraEffectRemoveFn(spell_deadmines_on_fire_AuraScript::AfterRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE_PERCENT, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_deadmines_on_fire_AuraScript(); + } +}; + void AddSC_deadmines() { + new npc_deadmines_defias_watcher(); + new spell_deadmines_on_fire(); } diff --git a/src/server/scripts/EasternKingdoms/Deadmines/deadmines.h b/src/server/scripts/EasternKingdoms/Deadmines/deadmines.h index 0fc63eb56ef..d018f5c52ed 100644 --- a/src/server/scripts/EasternKingdoms/Deadmines/deadmines.h +++ b/src/server/scripts/EasternKingdoms/Deadmines/deadmines.h @@ -35,7 +35,10 @@ enum DMDataTypes DATA_TEAM_IN_INSTANCE = 6, DATA_FIREWALL_PLATTER = 7, - DATA_LUMBERING_OAF = 8 + DATA_LUMBERING_OAF = 8, + DATA_FOE_REAPER_INTRO = 9, + DATA_FOE_REAPER_BUNNY = 10, + DATA_PROTOTYPE_REAPER = 11, }; enum DMCreatures @@ -43,6 +46,7 @@ enum DMCreatures // Bosses BOSS_GLUBTOK = 47162, BOSS_HELIX_GEARBREAKER = 47296, + BOSS_FOE_REAPER_5000 = 43778, // Horde Creatures NPC_SLINKY_SHARPSHIV = 46906, @@ -72,7 +76,12 @@ enum DMCreatures NPC_FROST_BLOSSOM_BUNNY = 47284, NPC_LUMBERING_OAF = 47297, NPC_HELIX_CREW = 49139, - NPC_STICKY_BOMB = 47314 + NPC_STICKY_BOMB = 47314, + NPC_DEFIAS_REAPER = 47403, + NPC_DEFIAS_WATCHER = 47404, + NPC_FOE_REAPER_TARGETING_BUNNY = 47468, + NPC_PROTOTYPE_REAPER = 49208, + NPC_MOLTEN_SLAG = 49229, }; enum DMGameObjects diff --git a/src/server/scripts/EasternKingdoms/Deadmines/instance_deadmines.cpp b/src/server/scripts/EasternKingdoms/Deadmines/instance_deadmines.cpp index 795d75c0c86..62b26c508a5 100644 --- a/src/server/scripts/EasternKingdoms/Deadmines/instance_deadmines.cpp +++ b/src/server/scripts/EasternKingdoms/Deadmines/instance_deadmines.cpp @@ -24,10 +24,13 @@ ObjectData const creatureData[] = { - { BOSS_GLUBTOK, DATA_GLUBTOK }, - { BOSS_HELIX_GEARBREAKER, DATA_HELIX_GEARBREAKER }, - { NPC_LUMBERING_OAF, DATA_LUMBERING_OAF }, - { 0, 0 }, // END + { BOSS_GLUBTOK, DATA_GLUBTOK }, + { BOSS_HELIX_GEARBREAKER, DATA_HELIX_GEARBREAKER }, + { BOSS_FOE_REAPER_5000, DATA_FOE_REAPER_5000 }, + { NPC_LUMBERING_OAF, DATA_LUMBERING_OAF }, + { NPC_FOE_REAPER_TARGETING_BUNNY, DATA_FOE_REAPER_BUNNY }, + { NPC_PROTOTYPE_REAPER, DATA_PROTOTYPE_REAPER }, + { 0, 0 }, // END }; ObjectData const gameobjectData[] = @@ -57,6 +60,7 @@ class instance_deadmines : public InstanceMapScript LoadDoorData(doorData); LoadObjectData(creatureData, gameobjectData); _teamInInstance = 0; + _foeReaper5000Intro = 0; } void OnPlayerEnter(Player* player) override @@ -106,6 +110,19 @@ class instance_deadmines : public InstanceMapScript if (creature->isDead() && GetBossState(DATA_HELIX_GEARBREAKER) != DONE) creature->Respawn(); break; + case NPC_DEFIAS_REAPER: + case NPC_DEFIAS_WATCHER: + if (!GetData(DATA_FOE_REAPER_INTRO) && creature->isDead()) + creature->Respawn(); + break; + case NPC_PROTOTYPE_REAPER: + if (!instance->IsHeroic()) + creature->SetVisible(false); + break; + case NPC_MOLTEN_SLAG: + if (Creature* reaper = GetCreature(DATA_FOE_REAPER_5000)) + reaper->AI()->JustSummoned(creature); + break; default: break; } @@ -119,6 +136,10 @@ class instance_deadmines : public InstanceMapScript _teamInInstance = data; SaveToDB(); break; + case DATA_FOE_REAPER_INTRO: + _foeReaper5000Intro = data; + SaveToDB(); + break; default: break; } @@ -130,6 +151,8 @@ class instance_deadmines : public InstanceMapScript { case DATA_TEAM_IN_INSTANCE: return _teamInInstance; + case DATA_FOE_REAPER_INTRO: + return _foeReaper5000Intro; default: return 0; } @@ -137,16 +160,20 @@ class instance_deadmines : public InstanceMapScript void WriteSaveDataMore(std::ostringstream& data) override { - data << _teamInInstance; + data << _teamInInstance << ' ' + << _foeReaper5000Intro; } void ReadSaveDataMore(std::istringstream& data) override { data >> _teamInInstance; + data >> _foeReaper5000Intro; + } protected: uint32 _teamInInstance; + uint32 _foeReaper5000Intro; }; diff --git a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp index 06549bd23dd..06b7f0593b0 100644 --- a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp +++ b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp @@ -71,6 +71,7 @@ void AddSC_deadmines(); //Deadmines void AddSC_instance_deadmines(); void AddSC_boss_glubtok(); void AddSC_boss_helix_gearbreaker(); +void AddSC_boss_foe_reaper_5000(); void AddSC_gilneas_c1(); //Gilneas void AddSC_gnomeregan(); //Gnomeregan void AddSC_instance_gnomeregan(); @@ -274,6 +275,7 @@ void AddEasternKingdomsScripts() AddSC_instance_deadmines(); AddSC_boss_glubtok(); AddSC_boss_helix_gearbreaker(); + AddSC_boss_foe_reaper_5000(); AddSC_gilneas_c1(); //Gilneas AddSC_gnomeregan(); //Gnomeregan AddSC_instance_gnomeregan();