mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/Scripts: boss Nightbane rework (Karazhan) (#18899)
Closes #10017
(cherrypicked from ad8a71c084)
This commit is contained in:
@@ -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);
|
||||
@@ -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
|
||||
{
|
||||
{-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}
|
||||
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
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
boss_nightbaneAI(Creature* creature) : BossAI(creature, DATA_NIGHTBANE), _flyCount(0) { }
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
|
||||
me->SetSpeedRate(MOVE_RUN, 2.0f);
|
||||
_Reset();
|
||||
_flyCount = 0;
|
||||
me->SetDisableGravity(true);
|
||||
me->SetWalk(false);
|
||||
me->setActive(true);
|
||||
|
||||
if (instance->GetBossState(DATA_NIGHTBANE) == DONE || instance->GetBossState(DATA_NIGHTBANE) == IN_PROGRESS)
|
||||
me->DisappearAndDie();
|
||||
else
|
||||
instance->SetBossState(DATA_NIGHTBANE, NOT_STARTED);
|
||||
|
||||
HandleTerraceDoors(true);
|
||||
if (GameObject* urn = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_GO_BLACKENED_URN)))
|
||||
urn->RemoveFlag(GO_FLAG_IN_USE);
|
||||
}
|
||||
|
||||
if (!Intro)
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
me->SetDisableGravity(true);
|
||||
CreatureAI::EnterEvadeMode(why);
|
||||
}
|
||||
|
||||
void JustReachedHome() override
|
||||
{
|
||||
_DespawnAtEvade();
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
HandleTerraceDoors(true);
|
||||
}
|
||||
|
||||
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 (!Intro && !Flying)
|
||||
ScriptedAI::MoveInLineOfSight(who);
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 id) override
|
||||
{
|
||||
if (type != POINT_MOTION_TYPE)
|
||||
if (events.IsInPhase(PHASE_FLY))
|
||||
{
|
||||
if (damage >= me->GetHealth())
|
||||
damage = me->GetHealth() -1;
|
||||
return;
|
||||
|
||||
if (Intro)
|
||||
{
|
||||
if (id >= 8)
|
||||
{
|
||||
Intro = false;
|
||||
me->SetHomePosition(IntroWay[7][0], IntroWay[7][1], IntroWay[7][2], 0);
|
||||
return;
|
||||
}
|
||||
|
||||
WaitTimer = 1;
|
||||
}
|
||||
|
||||
if (Flying)
|
||||
if ((_flyCount == 0 && HealthBelowPct(75)) || (_flyCount == 1 && HealthBelowPct(50)) || (_flyCount == 2 && HealthBelowPct(25)))
|
||||
{
|
||||
if (id == 0)
|
||||
{
|
||||
Talk(EMOTE_BREATH);
|
||||
Flying = false;
|
||||
Phase = 2;
|
||||
return;
|
||||
}
|
||||
|
||||
if (id == 3)
|
||||
{
|
||||
MovePhase = 4;
|
||||
WaitTimer = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (id == 8)
|
||||
{
|
||||
Flying = false;
|
||||
Phase = 1;
|
||||
Movement = true;
|
||||
return;
|
||||
}
|
||||
|
||||
WaitTimer = 1;
|
||||
events.SetPhase(PHASE_FLY);
|
||||
StartPhaseFly();
|
||||
}
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summoned) override
|
||||
void MovementInform(uint32 type, uint32 pointId) override
|
||||
{
|
||||
summoned->AI()->AttackStart(me->GetVictim());
|
||||
if (type == SPLINE_CHAIN_MOTION_TYPE)
|
||||
{
|
||||
switch (pointId)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
else if (type == POINT_MOTION_TYPE)
|
||||
{
|
||||
if (pointId == POINT_PHASE_TWO_FLY)
|
||||
{
|
||||
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);
|
||||
}
|
||||
else if (pointId == POINT_PHASE_TWO_PRE_FLY)
|
||||
events.ScheduleEvent(EVENT_PRE_FLY_END, Milliseconds(1));
|
||||
}
|
||||
}
|
||||
|
||||
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]);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->AttackStop();
|
||||
|
||||
Flying = true;
|
||||
|
||||
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 ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
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->SetFacingToObject(target, true);
|
||||
DoCast(target, SPELL_RAIN_OF_BONES);
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
/* The timer for this was never setup apparently, not sure if the code works properly:
|
||||
if (WaitTimer <= diff)
|
||||
{
|
||||
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
|
||||
{
|
||||
me->GetMotionMaster()->MovePoint(MovePhase, IntroWay[MovePhase][0], IntroWay[MovePhase][1], IntroWay[MovePhase][2]);
|
||||
++MovePhase;
|
||||
}
|
||||
}
|
||||
|
||||
WaitTimer = 0;
|
||||
} else WaitTimer -= diff;
|
||||
*/
|
||||
|
||||
if (!UpdateVictim())
|
||||
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;
|
||||
|
||||
uint32 Prozent = uint32(me->GetHealthPct());
|
||||
|
||||
if (Prozent < 75 && FlyCount == 0) // first take off 75%
|
||||
TakeOff();
|
||||
|
||||
if (Prozent < 50 && FlyCount == 1) // secound take off 50%
|
||||
TakeOff();
|
||||
|
||||
if (Prozent < 25 && FlyCount == 2) // third take off 25%
|
||||
TakeOff();
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
ExecuteEvent(eventId);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
|
||||
//Phase 2 "FLYING FIGHT"
|
||||
if (Phase == 2)
|
||||
{
|
||||
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 (DistractingAshTimer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
|
||||
DoCast(target, SPELL_DISTRACTING_ASH);
|
||||
DistractingAshTimer = 2000; //timer wrong
|
||||
} else DistractingAshTimer -= diff;
|
||||
}
|
||||
|
||||
if (RainBones)
|
||||
{
|
||||
if (SmokingBlastTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_SMOKING_BLAST);
|
||||
SmokingBlastTimer = 1500; //timer wrong
|
||||
} else SmokingBlastTimer -= diff;
|
||||
}
|
||||
|
||||
if (FireballBarrageTimer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_FARTHEST, 0))
|
||||
DoCast(target, SPELL_FIREBALL_BARRAGE);
|
||||
FireballBarrageTimer = 20000;
|
||||
} else FireballBarrageTimer -= diff;
|
||||
|
||||
if (FlyTimer <= diff) //landing
|
||||
{
|
||||
Talk(YELL_LAND_PHASE);
|
||||
|
||||
me->GetMotionMaster()->Clear(false);
|
||||
me->GetMotionMaster()->MovePoint(3, IntroWay[3][0], IntroWay[3][1], IntroWay[3][2]);
|
||||
|
||||
Flying = true;
|
||||
} else FlyTimer -= diff;
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
uint8 _flyCount;
|
||||
};
|
||||
};
|
||||
|
||||
// 37098 - Rain of Bones
|
||||
class spell_rain_of_bones : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_rain_of_bones() : SpellScriptLoader("spell_rain_of_bones") { }
|
||||
|
||||
class spell_rain_of_bones_AuraScript : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_rain_of_bones_AuraScript);
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_SUMMON_SKELETON });
|
||||
}
|
||||
|
||||
void OnTrigger(AuraEffect const* aurEff)
|
||||
{
|
||||
if (aurEff->GetTickNumber() % 5 == 0)
|
||||
GetTarget()->CastSpell(GetTarget(), SPELL_SUMMON_SKELETON, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_rain_of_bones_AuraScript::OnTrigger, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
{
|
||||
return new spell_rain_of_bones_AuraScript();
|
||||
}
|
||||
};
|
||||
|
||||
class go_blackened_urn : public GameObjectScript
|
||||
{
|
||||
public:
|
||||
go_blackened_urn() : GameObjectScript("go_blackened_urn") { }
|
||||
|
||||
bool OnGossipHello(Player* /*player*/, GameObject* go) override
|
||||
{
|
||||
if (go->HasFlag(GO_FLAG_IN_USE))
|
||||
return false;
|
||||
|
||||
InstanceScript* instance = go->GetInstanceScript();
|
||||
if (!instance || instance->GetBossState(DATA_NIGHTBANE) == DONE || instance->GetBossState(DATA_NIGHTBANE) == IN_PROGRESS)
|
||||
return false;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user