/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 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 Affero 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 "CreatureScript.h"
#include "GridNotifiers.h"
#include "ScriptedCreature.h"
#include "SpellScript.h"
#include "SpellScriptLoader.h"
#include "WorldPacket.h"
#include "the_eye.h"
enum KTYells
{
// Kael'thas Speech
SAY_INTRO = 0,
SAY_INTRO_CAPERNIAN = 1,
SAY_INTRO_TELONICUS = 2,
SAY_INTRO_THALADRED = 3,
SAY_INTRO_SANGUINAR = 4,
SAY_PHASE2_WEAPON = 5,
SAY_PHASE3_ADVANCE = 6,
SAY_PHASE4_INTRO2 = 7,
SAY_PHASE5_NUTS = 8,
SAY_SLAY = 9,
SAY_MINDCONTROL = 10,
SAY_GRAVITYLAPSE = 11,
SAY_SUMMON_PHOENIX = 12,
SAY_DEATH = 13,
SAY_PYROBLAST = 14,
// Advisors
SAY_THALADRED_AGGRO = 0,
SAY_SANGUINAR_AGGRO = 0,
SAY_CAPERNIAN_AGGRO = 0,
SAY_TELONICUS_AGGRO = 0,
SAY_THALADRED_DEATH = 1,
SAY_SANGUINAR_DEATH = 1,
SAY_CAPERNIAN_DEATH = 1,
SAY_TELONICUS_DEATH = 1,
EMOTE_THALADRED_FIXATE = 2
};
enum KTSpells
{
// _phase 2 spells
SPELL_SUMMON_WEAPONS = 36976,
SPELL_SUMMON_WEAPONA = 36958,
SPELL_SUMMON_WEAPONB = 36959,
SPELL_SUMMON_WEAPONC = 36960,
SPELL_SUMMON_WEAPOND = 36961,
SPELL_SUMMON_WEAPONE = 36962,
SPELL_SUMMON_WEAPONF = 36963,
SPELL_SUMMON_WEAPONG = 36964,
// _phase 3 spells
SPELL_RESURRECTION = 36450,
// _phase 4 spells
SPELL_FIREBALL = 36805,
SPELL_ARCANE_DISRUPTION = 36834,
SPELL_PHOENIX = 36723,
SPELL_MIND_CONTROL = 36797,
SPELL_SHOCK_BARRIER = 36815,
SPELL_PYROBLAST = 36819,
SPELL_FLAME_STRIKE = 36735,
SPELL_FLAME_STRIKE_DAMAGE = 36731,
// transition scene spells
SPELL_NETHERBEAM_AURA1 = 36364,
SPELL_NETHERBEAM_AURA2 = 36370,
SPELL_NETHERBEAM_AURA3 = 36371,
SPELL_NETHERBEAM1 = 36089,
SPELL_NETHERBEAM2 = 36090,
SPELL_KAEL_GAINING_POWER = 36091,
SPELL_KAEL_EXPLODES1 = 36376,
SPELL_KAEL_EXPLODES2 = 36375,
SPELL_KAEL_EXPLODES3 = 36373,
SPELL_KAEL_EXPLODES4 = 36354,
SPELL_KAEL_EXPLODES5 = 36092,
SPELL_GROW = 36184,
SPELL_KEAL_STUNNED = 36185,
SPELL_KAEL_FULL_POWER = 36187,
SPELL_FLOATING_DROWNED = 36550,
SPELL_DARK_BANISH_STATE = 52241, // wrong visual apparently
SPELL_ARCANE_EXPLOSION_VISUAL = 34807,
SPELL_PURE_NETHER_BEAM1 = 36196,
SPELL_PURE_NETHER_BEAM2 = 36197,
SPELL_PURE_NETHER_BEAM3 = 36198,
SPELL_PURE_NETHER_BEAM4 = 36201,
SPELL_PURE_NETHER_BEAM5 = 36290,
SPELL_PURE_NETHER_BEAM6 = 36291,
// _phase 5 spells
SPELL_GRAVITY_LAPSE = 35941,
SPELL_GRAVITY_LAPSE_TELEPORT1 = 35966,
SPELL_GRAVITY_LAPSE_KNOCKBACK = 34480,
SPELL_GRAVITY_LAPSE_AURA = 39432,
SPELL_SUMMON_NETHER_VAPOR = 35865,
SPELL_NETHER_BEAM = 35869,
SPELL_NETHER_BEAM_DAMAGE = 35873,
SPELL_REMOTE_TOY_STUN = 37029,
// Advisors
// Universal
SPELL_KAEL_PHASE_TWO = 36709,
// Sanguinar
SPELL_BELLOWING_ROAR = 44863,
// Capernian
SPELL_CAPERNIAN_FIREBALL = 36971,
SPELL_CONFLAGRATION = 37018,
SPELL_ARCANE_BURST = 36970,
// Telonicus
SPELL_BOMB = 37036,
SPELL_REMOTE_TOY = 37027,
// Thaladred
SPELL_PSYCHIC_BLOW = 36966,
SPELL_REND = 36965,
SPELL_SILENCE = 30225
};
enum KTPhases
{
PHASE_NONE = 0,
PHASE_SINGLE_ADVISOR = 1,
PHASE_WEAPONS = 2,
PHASE_TRANSITION = 3,
PHASE_ALL_ADVISORS = 4,
PHASE_FINAL = 5
};
enum KTMisc
{
POINT_MIDDLE = 1,
POINT_AIR = 2,
POINT_LAND = 3,
POINT_START_LAST_PHASE = 4,
DATA_RESURRECT_CAST = 1,
NPC_WORLD_TRIGGER = 19871,
NPC_NETHER_VAPOR = 21002,
NPC_NETHERSTRAND_LONGBOW = 21268,
NPC_STAFF_OF_DISINTEGRATION = 21274,
};
enum KTPreFightEvents
{
EVENT_PREFIGHT_PHASE1_01 = 1,
EVENT_PREFIGHT_PHASE1_02 = 2,
EVENT_PREFIGHT_PHASE5_01 = 3,
EVENT_PREFIGHT_PHASE5_02 = 4,
EVENT_PREFIGHT_PHASE6_02 = 5,
EVENT_PREFIGHT_PHASE6_03 = 6,
};
enum KTTransitionScene
{
EVENT_SCENE_1 = 50, // NYI
EVENT_SCENE_2 = 51,
EVENT_SCENE_3 = 52,
EVENT_SCENE_4 = 53,
EVENT_SCENE_5 = 54,
EVENT_SCENE_6 = 55,
EVENT_SCENE_7 = 56,
EVENT_SCENE_8 = 57,
EVENT_SCENE_9 = 58,
EVENT_SCENE_10 = 59,
EVENT_SCENE_11 = 60,
EVENT_SCENE_12 = 61,
EVENT_SCENE_13 = 62,
EVENT_SCENE_14 = 63,
EVENT_SCENE_15 = 64,
EVENT_SCENE_16 = 65
};
enum KTActions
{
ACTION_START_SANGUINAR = 0,
ACTION_START_CAPERNIAN = 1,
ACTION_START_TELONICUS = 2,
ACTION_START_WEAPONS = 3,
ACTION_PROGRESS_PHASE_CHECK = 4
};
enum KTSpellGroups
{
GROUP_PROGRESS_PHASE = 0,
GROUP_PYROBLAST = 1,
GROUP_SHOCK_BARRIER = 2,
GROUP_NETHER_BEAM = 3
};
const Position triggersPos[6] =
{
{799.11f, -38.95f, 85.0f, 0.0f},
{800.16f, 37.65f, 85.0f, 0.0f},
{847.64f, -16.19f, 64.05f, 0.0f},
{847.53f, 15.01f, 63.69f, 0.0f},
{843.44f, -7.87f, 67.14f, 0.0f},
{843.35f, 6.35f, 67.14f, 0.0f}
};
struct boss_kaelthas : public BossAI
{
boss_kaelthas(Creature* creature) : BossAI(creature, DATA_KAELTHAS) { }
void PrepareAdvisors()
{
for (uint8 advisorData = DATA_THALADRED; advisorData <= DATA_TELONICUS; ++advisorData)
{
if (Creature* advisor = instance->GetCreature(advisorData))
{
advisor->Respawn(true);
advisor->StopMovingOnCurrentPos();
advisor->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
advisor->SetReactState(REACT_PASSIVE);
summons.Summon(advisor);
}
}
}
void SetData(uint32 type, uint32 data) override
{
if (type == DATA_RESURRECT_CAST && data == DATA_RESURRECT_CAST)
{
summons.DoForAllSummons([&](WorldObject* summon){
if (Creature* summonedCreature = summon->ToCreature())
{
if (summonedCreature->GetEntry() >= NPC_LORD_SANGUINAR && summonedCreature->GetEntry() <= NPC_THALADRED)
{
summonedCreature->SetReactState(REACT_PASSIVE);
summonedCreature->setDeathState(DeathState::JustRespawned);
summonedCreature->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
}
}
});
}
}
void SetRoomState(GOState state)
{
//TODO: handle door closing
if (GameObject* window = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(GO_BRIDGE_WINDOW)))
window->SetGoState(state);
if (GameObject* window = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(GO_KAEL_STATUE_RIGHT)))
window->SetGoState(state);
if (GameObject* window = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(GO_KAEL_STATUE_LEFT)))
window->SetGoState(state);
}
void Reset() override
{
BossAI::Reset();
scheduler.Schedule(1s, [this](TaskContext)
{
PrepareAdvisors();
});
_phase = PHASE_NONE;
_transitionSceneReached = false;
me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_HOVER, true);
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE);
SetRoomState(GO_STATE_READY);
me->SetDisableGravity(false);
me->SetWalk(false);
}
void AttackStart(Unit* who) override
{
if (_phase == PHASE_FINAL /* check is scheduled&& events.GetNextEventTime(EVENT_GRAVITY_LAPSE_END) == 0*/)
BossAI::AttackStart(who);
}
void JustReachedHome() override
{
Reset();
}
void MoveInLineOfSight(Unit* who) override
{
if (_phase == PHASE_NONE && who->IsPlayer() && me->IsValidAttackTarget(who))
{
_phase = PHASE_SINGLE_ADVISOR;
me->SetInCombatWithZone();
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_DISABLE_MOVE);
Talk(SAY_INTRO);
ScheduleUniqueTimedEvent(23s, [&]
{
Talk(SAY_INTRO_THALADRED);
}, EVENT_PREFIGHT_PHASE1_01);
ScheduleUniqueTimedEvent(30s, [&]
{
if (Creature* thaladred = summons.GetCreatureWithEntry(NPC_THALADRED))
{
thaladred->SetReactState(REACT_AGGRESSIVE);
thaladred->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
thaladred->AI()->AttackStart(target);
thaladred->SetInCombatWithZone();
}
}, EVENT_PREFIGHT_PHASE1_02);
}
}
void KilledUnit(Unit* victim) override
{
if (victim->IsPlayer())
Talk(SAY_SLAY);
}
void JustSummoned(Creature* summon) override
{
summons.Summon(summon);
if (summon->GetEntry() == NPC_NETHER_VAPOR)
summon->GetMotionMaster()->MoveRandom(20.0f);
if (summon->GetEntry() >= NPC_NETHERSTRAND_LONGBOW && summon->GetEntry() <= NPC_STAFF_OF_DISINTEGRATION)
summon->SetReactState(REACT_PASSIVE);
}
void DoAction(int32 action) override
{
switch(action)
{
case ACTION_START_SANGUINAR:
IntroduceNewAdvisor(SAY_INTRO_SANGUINAR, ACTION_START_SANGUINAR);
break;
case ACTION_START_CAPERNIAN:
IntroduceNewAdvisor(SAY_INTRO_CAPERNIAN, ACTION_START_CAPERNIAN);
break;
case ACTION_START_TELONICUS:
IntroduceNewAdvisor(SAY_INTRO_TELONICUS, ACTION_START_TELONICUS);
break;
case ACTION_START_WEAPONS:
ScheduleUniqueTimedEvent(3s, [&]{
Talk(SAY_PHASE2_WEAPON);
DoCastSelf(SPELL_SUMMON_WEAPONS);
_phase = PHASE_WEAPONS;
}, EVENT_PREFIGHT_PHASE5_01);
ScheduleUniqueTimedEvent(9s, [&]{
summons.DoForAllSummons([&](WorldObject* summon)
{
if (Creature* summonedCreature = summon->ToCreature())
{
if (!summonedCreature->GetSpawnId())
{
summonedCreature->SetReactState(REACT_AGGRESSIVE);
summonedCreature->SetInCombatWithZone();
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
{
summonedCreature->AI()->AttackStart(target);
}
}
}
});
scheduler.Schedule(90s, GROUP_PROGRESS_PHASE, [this](TaskContext)
{
PhaseAllAdvisorsExecute();
});
}, EVENT_PREFIGHT_PHASE5_02);
break;
case ACTION_PROGRESS_PHASE_CHECK:
if (_phase == PHASE_ALL_ADVISORS)
{
bool advisorAlive = false;
summons.DoForAllSummons([&advisorAlive](WorldObject* summon)
{
if (Creature* summonedCreature = summon->ToCreature())
{
if (summonedCreature->IsAlive())
{
if (summonedCreature->GetEntry() >= NPC_LORD_SANGUINAR && summonedCreature->GetEntry() <= NPC_THALADRED)
{
advisorAlive = true;
return;
}
}
}
});
if (!advisorAlive)
PhaseKaelExecute();
}
default:
break;
}
}
void MovementInform(uint32 type, uint32 point) override
{
if (type != POINT_MOTION_TYPE)
return;
if (point == POINT_MIDDLE)
{
ExecuteMiddleEvent();
}
else if (point == POINT_START_LAST_PHASE)
{
me->SetDisableGravity(false);
me->SetWalk(false);
me->RemoveAurasDueToSpell(SPELL_KAEL_FULL_POWER);
me->SetReactState(REACT_AGGRESSIVE);
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
//re-set validator
scheduler.SetValidator([this]{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
ScheduleTimedEvent(0ms, [&]
{
DoCastVictim(SPELL_FIREBALL);
}, 2400ms, 7500ms);
ScheduleTimedEvent(10000ms, [&]
{
DoCastRandomTarget(SPELL_FLAME_STRIKE, 0, 100.0f);
}, 30250ms, 50650ms);
ScheduleTimedEvent(50000ms, [&]
{
Talk(SAY_SUMMON_PHOENIX);
DoCastSelf(SPELL_PHOENIX);
}, 61450ms, 96550ms);
ScheduleTimedEvent(5s, [&]
{
scheduler.DelayAll(30s);
me->setAttackTimer(BASE_ATTACK, 30000);
DoCastSelf(SPELL_GRAVITY_LAPSE);
DoCastSelf(SPELL_SUMMON_NETHER_VAPOR);
scheduler.Schedule(4s, GROUP_NETHER_BEAM, [this](TaskContext context)
{
DoCastSelf(SPELL_NETHER_BEAM);
context.Repeat(4s);
}).Schedule(0s, GROUP_SHOCK_BARRIER, [this](TaskContext context)
{
DoCastSelf(SPELL_SHOCK_BARRIER);
context.Repeat(10s);
}).Schedule(20500ms, GROUP_SHOCK_BARRIER, [this](TaskContext)
{
scheduler.CancelGroup(GROUP_SHOCK_BARRIER);
}).Schedule(32s, [this](TaskContext)
{
summons.DespawnEntry(NPC_NETHER_VAPOR);
scheduler.CancelGroup(GROUP_NETHER_BEAM);
if (Unit* victim = me->GetVictim())
{
me->SetTarget(victim->GetGUID());
me->GetMotionMaster()->MoveChase(victim);
}
});
me->SetTarget();
me->GetMotionMaster()->Clear();
me->StopMoving();
Talk(SAY_GRAVITYLAPSE);
}, 90s);
if (me->GetVictim())
{
me->SetTarget(me->GetVictim()->GetGUID());
AttackStart(me->GetVictim());
}
}
}
void ExecuteMiddleEvent()
{
scheduler.ClearValidator();
me->SetTarget();
me->SetFacingTo(M_PI);
me->SetWalk(true);
Talk(SAY_PHASE5_NUTS);
ScheduleUniqueTimedEvent(2500ms, [&]
{
me->SetTarget();
DoCastSelf(SPELL_KAEL_EXPLODES1, true);
DoCastSelf(SPELL_KAEL_GAINING_POWER);
}, EVENT_SCENE_2);
ScheduleUniqueTimedEvent(4000ms, [&]
{
me->SetTarget();
for (uint8 i = 0; i < 2; ++i)
if (Creature* trigger = me->SummonCreature(WORLD_TRIGGER, triggersPos[i], TEMPSUMMON_TIMED_DESPAWN, 60000))
trigger->CastSpell(me, SPELL_NETHERBEAM1 + i, false);
me->SetDisableGravity(true);
me->SendMovementFlagUpdate();
me->GetMotionMaster()->MoveTakeoff(POINT_AIR, me->GetPositionX(), me->GetPositionY(), 75.0f, 2.99);
DoCastSelf(SPELL_GROW, true);
}, EVENT_SCENE_3);
ScheduleUniqueTimedEvent(7000ms, [&]
{
me->SetTarget();
DoCastSelf(SPELL_GROW, true);
DoCastSelf(SPELL_KAEL_EXPLODES2, true);
DoCastSelf(SPELL_NETHERBEAM_AURA1, true);
for (uint8 i = 0; i < 2; ++i)
if (Creature* trigger = me->SummonCreature(WORLD_TRIGGER, triggersPos[i + 2], TEMPSUMMON_TIMED_DESPAWN, 60000))
trigger->CastSpell(me, SPELL_NETHERBEAM1 + i, false);
}, EVENT_SCENE_4);
ScheduleUniqueTimedEvent(10000ms, [&]
{
me->SetTarget();
DoCastSelf(SPELL_GROW, true);
DoCastSelf(SPELL_KAEL_EXPLODES3, true);
DoCastSelf(SPELL_NETHERBEAM_AURA2, true);
for (uint8 i = 0; i < 2; ++i)
if (Creature* trigger = me->SummonCreature(WORLD_TRIGGER, triggersPos[i + 4], TEMPSUMMON_TIMED_DESPAWN, 60000))
trigger->CastSpell(me, SPELL_NETHERBEAM1 + i, false);
}, EVENT_SCENE_5);
ScheduleUniqueTimedEvent(14000ms, [&]
{
DoCastSelf(SPELL_GROW, true);
DoCastSelf(SPELL_KAEL_EXPLODES4, true);
DoCastSelf(SPELL_NETHERBEAM_AURA3, true);
}, EVENT_SCENE_6);
ScheduleUniqueTimedEvent(17500ms, [&]
{
SetRoomState(GO_STATE_ACTIVE);
}, EVENT_SCENE_7);
ScheduleUniqueTimedEvent(19000ms, [&]
{
summons.DespawnEntry(WORLD_TRIGGER);
me->RemoveAurasDueToSpell(SPELL_NETHERBEAM_AURA1);
me->RemoveAurasDueToSpell(SPELL_NETHERBEAM_AURA2);
me->RemoveAurasDueToSpell(SPELL_NETHERBEAM_AURA3);
DoCastSelf(SPELL_KAEL_EXPLODES5, true);
DoCastSelf(SPELL_FLOATING_DROWNED);
//me->CastSpell(me, SPELL_KEAL_STUNNED, true);
}, EVENT_SCENE_8);
ScheduleUniqueTimedEvent(22000ms, [&]
{
DoCastSelf(SPELL_DARK_BANISH_STATE, true);
DoCastSelf(SPELL_ARCANE_EXPLOSION_VISUAL, true);
me->SummonCreature(NPC_WORLD_TRIGGER, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 15.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 60000);
if (Creature* trigger = me->SummonCreature(WORLD_TRIGGER, me->GetPositionX() + 5, me->GetPositionY(), me->GetPositionZ() + 15.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 60000))
trigger->CastSpell(me, SPELL_PURE_NETHER_BEAM1, true);
if (Creature* trigger = me->SummonCreature(WORLD_TRIGGER, me->GetPositionX() - 5, me->GetPositionY(), me->GetPositionZ() + 15.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 60000))
trigger->CastSpell(me, SPELL_PURE_NETHER_BEAM2, true);
}, EVENT_SCENE_9);
ScheduleUniqueTimedEvent(22800ms, [&]
{
if (Creature* trigger = me->SummonCreature(WORLD_TRIGGER, me->GetPositionX() - 5, me->GetPositionY() - 5, me->GetPositionZ() + 15.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 60000))
trigger->CastSpell(me, SPELL_PURE_NETHER_BEAM3, true);
if (Creature* trigger = me->SummonCreature(WORLD_TRIGGER, me->GetPositionX() + 5, me->GetPositionY() + 5, me->GetPositionZ() + 15.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 60000))
trigger->CastSpell(me, SPELL_PURE_NETHER_BEAM1, true);
}, EVENT_SCENE_10);
ScheduleUniqueTimedEvent(23600ms, [&]
{
if (Creature* trigger = me->SummonCreature(WORLD_TRIGGER, me->GetPositionX(), me->GetPositionY() + 5, me->GetPositionZ() + 15.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 60000))
trigger->CastSpell(me, SPELL_PURE_NETHER_BEAM2, true);
}, EVENT_SCENE_11);
ScheduleUniqueTimedEvent(24500ms, [&]
{
if (Creature* trigger = me->SummonCreature(WORLD_TRIGGER, me->GetPositionX(), me->GetPositionY() - 5, me->GetPositionZ() + 15.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 60000))
trigger->CastSpell(me, SPELL_PURE_NETHER_BEAM3, true);
if (Creature* trigger = me->SummonCreature(WORLD_TRIGGER, me->GetPositionX() + 5, me->GetPositionY() - 5, me->GetPositionZ() + 15.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 60000))
trigger->CastSpell(me, SPELL_PURE_NETHER_BEAM1, true);
}, EVENT_SCENE_12);
ScheduleUniqueTimedEvent(24800ms, [&]
{
if (Creature* trigger = me->SummonCreature(WORLD_TRIGGER, me->GetPositionX() - 5, me->GetPositionY() + 5, me->GetPositionZ() + 15.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 60000))
trigger->CastSpell(me, SPELL_PURE_NETHER_BEAM2, true);
}, EVENT_SCENE_13);
ScheduleUniqueTimedEvent(25300ms, [&]
{
if (Creature* trigger = me->SummonCreature(WORLD_TRIGGER, me->GetPositionX()-5, me->GetPositionY()+5, me->GetPositionZ()+15.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 60000))
trigger->CastSpell(me, SPELL_PURE_NETHER_BEAM3, true);
}, EVENT_SCENE_14);
ScheduleUniqueTimedEvent(32000ms, [&]
{
me->RemoveAurasDueToSpell(SPELL_FLOATING_DROWNED);
me->RemoveAurasDueToSpell(SPELL_KEAL_STUNNED);
DoCastSelf(SPELL_KAEL_FULL_POWER);
DoCastSelf(SPELL_KAEL_PHASE_TWO, true);
DoCastSelf(SPELL_PURE_NETHER_BEAM4, true);
DoCastSelf(SPELL_PURE_NETHER_BEAM5, true);
DoCastSelf(SPELL_PURE_NETHER_BEAM6, true);
}, EVENT_SCENE_15);
ScheduleUniqueTimedEvent(36000ms, [&]
{
summons.DespawnEntry(WORLD_TRIGGER);
me->CastStop();
me->GetMotionMaster()->Clear();
me->RemoveAurasDueToSpell(SPELL_DARK_BANISH_STATE); // WRONG VISUAL
me->GetMotionMaster()->MoveLand(POINT_LAND, me->GetPositionX(), me->GetPositionY(), 48.0f, 2.99f); // Moveland doesn't handle POINT_START_LAST_PHASE so we need to use MovePoint
me->GetMotionMaster()->MovePoint(POINT_START_LAST_PHASE, me->GetHomePosition(), false, true);
}, EVENT_SCENE_16);
}
void IntroduceNewAdvisor(KTYells talkIntroduction, KTActions kaelAction)
{
std::chrono::milliseconds attackStartTimer = 0ms;
EyeNPCs advisorNPCId = NPC_THALADRED;
scheduler.Schedule(2s, [this, talkIntroduction](TaskContext)
{
Talk(talkIntroduction);
});
//switch because talk times are different
switch(kaelAction)
{
case ACTION_START_SANGUINAR:
attackStartTimer = 14500ms;
advisorNPCId = NPC_LORD_SANGUINAR;
break;
case ACTION_START_CAPERNIAN:
attackStartTimer = 9000ms;
advisorNPCId = NPC_CAPERNIAN;
break;
case ACTION_START_TELONICUS:
attackStartTimer = 10400ms;
advisorNPCId = NPC_TELONICUS;
break;
default:
break;
}
scheduler.Schedule(attackStartTimer, [this, advisorNPCId](TaskContext)
{
if (Creature* advisor = summons.GetCreatureWithEntry(advisorNPCId))
{
advisor->SetReactState(REACT_AGGRESSIVE);
advisor->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
advisor->AI()->AttackStart(target);
advisor->SetInCombatWithZone();
}
});
}
void PhaseAllAdvisorsExecute()
{
_phase = PHASE_TRANSITION;
scheduler.CancelGroup(GROUP_PROGRESS_PHASE);
Talk(SAY_PHASE3_ADVANCE);
ScheduleUniqueTimedEvent(6s, [&]{
DoCastSelf(SPELL_RESURRECTION);
}, EVENT_PREFIGHT_PHASE6_02);
ScheduleUniqueTimedEvent(12s, [&]{
_phase = PHASE_ALL_ADVISORS;
summons.DoForAllSummons([&](WorldObject* summon)
{
if (Creature* summonedCreature = summon->ToCreature())
{
if (summonedCreature->GetSpawnId())
{
summonedCreature->SetReactState(REACT_AGGRESSIVE);
summonedCreature->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
summonedCreature->SetInCombatWithZone();
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
{
summonedCreature->AI()->AttackStart(target);
}
}
}
});
scheduler.Schedule(3min, GROUP_PROGRESS_PHASE, [this](TaskContext)
{
PhaseKaelExecute();
});
}, EVENT_PREFIGHT_PHASE6_03);
}
void PhaseKaelExecute()
{
scheduler.CancelAll();
Talk(SAY_PHASE4_INTRO2);
_phase = PHASE_FINAL;
DoResetThreatList();
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_DISABLE_MOVE);
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
{
AttackStart(target);
}
ScheduleHealthCheckEvent(50, [&]{
if(!_transitionSceneReached)
{
_transitionSceneReached = true;
scheduler.CancelAll();
me->CastStop();
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
me->SetReactState(REACT_PASSIVE);
me->GetMotionMaster()->MovePoint(POINT_MIDDLE, me->GetHomePosition(), true, true);
me->ClearUnitState(UNIT_STATE_MELEE_ATTACKING);
me->SendMeleeAttackStop();
ThreatContainer::StorageType threatList = me->GetThreatMgr().GetThreatList();
for (ThreatContainer::StorageType::const_iterator i = threatList.begin(); i != threatList.end(); ++i)
{
if (Unit* target = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid()))
{
target->AttackStop();
}
}
}
});
ScheduleTimedEvent(1000ms, [&]
{
DoCastVictim(SPELL_FIREBALL);
}, 2400ms, 7500ms);
ScheduleTimedEvent(15000ms, [&]
{
DoCastRandomTarget(SPELL_FLAME_STRIKE, 0, 100.0f);
}, 30250ms, 50650ms);
ScheduleTimedEvent(50000ms, [&]
{
Talk(SAY_SUMMON_PHOENIX);
DoCastSelf(SPELL_PHOENIX);
}, 35450ms, 41550ms);
ScheduleTimedEvent(20s, 23s, [&]
{
if (roll_chance_i(50))
Talk(SAY_MINDCONTROL);
me->CastCustomSpell(SPELL_MIND_CONTROL, SPELLVALUE_MAX_TARGETS, 3, me, false);
scheduler.Schedule(3s, [this](TaskContext)
{
DoCastSelf(SPELL_ARCANE_DISRUPTION);
});
}, 23s, 26s);
ScheduleTimedEvent(60s, [&]
{
Talk(SAY_PYROBLAST);
DoCastSelf(SPELL_SHOCK_BARRIER);
scheduler.DelayAll(10s);
scheduler.Schedule(0s, GROUP_PYROBLAST, [this](TaskContext context)
{
DoCastVictim(SPELL_PYROBLAST);
context.Repeat(4s);
}).Schedule(8500ms, GROUP_PYROBLAST, [this](TaskContext)
{
scheduler.CancelGroup(GROUP_PYROBLAST);
});
}, 50s);
}
void UpdateAI(uint32 diff) override
{
scheduler.Update(diff);
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
}
bool CheckEvadeIfOutOfCombatArea() const override
{
return me->GetHomePosition().GetExactDist2d(me) > 165.0f || !SelectTargetFromPlayerList(165.0f);
}
private:
uint32 _phase;
bool _transitionSceneReached = false;
};
struct npc_lord_sanguinar : public ScriptedAI
{
npc_lord_sanguinar(Creature* creature) : ScriptedAI(creature) {
_instance = creature->GetInstanceScript();
scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
void Reset() override
{
scheduler.CancelAll();
_hasDied = false;
me->SetReactState(REACT_PASSIVE);
}
void JustEngagedWith(Unit* /*who*/) override
{
if (!_hasDied)
{
Talk(SAY_SANGUINAR_AGGRO);
}
ScheduleTimedEvent(0s, 2s, [&]{
DoCastSelf(SPELL_BELLOWING_ROAR);
}, 30s, 40s);
}
void JustDied(Unit* /*killer*/) override
{
if (Creature* kael = _instance->GetCreature(DATA_KAELTHAS))
{
kael->AI()->DoAction(ACTION_PROGRESS_PHASE_CHECK);
if (!_hasDied)
{
Talk(SAY_SANGUINAR_DEATH);
DoCastSelf(SPELL_KAEL_PHASE_TWO, true);
kael->AI()->DoAction(ACTION_START_CAPERNIAN);
_hasDied = true;
}
}
scheduler.CancelAll();
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
scheduler.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
DoMeleeAttackIfReady();
}
private:
InstanceScript* _instance;
bool _hasDied;
};
struct npc_capernian : public ScriptedAI
{
npc_capernian(Creature* creature) : ScriptedAI(creature) {
_instance = creature->GetInstanceScript();
scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
void Reset() override
{
scheduler.CancelAll();
_hasDied = false;
me->SetReactState(REACT_PASSIVE);
}
void AttackStart(Unit* who) override
{
if (who && who->isTargetableForAttack() && me->GetReactState() != REACT_PASSIVE)
{
if (me->Attack(who, false))
{
me->GetMotionMaster()->MoveChase(who, 30.0f, 0);
me->AddThreat(who, 0.0f);
}
}
}
void JustEngagedWith(Unit* /*who*/) override
{
if (!_hasDied)
{
Talk(SAY_CAPERNIAN_AGGRO);
}
ScheduleTimedEvent(0ms, [&]{
if (!me->CanCastSpell(SPELL_CAPERNIAN_FIREBALL))
{
me->ResumeChasingVictim();
}
else
{
me->GetMotionMaster()->MoveChase(me->GetVictim(), 30.0f);
DoCastVictim(SPELL_CAPERNIAN_FIREBALL);
}
}, 2500ms);
ScheduleTimedEvent(7000ms, 10000ms, [&]{
DoCastRandomTarget(SPELL_CONFLAGRATION, 0, 30.0f);
}, 18500ms, 20500ms);
ScheduleTimedEvent(3s, [&]{
DoCastRandomTarget(SPELL_ARCANE_BURST, 0, 8.0f);
}, 6s);
}
void JustDied(Unit* /*killer*/) override
{
if (Creature* kael = _instance->GetCreature(DATA_KAELTHAS))
{
kael->AI()->DoAction(ACTION_PROGRESS_PHASE_CHECK);
if (!_hasDied)
{
Talk(SAY_CAPERNIAN_DEATH);
DoCastSelf(SPELL_KAEL_PHASE_TWO, true);
kael->AI()->DoAction(ACTION_START_TELONICUS);
_hasDied = true;
}
}
scheduler.CancelAll();
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
scheduler.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
DoMeleeAttackIfReady();
}
private:
InstanceScript* _instance;
bool _hasDied;
};
struct npc_telonicus : public ScriptedAI
{
npc_telonicus(Creature* creature) : ScriptedAI(creature) {
_instance = creature->GetInstanceScript();
scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
void Reset() override
{
scheduler.CancelAll();
_hasDied = false;
me->SetReactState(REACT_PASSIVE);
}
void JustEngagedWith(Unit* /*who*/) override
{
if (!_hasDied)
{
Talk(SAY_TELONICUS_AGGRO);
}
ScheduleTimedEvent(0ms, [&]{
DoCastVictim(SPELL_BOMB);
}, 3600ms, 7100ms);
ScheduleTimedEvent(13250ms, [&]{
DoCastRandomTarget(SPELL_REMOTE_TOY, 0, 100.0f);
}, 15750ms);
}
void JustDied(Unit* /*killer*/) override
{
if (Creature* kael = _instance->GetCreature(DATA_KAELTHAS))
{
kael->AI()->DoAction(ACTION_PROGRESS_PHASE_CHECK);
if (!_hasDied)
{
Talk(SAY_TELONICUS_DEATH);
DoCastSelf(SPELL_KAEL_PHASE_TWO, true);
kael->AI()->DoAction(ACTION_START_WEAPONS);
_hasDied = true;
}
}
scheduler.CancelAll();
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
scheduler.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
DoMeleeAttackIfReady();
}
private:
InstanceScript* _instance;
bool _hasDied;
};
struct npc_thaladred : public ScriptedAI
{
npc_thaladred(Creature* creature) : ScriptedAI(creature) {
_instance = creature->GetInstanceScript();
scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
}
void Reset() override
{
scheduler.CancelAll();
me->SetReactState(REACT_PASSIVE);
_hasDied = false;
}
void JustEngagedWith(Unit* /*who*/) override
{
if (!_hasDied)
{
Talk(SAY_THALADRED_AGGRO);
}
ScheduleTimedEvent(100ms, [&]
{
DoResetThreatList();
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
{
me->AddThreat(target, 10000000.0f);
Talk(EMOTE_THALADRED_FIXATE, target);
}
}, 10000ms);
ScheduleTimedEvent(4000ms, 19350ms, [&]
{
DoCastVictim(SPELL_PSYCHIC_BLOW);
}, 15700ms, 48900ms);
ScheduleTimedEvent(3000ms, 6050ms, [&]
{
DoCastVictim(SPELL_REND);
}, 15700ms, 48900ms);
ScheduleTimedEvent(3000ms, 6050ms, [&]
{
if (Unit* victim = me->GetVictim())
{
if (victim->IsNonMeleeSpellCast(false, false, true))
{
DoCastSelf(SPELL_SILENCE);
}
}
}, 3600ms, 15200ms);
}
void JustDied(Unit* /*killer*/) override
{
if (Creature* kael = _instance->GetCreature(DATA_KAELTHAS))
{
kael->AI()->DoAction(ACTION_PROGRESS_PHASE_CHECK);
if (!_hasDied)
{
Talk(SAY_THALADRED_DEATH);
DoCastSelf(SPELL_KAEL_PHASE_TWO, true);
kael->AI()->DoAction(ACTION_START_SANGUINAR);
_hasDied = true;
}
}
scheduler.CancelAll();
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
scheduler.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
DoMeleeAttackIfReady();
}
private:
InstanceScript* _instance;
bool _hasDied;
};
class spell_kaelthas_kael_phase_two : public SpellScript
{
PrepareSpellScript(spell_kaelthas_kael_phase_two);
bool Load() override
{
if (GetCaster()->GetTypeId() == TYPEID_UNIT)
if (InstanceScript* instance = GetCaster()->GetInstanceScript())
if (Creature* kael = instance->GetCreature(DATA_KAELTHAS))
kael->AI()->SummonedCreatureDies(GetCaster()->ToCreature(), nullptr);
return true;
}
void Register() override
{
}
};
class spell_kaelthas_remote_toy : public AuraScript
{
PrepareAuraScript(spell_kaelthas_remote_toy);
void HandlePeriodic(AuraEffect const* /*aurEff*/)
{
PreventDefaultAction();
if (roll_chance_i(66))
GetUnitOwner()->CastSpell(GetUnitOwner(), SPELL_REMOTE_TOY_STUN, true);
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_kaelthas_remote_toy::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
}
};
class spell_kaelthas_summon_weapons : public SpellScript
{
PrepareSpellScript(spell_kaelthas_summon_weapons);
void HandleScriptEffect(SpellEffIndex effIndex)
{
PreventHitEffect(effIndex);
for (uint32 i = SPELL_SUMMON_WEAPONA; i <= SPELL_SUMMON_WEAPONG; ++i)
GetCaster()->CastSpell(GetCaster(), i, true);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_kaelthas_summon_weapons::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
class spell_kaelthas_resurrection : public SpellScript
{
PrepareSpellScript(spell_kaelthas_resurrection);
void HandleBeforeCast()
{
GetCaster()->GetAI()->SetData(DATA_RESURRECT_CAST, DATA_RESURRECT_CAST);
}
void Register() override
{
BeforeCast += SpellCastFn(spell_kaelthas_resurrection::HandleBeforeCast);
}
};
class spell_kaelthas_mind_control : public SpellScript
{
PrepareSpellScript(spell_kaelthas_mind_control);
void SelectTarget(std::list& targets)
{
if (Unit* victim = GetCaster()->GetVictim())
{
targets.remove_if(Acore::ObjectGUIDCheck(victim->GetGUID(), true));
}
targets.remove_if([&](WorldObject const* target) -> bool
{
if (!target->ToPlayer())
return true;
return (!GetCaster()->IsWithinLOSInMap(target));
});
}
void HandleEffect(SpellEffIndex /*effIndex*/)
{
if (!GetCaster() || !GetHitPlayer())
return;
if (Player* player = GetHitPlayer())
GetCaster()->GetThreatMgr().ResetThreat(player);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_kaelthas_mind_control::SelectTarget, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
OnEffectHitTarget += SpellEffectFn(spell_kaelthas_mind_control::HandleEffect, EFFECT_ALL, SPELL_AURA_ANY);
}
};
class spell_kaelthas_burn : public AuraScript
{
PrepareAuraScript(spell_kaelthas_burn);
void HandlePeriodic(AuraEffect const* /*aurEff*/)
{
Unit::DealDamage(GetUnitOwner(), GetUnitOwner(), GetUnitOwner()->CountPctFromMaxHealth(5) + 1);
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_kaelthas_burn::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
}
};
class spell_kaelthas_flame_strike : public AuraScript
{
PrepareAuraScript(spell_kaelthas_flame_strike);
bool Load() override
{
return GetUnitOwner()->GetTypeId() == TYPEID_UNIT;
}
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
GetUnitOwner()->RemoveAllAuras();
GetUnitOwner()->CastSpell(GetUnitOwner(), SPELL_FLAME_STRIKE_DAMAGE, true);
GetUnitOwner()->ToCreature()->DespawnOrUnsummon(2000);
}
void Register() override
{
OnEffectRemove += AuraEffectRemoveFn(spell_kaelthas_flame_strike::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
class lapseTeleport : public BasicEvent
{
public:
lapseTeleport(Player* owner) : _owner(owner)
{
}
bool Execute(uint64 /*execTime*/, uint32 /*diff*/) override
{
if (_owner->IsBeingTeleportedNear())
_owner->m_Events.AddEvent(new lapseTeleport(_owner), _owner->m_Events.CalculateTime(1));
else if (!_owner->IsBeingTeleported())
{
_owner->CastSpell(_owner, SPELL_GRAVITY_LAPSE_KNOCKBACK, true);
_owner->CastSpell(_owner, SPELL_GRAVITY_LAPSE_AURA, true);
}
return true;
}
private:
Player* _owner;
};
class spell_kaelthas_gravity_lapse : public SpellScript
{
PrepareSpellScript(spell_kaelthas_gravity_lapse);
bool Load() override
{
_currentSpellId = SPELL_GRAVITY_LAPSE_TELEPORT1;
return true;
}
void HandleScriptEffect(SpellEffIndex effIndex)
{
PreventHitEffect(effIndex);
if (_currentSpellId < SPELL_GRAVITY_LAPSE_TELEPORT1 + 25)
if (Player* target = GetHitPlayer())
{
GetCaster()->CastSpell(target, _currentSpellId++, true);
target->m_Events.AddEvent(new lapseTeleport(target), target->m_Events.CalculateTime(1));
}
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_kaelthas_gravity_lapse::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
private:
uint32 _currentSpellId;
};
class spell_kaelthas_nether_beam : public SpellScript
{
PrepareSpellScript(spell_kaelthas_nether_beam);
void HandleScriptEffect(SpellEffIndex effIndex)
{
PreventHitEffect(effIndex);
ThreatContainer::StorageType const& ThreatList = GetCaster()-> GetThreatMgr().GetThreatList();
std::list targetList;
for (ThreatContainer::StorageType::const_iterator itr = ThreatList.begin(); itr != ThreatList.end(); ++itr)
{
Unit* target = ObjectAccessor::GetUnit(*GetCaster(), (*itr)->getUnitGuid());
if (target && target->IsPlayer())
targetList.push_back(target);
}
Acore::Containers::RandomResize(targetList, 5);
for (std::list::const_iterator itr = targetList.begin(); itr != targetList.end(); ++itr)
GetCaster()->CastSpell(*itr, SPELL_NETHER_BEAM_DAMAGE, true);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_kaelthas_nether_beam::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
class spell_kaelthas_summon_nether_vapor : public SpellScript
{
PrepareSpellScript(spell_kaelthas_summon_nether_vapor);
void HandleScriptEffect(SpellEffIndex effIndex)
{
PreventHitEffect(effIndex);
for (uint32 i = 0; i < 5; ++i)
GetCaster()->SummonCreature(NPC_NETHER_VAPOR, GetCaster()->GetPositionX() + 6 * cos(i / 5.0f * 2 * M_PI), GetCaster()->GetPositionY() + 6 * std::sin(i / 5.0f * 2 * M_PI), GetCaster()->GetPositionZ() + 7.0f + i, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 30000);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_kaelthas_summon_nether_vapor::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
class spell_kael_pyroblast : public SpellScript
{
PrepareSpellScript(spell_kael_pyroblast);
void FilterTargets(std::list& targets)
{
if (GetCaster()->GetVictim())
{
if (Unit* victim = GetCaster()->GetVictim())
targets.remove_if(Acore::ObjectGUIDCheck(victim->GetGUID(), false));
}
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_kael_pyroblast::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
}
};
void AddSC_boss_kaelthas()
{
RegisterTheEyeAI(boss_kaelthas);
RegisterTheEyeAI(npc_lord_sanguinar);
RegisterTheEyeAI(npc_capernian);
RegisterTheEyeAI(npc_telonicus);
RegisterTheEyeAI(npc_thaladred);
RegisterSpellScript(spell_kaelthas_kael_phase_two);
RegisterSpellScript(spell_kaelthas_remote_toy);
RegisterSpellScript(spell_kaelthas_summon_weapons);
RegisterSpellScript(spell_kaelthas_resurrection);
RegisterSpellScript(spell_kaelthas_mind_control);
RegisterSpellScript(spell_kaelthas_burn);
RegisterSpellScript(spell_kaelthas_flame_strike);
RegisterSpellScript(spell_kaelthas_gravity_lapse);
RegisterSpellScript(spell_kaelthas_nether_beam);
RegisterSpellScript(spell_kaelthas_summon_nether_vapor);
RegisterSpellScript(spell_kael_pyroblast);
}