mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-29 08:33:47 +00:00
1420 lines
59 KiB
C++
1420 lines
59 KiB
C++
/*
|
|
* Originally written by Xinef - Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: http://github.com/azerothcore/azerothcore-wotlk/LICENSE-AGPL
|
|
*/
|
|
|
|
#include "ScriptMgr.h"
|
|
#include "ScriptedCreature.h"
|
|
#include "ScriptedEscortAI.h"
|
|
#include "black_temple.h"
|
|
|
|
enum Says
|
|
{
|
|
SAY_ILLIDAN_MINION = 0,
|
|
SAY_ILLIDAN_KILL = 1,
|
|
SAY_ILLIDAN_TAKEOFF = 2,
|
|
SAY_ILLIDAN_SUMMONFLAMES = 3,
|
|
SAY_ILLIDAN_EYE_BLAST = 4,
|
|
SAY_ILLIDAN_MORPH = 5,
|
|
SAY_ILLIDAN_ENRAGE = 6,
|
|
SAY_ILLIDAN_TAUNT = 7,
|
|
SAY_ILLIDAN_AKAMA1 = 8,
|
|
SAY_ILLIDAN_AKAMA2 = 9,
|
|
SAY_ILLIDAN_AKAMA3 = 10,
|
|
SAY_ILLIDAN_MAIEV1 = 11,
|
|
SAY_ILLIDAN_MAIEV2 = 12,
|
|
SAY_ILLIDAN_MAIEV3 = 13,
|
|
SAY_ILLIDAN_FRENZY = 14,
|
|
|
|
SAY_UDALO = 0,
|
|
SAY_OLUM = 0,
|
|
SAY_AKAMA_DOORS = 0,
|
|
SAY_AKAMA_FAIL = 1,
|
|
SAY_AKAMA_BEWARE = 2,
|
|
SAY_AKAMA_LEAVE = 3,
|
|
SAY_AKAMA_ILLIDAN1 = 4,
|
|
SAY_AKAMA_ILLIDAN2 = 5,
|
|
SAY_AKAMA_ILLIDAN3 = 6,
|
|
|
|
SAY_MAIEV_SHADOWSONG_TAUNT = 0,
|
|
SAY_MAIEV_SHADOWSONG_ILLIDAN1 = 1,
|
|
SAY_MAIEV_SHADOWSONG_ILLIDAN2 = 2,
|
|
SAY_MAIEV_SHADOWSONG_ILLIDAN3 = 3,
|
|
SAY_MAIEV_SHADOWSONG_ILLIDAN4 = 4,
|
|
SAY_MAIEV_SHADOWSONG_ILLIDAN5 = 5,
|
|
|
|
EMOTE_AZZINOTH_GAZE = 0
|
|
};
|
|
|
|
enum Spells
|
|
{
|
|
// Phase 1
|
|
SPELL_DUAL_WIELD = 42459,
|
|
SPELL_BERSERK = 45078,
|
|
SPELL_FLAME_CRASH = 40832,
|
|
SPELL_DRAW_SOUL = 40904,
|
|
SPELL_DRAW_SOUL_HEAL = 40903,
|
|
SPELL_PARASITIC_SHADOWFIEND = 41917,
|
|
SPELL_PARASITIC_SHADOWFIEND_TRIGGER = 41914,
|
|
SPELL_SUMMON_PARASITIC_SHADOWFIENDS = 41915,
|
|
|
|
// Phase 2
|
|
SPELL_THROW_GLAIVE = 39635,
|
|
SPELL_THROW_GLAIVE2 = 39849,
|
|
SPELL_GLAIVE_RETURNS = 39873,
|
|
SPELL_SUMMON_GLAIVE = 41466,
|
|
SPELL_FIREBALL = 40598,
|
|
SPELL_DARK_BARRAGE = 40585,
|
|
SPELL_EYE_BLAST = 39908,
|
|
SPELL_UNCAGED_WRATH = 39869,
|
|
SPELL_FLAME_BLAST = 40631,
|
|
SPELL_CHARGE = 42003,
|
|
|
|
// Phase 3
|
|
SPELL_AGONIZING_FLAMES = 40932,
|
|
SPELL_SUMMON_MAIEV = 40403,
|
|
SPELL_SHADOW_PRISON = 40647,
|
|
SPELL_TELEPORT_VISUAL_ONLY = 41232,
|
|
|
|
// Phase 4
|
|
SPELL_DEMON_TRANSFORM_1 = 40511,
|
|
SPELL_DEMON_TRANSFORM_2 = 40398,
|
|
SPELL_DEMON_TRANSFORM_3 = 40510,
|
|
SPELL_DEMON_FORM = 40506,
|
|
SPELL_SHADOW_BLAST = 41078,
|
|
SPELL_FLAME_BURST = 41126,
|
|
SPELL_FLAME_BURST_EFFECT = 41131,
|
|
SPELL_SUMMON_SHADOW_DEMON = 41117,
|
|
SPELL_CONSUME_SOUL = 41080,
|
|
SPELL_FIND_TARGET = 41081,
|
|
|
|
// Phase 5
|
|
SPELL_FRENZY = 40683,
|
|
SPELL_TELEPORT_MAIEV = 41221,
|
|
SPELL_SHADOW_STRIKE = 40685,
|
|
SPELL_THROW_DAGGER = 41152,
|
|
SPELL_DEATH = 41220,
|
|
|
|
// Cage
|
|
SPELL_CAGED_DEBUFF = 40695,
|
|
SPELL_CAGED_SUMMON1 = 40696,
|
|
SPELL_CAGED_SUMMON8 = 40703,
|
|
SPELL_CAGE_TRAP = 40760
|
|
};
|
|
|
|
enum Misc
|
|
{
|
|
ACTION_FIGHT_MINIONS = 1,
|
|
ACTION_RETURN_BLADE = 2,
|
|
ACTION_ILLIDAN_CAGED = 3,
|
|
ACTION_ILLIDAN_DEAD = 4,
|
|
ACTION_MAIEV_SET_DIST30 = 5,
|
|
ACTION_MAIEV_SET_DIST0 = 6,
|
|
ACTION_MAIEV_OUTRO = 7,
|
|
|
|
MAX_EYE_BEAM_POS = 4,
|
|
|
|
POINT_ILLIDAN_HOVER = 10,
|
|
POINT_ILLIDAN_MIDDLE = 11,
|
|
|
|
NPC_ILLIDAN_DB_TARGET = 23070,
|
|
NPC_MAIEV_SHADOWSONG = 23197,
|
|
|
|
GO_CAGE_TRAP = 185916
|
|
};
|
|
|
|
enum Events
|
|
{
|
|
EVENT_SPELL_FLAME_CRASH = 1,
|
|
EVENT_SPELL_BERSERK = 2,
|
|
EVENT_SPELL_DRAW_SOUL = 3,
|
|
EVENT_SPELL_PARASITIC_SHADOWFIEND = 4,
|
|
EVENT_SPELL_AGONIZING_FLAMES = 5,
|
|
EVENT_SPELL_FRENZY = 6,
|
|
|
|
EVENT_SUMMON_MINIONS = 20,
|
|
EVENT_SUMMON_MINIONS2 = 21,
|
|
|
|
EVENT_PHASE_2_START = 40,
|
|
EVENT_SPELL_FIREBALL = 41,
|
|
EVENT_SPELL_DARK_BARRAGE = 42,
|
|
EVENT_START_PHASE_2_END = 43,
|
|
EVENT_START_PHASE_2_WEAPON = 44,
|
|
EVENT_START_PHASE_3_LAND = 45,
|
|
EVENT_PHASE_2_SUMMON1 = 46,
|
|
EVENT_PHASE_2_SUMMON2 = 47,
|
|
EVENT_PHASE_2_EYE_BEAM = 48,
|
|
EVENT_PHASE_2_EYE_BEAM_START = 49,
|
|
EVENT_PHASE_2_CHANGE_POS = 50,
|
|
EVENT_PHASE_2_INTERRUPT = 51,
|
|
|
|
EVENT_PHASE_4_START = 60,
|
|
EVENT_PHASE_5_START = 61,
|
|
EVENT_PHASE_5_SCENE1 = 62,
|
|
EVENT_PHASE_5_SCENE2 = 63,
|
|
EVENT_PHASE_5_SCENE3 = 64,
|
|
EVENT_PHASE_5_SCENE4 = 65,
|
|
EVENT_PHASE_5_SCENE5 = 66,
|
|
|
|
EVENT_REMOVE_DEMON_FORM = 80,
|
|
EVENT_SPELL_FLAME_BURST = 81,
|
|
EVENT_SPELL_SHADOW_BLAST = 82,
|
|
EVENT_SPELL_SHADOW_DEMONS = 83,
|
|
EVENT_MOVE_MAIEV = 84,
|
|
EVENT_FINISH_TRANSFORM = 85, // Dummy, counter only
|
|
|
|
EVENT_OUTRO_DEMON = 90,
|
|
EVENT_OUTRO_1 = 91,
|
|
EVENT_OUTRO_2 = 92,
|
|
EVENT_OUTRO_3 = 93,
|
|
|
|
EVENT_KILL_TALK = 100,
|
|
EVENT_SAY_TAUNT = 101,
|
|
|
|
GROUP_PHASE_2_ABILITY = 1
|
|
};
|
|
|
|
const Position eyeBeamPos[MAX_EYE_BEAM_POS*2] =
|
|
{
|
|
{639.97f, 301.63f, 354.0f, 0.0f},
|
|
{658.83f, 265.10f, 354.0f, 0.0f},
|
|
{656.86f, 344.07f, 354.0f, 0.0f},
|
|
{640.70f, 310.47f, 354.0f, 0.0f},
|
|
|
|
{706.22f, 273.26f, 354.0f, 0.0f},
|
|
{717.55f, 328.33f, 354.0f, 0.0f},
|
|
{718.06f, 286.08f, 354.0f, 0.0f},
|
|
{705.92f, 337.14f, 354.0f, 0.0f}
|
|
};
|
|
|
|
const Position airHoverPos[MAX_EYE_BEAM_POS] =
|
|
{
|
|
{658.83f, 265.10f, 356.0f, 0.0f},
|
|
{706.22f, 273.26f, 356.0f, 0.0f},
|
|
{705.92f, 337.14f, 356.0f, 0.0f},
|
|
{656.86f, 344.07f, 356.0f, 0.0f}
|
|
};
|
|
|
|
class boss_illidan_stormrage : public CreatureScript
|
|
{
|
|
public:
|
|
boss_illidan_stormrage() : CreatureScript("boss_illidan_stormrage") { }
|
|
|
|
struct boss_illidan_stormrageAI : public BossAI
|
|
{
|
|
boss_illidan_stormrageAI(Creature* creature) : BossAI(creature, DATA_ILLIDAN_STORMRAGE)
|
|
{
|
|
}
|
|
|
|
EventMap events2;
|
|
uint8 beamPosId;
|
|
|
|
void Reset()
|
|
{
|
|
BossAI::Reset();
|
|
events2.Reset();
|
|
me->SetDisableGravity(false);
|
|
me->CastSpell(me, SPELL_DUAL_WIELD, true);
|
|
me->LoadEquipment(0, true);
|
|
me->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC);
|
|
beamPosId = urand(0, 3);
|
|
}
|
|
|
|
void EnterEvadeMode()
|
|
{
|
|
BossAI::EnterEvadeMode();
|
|
|
|
if (Creature* akama = ObjectAccessor::GetCreature(*me, instance->GetData64(NPC_AKAMA)))
|
|
akama->AI()->EnterEvadeMode();
|
|
}
|
|
|
|
bool CanAIAttack(const Unit* target) const
|
|
{
|
|
return target->GetEntry() != NPC_AKAMA && target->GetEntry() != NPC_MAIEV_SHADOWSONG;
|
|
}
|
|
|
|
void DoAction(int32 param)
|
|
{
|
|
if (param == ACTION_ILLIDAN_CAGED)
|
|
{
|
|
me->RemoveAurasDueToSpell(SPELL_FRENZY);
|
|
events.Reset();
|
|
events.ScheduleEvent(EVENT_PHASE_4_START, 16000);
|
|
}
|
|
}
|
|
|
|
void JustSummoned(Creature* summon)
|
|
{
|
|
summons.Summon(summon);
|
|
if (summon->GetEntry() == NPC_ILLIDAN_DB_TARGET)
|
|
me->CastSpell(summon, SPELL_EYE_BLAST, false);
|
|
else if (summon->GetEntry() == NPC_MAIEV_SHADOWSONG)
|
|
{
|
|
me->SetTarget(summon->GetGUID());
|
|
me->SetFacingToObject(summon);
|
|
summon->SetFacingToObject(me);
|
|
summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
|
summon->SetReactState(REACT_PASSIVE);
|
|
summon->CastSpell(summon, SPELL_TELEPORT_VISUAL_ONLY, true);
|
|
}
|
|
}
|
|
|
|
void SummonedCreatureDies(Creature* summon, Unit*)
|
|
{
|
|
summons.Despawn(summon);
|
|
}
|
|
|
|
void SummonedCreatureDespawn(Creature* summon)
|
|
{
|
|
summons.Despawn(summon);
|
|
}
|
|
|
|
void MovementInform(uint32 type, uint32 id)
|
|
{
|
|
if (type != POINT_MOTION_TYPE)
|
|
return;
|
|
|
|
if (id == POINT_ILLIDAN_HOVER)
|
|
{
|
|
if (events2.GetNextEventTime(EVENT_START_PHASE_2_END) == 0)
|
|
{
|
|
events.ScheduleEvent(EVENT_PHASE_2_SUMMON2, 2000);
|
|
events.ScheduleEvent(EVENT_PHASE_2_CHANGE_POS, 6000);
|
|
events.ScheduleEvent(EVENT_PHASE_2_EYE_BEAM, 15000, GROUP_PHASE_2_ABILITY);
|
|
events2.ScheduleEvent(EVENT_START_PHASE_2_END, 10000);
|
|
}
|
|
me->SetFacingTo(me->GetAngle(676.02f, 305.45f));
|
|
}
|
|
else if (id == POINT_ILLIDAN_MIDDLE)
|
|
{
|
|
EntryCheckPredicate pred(NPC_BLADE_OF_AZZINOTH);
|
|
summons.DoAction(ACTION_RETURN_BLADE, pred);
|
|
events.ScheduleEvent(EVENT_START_PHASE_2_WEAPON, 1500);
|
|
events.ScheduleEvent(EVENT_START_PHASE_3_LAND, 4000);
|
|
}
|
|
}
|
|
|
|
void ScheduleNormalEvents(uint8 phase)
|
|
{
|
|
events.ScheduleEvent(EVENT_SPELL_FLAME_CRASH, 15000);
|
|
events.ScheduleEvent(EVENT_SPELL_DRAW_SOUL, 30000);
|
|
events.ScheduleEvent(EVENT_SPELL_PARASITIC_SHADOWFIEND, 20000);
|
|
events.ScheduleEvent(EVENT_SAY_TAUNT, 40000);
|
|
if (phase >= 3)
|
|
{
|
|
events.ScheduleEvent(EVENT_PHASE_4_START, 60000);
|
|
events.ScheduleEvent(EVENT_SPELL_AGONIZING_FLAMES, 10000);
|
|
}
|
|
if (phase >= 5)
|
|
events.ScheduleEvent(EVENT_SPELL_FRENZY, 40000);
|
|
}
|
|
|
|
void EnterCombat(Unit* who)
|
|
{
|
|
summons.DespawnAll();
|
|
BossAI::EnterCombat(who);
|
|
ScheduleNormalEvents(1);
|
|
events.ScheduleEvent(EVENT_SPELL_BERSERK, 25*MINUTE*IN_MILLISECONDS);
|
|
events.ScheduleEvent(EVENT_SUMMON_MINIONS, 1000);
|
|
events.ScheduleEvent(EVENT_PHASE_2_START, 1000);
|
|
}
|
|
|
|
void AttackStart(Unit* victim)
|
|
{
|
|
if (victim && me->Attack(victim, true))
|
|
me->GetMotionMaster()->MoveChase(victim, events.GetNextEventTime(EVENT_REMOVE_DEMON_FORM) != 0 ? 35.0f : 0.0f);
|
|
}
|
|
|
|
void MoveInLineOfSight(Unit*) { }
|
|
|
|
void JustDied(Unit* /*killer*/)
|
|
{
|
|
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NON_ATTACKABLE);
|
|
summons.DespawnEntry(NPC_PARASITIC_SHADOWFIEND);
|
|
instance->SetBossState(DATA_ILLIDAN_STORMRAGE, DONE);
|
|
instance->SaveToDB();
|
|
}
|
|
|
|
void KilledUnit(Unit* /*victim*/)
|
|
{
|
|
if (events.GetNextEventTime(EVENT_KILL_TALK) == 0)
|
|
{
|
|
Talk(SAY_ILLIDAN_KILL);
|
|
events.ScheduleEvent(EVENT_KILL_TALK, 6000);
|
|
}
|
|
}
|
|
|
|
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask)
|
|
{
|
|
if (damage >= me->GetHealth())
|
|
{
|
|
damage = 0;
|
|
|
|
// xinef: do not allow to start outro when transforming
|
|
if (events.GetNextEventTime(EVENT_FINISH_TRANSFORM))
|
|
return;
|
|
|
|
if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
|
|
{
|
|
if (Creature* maiev = summons.GetCreatureWithEntry(NPC_MAIEV_SHADOWSONG))
|
|
{
|
|
maiev->StopMovingOnCurrentPos();
|
|
maiev->GetMotionMaster()->Clear();
|
|
maiev->SetReactState(REACT_PASSIVE);
|
|
maiev->SetFullHealth();
|
|
maiev->RemoveAllAuras();
|
|
maiev->CombatStop();
|
|
}
|
|
|
|
if (events.GetNextEventTime(EVENT_REMOVE_DEMON_FORM) != 0)
|
|
{
|
|
me->CastSpell(me, SPELL_DEMON_TRANSFORM_1, true);
|
|
events2.ScheduleEvent(EVENT_OUTRO_DEMON, 12000);
|
|
}
|
|
else
|
|
{
|
|
me->CastSpell(me, SPELL_TELEPORT_MAIEV, true);
|
|
me->CastSpell(me, SPELL_DEATH, true);
|
|
events2.ScheduleEvent(EVENT_OUTRO_1, 1000);
|
|
}
|
|
|
|
if (Creature* maiev = summons.GetCreatureWithEntry(NPC_MAIEV_SHADOWSONG))
|
|
{
|
|
maiev->SetTarget(me->GetGUID());
|
|
maiev->SetFacingToObject(me);
|
|
}
|
|
|
|
events.Reset();
|
|
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
|
|
}
|
|
}
|
|
}
|
|
|
|
void UpdateAI(uint32 diff)
|
|
{
|
|
events2.Update(diff);
|
|
switch (events2.ExecuteEvent())
|
|
{
|
|
case EVENT_SUMMON_MINIONS2:
|
|
if (Creature* akama = ObjectAccessor::GetCreature(*me, instance->GetData64(NPC_AKAMA)))
|
|
akama->AI()->DoAction(ACTION_FIGHT_MINIONS);
|
|
break;
|
|
case EVENT_PHASE_2_EYE_BEAM_START:
|
|
Talk(SAY_ILLIDAN_EYE_BLAST);
|
|
if (Creature* trigger = summons.GetCreatureWithEntry(NPC_ILLIDAN_DB_TARGET))
|
|
trigger->GetMotionMaster()->MovePoint(0, eyeBeamPos[beamPosId+MAX_EYE_BEAM_POS], false, true);
|
|
break;
|
|
case EVENT_PHASE_2_INTERRUPT:
|
|
me->InterruptNonMeleeSpells(false);
|
|
break;
|
|
case EVENT_START_PHASE_2_END:
|
|
summons.RemoveNotExisting();
|
|
if (!summons.HasEntry(NPC_FLAME_OF_AZZINOTH))
|
|
{
|
|
events.Reset();
|
|
events2.Reset();
|
|
me->InterruptNonMeleeSpells(false);
|
|
me->GetMotionMaster()->MovePoint(POINT_ILLIDAN_MIDDLE, 676.02f, 305.45f, 353.6f);
|
|
break;
|
|
}
|
|
events2.ScheduleEvent(EVENT_START_PHASE_2_END, 1000);
|
|
break;
|
|
case EVENT_OUTRO_DEMON:
|
|
me->CastSpell(me, SPELL_TELEPORT_MAIEV, true);
|
|
me->CastSpell(me, SPELL_DEATH, true);
|
|
events2.ScheduleEvent(EVENT_OUTRO_1, 1000);
|
|
break;
|
|
case EVENT_OUTRO_1:
|
|
if (Creature* maiev = summons.GetCreatureWithEntry(NPC_MAIEV_SHADOWSONG))
|
|
{
|
|
maiev->SetTarget(me->GetGUID());
|
|
maiev->SetFacingToObject(me);
|
|
maiev->AI()->DoAction(ACTION_MAIEV_OUTRO);
|
|
maiev->AI()->Talk(SAY_MAIEV_SHADOWSONG_ILLIDAN3);
|
|
}
|
|
|
|
if (Creature* akama = ObjectAccessor::GetCreature(*me, instance->GetData64(NPC_AKAMA)))
|
|
{
|
|
akama->AI()->DoAction(ACTION_ILLIDAN_DEAD);
|
|
akama->SetTarget(me->GetGUID());
|
|
akama->GetMotionMaster()->MovePoint(0, 695.63f, 306.63f, 354.26f);
|
|
}
|
|
events2.ScheduleEvent(EVENT_OUTRO_2, 6000);
|
|
break;
|
|
case EVENT_OUTRO_2:
|
|
Talk(SAY_ILLIDAN_MAIEV3);
|
|
events2.ScheduleEvent(EVENT_OUTRO_3, 17000);
|
|
break;
|
|
case EVENT_OUTRO_3:
|
|
Unit::Kill(NULL, me);
|
|
break;
|
|
}
|
|
|
|
|
|
EnterEvadeIfOutOfCombatArea();
|
|
|
|
if (!UpdateVictim())
|
|
return;
|
|
|
|
events.Update(diff);
|
|
if (me->HasUnitState(UNIT_STATE_CASTING))
|
|
return;
|
|
|
|
switch (uint32 eventId = events.ExecuteEvent())
|
|
{
|
|
case EVENT_SUMMON_MINIONS:
|
|
if (me->HealthBelowPct(90))
|
|
{
|
|
Talk(SAY_ILLIDAN_MINION);
|
|
events2.ScheduleEvent(EVENT_SUMMON_MINIONS2, 10000);
|
|
break;
|
|
}
|
|
events.ScheduleEvent(EVENT_SUMMON_MINIONS, 1000);
|
|
break;
|
|
// ///////////////////////////
|
|
// PHASE 1, 3, 5
|
|
// ///////////////////////////
|
|
case EVENT_SPELL_BERSERK:
|
|
Talk(SAY_ILLIDAN_ENRAGE);
|
|
me->CastSpell(me, SPELL_BERSERK, true);
|
|
break;
|
|
case EVENT_SPELL_FLAME_CRASH:
|
|
me->CastSpell(me->GetVictim(), SPELL_FLAME_CRASH, false);
|
|
events.ScheduleEvent(EVENT_SPELL_FLAME_CRASH, 25000);
|
|
break;
|
|
case EVENT_SPELL_DRAW_SOUL:
|
|
me->CastSpell(me->GetVictim(), SPELL_DRAW_SOUL, false);
|
|
events.ScheduleEvent(EVENT_SPELL_DRAW_SOUL, 40000);
|
|
break;
|
|
case EVENT_SPELL_PARASITIC_SHADOWFIEND:
|
|
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
|
|
me->CastSpell(target, SPELL_PARASITIC_SHADOWFIEND, false);
|
|
events.ScheduleEvent(EVENT_SPELL_PARASITIC_SHADOWFIEND, 30000);
|
|
break;
|
|
case EVENT_SAY_TAUNT:
|
|
Talk(SAY_ILLIDAN_TAUNT);
|
|
events.ScheduleEvent(EVENT_SAY_TAUNT, urand(30000, 60000));
|
|
break;
|
|
case EVENT_SPELL_FRENZY:
|
|
Talk(SAY_ILLIDAN_FRENZY);
|
|
me->CastSpell(me, SPELL_FRENZY, false);
|
|
break;
|
|
case EVENT_SPELL_AGONIZING_FLAMES:
|
|
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
|
|
me->CastSpell(target, SPELL_AGONIZING_FLAMES, false);
|
|
break;
|
|
case EVENT_PHASE_5_START:
|
|
if (me->HealthBelowPct(30))
|
|
{
|
|
me->CastSpell(me, SPELL_SHADOW_PRISON, true);
|
|
me->SendMeleeAttackStop(me->GetVictim());
|
|
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NON_ATTACKABLE);
|
|
Talk(SAY_ILLIDAN_MAIEV1);
|
|
events.Reset();
|
|
events.ScheduleEvent(EVENT_PHASE_5_SCENE1, 9000);
|
|
events.ScheduleEvent(EVENT_PHASE_5_SCENE2, 18000);
|
|
events.ScheduleEvent(EVENT_PHASE_5_SCENE3, 24000);
|
|
events.ScheduleEvent(EVENT_PHASE_5_SCENE4, 27000);
|
|
events.ScheduleEvent(EVENT_PHASE_5_SCENE5, 30000);
|
|
break;
|
|
}
|
|
events.ScheduleEvent(EVENT_PHASE_5_START, 1000);
|
|
break;
|
|
case EVENT_PHASE_5_SCENE1:
|
|
me->CastSpell(me, SPELL_SUMMON_MAIEV, true);
|
|
break;
|
|
case EVENT_PHASE_5_SCENE2:
|
|
Talk(SAY_ILLIDAN_MAIEV2);
|
|
break;
|
|
case EVENT_PHASE_5_SCENE3:
|
|
if (Creature* maiev = summons.GetCreatureWithEntry(NPC_MAIEV_SHADOWSONG))
|
|
maiev->AI()->Talk(SAY_MAIEV_SHADOWSONG_ILLIDAN2);
|
|
break;
|
|
case EVENT_PHASE_5_SCENE4:
|
|
if (Creature* maiev = summons.GetCreatureWithEntry(NPC_MAIEV_SHADOWSONG))
|
|
maiev->HandleEmoteCommand(EMOTE_ONESHOT_ROAR);
|
|
break;
|
|
case EVENT_PHASE_5_SCENE5:
|
|
me->SetTarget(me->GetVictim()->GetGUID());
|
|
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NON_ATTACKABLE);
|
|
if (Creature* maiev = summons.GetCreatureWithEntry(NPC_MAIEV_SHADOWSONG))
|
|
{
|
|
maiev->SetReactState(REACT_AGGRESSIVE);
|
|
maiev->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
|
maiev->AI()->AttackStart(me);
|
|
}
|
|
ScheduleNormalEvents(5);
|
|
break;
|
|
// ///////////////////////////
|
|
// PHASE 2
|
|
// ///////////////////////////
|
|
case EVENT_PHASE_2_START:
|
|
if (me->HealthBelowPct(65))
|
|
{
|
|
if (events2.GetNextEventTime(EVENT_SUMMON_MINIONS2) != 0)
|
|
events2.RescheduleEvent(EVENT_SUMMON_MINIONS2, 0);
|
|
|
|
Talk(SAY_ILLIDAN_TAKEOFF);
|
|
me->SendMeleeAttackStop(me->GetVictim());
|
|
me->SetTarget(0);
|
|
me->GetMotionMaster()->Clear();
|
|
me->StopMovingOnCurrentPos();
|
|
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
|
me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
|
|
me->SetDisableGravity(true);
|
|
|
|
events.Reset();
|
|
events.ScheduleEvent(EVENT_PHASE_2_SUMMON1, 6000);
|
|
break;
|
|
}
|
|
events.ScheduleEvent(EVENT_PHASE_2_START, 1000);
|
|
break;
|
|
case EVENT_PHASE_2_SUMMON1:
|
|
me->LoadEquipment(1, true);
|
|
me->GetMotionMaster()->MovePoint(POINT_ILLIDAN_HOVER, 727.875f, 305.365f, 356.0f, false, true);
|
|
break;
|
|
case EVENT_PHASE_2_SUMMON2:
|
|
Talk(SAY_ILLIDAN_SUMMONFLAMES);
|
|
me->LoadEquipment(0, true);
|
|
me->CastSpell(me, SPELL_THROW_GLAIVE, false);
|
|
me->CastSpell(me, SPELL_THROW_GLAIVE2, false);
|
|
break;
|
|
case EVENT_PHASE_2_CHANGE_POS:
|
|
beamPosId = (++beamPosId)%MAX_EYE_BEAM_POS;
|
|
events.ScheduleEvent(EVENT_SPELL_FIREBALL, 8000, GROUP_PHASE_2_ABILITY);
|
|
events.ScheduleEvent(EVENT_SPELL_DARK_BARRAGE, 18000, GROUP_PHASE_2_ABILITY);
|
|
events.ScheduleEvent(EVENT_PHASE_2_EYE_BEAM, urand(25000, 50000), GROUP_PHASE_2_ABILITY);
|
|
me->GetMotionMaster()->MovePoint(POINT_ILLIDAN_HOVER, airHoverPos[beamPosId], false, true);
|
|
break;
|
|
case EVENT_PHASE_2_EYE_BEAM:
|
|
me->SummonCreature(NPC_ILLIDAN_DB_TARGET, eyeBeamPos[beamPosId], TEMPSUMMON_TIMED_DESPAWN, 15000);
|
|
events.CancelEventGroup(GROUP_PHASE_2_ABILITY);
|
|
events.ScheduleEvent(EVENT_PHASE_2_CHANGE_POS, 20000);
|
|
|
|
events2.ScheduleEvent(EVENT_PHASE_2_EYE_BEAM_START, 2000);
|
|
events2.ScheduleEvent(EVENT_PHASE_2_INTERRUPT, 20000);
|
|
break;
|
|
case EVENT_SPELL_FIREBALL:
|
|
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
|
|
me->CastSpell(target, SPELL_FIREBALL, false);
|
|
events.ScheduleEvent(EVENT_SPELL_FIREBALL, 2200, GROUP_PHASE_2_ABILITY);
|
|
break;
|
|
case EVENT_SPELL_DARK_BARRAGE:
|
|
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
|
|
me->CastSpell(target, SPELL_DARK_BARRAGE, false);
|
|
events.ScheduleEvent(EVENT_SPELL_DARK_BARRAGE, 30000, GROUP_PHASE_2_ABILITY);
|
|
break;
|
|
case EVENT_START_PHASE_2_WEAPON:
|
|
me->LoadEquipment(1, true);
|
|
me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
|
|
me->SetDisableGravity(false);
|
|
break;
|
|
case EVENT_START_PHASE_3_LAND:
|
|
me->getThreatManager().resetAllAggro();
|
|
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
|
me->SetTarget(me->GetVictim()->GetGUID());
|
|
AttackStart(me->GetVictim());
|
|
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
|
ScheduleNormalEvents(3);
|
|
events.ScheduleEvent(EVENT_PHASE_5_START, 1000);
|
|
break;
|
|
// ///////////////////////////
|
|
// PHASE 4
|
|
// ///////////////////////////
|
|
case EVENT_PHASE_4_START:
|
|
me->CastSpell(me, SPELL_DEMON_TRANSFORM_1, true);
|
|
me->getThreatManager().resetAllAggro();
|
|
me->GetMotionMaster()->MoveChase(me->GetVictim(), 35.0f);
|
|
events.Reset();
|
|
events.ScheduleEvent(EVENT_SPELL_SHADOW_BLAST, 11000);
|
|
events.ScheduleEvent(EVENT_MOVE_MAIEV, 5000);
|
|
events.ScheduleEvent(EVENT_FINISH_TRANSFORM, 10500);
|
|
events.ScheduleEvent(EVENT_SPELL_FLAME_BURST, 21000);
|
|
events.ScheduleEvent(EVENT_SPELL_SHADOW_DEMONS, 36000);
|
|
events.ScheduleEvent(EVENT_REMOVE_DEMON_FORM, 60000);
|
|
break;
|
|
case EVENT_SPELL_SHADOW_BLAST:
|
|
me->CastSpell(me->GetVictim(), SPELL_SHADOW_BLAST, false);
|
|
events.ScheduleEvent(EVENT_SPELL_SHADOW_BLAST, 2200);
|
|
break;
|
|
case EVENT_SPELL_FLAME_BURST:
|
|
me->CastSpell(me, SPELL_FLAME_BURST, false);
|
|
events.ScheduleEvent(EVENT_SPELL_FLAME_BURST, 22000);
|
|
break;
|
|
case EVENT_SPELL_SHADOW_DEMONS:
|
|
me->CastSpell(me, SPELL_SUMMON_SHADOW_DEMON, false);
|
|
break;
|
|
case EVENT_REMOVE_DEMON_FORM:
|
|
me->CastSpell(me, SPELL_DEMON_TRANSFORM_1, true);
|
|
me->getThreatManager().resetAllAggro();
|
|
events.Reset();
|
|
if (summons.HasEntry(NPC_MAIEV_SHADOWSONG))
|
|
{
|
|
ScheduleNormalEvents(5);
|
|
events.DelayEvents(11000);
|
|
events.ScheduleEvent(EVENT_MOVE_MAIEV, 10000);
|
|
events.ScheduleEvent(EVENT_FINISH_TRANSFORM, 10500);
|
|
}
|
|
else
|
|
{
|
|
ScheduleNormalEvents(3);
|
|
events.ScheduleEvent(EVENT_PHASE_5_START, 1000);
|
|
events.DelayEvents(11000);
|
|
events.ScheduleEvent(EVENT_FINISH_TRANSFORM, 10500);
|
|
}
|
|
break;
|
|
case EVENT_MOVE_MAIEV:
|
|
if (Creature* maiev = summons.GetCreatureWithEntry(NPC_MAIEV_SHADOWSONG))
|
|
{
|
|
if (events.GetNextEventTime(EVENT_REMOVE_DEMON_FORM) != 0)
|
|
{
|
|
maiev->AI()->DoAction(ACTION_MAIEV_SET_DIST30);
|
|
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, -25.0f, true))
|
|
maiev->GetMotionMaster()->MoveCharge(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 7.0f, 0);
|
|
else
|
|
maiev->GetMotionMaster()->MoveCharge(678.04f, 378.34f, 353.0f, 7.0f, 0);
|
|
}
|
|
else
|
|
{
|
|
maiev->AI()->DoAction(ACTION_MAIEV_SET_DIST0);
|
|
maiev->GetMotionMaster()->MoveChase(me, 0.0f);
|
|
}
|
|
}
|
|
break;
|
|
case EVENT_FINISH_TRANSFORM:
|
|
me->GetMotionMaster()->MoveChase(me->GetVictim(), events.GetNextEventTime(EVENT_REMOVE_DEMON_FORM) != 0 ? 35.0f : 0.0f);
|
|
break;
|
|
}
|
|
|
|
if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
|
|
DoMeleeAttackIfReady();
|
|
}
|
|
|
|
bool CheckEvadeIfOutOfCombatArea() const
|
|
{
|
|
return me->GetHomePosition().GetExactDist(me) > 90.0f || !SelectTargetFromPlayerList(80.0f);
|
|
}
|
|
};
|
|
|
|
CreatureAI* GetAI(Creature* creature) const
|
|
{
|
|
return GetInstanceAI<boss_illidan_stormrageAI>(creature);
|
|
}
|
|
};
|
|
|
|
enum Akama
|
|
{
|
|
POINT_DOORS = 20,
|
|
POINT_ILLIDAN = 32,
|
|
POINT_FIGHT_MINIONS = 40,
|
|
|
|
SPELL_AKAMA_DOOR_OPEN = 41268,
|
|
SPELL_AKAMA_DOOR_FAIL = 41271,
|
|
SPELL_DEATHSWORN_DOOR_OPEN = 41269,
|
|
SPELL_HEALING_POTION = 40535,
|
|
SPELL_CHAIN_LIGHTNING = 40536,
|
|
|
|
NPC_SPIRIT_OF_OLUM = 23411,
|
|
NPC_SPIRIT_OF_UDALO = 23410,
|
|
NPC_ILLIDARI_ELITE = 23226,
|
|
|
|
EVENT_AKAMA_SCENE_1 = 1,
|
|
EVENT_AKAMA_SCENE_2 = 2,
|
|
EVENT_AKAMA_SCENE_3 = 3,
|
|
EVENT_AKAMA_SCENE_4 = 4,
|
|
EVENT_AKAMA_SCENE_5 = 5,
|
|
EVENT_AKAMA_SCENE_6 = 6,
|
|
EVENT_AKAMA_SCENE_7 = 7,
|
|
EVENT_AKAMA_SCENE_8 = 8,
|
|
EVENT_AKAMA_SCENE_9 = 9,
|
|
EVENT_AKAMA_SCENE_10 = 10,
|
|
EVENT_AKAMA_SCENE_11 = 11,
|
|
EVENT_AKAMA_SCENE_20 = 20,
|
|
EVENT_AKAMA_SCENE_21 = 21,
|
|
EVENT_AKAMA_SCENE_22 = 22,
|
|
EVENT_AKAMA_SCENE_23 = 23,
|
|
EVENT_AKAMA_SCENE_24 = 24,
|
|
EVENT_AKAMA_SCENE_25 = 25,
|
|
EVENT_AKAMA_SCENE_26 = 26,
|
|
EVENT_AKAMA_SCENE_27 = 27,
|
|
EVENT_AKAMA_SCENE_28 = 28,
|
|
EVENT_AKAMA_SCENE_29 = 29,
|
|
|
|
EVENT_AKAMA_SUMMON_ILLIDARI = 100,
|
|
EVENT_AKAMA_SPELL_CHAIN = 101,
|
|
EVENT_AKAMA_HEALTH = 102
|
|
};
|
|
|
|
class npc_akama_illidan : public CreatureScript
|
|
{
|
|
public:
|
|
npc_akama_illidan() : CreatureScript("npc_akama_illidan") { }
|
|
|
|
struct npc_akama_illidanAI : public npc_escortAI
|
|
{
|
|
npc_akama_illidanAI(Creature* creature) : npc_escortAI(creature), summons(me)
|
|
{
|
|
instance = creature->GetInstanceScript();
|
|
if (instance->GetBossState(DATA_AKAMA_FINISHED) == DONE)
|
|
{
|
|
me->GetMap()->LoadGrid(751.664f, 238.933f);
|
|
me->SetHomePosition(751.664f, 238.933f, 353.106f, 2.18f);
|
|
me->NearTeleportTo(751.664f, 238.933f, 353.106f, 2.18f);
|
|
}
|
|
}
|
|
|
|
void DoAction(int32 param)
|
|
{
|
|
if (param == ACTION_FIGHT_MINIONS)
|
|
{
|
|
me->CombatStop(true);
|
|
events.ScheduleEvent(EVENT_AKAMA_SUMMON_ILLIDARI, 8000);
|
|
events.ScheduleEvent(EVENT_AKAMA_SPELL_CHAIN, 7000);
|
|
events.ScheduleEvent(EVENT_AKAMA_HEALTH, 1000);
|
|
me->GetMotionMaster()->MoveCharge(741.97f, 358.74f, 353.0f, 10.0f, POINT_FIGHT_MINIONS);
|
|
Talk(SAY_AKAMA_LEAVE);
|
|
}
|
|
else if (param == ACTION_ILLIDAN_DEAD)
|
|
{
|
|
events.Reset();
|
|
summons.DespawnAll();
|
|
me->CombatStop(true);
|
|
}
|
|
}
|
|
|
|
void Reset()
|
|
{
|
|
me->SetReactState(REACT_AGGRESSIVE);
|
|
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
|
|
me->setActive(false);
|
|
me->SetVisible(instance->GetBossState(DATA_ILLIDARI_COUNCIL) == DONE && instance->GetBossState(DATA_ILLIDAN_STORMRAGE) != DONE);
|
|
events.Reset();
|
|
summons.DespawnAll();
|
|
}
|
|
|
|
void sGossipSelect(Player* player, uint32 /*sender*/, uint32 /*action*/)
|
|
{
|
|
player->CLOSE_GOSSIP_MENU();
|
|
me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
|
|
me->setActive(true);
|
|
|
|
if (instance->GetBossState(DATA_AKAMA_FINISHED) != DONE)
|
|
{
|
|
me->SetReactState(REACT_PASSIVE);
|
|
Start(false, true);
|
|
SetDespawnAtEnd(false);
|
|
}
|
|
else
|
|
{
|
|
me->GetMotionMaster()->MovePoint(POINT_ILLIDAN, 744.45f, 304.84f, 353.0f);
|
|
events.Reset();
|
|
events.ScheduleEvent(EVENT_AKAMA_SCENE_20, 5000);
|
|
events.ScheduleEvent(EVENT_AKAMA_SCENE_21, 8000);
|
|
events.ScheduleEvent(EVENT_AKAMA_SCENE_22, 10000);
|
|
events.ScheduleEvent(EVENT_AKAMA_SCENE_23, 23000);
|
|
events.ScheduleEvent(EVENT_AKAMA_SCENE_24, 34000);
|
|
events.ScheduleEvent(EVENT_AKAMA_SCENE_25, 41000);
|
|
events.ScheduleEvent(EVENT_AKAMA_SCENE_26, 46000);
|
|
events.ScheduleEvent(EVENT_AKAMA_SCENE_27, 49000);
|
|
events.ScheduleEvent(EVENT_AKAMA_SCENE_28, 49200);
|
|
events.ScheduleEvent(EVENT_AKAMA_SCENE_29, 52000);
|
|
}
|
|
}
|
|
|
|
void JustSummoned(Creature* summon)
|
|
{
|
|
summons.Summon(summon);
|
|
summon->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
|
|
if (summon->GetEntry() == NPC_ILLIDARI_ELITE)
|
|
{
|
|
me->AddThreat(summon, 1000000.0f);
|
|
summon->AddThreat(me, 1000000.0f);
|
|
summon->AI()->AttackStart(me);
|
|
AttackStart(summon);
|
|
}
|
|
}
|
|
|
|
void WaypointReached(uint32 pointId)
|
|
{
|
|
if (pointId == POINT_DOORS)
|
|
{
|
|
SetEscortPaused(true);
|
|
events.ScheduleEvent(EVENT_AKAMA_SCENE_1, 0);
|
|
events.ScheduleEvent(EVENT_AKAMA_SCENE_2, 4000);
|
|
events.ScheduleEvent(EVENT_AKAMA_SCENE_3, 7000);
|
|
events.ScheduleEvent(EVENT_AKAMA_SCENE_4, 17000);
|
|
events.ScheduleEvent(EVENT_AKAMA_SCENE_5, 23000);
|
|
events.ScheduleEvent(EVENT_AKAMA_SCENE_6, 25000);
|
|
events.ScheduleEvent(EVENT_AKAMA_SCENE_7, 31000);
|
|
events.ScheduleEvent(EVENT_AKAMA_SCENE_8, 40000);
|
|
events.ScheduleEvent(EVENT_AKAMA_SCENE_9, 54000);
|
|
events.ScheduleEvent(EVENT_AKAMA_SCENE_10, 57000);
|
|
events.ScheduleEvent(EVENT_AKAMA_SCENE_11, 62000);
|
|
}
|
|
else if (pointId == POINT_ILLIDAN)
|
|
{
|
|
me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
|
|
me->setActive(false);
|
|
me->SetReactState(REACT_AGGRESSIVE);
|
|
}
|
|
}
|
|
|
|
void MoveInLineOfSight(Unit* /*who*/) { }
|
|
|
|
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask)
|
|
{
|
|
if (damage >= me->GetHealth())
|
|
damage = 0;
|
|
}
|
|
|
|
void UpdateEscortAI(uint32 diff)
|
|
{
|
|
events.Update(diff);
|
|
switch (events.ExecuteEvent())
|
|
{
|
|
case EVENT_AKAMA_SCENE_1:
|
|
me->SetFacingTo(0.0f);
|
|
break;
|
|
case EVENT_AKAMA_SCENE_2:
|
|
Talk(SAY_AKAMA_DOORS);
|
|
break;
|
|
case EVENT_AKAMA_SCENE_3:
|
|
me->CastSpell(me, SPELL_AKAMA_DOOR_FAIL, false);
|
|
break;
|
|
case EVENT_AKAMA_SCENE_4:
|
|
Talk(SAY_AKAMA_FAIL);
|
|
break;
|
|
case EVENT_AKAMA_SCENE_5:
|
|
me->SummonCreature(NPC_SPIRIT_OF_UDALO, me->GetPositionX()-5.0f, me->GetPositionY()+8.0f, me->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 60000);
|
|
me->SummonCreature(NPC_SPIRIT_OF_OLUM, me->GetPositionX()-5.0f, me->GetPositionY()-8.0f, me->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 60000);
|
|
break;
|
|
case EVENT_AKAMA_SCENE_6:
|
|
if (Creature* udalo = me->FindNearestCreature(NPC_SPIRIT_OF_UDALO, 15.0f))
|
|
udalo->AI()->Talk(SAY_UDALO);
|
|
break;
|
|
case EVENT_AKAMA_SCENE_7:
|
|
if (Creature* olum = me->FindNearestCreature(NPC_SPIRIT_OF_OLUM, 15.0f))
|
|
olum->AI()->Talk(SAY_OLUM);
|
|
break;
|
|
case EVENT_AKAMA_SCENE_8:
|
|
me->CastSpell(me, SPELL_AKAMA_DOOR_OPEN, false);
|
|
if (Creature* olum = me->FindNearestCreature(NPC_SPIRIT_OF_OLUM, 15.0f))
|
|
olum->CastSpell(olum, SPELL_AKAMA_DOOR_OPEN, false);
|
|
if (Creature* udalo = me->FindNearestCreature(NPC_SPIRIT_OF_UDALO, 15.0f))
|
|
udalo->CastSpell(udalo, SPELL_AKAMA_DOOR_OPEN, false);
|
|
break;
|
|
case EVENT_AKAMA_SCENE_9:
|
|
instance->SetBossState(DATA_AKAMA_FINISHED, NOT_STARTED);
|
|
instance->SetBossState(DATA_AKAMA_FINISHED, DONE);
|
|
break;
|
|
case EVENT_AKAMA_SCENE_10:
|
|
Talk(SAY_AKAMA_BEWARE);
|
|
break;
|
|
case EVENT_AKAMA_SCENE_11:
|
|
SetEscortPaused(false);
|
|
break;
|
|
case EVENT_AKAMA_SCENE_20:
|
|
if (Creature* illidan = ObjectAccessor::GetCreature(*me, instance->GetData64(NPC_ILLIDAN_STORMRAGE)))
|
|
illidan->SetStandState(UNIT_STAND_STATE_STAND);
|
|
break;
|
|
case EVENT_AKAMA_SCENE_21:
|
|
me->SetFacingTo(M_PI);
|
|
break;
|
|
case EVENT_AKAMA_SCENE_22:
|
|
if (Creature* illidan = ObjectAccessor::GetCreature(*me, instance->GetData64(NPC_ILLIDAN_STORMRAGE)))
|
|
illidan->AI()->Talk(SAY_ILLIDAN_AKAMA1);
|
|
break;
|
|
case EVENT_AKAMA_SCENE_23:
|
|
Talk(SAY_AKAMA_ILLIDAN1);
|
|
break;
|
|
case EVENT_AKAMA_SCENE_24:
|
|
if (Creature* illidan = ObjectAccessor::GetCreature(*me, instance->GetData64(NPC_ILLIDAN_STORMRAGE)))
|
|
illidan->AI()->Talk(SAY_ILLIDAN_AKAMA2);
|
|
break;
|
|
case EVENT_AKAMA_SCENE_25:
|
|
Talk(SAY_AKAMA_ILLIDAN2);
|
|
break;
|
|
case EVENT_AKAMA_SCENE_26:
|
|
if (Creature* illidan = ObjectAccessor::GetCreature(*me, instance->GetData64(NPC_ILLIDAN_STORMRAGE)))
|
|
illidan->AI()->Talk(SAY_ILLIDAN_AKAMA3);
|
|
break;
|
|
case EVENT_AKAMA_SCENE_27:
|
|
if (Creature* illidan = ObjectAccessor::GetCreature(*me, instance->GetData64(NPC_ILLIDAN_STORMRAGE)))
|
|
illidan->LoadEquipment(1, true);
|
|
break;
|
|
case EVENT_AKAMA_SCENE_28:
|
|
if (Creature* illidan = ObjectAccessor::GetCreature(*me, instance->GetData64(NPC_ILLIDAN_STORMRAGE)))
|
|
illidan->HandleEmoteCommand(EMOTE_ONESHOT_TALK_NO_SHEATHE);
|
|
break;
|
|
case EVENT_AKAMA_SCENE_29:
|
|
if (Creature* illidan = ObjectAccessor::GetCreature(*me, instance->GetData64(NPC_ILLIDAN_STORMRAGE)))
|
|
{
|
|
illidan->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC);
|
|
illidan->SetInCombatWithZone();
|
|
AttackStart(illidan);
|
|
}
|
|
break;
|
|
case EVENT_AKAMA_SUMMON_ILLIDARI:
|
|
me->SummonCreature(NPC_ILLIDARI_ELITE, 742.55f, 359.12f, 353.0f, 4.35f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000);
|
|
events.ScheduleEvent(EVENT_AKAMA_SUMMON_ILLIDARI, urand(2000, 6000));
|
|
break;
|
|
case EVENT_AKAMA_SPELL_CHAIN:
|
|
if (me->GetVictim())
|
|
me->CastSpell(me->GetVictim(), SPELL_CHAIN_LIGHTNING, false);
|
|
events.ScheduleEvent(EVENT_AKAMA_SPELL_CHAIN, 20000);
|
|
break;
|
|
case EVENT_AKAMA_HEALTH:
|
|
if (me->HealthBelowPct(20))
|
|
me->CastSpell(me, SPELL_HEALING_POTION, false);
|
|
events.ScheduleEvent(EVENT_AKAMA_HEALTH, 1000);
|
|
break;
|
|
}
|
|
|
|
DoMeleeAttackIfReady();
|
|
}
|
|
|
|
private:
|
|
EventMap events;
|
|
SummonList summons;
|
|
InstanceScript* instance;
|
|
};
|
|
|
|
CreatureAI* GetAI(Creature* creature) const
|
|
{
|
|
return GetInstanceAI<npc_akama_illidanAI>(creature);
|
|
}
|
|
};
|
|
|
|
class spell_illidan_draw_soul : public SpellScriptLoader
|
|
{
|
|
public:
|
|
spell_illidan_draw_soul() : SpellScriptLoader("spell_illidan_draw_soul") { }
|
|
|
|
class spell_illidan_draw_soul_SpellScript : public SpellScript
|
|
{
|
|
PrepareSpellScript(spell_illidan_draw_soul_SpellScript);
|
|
|
|
void HandleScriptEffect(SpellEffIndex effIndex)
|
|
{
|
|
PreventHitDefaultEffect(effIndex);
|
|
if (Unit* target = GetHitUnit())
|
|
target->CastSpell(GetCaster(), SPELL_DRAW_SOUL_HEAL, true);
|
|
}
|
|
|
|
void Register()
|
|
{
|
|
OnEffectHitTarget += SpellEffectFn(spell_illidan_draw_soul_SpellScript::HandleScriptEffect, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
|
|
}
|
|
};
|
|
|
|
SpellScript* GetSpellScript() const
|
|
{
|
|
return new spell_illidan_draw_soul_SpellScript();
|
|
}
|
|
};
|
|
|
|
class spell_illidan_parasitic_shadowfiend : public SpellScriptLoader
|
|
{
|
|
public:
|
|
spell_illidan_parasitic_shadowfiend() : SpellScriptLoader("spell_illidan_parasitic_shadowfiend") { }
|
|
|
|
class spell_illidan_parasitic_shadowfiend_AuraScript : public AuraScript
|
|
{
|
|
PrepareAuraScript(spell_illidan_parasitic_shadowfiend_AuraScript)
|
|
|
|
void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
|
{
|
|
if (!GetTarget()->HasAura(SPELL_SHADOW_PRISON) && GetTarget()->GetInstanceScript() && GetTarget()->GetInstanceScript()->IsEncounterInProgress())
|
|
GetTarget()->CastSpell(GetTarget(), SPELL_SUMMON_PARASITIC_SHADOWFIENDS, true);
|
|
}
|
|
|
|
void Register()
|
|
{
|
|
AfterEffectRemove += AuraEffectRemoveFn(spell_illidan_parasitic_shadowfiend_AuraScript::HandleEffectRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL);
|
|
}
|
|
};
|
|
|
|
AuraScript* GetAuraScript() const
|
|
{
|
|
return new spell_illidan_parasitic_shadowfiend_AuraScript();
|
|
}
|
|
};
|
|
|
|
class spell_illidan_parasitic_shadowfiend_trigger : public SpellScriptLoader
|
|
{
|
|
public:
|
|
spell_illidan_parasitic_shadowfiend_trigger() : SpellScriptLoader("spell_illidan_parasitic_shadowfiend_trigger") { }
|
|
|
|
class spell_illidan_parasitic_shadowfiend_trigger_AuraScript : public AuraScript
|
|
{
|
|
PrepareAuraScript(spell_illidan_parasitic_shadowfiend_trigger_AuraScript)
|
|
|
|
void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
|
{
|
|
if (!GetTarget()->HasAura(SPELL_SHADOW_PRISON) && GetTarget()->GetInstanceScript() && GetTarget()->GetInstanceScript()->IsEncounterInProgress())
|
|
GetTarget()->CastSpell(GetTarget(), SPELL_SUMMON_PARASITIC_SHADOWFIENDS, true);
|
|
}
|
|
|
|
void Register()
|
|
{
|
|
AfterEffectRemove += AuraEffectRemoveFn(spell_illidan_parasitic_shadowfiend_trigger_AuraScript::HandleEffectRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL);
|
|
}
|
|
};
|
|
|
|
AuraScript* GetAuraScript() const
|
|
{
|
|
return new spell_illidan_parasitic_shadowfiend_trigger_AuraScript();
|
|
}
|
|
|
|
class spell_illidan_parasitic_shadowfiend_trigger_SpellScript : public SpellScript
|
|
{
|
|
PrepareSpellScript(spell_illidan_parasitic_shadowfiend_trigger_SpellScript);
|
|
|
|
void HandleScriptEffect(SpellEffIndex effIndex)
|
|
{
|
|
PreventHitDefaultEffect(effIndex);
|
|
if (Creature* target = GetHitCreature())
|
|
target->DespawnOrUnsummon(1);
|
|
}
|
|
|
|
void Register()
|
|
{
|
|
OnEffectHitTarget += SpellEffectFn(spell_illidan_parasitic_shadowfiend_trigger_SpellScript::HandleScriptEffect, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
|
|
}
|
|
};
|
|
|
|
SpellScript* GetSpellScript() const
|
|
{
|
|
return new spell_illidan_parasitic_shadowfiend_trigger_SpellScript();
|
|
}
|
|
};
|
|
|
|
class spell_illidan_glaive_throw : public SpellScriptLoader
|
|
{
|
|
public:
|
|
spell_illidan_glaive_throw() : SpellScriptLoader("spell_illidan_glaive_throw") { }
|
|
|
|
class spell_illidan_glaive_throw_SpellScript : public SpellScript
|
|
{
|
|
PrepareSpellScript(spell_illidan_glaive_throw_SpellScript);
|
|
|
|
void HandleDummy(SpellEffIndex effIndex)
|
|
{
|
|
PreventHitEffect(effIndex);
|
|
if (Unit* target = GetHitUnit())
|
|
target->CastSpell(target, SPELL_SUMMON_GLAIVE, true);
|
|
}
|
|
|
|
void Register()
|
|
{
|
|
OnEffectHitTarget += SpellEffectFn(spell_illidan_glaive_throw_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
|
|
}
|
|
};
|
|
|
|
SpellScript* GetSpellScript() const
|
|
{
|
|
return new spell_illidan_glaive_throw_SpellScript();
|
|
}
|
|
};
|
|
|
|
class spell_illidan_tear_of_azzinoth_summon_channel : public SpellScriptLoader
|
|
{
|
|
public:
|
|
spell_illidan_tear_of_azzinoth_summon_channel() : SpellScriptLoader("spell_illidan_tear_of_azzinoth_summon_channel") { }
|
|
|
|
class spell_illidan_tear_of_azzinoth_summon_channel_AuraScript : public AuraScript
|
|
{
|
|
PrepareAuraScript(spell_illidan_tear_of_azzinoth_summon_channel_AuraScript);
|
|
|
|
void OnPeriodic(AuraEffect const* /*aurEff*/)
|
|
{
|
|
PreventDefaultAction();
|
|
if (Unit* caster = GetCaster())
|
|
{
|
|
if (GetTarget()->GetDistance2d(caster) > 25.0f)
|
|
{
|
|
SetDuration(0);
|
|
GetTarget()->CastSpell(GetTarget(), SPELL_UNCAGED_WRATH, true);
|
|
}
|
|
}
|
|
|
|
// xinef: ugly hax, dunno how it really works on blizz
|
|
Map::PlayerList const& pl = GetTarget()->GetMap()->GetPlayers();
|
|
for (Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr)
|
|
if (Player* player = itr->GetSource())
|
|
if (player->GetPositionX() > 693.4f || player->GetPositionY() < 271.8f || player->GetPositionX() < 658.43f || player->GetPositionY() > 338.68f)
|
|
{
|
|
GetTarget()->CastSpell(player, SPELL_CHARGE, true);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Register()
|
|
{
|
|
OnEffectPeriodic += AuraEffectPeriodicFn(spell_illidan_tear_of_azzinoth_summon_channel_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
|
}
|
|
};
|
|
|
|
AuraScript* GetAuraScript() const
|
|
{
|
|
return new spell_illidan_tear_of_azzinoth_summon_channel_AuraScript();
|
|
}
|
|
};
|
|
|
|
class spell_illidan_shadow_prison : public SpellScriptLoader
|
|
{
|
|
public:
|
|
spell_illidan_shadow_prison() : SpellScriptLoader("spell_illidan_shadow_prison") { }
|
|
|
|
class spell_illidan_shadow_prison_SpellScript : public SpellScript
|
|
{
|
|
PrepareSpellScript(spell_illidan_shadow_prison_SpellScript);
|
|
|
|
void FilterTargets(std::list<WorldObject*>& targets)
|
|
{
|
|
targets.remove_if(PlayerOrPetCheck());
|
|
}
|
|
|
|
void Register()
|
|
{
|
|
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_illidan_shadow_prison_SpellScript::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
|
|
}
|
|
};
|
|
|
|
SpellScript* GetSpellScript() const
|
|
{
|
|
return new spell_illidan_shadow_prison_SpellScript();
|
|
}
|
|
};
|
|
|
|
class spell_illidan_demon_transform1 : public SpellScriptLoader
|
|
{
|
|
public:
|
|
spell_illidan_demon_transform1() : SpellScriptLoader("spell_illidan_demon_transform1") { }
|
|
|
|
class spell_illidan_demon_transform1_AuraScript : public AuraScript
|
|
{
|
|
PrepareAuraScript(spell_illidan_demon_transform1_AuraScript);
|
|
|
|
bool Load()
|
|
{
|
|
return GetUnitOwner()->GetTypeId() == TYPEID_UNIT;
|
|
}
|
|
|
|
void OnPeriodic(AuraEffect const* /*aurEff*/)
|
|
{
|
|
PreventDefaultAction();
|
|
SetDuration(0);
|
|
GetUnitOwner()->CastSpell(GetUnitOwner(), SPELL_DEMON_TRANSFORM_2, true);
|
|
GetUnitOwner()->ToCreature()->LoadEquipment(0, true);
|
|
}
|
|
|
|
void Register()
|
|
{
|
|
OnEffectPeriodic += AuraEffectPeriodicFn(spell_illidan_demon_transform1_AuraScript::OnPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
|
}
|
|
};
|
|
|
|
AuraScript* GetAuraScript() const
|
|
{
|
|
return new spell_illidan_demon_transform1_AuraScript();
|
|
}
|
|
};
|
|
|
|
class spell_illidan_demon_transform2 : public SpellScriptLoader
|
|
{
|
|
public:
|
|
spell_illidan_demon_transform2() : SpellScriptLoader("spell_illidan_demon_transform2") { }
|
|
|
|
class spell_illidan_demon_transform2_AuraScript : public AuraScript
|
|
{
|
|
PrepareAuraScript(spell_illidan_demon_transform2_AuraScript);
|
|
|
|
bool Load()
|
|
{
|
|
return GetUnitOwner()->GetTypeId() == TYPEID_UNIT;
|
|
}
|
|
|
|
void OnPeriodic(AuraEffect const* aurEff)
|
|
{
|
|
PreventDefaultAction();
|
|
|
|
if (aurEff->GetTickNumber() == 1)
|
|
{
|
|
if (GetUnitOwner()->GetDisplayId() == GetUnitOwner()->GetNativeDisplayId())
|
|
GetUnitOwner()->CastSpell(GetUnitOwner(), SPELL_DEMON_FORM, true);
|
|
else
|
|
GetUnitOwner()->RemoveAurasDueToSpell(SPELL_DEMON_FORM);
|
|
}
|
|
else if (aurEff->GetTickNumber() == 2)
|
|
{
|
|
SetDuration(0);
|
|
GetUnitOwner()->CastSpell(GetUnitOwner(), SPELL_DEMON_TRANSFORM_3, true);
|
|
if (Aura* aura = GetUnitOwner()->GetAura(SPELL_DEMON_TRANSFORM_3))
|
|
aura->SetDuration(4500);
|
|
|
|
if (!GetUnitOwner()->HasAura(SPELL_DEMON_FORM))
|
|
GetUnitOwner()->ToCreature()->LoadEquipment(1, true);
|
|
}
|
|
}
|
|
|
|
void Register()
|
|
{
|
|
OnEffectPeriodic += AuraEffectPeriodicFn(spell_illidan_demon_transform2_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
|
}
|
|
};
|
|
|
|
AuraScript* GetAuraScript() const
|
|
{
|
|
return new spell_illidan_demon_transform2_AuraScript();
|
|
}
|
|
};
|
|
|
|
class spell_illidan_flame_burst : public SpellScriptLoader
|
|
{
|
|
public:
|
|
spell_illidan_flame_burst() : SpellScriptLoader("spell_illidan_flame_burst") { }
|
|
|
|
class spell_illidan_flame_burst_SpellScript : public SpellScript
|
|
{
|
|
PrepareSpellScript(spell_illidan_flame_burst_SpellScript);
|
|
|
|
void HandleScriptEffect(SpellEffIndex effIndex)
|
|
{
|
|
PreventHitEffect(effIndex);
|
|
if (Unit* target = GetHitUnit())
|
|
target->CastSpell(target, SPELL_FLAME_BURST_EFFECT, true);
|
|
}
|
|
|
|
void Register()
|
|
{
|
|
OnEffectHitTarget += SpellEffectFn(spell_illidan_flame_burst_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
|
}
|
|
};
|
|
|
|
SpellScript* GetSpellScript() const
|
|
{
|
|
return new spell_illidan_flame_burst_SpellScript();
|
|
}
|
|
};
|
|
|
|
class spell_illidan_found_target : public SpellScriptLoader
|
|
{
|
|
public:
|
|
spell_illidan_found_target() : SpellScriptLoader("spell_illidan_found_target") { }
|
|
|
|
class spell_illidan_found_target_SpellScript : public SpellScript
|
|
{
|
|
PrepareSpellScript(spell_illidan_found_target_SpellScript);
|
|
|
|
void HandleDummy(SpellEffIndex effIndex)
|
|
{
|
|
PreventHitEffect(effIndex);
|
|
if (Unit* target = GetHitUnit())
|
|
if (GetCaster()->GetDistance(target) < 2.0f)
|
|
{
|
|
GetCaster()->CastSpell(target, SPELL_CONSUME_SOUL, true);
|
|
GetCaster()->CastSpell(GetCaster(), SPELL_FIND_TARGET, true);
|
|
}
|
|
}
|
|
|
|
void Register()
|
|
{
|
|
OnEffectHitTarget += SpellEffectFn(spell_illidan_found_target_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
|
|
}
|
|
};
|
|
|
|
SpellScript* GetSpellScript() const
|
|
{
|
|
return new spell_illidan_found_target_SpellScript();
|
|
}
|
|
};
|
|
|
|
class spell_illidan_cage_trap : public SpellScriptLoader
|
|
{
|
|
public:
|
|
spell_illidan_cage_trap() : SpellScriptLoader("spell_illidan_cage_trap") { }
|
|
|
|
class spell_illidan_cage_trap_SpellScript : public SpellScript
|
|
{
|
|
PrepareSpellScript(spell_illidan_cage_trap_SpellScript);
|
|
|
|
bool Load()
|
|
{
|
|
return GetCaster()->GetTypeId() == TYPEID_UNIT;
|
|
}
|
|
|
|
void HandleScriptEffect(SpellEffIndex effIndex)
|
|
{
|
|
PreventHitEffect(effIndex);
|
|
if (Creature* target = GetHitCreature())
|
|
if (GetCaster()->GetExactDist2d(target) < 4.0f)
|
|
{
|
|
target->AI()->DoAction(ACTION_ILLIDAN_CAGED);
|
|
target->CastSpell(target, SPELL_CAGE_TRAP, true);
|
|
GetCaster()->ToCreature()->DespawnOrUnsummon(1);
|
|
if (GameObject* gobject = GetCaster()->FindNearestGameObject(GO_CAGE_TRAP, 10.0f))
|
|
gobject->SetLootState(GO_JUST_DEACTIVATED);
|
|
}
|
|
}
|
|
|
|
void Register()
|
|
{
|
|
OnEffectHitTarget += SpellEffectFn(spell_illidan_cage_trap_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
|
}
|
|
};
|
|
|
|
SpellScript* GetSpellScript() const
|
|
{
|
|
return new spell_illidan_cage_trap_SpellScript();
|
|
}
|
|
};
|
|
|
|
class spell_illidan_cage_trap_stun : public SpellScriptLoader
|
|
{
|
|
public:
|
|
spell_illidan_cage_trap_stun() : SpellScriptLoader("spell_illidan_cage_trap_stun") { }
|
|
|
|
class spell_illidan_cage_trap_stun_AuraScript : public AuraScript
|
|
{
|
|
PrepareAuraScript(spell_illidan_cage_trap_stun_AuraScript);
|
|
|
|
void OnPeriodic(AuraEffect const* /*aurEff*/)
|
|
{
|
|
PreventDefaultAction();
|
|
SetDuration(0);
|
|
|
|
for (uint32 i = SPELL_CAGED_SUMMON1; i <= SPELL_CAGED_SUMMON8; ++i)
|
|
GetTarget()->CastSpell(GetTarget(), i, true);
|
|
GetTarget()->CastSpell(GetTarget(), SPELL_CAGED_DEBUFF, true);
|
|
}
|
|
|
|
void Register()
|
|
{
|
|
OnEffectPeriodic += AuraEffectPeriodicFn(spell_illidan_cage_trap_stun_AuraScript::OnPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
|
}
|
|
};
|
|
|
|
AuraScript* GetAuraScript() const
|
|
{
|
|
return new spell_illidan_cage_trap_stun_AuraScript();
|
|
}
|
|
};
|
|
|
|
void AddSC_boss_illidan()
|
|
{
|
|
new boss_illidan_stormrage();
|
|
new npc_akama_illidan();
|
|
new spell_illidan_draw_soul();
|
|
new spell_illidan_parasitic_shadowfiend();
|
|
new spell_illidan_parasitic_shadowfiend_trigger();
|
|
new spell_illidan_glaive_throw();
|
|
new spell_illidan_tear_of_azzinoth_summon_channel();
|
|
new spell_illidan_shadow_prison();
|
|
new spell_illidan_demon_transform1();
|
|
new spell_illidan_demon_transform2();
|
|
new spell_illidan_flame_burst();
|
|
new spell_illidan_found_target();
|
|
new spell_illidan_cage_trap();
|
|
new spell_illidan_cage_trap_stun();
|
|
}
|