diff options
author | Gustavo <sirikfoll@hotmail.com> | 2017-02-04 12:56:00 -0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2019-06-15 18:41:09 +0200 |
commit | 2dcc2d0f058bc2e1d5a66352ec76db18bee189dc (patch) | |
tree | b683ed33d4741e4f5c8f07dee504b48fbc7f0331 | |
parent | a73713b348c4a60302feb7f1fa7af9f8df00c252 (diff) |
Core/Scripts: boss Nightbane rework (Karazhan) (#18899)
Closes #10017
(cherrypicked from ad8a71c0848e9746922bb2b6b90574032ffc1db8)
4 files changed, 379 insertions, 304 deletions
diff --git a/sql/updates/world/master/2019_06_15_08_world_2017_02_04_01_world.sql b/sql/updates/world/master/2019_06_15_08_world_2017_02_04_01_world.sql new file mode 100644 index 00000000000..3764d97852e --- /dev/null +++ b/sql/updates/world/master/2019_06_15_08_world_2017_02_04_01_world.sql @@ -0,0 +1,43 @@ +UPDATE `creature_template` SET `flags_extra`=536871681, `InhabitType`=7 WHERE `entry`=17225; +UPDATE `creature_text` SET `TextRange`=3 WHERE `CreatureID`=17225; +UPDATE `creature_model_info` SET `BoundingRadius`=0.45, `CombatReach`=10.5 WHERE `DisplayID`=18062; +UPDATE `creature_template_addon` SET `bytes2`=1 WHERE `entry`=17225; +UPDATE `gameobject_template` SET `ScriptName`= 'go_blackened_urn' WHERE `entry`=194092; + +DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_rain_of_bones'; +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`)VALUES +(37098,'spell_rain_of_bones'); + +DELETE FROM `script_spline_chain_meta` WHERE `entry`=17225; +INSERT INTO `script_spline_chain_meta` (`entry`,`chainId`,`splineId`,`expectedDuration`,`msUntilNext`) VALUES +(17225, 1, 0, 3689, 0), +(17225, 2, 0, 26021, 0), +(17225, 3, 0, 2697, 0), +(17225, 4, 0, 15920, 0), +(17225, 5, 0, 15920, 0); + +DELETE FROM `script_spline_chain_waypoints` WHERE `entry`=17225; +INSERT INTO `script_spline_chain_waypoints` (`entry`,`chainId`,`splineId`,`wpId`,`x`,`y`,`z`) VALUES +(17225, 1, 0, 0, -11003.710, -1760.1940, 140.25340), +(17225, 1, 0, 1, -11018.860, -1797.2690, 172.85250), +(17225, 2, 0, 0, -11018.860, -1797.2690, 172.85250), +(17225, 2, 0, 1, -11105.760, -1875.9000, 158.97800), +(17225, 2, 0, 2, -11175.100, -1857.2240, 101.00590), +(17225, 2, 0, 3, -11296.930, -1764.5310, 101.00590), +(17225, 2, 0, 4, -11258.900, -1722.3720, 101.00590), +(17225, 2, 0, 5, -11176.760, -1809.5990, 101.00590), +(17225, 2, 0, 6, -11191.110, -1889.3960, 107.89480), +(17225, 2, 0, 7, -11152.180, -1863.3180, 101.00590), +(17225, 2, 0, 8, -11130.680, -1891.4230, 107.89630), +(17225, 2, 0, 9, -11110.670, -1878.7710, 107.89690), +(17225, 3, 0, 0, -11110.670, -1878.7710, 107.89690), +(17225, 3, 0, 1, -11142.710, -1891.1930, 92.250380), +(17225, 4, 0, 0, -11162.230, -1900.3290, 94.727470), +(17225, 4, 0, 1, -11162.230, -1900.3290, 91.472650), +(17225, 5, 0, 0, -11160.130, -1870.6830, 97.738760), +(17225, 5, 0, 1, -11117.730, -1941.2610, 127.17200), +(17225, 5, 0, 2, -11123.780, -1968.2430, 125.92200), +(17225, 5, 0, 3, -11148.340, -1972.9800, 116.69970), +(17225, 5, 0, 4, -11161.620, -1945.7250, 103.08860), +(17225, 5, 0, 5, -11168.010, -1922.9050, 97.394150), +(17225, 5, 0, 6, -11162.230, -1900.3290, 94.727470); diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp index 35b9603c6c1..1928133ab1a 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp @@ -1,6 +1,5 @@ /* - * Copyright (C) 2008-2019 TrinityCore <https://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> + * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -16,56 +15,103 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Boss_Nightbane -SD%Complete: 80 -SDComment: SDComment: Timers may incorrect -SDCategory: Karazhan -EndScriptData */ - +#include "GameObject.h" #include "ScriptMgr.h" #include "InstanceScript.h" #include "karazhan.h" #include "MotionMaster.h" #include "ScriptedCreature.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" -enum Spells +enum NightbaneSpells { - // phase 1 - SPELL_BELLOWING_ROAR = 39427, + SPELL_BELLOWING_ROAR = 36922, SPELL_CHARRED_EARTH = 30129, + SPELL_CLEAVE = 30131, SPELL_DISTRACTING_ASH = 30130, - SPELL_SMOLDERING_BREATH = 30210, - SPELL_TAIL_SWEEP = 25653, - // phase 2 SPELL_RAIN_OF_BONES = 37098, - SPELL_SMOKING_BLAST = 37057, - SPELL_FIREBALL_BARRAGE = 30282, - SPELL_SEARING_CINDERS = 30127, - SPELL_SUMMON_SKELETON = 30170 + SPELL_SMOKING_BLAST = 30128, + SPELL_SMOKING_BLAST_T = 37057, + SPELL_SMOLDERING_BREATH = 30210, + SPELL_SUMMON_SKELETON = 30170, + SPELL_TAIL_SWEEP = 25653 }; enum Says { - EMOTE_SUMMON = 0, // Not used in script + EMOTE_SUMMON = 0, YELL_AGGRO = 1, YELL_FLY_PHASE = 2, YELL_LAND_PHASE = 3, EMOTE_BREATH = 4 }; -float IntroWay[8][3] = +enum NightbanePoints +{ + POINT_INTRO_START = 0, + POINT_INTRO_END = 1, + POINT_INTRO_LANDING = 2, + POINT_PHASE_TWO_FLY = 3, + POINT_PHASE_TWO_PRE_FLY = 4, + POINT_PHASE_TWO_LANDING = 5, + POINT_PHASE_TWO_END = 6 +}; + +enum NightbaneSplineChain +{ + SPLINE_CHAIN_INTRO_START = 1, + SPLINE_CHAIN_INTRO_END = 2, + SPLINE_CHAIN_INTRO_LANDING = 3, + SPLINE_CHAIN_SECOND_LANDING = 4, + SPLINE_CHAIN_PHASE_TWO = 5 +}; + +enum NightbaneEvents +{ + EVENT_BELLOWING_ROAR = 1, + EVENT_CHARRED_EARTH, + EVENT_CLEAVE, + EVENT_DISTRACTING_ASH, + EVENT_EMOTE_BREATH, + EVENT_END_INTRO, + EVENT_END_PHASE_TWO, + EVENT_INTRO_LANDING, + EVENT_LAND, + EVENT_LANDED, + EVENT_PRE_FLY_END, + EVENT_PRE_LAND, + EVENT_RAIN_OF_BONES, + EVENT_SMOLDERING_BREATH, + EVENT_SMOKING_BLAST, + EVENT_SMOKING_BLAST_T, + EVENT_START_INTRO_PATH, + EVENT_TAIL_SWEEP +}; + +enum NightbanePhases +{ + PHASE_INTRO = 0, + PHASE_GROUND, + PHASE_FLY +}; + +enum NightbaneGroups { - {-11053.37f, -1794.48f, 149.00f}, - {-11141.07f, -1841.40f, 125.00f}, - {-11187.28f, -1890.23f, 125.00f}, - {-11189.20f, -1931.25f, 125.00f}, - {-11153.76f, -1948.93f, 125.00f}, - {-11128.73f, -1929.75f, 125.00f}, - {-11140.00f, -1915.00f, 122.00f}, - {-11163.00f, -1903.00f, 91.473f} + GROUP_GROUND = 1, + GROUP_FLY }; +enum NightbaneMisc +{ + ACTION_SUMMON = 0, + PATH_PHASE_TWO = 13547500 +}; + +Position const FlyPosition = { -11160.13f, -1870.683f, 97.73876f, 0.0f }; +Position const FlyPositionLeft = { -11094.42f, -1866.992f, 107.8375f, 0.0f }; +Position const FlyPositionRight = { -11193.77f, -1921.983f, 107.9845f, 0.0f }; + class boss_nightbane : public CreatureScript { public: @@ -76,89 +122,61 @@ public: return GetKarazhanAI<boss_nightbaneAI>(creature); } - struct boss_nightbaneAI : public ScriptedAI + struct boss_nightbaneAI : public BossAI { - boss_nightbaneAI(Creature* creature) : ScriptedAI(creature) - { - Initialize(); - instance = creature->GetInstanceScript(); - Intro = true; - RainBones = false; - Skeletons = false; - FlyTimer = 0; - } + boss_nightbaneAI(Creature* creature) : BossAI(creature, DATA_NIGHTBANE), _flyCount(0) { } - void Initialize() + void Reset() override { - BellowingRoarTimer = 30000; - CharredEarthTimer = 15000; - DistractingAshTimer = 20000; - SmolderingBreathTimer = 10000; - TailSweepTimer = 12000; - RainofBonesTimer = 10000; - SmokingBlastTimer = 20000; - FireballBarrageTimer = 13000; - SearingCindersTimer = 14000; - WaitTimer = 1000; - - Phase = 1; - FlyCount = 0; - MovePhase = 0; - - Flying = false; - Movement = false; + _Reset(); + _flyCount = 0; + me->SetDisableGravity(true); + HandleTerraceDoors(true); + if (GameObject* urn = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_GO_BLACKENED_URN))) + urn->RemoveFlag(GO_FLAG_IN_USE); } - InstanceScript* instance; - - uint32 Phase; - - bool RainBones; - bool Skeletons; - - uint32 BellowingRoarTimer; - uint32 CharredEarthTimer; - uint32 DistractingAshTimer; - uint32 SmolderingBreathTimer; - uint32 TailSweepTimer; - uint32 RainofBonesTimer; - uint32 SmokingBlastTimer; - uint32 FireballBarrageTimer; - uint32 SearingCindersTimer; - - uint32 FlyCount; - uint32 FlyTimer; - - bool Intro; - bool Flying; - bool Movement; - - uint32 WaitTimer; - uint32 MovePhase; - - void Reset() override + void EnterEvadeMode(EvadeReason why) override { - Initialize(); - - me->SetSpeedRate(MOVE_RUN, 2.0f); me->SetDisableGravity(true); - me->SetWalk(false); - me->setActive(true); + CreatureAI::EnterEvadeMode(why); + } - if (instance->GetBossState(DATA_NIGHTBANE) == DONE || instance->GetBossState(DATA_NIGHTBANE) == IN_PROGRESS) - me->DisappearAndDie(); - else - instance->SetBossState(DATA_NIGHTBANE, NOT_STARTED); + void JustReachedHome() override + { + _DespawnAtEvade(); + } + void JustDied(Unit* /*killer*/) override + { + _JustDied(); HandleTerraceDoors(true); + } - if (!Intro) + void DoAction(int32 action) override + { + if (action == ACTION_SUMMON) { - me->SetHomePosition(IntroWay[7][0], IntroWay[7][1], IntroWay[7][2], 0); - me->GetMotionMaster()->MoveTargetedHome(); + Talk(EMOTE_SUMMON); + events.SetPhase(PHASE_INTRO); + me->setActive(true); + me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); + me->GetMotionMaster()->MoveAlongSplineChain(POINT_INTRO_START, SPLINE_CHAIN_INTRO_START, false); + HandleTerraceDoors(false); } } + void SetupGroundPhase() + { + events.SetPhase(PHASE_GROUND); + events.ScheduleEvent(EVENT_CLEAVE, Seconds(0), Seconds(15), GROUP_GROUND); + events.ScheduleEvent(EVENT_TAIL_SWEEP, Seconds(4), Seconds(23), GROUP_GROUND); + events.ScheduleEvent(EVENT_BELLOWING_ROAR, Seconds(48), GROUP_GROUND); + events.ScheduleEvent(EVENT_CHARRED_EARTH, Seconds(12), Seconds(18), GROUP_GROUND); + events.ScheduleEvent(EVENT_SMOLDERING_BREATH, Seconds(26), Seconds(30), GROUP_GROUND); + events.ScheduleEvent(EVENT_DISTRACTING_ASH, Seconds(82), GROUP_GROUND); + } + void HandleTerraceDoors(bool open) { instance->HandleGameObject(instance->GetGuidData(DATA_MASTERS_TERRACE_DOOR_1), open); @@ -167,264 +185,261 @@ public: void EnterCombat(Unit* /*who*/) override { - instance->SetBossState(DATA_NIGHTBANE, IN_PROGRESS); - - HandleTerraceDoors(false); + _EnterCombat(); Talk(YELL_AGGRO); + SetupGroundPhase(); } - void AttackStart(Unit* who) override + void DamageTaken(Unit* /*attacker*/, uint32& damage) override { - if (!Intro && !Flying) - ScriptedAI::AttackStart(who); - } - - void JustDied(Unit* /*killer*/) override - { - instance->SetBossState(DATA_NIGHTBANE, DONE); - - HandleTerraceDoors(true); - } - - void MoveInLineOfSight(Unit* who) override + if (events.IsInPhase(PHASE_FLY)) + { + if (damage >= me->GetHealth()) + damage = me->GetHealth() -1; + return; + } - { - if (!Intro && !Flying) - ScriptedAI::MoveInLineOfSight(who); + if ((_flyCount == 0 && HealthBelowPct(75)) || (_flyCount == 1 && HealthBelowPct(50)) || (_flyCount == 2 && HealthBelowPct(25))) + { + events.SetPhase(PHASE_FLY); + StartPhaseFly(); + } } - void MovementInform(uint32 type, uint32 id) override + void MovementInform(uint32 type, uint32 pointId) override { - if (type != POINT_MOTION_TYPE) - return; - - if (Intro) + if (type == SPLINE_CHAIN_MOTION_TYPE) { - if (id >= 8) + switch (pointId) { - Intro = false; - me->SetHomePosition(IntroWay[7][0], IntroWay[7][1], IntroWay[7][2], 0); - return; + case POINT_INTRO_START: + me->SetAnimTier(UNIT_BYTE1_FLAG_NONE, false); + events.ScheduleEvent(EVENT_START_INTRO_PATH, Milliseconds(1)); + break; + case POINT_INTRO_END: + events.ScheduleEvent(EVENT_END_INTRO, Seconds(2)); + break; + case POINT_INTRO_LANDING: + me->SetDisableGravity(false); + me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); + events.ScheduleEvent(EVENT_INTRO_LANDING, Seconds(3)); + break; + case POINT_PHASE_TWO_LANDING: + events.SetPhase(PHASE_GROUND); + me->SetDisableGravity(false); + me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); + events.ScheduleEvent(EVENT_LANDED, Seconds(3)); + break; + case POINT_PHASE_TWO_END: + events.ScheduleEvent(EVENT_END_PHASE_TWO, Milliseconds(1)); + break; + default: + break; } - - WaitTimer = 1; } - - if (Flying) + else if (type == POINT_MOTION_TYPE) { - if (id == 0) + if (pointId == POINT_PHASE_TWO_FLY) { - Talk(EMOTE_BREATH); - Flying = false; - Phase = 2; - return; + events.ScheduleEvent(EVENT_PRE_LAND, Seconds(33), GROUP_FLY); + events.ScheduleEvent(EVENT_EMOTE_BREATH, Seconds(2), GROUP_FLY); + events.ScheduleEvent(EVENT_SMOKING_BLAST_T, Seconds(21), GROUP_FLY); + events.ScheduleEvent(EVENT_SMOKING_BLAST, Seconds(17), GROUP_FLY); } - - if (id == 3) - { - MovePhase = 4; - WaitTimer = 1; - return; - } - - if (id == 8) - { - Flying = false; - Phase = 1; - Movement = true; - return; - } - - WaitTimer = 1; + else if (pointId == POINT_PHASE_TWO_PRE_FLY) + events.ScheduleEvent(EVENT_PRE_FLY_END, Milliseconds(1)); } } - void JustSummoned(Creature* summoned) override - { - summoned->AI()->AttackStart(me->GetVictim()); - } - - void TakeOff() + void StartPhaseFly() { + ++_flyCount; Talk(YELL_FLY_PHASE); - - me->InterruptSpell(CURRENT_GENERIC_SPELL); + events.CancelEventGroup(GROUP_GROUND); + me->InterruptNonMeleeSpells(false); me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); me->SetDisableGravity(true); - (*me).GetMotionMaster()->Clear(false); - (*me).GetMotionMaster()->MovePoint(0, IntroWay[2][0], IntroWay[2][1], IntroWay[2][2]); - - Flying = true; + me->SetReactState(REACT_PASSIVE); + me->AttackStop(); - FlyTimer = urand(45000, 60000); //timer wrong between 45 and 60 seconds - ++FlyCount; - - RainofBonesTimer = 5000; //timer wrong (maybe) - RainBones = false; - Skeletons = false; + if (me->GetDistance(FlyPositionLeft) < me->GetDistance(FlyPosition)) + me->GetMotionMaster()->MovePoint(POINT_PHASE_TWO_PRE_FLY, FlyPositionLeft, true); + else if (me->GetDistance(FlyPositionRight) < me->GetDistance(FlyPosition)) + me->GetMotionMaster()->MovePoint(POINT_PHASE_TWO_PRE_FLY, FlyPositionRight, true); + else + me->GetMotionMaster()->MovePoint(POINT_PHASE_TWO_FLY, FlyPosition, true); } - void UpdateAI(uint32 diff) override + void ExecuteEvent(uint32 eventId) override { - /* The timer for this was never setup apparently, not sure if the code works properly: - if (WaitTimer <= diff) + switch (eventId) { - if (Intro) - { - if (MovePhase >= 7) - { - me->SetLevitate(false); - me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); - me->GetMotionMaster()->MovePoint(8, IntroWay[7][0], IntroWay[7][1], IntroWay[7][2]); - } - else - { - me->GetMotionMaster()->MovePoint(MovePhase, IntroWay[MovePhase][0], IntroWay[MovePhase][1], IntroWay[MovePhase][2]); - ++MovePhase; - } - } - if (Flying) - { - if (MovePhase >= 7) - { - me->SetLevitate(false); - me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); - me->GetMotionMaster()->MovePoint(8, IntroWay[7][0], IntroWay[7][1], IntroWay[7][2]); - } - else + case EVENT_BELLOWING_ROAR: + DoCastAOE(SPELL_BELLOWING_ROAR); + break; + case EVENT_CHARRED_EARTH: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) + DoCast(target, SPELL_CHARRED_EARTH); + events.Repeat(Seconds(18), Seconds(21)); + break; + case EVENT_CLEAVE: + DoCastVictim(SPELL_CLEAVE); + events.Repeat(Seconds(6), Seconds(15)); + break; + case EVENT_DISTRACTING_ASH: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) + DoCast(target, SPELL_DISTRACTING_ASH); + break; + case EVENT_EMOTE_BREATH: + Talk(EMOTE_BREATH); + events.ScheduleEvent(EVENT_RAIN_OF_BONES, Seconds(3), GROUP_FLY); + break; + case EVENT_END_INTRO: + me->GetMotionMaster()->MoveAlongSplineChain(POINT_INTRO_LANDING, SPLINE_CHAIN_INTRO_LANDING, false); + break; + case EVENT_END_PHASE_TWO: + me->GetMotionMaster()->MoveAlongSplineChain(POINT_PHASE_TWO_LANDING, SPLINE_CHAIN_SECOND_LANDING, false); + break; + case EVENT_INTRO_LANDING: + me->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_PC); + me->SetInCombatWithZone(); + break; + case EVENT_LAND: + Talk(YELL_LAND_PHASE); + me->SetDisableGravity(true); + me->GetMotionMaster()->MoveAlongSplineChain(POINT_PHASE_TWO_END, SPLINE_CHAIN_PHASE_TWO, false); + break; + case EVENT_LANDED: + SetupGroundPhase(); + me->SetReactState(REACT_AGGRESSIVE); + break; + case EVENT_PRE_FLY_END: + me->GetMotionMaster()->MovePoint(POINT_PHASE_TWO_FLY, FlyPosition, true); + break; + case EVENT_PRE_LAND: + events.CancelEventGroup(GROUP_FLY); + events.ScheduleEvent(EVENT_LAND, Seconds(2), GROUP_GROUND); + break; + case EVENT_START_INTRO_PATH: + me->GetMotionMaster()->MoveAlongSplineChain(POINT_INTRO_END, SPLINE_CHAIN_INTRO_END, false); + break; + case EVENT_RAIN_OF_BONES: + DoResetThreat(); + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) { - me->GetMotionMaster()->MovePoint(MovePhase, IntroWay[MovePhase][0], IntroWay[MovePhase][1], IntroWay[MovePhase][2]); - ++MovePhase; + me->SetFacingToObject(target, true); + DoCast(target, SPELL_RAIN_OF_BONES); } - } - - WaitTimer = 0; - } else WaitTimer -= diff; - */ + break; + case EVENT_SMOLDERING_BREATH: + DoCastVictim(SPELL_SMOLDERING_BREATH); + events.Repeat(Seconds(28), Seconds(40)); + break; + case EVENT_SMOKING_BLAST: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) + DoCast(target, SPELL_SMOKING_BLAST); + events.Repeat(Milliseconds(1400)); + break; + case EVENT_SMOKING_BLAST_T: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) + DoCast(target, SPELL_SMOKING_BLAST_T); + events.Repeat(Seconds(5), Seconds(7)); + break; + case EVENT_TAIL_SWEEP: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) + if (!me->HasInArc(float(M_PI), target)) + DoCast(target, SPELL_TAIL_SWEEP); + events.Repeat(Seconds(20), Seconds(30)); + break; + default: + break; + } + } - if (!UpdateVictim()) + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim() && !events.IsInPhase(PHASE_INTRO)) return; - if (Flying) + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) return; - // Phase 1 "GROUND FIGHT" - if (Phase == 1) + while (uint32 eventId = events.ExecuteEvent()) { - if (Movement) - { - DoStartMovement(me->GetVictim()); - Movement = false; - } - - if (BellowingRoarTimer <= diff) - { - DoCastVictim(SPELL_BELLOWING_ROAR); - BellowingRoarTimer = urand(30000, 40000); - } else BellowingRoarTimer -= diff; - - if (SmolderingBreathTimer <= diff) - { - DoCastVictim(SPELL_SMOLDERING_BREATH); - SmolderingBreathTimer = 20000; - } else SmolderingBreathTimer -= diff; - - if (CharredEarthTimer <= diff) - { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_CHARRED_EARTH); - CharredEarthTimer = 20000; - } else CharredEarthTimer -= diff; - - if (TailSweepTimer <= diff) - { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - if (!me->HasInArc(float(M_PI), target)) - DoCast(target, SPELL_TAIL_SWEEP); - TailSweepTimer = 15000; - } else TailSweepTimer -= diff; - - if (SearingCindersTimer <= diff) - { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_SEARING_CINDERS); - SearingCindersTimer = 10000; - } else SearingCindersTimer -= diff; + ExecuteEvent(eventId); + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + } - uint32 Prozent = uint32(me->GetHealthPct()); + DoMeleeAttackIfReady(); + } - if (Prozent < 75 && FlyCount == 0) // first take off 75% - TakeOff(); + private: + uint8 _flyCount; + }; +}; - if (Prozent < 50 && FlyCount == 1) // secound take off 50% - TakeOff(); +// 37098 - Rain of Bones +class spell_rain_of_bones : public SpellScriptLoader +{ + public: + spell_rain_of_bones() : SpellScriptLoader("spell_rain_of_bones") { } - if (Prozent < 25 && FlyCount == 2) // third take off 25% - TakeOff(); + class spell_rain_of_bones_AuraScript : public AuraScript + { + PrepareAuraScript(spell_rain_of_bones_AuraScript); - DoMeleeAttackIfReady(); + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_SUMMON_SKELETON }); } - //Phase 2 "FLYING FIGHT" - if (Phase == 2) + void OnTrigger(AuraEffect const* aurEff) { - if (!RainBones) - { - if (!Skeletons) - { - for (uint8 i = 0; i <= 3; ++i) - { - DoCastVictim(SPELL_SUMMON_SKELETON); - Skeletons = true; - } - } - - if (RainofBonesTimer < diff && !RainBones) // only once at the beginning of phase 2 - { - DoCastVictim(SPELL_RAIN_OF_BONES); - RainBones = true; - SmokingBlastTimer = 20000; - } else RainofBonesTimer -= diff; + if (aurEff->GetTickNumber() % 5 == 0) + GetTarget()->CastSpell(GetTarget(), SPELL_SUMMON_SKELETON, true); + } - if (DistractingAshTimer <= diff) - { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_DISTRACTING_ASH); - DistractingAshTimer = 2000; //timer wrong - } else DistractingAshTimer -= diff; - } + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_rain_of_bones_AuraScript::OnTrigger, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + }; - if (RainBones) - { - if (SmokingBlastTimer <= diff) - { - DoCastVictim(SPELL_SMOKING_BLAST); - SmokingBlastTimer = 1500; //timer wrong - } else SmokingBlastTimer -= diff; - } + AuraScript* GetAuraScript() const override + { + return new spell_rain_of_bones_AuraScript(); + } +}; - if (FireballBarrageTimer <= diff) - { - if (Unit* target = SelectTarget(SELECT_TARGET_FARTHEST, 0)) - DoCast(target, SPELL_FIREBALL_BARRAGE); - FireballBarrageTimer = 20000; - } else FireballBarrageTimer -= diff; +class go_blackened_urn : public GameObjectScript +{ +public: + go_blackened_urn() : GameObjectScript("go_blackened_urn") { } - if (FlyTimer <= diff) //landing - { - Talk(YELL_LAND_PHASE); + bool OnGossipHello(Player* /*player*/, GameObject* go) override + { + if (go->HasFlag(GO_FLAG_IN_USE)) + return false; - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MovePoint(3, IntroWay[3][0], IntroWay[3][1], IntroWay[3][2]); + InstanceScript* instance = go->GetInstanceScript(); + if (!instance || instance->GetBossState(DATA_NIGHTBANE) == DONE || instance->GetBossState(DATA_NIGHTBANE) == IN_PROGRESS) + return false; - Flying = true; - } else FlyTimer -= diff; - } + if (Creature* nightbane = ObjectAccessor::GetCreature(*go, instance->GetGuidData(DATA_NIGHTBANE))) + { + go->AddFlag(GO_FLAG_IN_USE); + nightbane->AI()->DoAction(ACTION_SUMMON); } - }; + return false; + } }; void AddSC_boss_nightbane() { new boss_nightbane(); + new spell_rain_of_bones(); + new go_blackened_urn(); } diff --git a/src/server/scripts/EasternKingdoms/Karazhan/instance_karazhan.cpp b/src/server/scripts/EasternKingdoms/Karazhan/instance_karazhan.cpp index 5c4ac116ba1..87b5f135471 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/instance_karazhan.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/instance_karazhan.cpp @@ -88,6 +88,11 @@ public: case NPC_MOROES: MoroesGUID = creature->GetGUID(); break; + case NPC_NIGHTBANE: + NightbaneGUID = creature->GetGUID(); + break; + default: + break; } } @@ -227,6 +232,9 @@ public: case GO_DUST_COVERED_CHEST: DustCoveredChest = go->GetGUID(); break; + case GO_BLACKENED_URN: + BlackenedUrnGUID = go->GetGUID(); + break; } switch (OperaEvent) @@ -266,6 +274,8 @@ public: return TerestianGUID; case DATA_MOROES: return MoroesGUID; + case DATA_NIGHTBANE: + return NightbaneGUID; case DATA_GO_STAGEDOORLEFT: return StageDoorLeftGUID; case DATA_GO_STAGEDOORRIGHT: @@ -290,6 +300,8 @@ public: return MastersTerraceDoor[1]; case DATA_IMAGE_OF_MEDIVH: return ImageGUID; + case DATA_GO_BLACKENED_URN: + return BlackenedUrnGUID; } return ObjectGuid::Empty; @@ -305,6 +317,7 @@ public: ObjectGuid KilrekGUID; ObjectGuid TerestianGUID; ObjectGuid MoroesGUID; + ObjectGuid NightbaneGUID; ObjectGuid LibraryDoor; // Door at Shade of Aran ObjectGuid MassiveDoor; // Door at Netherspite ObjectGuid SideEntranceDoor; // Side Entrance @@ -314,6 +327,7 @@ public: ObjectGuid MastersTerraceDoor[2]; ObjectGuid ImageGUID; ObjectGuid DustCoveredChest; + ObjectGuid BlackenedUrnGUID; }; }; diff --git a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.h b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.h index 8ee4bc7cd65..f2f19284694 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.h +++ b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.h @@ -56,7 +56,8 @@ enum KZDataTypes DATA_IMAGE_OF_MEDIVH = 26, DATA_MASTERS_TERRACE_DOOR_1 = 27, DATA_MASTERS_TERRACE_DOOR_2 = 28, - DATA_GO_SIDE_ENTRANCE_DOOR = 29 + DATA_GO_SIDE_ENTRANCE_DOOR = 29, + DATA_GO_BLACKENED_URN = 30 }; enum KZOperaEvents @@ -73,6 +74,7 @@ enum KZMiscCreatures NPC_SHADIKITH_THE_GLIDER = 16180, NPC_TERESTIAN_ILLHOOF = 15688, NPC_MOROES = 15687, + NPC_NIGHTBANE = 17225, NPC_ATTUMEN_UNMOUNTED = 15550, NPC_ATTUMEN_MOUNTED = 16152, NPC_MIDNIGHT = 16151, @@ -102,7 +104,8 @@ enum KZGameObjectIds GO_MASTERS_TERRACE_DOOR = 184274, GO_MASTERS_TERRACE_DOOR2 = 184280, GO_SIDE_ENTRANCE_DOOR = 184275, - GO_DUST_COVERED_CHEST = 185119 + GO_DUST_COVERED_CHEST = 185119, + GO_BLACKENED_URN = 194092 }; enum KZMisc |