aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/world/master/2019_06_15_08_world_2017_02_04_01_world.sql43
-rw-r--r--src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp619
-rw-r--r--src/server/scripts/EasternKingdoms/Karazhan/instance_karazhan.cpp14
-rw-r--r--src/server/scripts/EasternKingdoms/Karazhan/karazhan.h7
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