/* * Originally written by Xinef - Copyright (C) 2016+ AzerothCore , 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(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(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& 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(); }