diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/server/game/Spells/SpellInfo.cpp | 2 | ||||
| -rw-r--r-- | src/server/scripts/Outland/BlackTemple/black_temple.h | 5 | ||||
| -rw-r--r-- | src/server/scripts/Outland/BlackTemple/boss_illidan.cpp | 3213 | 
3 files changed, 1496 insertions, 1724 deletions
| diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 6b3f869064a..9a9c1c2daaf 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -3369,6 +3369,8 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const                  case 54836: // Wrath of the Plaguebringer                  case 61987: // Avenging Wrath Marker                  case 61988: // Divine Shield exclude aura +                case 41914: // Parasitic Shadowfiend (Illidan) +                case 41917: // Parasitic Shadowfiend (Illidan)                      return false;                  case 30877: // Tag Murloc                  case 61716: // Rabbit Costume diff --git a/src/server/scripts/Outland/BlackTemple/black_temple.h b/src/server/scripts/Outland/BlackTemple/black_temple.h index a1e1f44ab8a..02b587d374f 100644 --- a/src/server/scripts/Outland/BlackTemple/black_temple.h +++ b/src/server/scripts/Outland/BlackTemple/black_temple.h @@ -105,7 +105,8 @@ enum BTCreatureIds      NPC_ILLIDARI_ELITE              = 23226,      NPC_GLAIVE_TARGET               = 23448,      NPC_GLAIVE_WORLD_TRIGGER        = 22515, -    NPC_DEMON_FIRE                  = 23069 +    NPC_DEMON_FIRE                  = 23069, +    NPC_PARASITIC_SHADOWFIEND       = 23498  };  enum BTGameObjectIds @@ -143,4 +144,6 @@ inline AI* GetBlackTempleAI(T* obj)      return GetInstanceAI<AI>(obj, BTScriptName);  } +#define RegisterBlackTempleCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetBlackTempleAI) +  #endif // BLACK_TEMPLE_H_ diff --git a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp index 06baefff08b..3c2eb05a083 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp @@ -159,6 +159,8 @@ enum IllidanSpells      SPELL_DRAW_SOUL                     = 40904,      SPELL_DRAW_SOUL_HEAL                = 40903,      SPELL_PARASITIC_SHADOWFIEND         = 41917, +    SPELL_PARASITIC_SHADOWFIEND_2       = 41914, +    SPELL_REMOVE_PARASITIC_SHADOWFIEND  = 41923,      SPELL_AGONIZING_FLAMES              = 40932,      SPELL_AGONIZING_FLAMES_SELECTOR     = 40834,      SPELL_FRENZY                        = 40683, @@ -211,6 +213,7 @@ enum IllidanActions      ACTION_FLAME_DEAD,      ACTION_FINALIZE_AIR_PHASE,      ACTION_START_PHASE_4, +    ACTION_RESUME_COMBAT,      ACTION_ILLIDAN_CAGED,      ACTION_START_OUTRO,      ACTION_MAIEV_DOWN_FADE @@ -446,2106 +449,1870 @@ private:      Unit const* _me;  }; -class boss_illidan_stormrage : public CreatureScript +struct boss_illidan_stormrage : public BossAI  { -public: -    boss_illidan_stormrage() : CreatureScript("boss_illidan_stormrage") { } +    boss_illidan_stormrage(Creature* creature) : BossAI(creature, DATA_ILLIDAN_STORMRAGE), +        _minionsCount(0), _flameCount(0), _orientation(0.0f), _pillarIndex(0), _phase(0), _dead(false), _isDemon(false) { } + +    void Reset() override +    { +        _Reset(); +        specialEvents.Reset(); +        me->SummonCreatureGroup(SUMMON_GROUP); +        me->LoadEquipment(1, true); +        me->SetSheath(SHEATH_STATE_UNARMED); +        me->SetControlled(false, UNIT_STATE_ROOT); +        me->SetDisableGravity(false); +        _dead = false; +        _minionsCount = 0; +        _flameCount = 0; +        _phase = PHASE_1; +        _isDemon = false; +        if (instance->GetData(DATA_AKAMA_ILLIDAN_INTRO) && instance->GetBossState(DATA_ILLIDARI_COUNCIL) == DONE) +            if (Creature* akama = instance->GetCreature(DATA_AKAMA)) +                akama->AI()->DoAction(ACTION_ACTIVE_AKAMA_INTRO); +    } + +    void EnterCombat(Unit* /*who*/) override +    { +        _EnterCombat(); +        me->SetCanDualWield(true); +        if (GameObject* musicController = instance->GetGameObject(DATA_ILLIDAN_MUSIC_CONTROLLER)) +            musicController->PlayDirectMusic(EVENT_BT_SUMMIT_WALK_3_SOUND_ID); +        specialEvents.ScheduleEvent(EVENT_EVADE_CHECK, Seconds(10)); +        specialEvents.ScheduleEvent(EVENT_BERSERK, Minutes(25)); +        ScheduleEvents(GROUP_PHASE_1, GROUP_PHASE_1); +        events.ScheduleEvent(EVENT_TAUNT, Seconds(30), Seconds(60), GROUP_PHASE_ALL); +    } + +    void JustSummoned(Creature* summon) override +    { +        if (summon->GetEntry() == NPC_PARASITIC_SHADOWFIEND) +            summons.Summon(summon); +        else +            BossAI::JustSummoned(summon); +    } + +    void ChangeOrientation(float orientation) +    { +        _orientation = orientation; +        events.ScheduleEvent(EVENT_CHANGE_ORIENTATION, Milliseconds(1), GROUP_PHASE_ALL); +    } + +    void KilledUnit(Unit* victim) override +    { +        if (victim->GetTypeId() == TYPEID_PLAYER) +            Talk(SAY_ILLIDAN_KILL); +    } + +    void ScheduleEvents(uint8 phase, uint8 group) +    { +        switch (phase) +        { +            case GROUP_PHASE_1: +                events.ScheduleEvent(EVENT_FLAME_CRASH, Seconds(30), group); +                events.ScheduleEvent(EVENT_DRAW_SOUL, Seconds(34), group); +                events.ScheduleEvent(EVENT_SHEAR, Seconds(10), group); +                events.ScheduleEvent(EVENT_PARASITIC_SHADOWFIEND, Seconds(26), group); +                break; +            case GROUP_PHASE_2: +                events.ScheduleEvent(EVENT_FIREBALL, Seconds(1), Seconds(8), group); +                events.ScheduleEvent(EVENT_EYE_BLAST, Seconds(1), Seconds(30), group); +                if (roll_chance_i(50)) +                    events.ScheduleEvent(EVENT_DARK_BARRAGE, Seconds(1), Seconds(20), group); +                break; +            case GROUP_PHASE_3: +                ScheduleEvents(GROUP_PHASE_1, group); +                events.ScheduleEvent(EVENT_AGONIZING_FLAMES, Seconds(21), group); +                events.ScheduleEvent(EVENT_DEMON, Seconds(60), group); +                break; +            case GROUP_PHASE_DEMON: +                events.ScheduleEvent(EVENT_SHADOW_BLAST, Seconds(1), group); +                events.ScheduleEvent(EVENT_FLAME_BURST, Seconds(6), group); +                events.ScheduleEvent(EVENT_SHADOW_DEMON, Seconds(18), Seconds(30), group); +                break; +            case GROUP_PHASE_4: +                ScheduleEvents(GROUP_PHASE_3, group); +                events.ScheduleEvent(EVENT_FRENZY, Seconds(40), group); +                break; +            default: +                break; +        } +    } + +    void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override +    { +        if (summon->GetEntry() == NPC_ILLIDARI_ELITE) +            _minionsCount--; +    } -    struct boss_illidan_stormrageAI : public BossAI +    void EnterEvadeMode(EvadeReason /*why*/) override      { -        boss_illidan_stormrageAI(Creature* creature) : BossAI(creature, DATA_ILLIDAN_STORMRAGE), -            _minionsCount(0), _flameCount(0), _orientation(0.0f), _pillarIndex(0), _phase(0), _dead(false), _isDemon(false) { } +        summons.DespawnAll(); +        specialEvents.Reset(); +        _DespawnAtEvade(); +    } -        void Reset() override +    void DoAction(int32 actionId) override +    { +        switch (actionId)          { -            _Reset(); -            specialEvents.Reset(); -            me->SummonCreatureGroup(SUMMON_GROUP); -            me->LoadEquipment(1, true); -            me->SetSheath(SHEATH_STATE_UNARMED); -            me->SetControlled(false, UNIT_STATE_ROOT); -            me->SetDisableGravity(false); -            _dead = false; -            _minionsCount = 0; -            _flameCount = 0; -            _phase = PHASE_1; -            _isDemon = false; -            if (instance->GetData(DATA_AKAMA_ILLIDAN_INTRO) && instance->GetBossState(DATA_ILLIDARI_COUNCIL) == DONE) +            case ACTION_START_ENCOUNTER: +                events.SetPhase(PHASE_INTRO); +                me->RemoveAurasDueToSpell(SPELL_KNEEL); +                events.ScheduleEvent(EVENT_START_INTRO, Seconds(2), GROUP_PHASE_ALL); +                events.ScheduleEvent(EVENT_UNCONVINCED, Seconds(24), GROUP_PHASE_ALL);                  if (Creature* akama = instance->GetCreature(DATA_AKAMA)) -                    akama->AI()->DoAction(ACTION_ACTIVE_AKAMA_INTRO); +                    akama->AI()->DoAction(ACTION_FREE); +                break; +            case ACTION_INTRO_DONE: +                instance->SetData(DATA_AKAMA_ILLIDAN_INTRO, 0); +                break; +            case ACTION_START_MINIONS: +                Talk(SAY_ILLIDAN_MINION); +                if (Creature* akama = instance->GetCreature(DATA_AKAMA)) +                    akama->AI()->DoAction(ACTION_START_MINIONS); +                break; +            case ACTION_START_MINIONS_WEAVE: +                events.ScheduleEvent(EVENT_MINIONS_WEAVE, Milliseconds(1), GROUP_PHASE_ALL); +                break; +            case ACTION_START_PHASE_2: +            { +                me->SetReactState(REACT_PASSIVE); +                me->AttackStop(); +                me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); +                me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); +                me->SetDisableGravity(true); +                DoPlaySoundToSet(me, ILLIDAN_TAKEOFF_SOUND_ID); +                events.ScheduleEvent(EVENT_FLY, Seconds(1), GROUP_PHASE_ALL); +                events.CancelEventGroup(GROUP_PHASE_1); +                break; +            } +            case ACTION_FLAME_DEAD: +                _flameCount++; +                if (_flameCount == 2) +                { +                    _flameCount = 0; +                    DoAction(ACTION_FINALIZE_AIR_PHASE); +                } +                break; +            case ACTION_FINALIZE_AIR_PHASE: +                me->InterruptNonMeleeSpells(false); +                me->GetMotionMaster()->Clear(); +                events.CancelEventGroup(GROUP_PHASE_2); +                _phase = PHASE_3; +                events.CancelEvent(EVENT_FLY_TO_RANDOM_PILLAR); +                me->GetMotionMaster()->MovePoint(POINT_ILLIDAN_MIDDLE, IllidanMiddlePoint); +                break; +            case ACTION_START_PHASE_4: +                events.CancelEventGroup(GROUP_PHASE_3); +                DoCastSelf(SPELL_SHADOW_PRISON, true); +                summons.DoAction(ACTION_START_PHASE_4, EntryCheckPredicate(NPC_PARASITIC_SHADOWFIEND)); +                me->SetReactState(REACT_PASSIVE); +                me->AttackStop(); +                me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); +                events.ScheduleEvent(EVENT_SHADOW_PRISON_TEXT, Milliseconds(500), GROUP_PHASE_ALL); +                break; +            case ACTION_ILLIDAN_CAGED: +                for (uint32 summonSpell : SummonCageTrapSpells) +                    DoCastSelf(summonSpell, true); +                DoCastSelf(SPELL_CAGE_TRAP, true); +                break; +            case ACTION_START_OUTRO: +                me->AttackStop(); +                events.Reset(); +                specialEvents.Reset(); +                DoCastSelf(SPELL_DEATH, true); +                me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); +                events.ScheduleEvent(EVENT_DEFEATED_TEXT, Seconds(4)); +                break; +            default: +                break;          } +    } + +    void JustDied(Unit* /*killer*/) override +    { +        me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); +        instance->SetBossState(DATA_ILLIDAN_STORMRAGE, DONE); +        events.Reset(); +    } + +    void MovementInform(uint32 type, uint32 pointId) override +    { +        if (type != POINT_MOTION_TYPE && type != EFFECT_MOTION_TYPE) +            return; -        void EnterCombat(Unit* /*who*/) override +        switch (pointId)          { -            _EnterCombat(); -            me->SetCanDualWield(true); -            if (GameObject* musicController = instance->GetGameObject(DATA_ILLIDAN_MUSIC_CONTROLLER)) -                musicController->PlayDirectMusic(EVENT_BT_SUMMIT_WALK_3_SOUND_ID); -            specialEvents.ScheduleEvent(EVENT_EVADE_CHECK, Seconds(10)); -            specialEvents.ScheduleEvent(EVENT_BERSERK, Minutes(25)); -            ScheduleEvents(GROUP_PHASE_1, GROUP_PHASE_1); -            events.ScheduleEvent(EVENT_TAUNT, Seconds(30), Seconds(60), GROUP_PHASE_ALL); +            case POINT_THROW_GLAIVE: +                DoPlaySoundToSet(me, ILLIDAN_WARGLAIVE_SOUND_ID); +                events.ScheduleEvent(EVENT_THROW_WARGLAIVE, Seconds(2), GROUP_PHASE_ALL); +                events.ScheduleEvent(EVENT_FACE_MIDDLE, Milliseconds(1), GROUP_PHASE_ALL); +                break; +            case POINT_RANDOM_PILLAR: +            { +                float orientation = IllidanPhase2Positions[_pillarIndex].GetOrientation(); +                ChangeOrientation(orientation); +                ScheduleEvents(GROUP_PHASE_2, GROUP_PHASE_2); +                break; +            } +            case POINT_ILLIDAN_MIDDLE: +            { +                float orientation = IllidanMiddlePoint.GetOrientation(); +                ChangeOrientation(orientation); + +                std::list<Creature*> triggers; +                GetCreatureListWithEntryInGrid(triggers, me, NPC_BLADE_OF_AZZINOTH, 150.0f); +                for (Creature* trigger : triggers) +                    trigger->CastSpell(trigger, SPELL_GLAIVE_RETURNS, true); + +                events.ScheduleEvent(EVENT_GLAIVE_EMOTE, Seconds(3), GROUP_PHASE_ALL); +                break; +            } +            default: +                break;          } +    } -        void ChangeOrientation(float orientation) +    void EnterEvadeModeIfNeeded() +    { +        Map::PlayerList const& players = me->GetMap()->GetPlayers(); +        for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) +            if (Player* player = i->GetSource()) +                if (player->IsAlive() && !player->IsGameMaster() && CheckBoundary(player)) +                    return; + +        EnterEvadeMode(EVADE_REASON_NO_HOSTILES); +    } + +    void SummonMinions() +    { +        uint8 needSummon = MAX_MINIONS_NUMBER - _minionsCount; +        for (uint8 i = 0; i < needSummon; ++i)          { -            _orientation = orientation; -            events.ScheduleEvent(EVENT_CHANGE_ORIENTATION, Milliseconds(1), GROUP_PHASE_ALL); +            _minionsCount++; +            me->SummonCreature(NPC_ILLIDARI_ELITE, MinionsSpawnPositions[i], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 6000);          } +    } -        void KilledUnit(Unit* victim) override +    void DamageTaken(Unit* who, uint32 &damage) override +    { + +        if (damage >= me->GetHealth() && who->GetGUID() != me->GetGUID())          { -            if (victim->GetTypeId() == TYPEID_PLAYER) -                Talk(SAY_ILLIDAN_KILL); +            damage = me->GetHealth() - 1; +            if (!_dead) +            { +                if (_isDemon) +                { +                    events.Reset(); +                    specialEvents.Reset(); +                    DoCastSelf(SPELL_DEMON_TRANSFORM_1); +                    return; +                } +                _dead = true; +                summons.DespawnEntry(NPC_PARASITIC_SHADOWFIEND); +                DoCastSelf(SPELL_REMOVE_PARASITIC_SHADOWFIEND, true); +                DoAction(ACTION_START_OUTRO); +                if (Creature* maiev = instance->GetCreature(DATA_MAIEV)) +                    maiev->AI()->DoAction(ACTION_START_OUTRO); +            } +        } +        else if (me->HealthBelowPct(90) && _phase < PHASE_MINIONS) +        { +            _phase = PHASE_MINIONS; +            DoAction(ACTION_START_MINIONS); +        } +        else if (me->HealthBelowPct(65) && _phase < PHASE_2) +        { +            _phase = PHASE_2; +            DoAction(ACTION_START_PHASE_2); +        } +        else if (me->HealthBelowPct(30) && _phase < PHASE_4) +        { +            _phase = PHASE_4; + +            if (_isDemon) +            { +                _isDemon = false; +                me->SetControlled(false, UNIT_STATE_ROOT); +                events.CancelEventGroup(GROUP_PHASE_DEMON); +                me->InterruptNonMeleeSpells(false); +                DoCastSelf(SPELL_DEMON_TRANSFORM_1, true); +                events.ScheduleEvent(EVENT_PHASE_4_DELAYED, Seconds(12), GROUP_PHASE_ALL); +            } +            else +                DoAction(ACTION_START_PHASE_4);          } +    } -        void ScheduleEvents(uint8 phase, uint8 group) +    void ExecuteSpecialEvents() +    { +        while (uint32 eventId = specialEvents.ExecuteEvent())          { -            switch (phase) +            switch (eventId)              { -                case GROUP_PHASE_1: -                    events.ScheduleEvent(EVENT_FLAME_CRASH, Seconds(30), group); -                    events.ScheduleEvent(EVENT_DRAW_SOUL, Seconds(34), group); -                    events.ScheduleEvent(EVENT_SHEAR, Seconds(10), group); -                    events.ScheduleEvent(EVENT_PARASITIC_SHADOWFIEND, Seconds(26), group); -                    break; -                case GROUP_PHASE_2: -                    events.ScheduleEvent(EVENT_FIREBALL, Seconds(1), Seconds(8), group); -                    events.ScheduleEvent(EVENT_EYE_BLAST, Seconds(1), Seconds(30), group); -                    if (roll_chance_i(50)) -                        events.ScheduleEvent(EVENT_DARK_BARRAGE, Seconds(1), Seconds(20), group); -                    break; -                case GROUP_PHASE_3: -                    ScheduleEvents(GROUP_PHASE_1, group); -                    events.ScheduleEvent(EVENT_AGONIZING_FLAMES, Seconds(21), group); -                    events.ScheduleEvent(EVENT_DEMON, Seconds(60), group); -                    break; -                case GROUP_PHASE_DEMON: -                    events.ScheduleEvent(EVENT_SHADOW_BLAST, Seconds(1), group); -                    events.ScheduleEvent(EVENT_FLAME_BURST, Seconds(6), group); -                    events.ScheduleEvent(EVENT_SHADOW_DEMON, Seconds(18), Seconds(30), group); -                    break; -                case GROUP_PHASE_4: -                    ScheduleEvents(GROUP_PHASE_3, group); -                    events.ScheduleEvent(EVENT_FRENZY, Seconds(40), group); +                case EVENT_BERSERK: +                    Talk(SAY_ILLIDAN_ENRAGE); +                    DoCastSelf(SPELL_BERSERK, true); +                    break; +                case EVENT_CANCEL_DEMON_FORM: +                    me->InterruptNonMeleeSpells(false); +                    me->SetControlled(false, UNIT_STATE_ROOT); +                    events.CancelEventGroup(GROUP_PHASE_DEMON); +                    DoCastSelf(SPELL_DEMON_TRANSFORM_1, true); +                    events.ScheduleEvent(EVENT_RESUME_COMBAT_DEMON, Seconds(12), GROUP_PHASE_ALL); +                    _isDemon = false; +                    break; +                case EVENT_EVADE_CHECK: +                    EnterEvadeModeIfNeeded(); +                    specialEvents.Repeat(Seconds(10));                      break;                  default:                      break;              }          } +    } -        void JustSummoned(Creature* summon) override -        { -            BossAI::JustSummoned(summon); -            if (summon->GetEntry() == NPC_ILLIDARI_ELITE) -                if (Creature* akama = instance->GetCreature(DATA_AKAMA)) -                    AddThreat(akama, 1000.0f, summon); -        } +    void UpdateAI(uint32 diff) override +    { +        if (!UpdateVictim() && !events.IsInPhase(PHASE_INTRO)) +            return; -        void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override -        { -            if (summon->GetEntry() == NPC_ILLIDARI_ELITE) -                _minionsCount--; -        } +        specialEvents.Update(diff); -        void EnterEvadeMode(EvadeReason /*why*/) override -        { -            summons.DespawnAll(); -            specialEvents.Reset(); -            _DespawnAtEvade(); -        } +        ExecuteSpecialEvents(); + +        if (me->HasUnitState(UNIT_STATE_CASTING)) +            return; -        void DoAction(int32 actionId) override +        events.Update(diff); + +        while (uint32 eventId = events.ExecuteEvent())          { -            switch (actionId) +            switch (eventId)              { -                case ACTION_START_ENCOUNTER: -                    events.SetPhase(PHASE_INTRO); -                    me->RemoveAurasDueToSpell(SPELL_KNEEL); -                    events.ScheduleEvent(EVENT_START_INTRO, Seconds(2), GROUP_PHASE_ALL); -                    events.ScheduleEvent(EVENT_UNCONVINCED, Seconds(24), GROUP_PHASE_ALL); -                    if (Creature* akama = instance->GetCreature(DATA_AKAMA)) -                        akama->AI()->DoAction(ACTION_FREE); +                case EVENT_START_INTRO: +                    Talk(SAY_ILLIDAN_DUPLICITY);                      break; -                case ACTION_INTRO_DONE: -                    instance->SetData(DATA_AKAMA_ILLIDAN_INTRO, 0); +                case EVENT_UNCONVINCED: +                    Talk(SAY_ILLIDAN_UNCONVINCED); +                    events.ScheduleEvent(EVENT_PREPARED, Seconds(14), GROUP_PHASE_ALL);                      break; -                case ACTION_START_MINIONS: -                    Talk(SAY_ILLIDAN_MINION); +                case EVENT_PREPARED: +                    Talk(SAY_ILLIDAN_PREPARED); +                    me->SetSheath(SHEATH_STATE_MELEE); +                    events.ScheduleEvent(EVENT_ENCOUNTER_START, Seconds(3), GROUP_PHASE_ALL); +                    break; +                case EVENT_ENCOUNTER_START: +                    me->SetImmuneToAll(false); +                    DoZoneInCombat();                      if (Creature* akama = instance->GetCreature(DATA_AKAMA)) -                        akama->AI()->DoAction(ACTION_START_MINIONS); +                        akama->AI()->DoAction(ACTION_START_ENCOUNTER);                      break; -                case ACTION_START_MINIONS_WEAVE: -                    events.ScheduleEvent(EVENT_MINIONS_WEAVE, Milliseconds(1), GROUP_PHASE_ALL); +                case EVENT_FLAME_CRASH: +                    DoCastVictim(SPELL_FLAME_CRASH); +                    events.Repeat(Seconds(30));                      break; -                case ACTION_START_PHASE_2: -                { -                    me->SetReactState(REACT_PASSIVE); -                    me->AttackStop(); -                    me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); -                    me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); -                    me->SetDisableGravity(true); -                    DoPlaySoundToSet(me, ILLIDAN_TAKEOFF_SOUND_ID); -                    events.ScheduleEvent(EVENT_FLY, Seconds(1), GROUP_PHASE_ALL); -                    events.CancelEventGroup(GROUP_PHASE_1); +                case EVENT_DRAW_SOUL: +                    DoCastAOE(SPELL_DRAW_SOUL); +                    events.Repeat(Seconds(34));                      break; -                } -                case ACTION_FLAME_DEAD: -                    _flameCount++; -                    if (_flameCount == 2) -                    { -                        _flameCount = 0; -                        DoAction(ACTION_FINALIZE_AIR_PHASE); -                    } +                case EVENT_SHEAR: +                    DoCastVictim(SPELL_SHEAR); +                    events.Repeat(Seconds(12));                      break; -                case ACTION_FINALIZE_AIR_PHASE: -                    me->InterruptNonMeleeSpells(false); -                    me->GetMotionMaster()->Clear(); -                    events.CancelEventGroup(GROUP_PHASE_2); -                    _phase = PHASE_3; -                    events.CancelEvent(EVENT_FLY_TO_RANDOM_PILLAR); -                    me->GetMotionMaster()->MovePoint(POINT_ILLIDAN_MIDDLE, IllidanMiddlePoint); +                case EVENT_PARASITIC_SHADOWFIEND: +                    if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) +                        DoCast(target, SPELL_PARASITIC_SHADOWFIEND); +                    events.Repeat(Seconds(30));                      break; -                case ACTION_START_PHASE_4: -                    events.CancelEventGroup(GROUP_PHASE_3); -                    DoCastSelf(SPELL_SHADOW_PRISON, true); -                    me->SetReactState(REACT_PASSIVE); -                    me->AttackStop(); -                    me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); -                    events.ScheduleEvent(EVENT_SHADOW_PRISON_TEXT, Milliseconds(500), GROUP_PHASE_ALL); +                case EVENT_MINIONS_WEAVE: +                    if (_dead) +                        return; +                    SummonMinions(); +                    events.Repeat(Seconds(30));                      break; -                case ACTION_ILLIDAN_CAGED: -                    for (uint32 summonSpell : SummonCageTrapSpells) -                        DoCastSelf(summonSpell, true); -                    DoCastSelf(SPELL_CAGE_TRAP, true); +                case EVENT_MOVE_TO_WARGLAIVE_POINT: +                { +                    Position pos; +                    std::list<Creature*> triggers; +                    GetCreatureListWithEntryInGrid(triggers, me, NPC_GLAIVE_WORLD_TRIGGER, 150.0f); +                    triggers.remove_if([](WorldObject* unit) +                    { +                        return unit->GetPositionZ() < 355.0f || unit->GetPositionZ() > 365.0f; +                    }); + +                    if (triggers.empty()) +                        break; + +                    triggers.sort(Trinity::ObjectDistanceOrderPred(me)); +                    pos.Relocate(triggers.front()); +                    pos.SetOrientation(0.0f); +                    me->GetMotionMaster()->MovePoint(POINT_THROW_GLAIVE, pos); +                    if (GameObject* musicController = instance->GetGameObject(DATA_ILLIDAN_MUSIC_CONTROLLER)) +                        musicController->PlayDirectMusic(EVENT_BT_STORM_WALK_HERO_2_SOUND_ID);                      break; -                case ACTION_START_OUTRO: -                    me->AttackStop(); -                    events.Reset(); -                    specialEvents.Reset(); -                    DoCastSelf(SPELL_DEATH, true); -                    me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); -                    events.ScheduleEvent(EVENT_DEFEATED_TEXT, Seconds(4)); +                } +                case EVENT_THROW_WARGLAIVE: +                    DoCastAOE(SPELL_THROW_GLAIVE); +                    events.ScheduleEvent(EVENT_THROW_WARGLAIVE_2, Seconds(1), GROUP_PHASE_ALL);                      break; -                default: +                case EVENT_THROW_WARGLAIVE_2: +                    DoCastAOE(SPELL_THROW_GLAIVE2); +                    me->SetSheath(SHEATH_STATE_UNARMED); +                    events.ScheduleEvent(EVENT_FLY_TO_RANDOM_PILLAR, Seconds(2), GROUP_PHASE_ALL);                      break; -            } -        } - -        void JustDied(Unit* /*killer*/) override -        { -            me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); -            instance->SetBossState(DATA_ILLIDAN_STORMRAGE, DONE); -            events.Reset(); -        } - -        void MovementInform(uint32 type, uint32 pointId) override -        { -            if (type != POINT_MOTION_TYPE && type != EFFECT_MOTION_TYPE) -                return; - -            switch (pointId) -            { -                case POINT_THROW_GLAIVE: -                    DoPlaySoundToSet(me, ILLIDAN_WARGLAIVE_SOUND_ID); -                    events.ScheduleEvent(EVENT_THROW_WARGLAIVE, Seconds(2), GROUP_PHASE_ALL); -                    events.ScheduleEvent(EVENT_FACE_MIDDLE, Milliseconds(1), GROUP_PHASE_ALL); +                case EVENT_CHANGE_ORIENTATION: +                    me->SetFacingTo(_orientation); +                    break; +                case EVENT_FLY: +                    ChangeOrientation(3.137039f); +                    events.ScheduleEvent(EVENT_MOVE_TO_WARGLAIVE_POINT, Seconds(6), GROUP_PHASE_ALL);                      break; -                case POINT_RANDOM_PILLAR: +                case EVENT_FLY_TO_RANDOM_PILLAR:                  { -                    float orientation = IllidanPhase2Positions[_pillarIndex].GetOrientation(); -                    ChangeOrientation(orientation); -                    ScheduleEvents(GROUP_PHASE_2, GROUP_PHASE_2); +                    events.CancelEventGroup(GROUP_PHASE_2); +                    _pillarIndex = urand(0, 3); +                    me->GetMotionMaster()->MovePoint(POINT_RANDOM_PILLAR, IllidanPhase2Positions[_pillarIndex]); +                    events.Repeat(Seconds(30));                      break;                  } -                case POINT_ILLIDAN_MIDDLE: +                case EVENT_FACE_MIDDLE:                  { -                    float orientation = IllidanMiddlePoint.GetOrientation(); -                    ChangeOrientation(orientation); - -                    std::list<Creature*> triggers; -                    GetCreatureListWithEntryInGrid(triggers, me, NPC_BLADE_OF_AZZINOTH, 150.0f); -                    for (Creature* trigger : triggers) -                        trigger->CastSpell(trigger, SPELL_GLAIVE_RETURNS, true); - -                    events.ScheduleEvent(EVENT_GLAIVE_EMOTE, Seconds(3), GROUP_PHASE_ALL); +                    float angle = me->GetAngle(IllidanMiddlePoint); +                    me->SetFacingTo(angle);                      break;                  } -                default: -                    break; -            } -        } - -        void EnterEvadeModeIfNeeded() -        { -            Map::PlayerList const& players = me->GetMap()->GetPlayers(); -            for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) -                if (Player* player = i->GetSource()) -                    if (player->IsAlive() && !player->IsGameMaster() && CheckBoundary(player)) -                        return; - -            EnterEvadeMode(EVADE_REASON_NO_HOSTILES); -        } - -        void SummonMinions() -        { -            uint8 needSummon = MAX_MINIONS_NUMBER - _minionsCount; -            for (uint8 i = 0; i < needSummon; ++i) -            { -                _minionsCount++; -                me->SummonCreature(NPC_ILLIDARI_ELITE, MinionsSpawnPositions[i], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 6000); -            } -        } - -        void DamageTaken(Unit* who, uint32 &damage) override -        { - -            if (damage >= me->GetHealth() && who->GetGUID() != me->GetGUID()) -            { -                damage = me->GetHealth() - 1; -                if (!_dead) +                case EVENT_EYE_BLAST:                  { -                    if (_isDemon) +                    events.CancelEvent(EVENT_DARK_BARRAGE); +                    Position pos = IllidanDBTargetSpawnPositions[_pillarIndex]; +                    if (TempSummon* dbTarget = me->SummonCreature(NPC_ILLIDAN_DB_TARGET, pos, TEMPSUMMON_MANUAL_DESPAWN))                      { -                        events.Reset(); -                        specialEvents.Reset(); -                        DoCastSelf(SPELL_DEMON_TRANSFORM_1); -                        return; +                        Talk(SAY_ILLIDAN_EYE_BLAST); +                        DoCast(dbTarget, SPELL_EYE_BLAST); +                        dbTarget->GetMotionMaster()->MovePoint(POINT_DB_TARGET, IllidanDBTargetPoints[_pillarIndex]);                      } -                    _dead = true; -                    DoAction(ACTION_START_OUTRO); -                    if (Creature* maiev = instance->GetCreature(DATA_MAIEV)) -                        maiev->AI()->DoAction(ACTION_START_OUTRO); +                    break;                  } -            } -            else if (me->HealthBelowPct(90) && _phase < PHASE_MINIONS) -            { -                _phase = PHASE_MINIONS; -                DoAction(ACTION_START_MINIONS); -            } -            else if (me->HealthBelowPct(65) && _phase < PHASE_2) -            { -                _phase = PHASE_2; -                DoAction(ACTION_START_PHASE_2); -            } -            else if (me->HealthBelowPct(30) && _phase < PHASE_4) -            { -                _phase = PHASE_4; - -                if (_isDemon) +                case EVENT_DARK_BARRAGE:                  { -                    _isDemon = false; -                    me->SetControlled(false, UNIT_STATE_ROOT); -                    events.CancelEventGroup(GROUP_PHASE_DEMON); -                    me->InterruptNonMeleeSpells(false); +                    if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 150.0f, true)) +                        DoCast(target, SPELL_DARK_BARRAGE); +                    events.RescheduleEvent(EVENT_EYE_BLAST, Seconds(5), GROUP_PHASE_2); +                    uint32 currentTime = events.GetNextEventTime(EVENT_FLY_TO_RANDOM_PILLAR); +                    events.RescheduleEvent(EVENT_FLY_TO_RANDOM_PILLAR, Seconds(currentTime) + Seconds(30), GROUP_PHASE_2); +                    break; +                } +                case EVENT_FIREBALL: +                    if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 150.0f, true)) +                        DoCast(target, SPELL_FIREBALL); +                    events.Repeat(Seconds(2), Seconds(4)); +                    break; +                case EVENT_GLAIVE_EMOTE: +                    me->SetDisableGravity(false); +                    me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); +                    me->SetSheath(SHEATH_STATE_MELEE); +                    events.ScheduleEvent(EVENT_RESUME_COMBAT, Seconds(3), GROUP_PHASE_ALL); +                    break; +                case EVENT_RESUME_COMBAT: +                    me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); +                    me->SetReactState(REACT_AGGRESSIVE); +                    ScheduleEvents(GROUP_PHASE_3, GROUP_PHASE_3); +                    if (GameObject* musicController = instance->GetGameObject(DATA_ILLIDAN_MUSIC_CONTROLLER)) +                        musicController->PlayDirectMusic(EVENT_BT_STORM_WALK_UNI_3_SOUND_ID); +                    break; +                case EVENT_AGONIZING_FLAMES: +                    DoCastSelf(SPELL_AGONIZING_FLAMES_SELECTOR); +                    events.Repeat(Seconds(53)); +                    break; +                case EVENT_DEMON: +                    me->SetControlled(true, UNIT_STATE_ROOT); +                    _isDemon = true; +                    events.CancelEventGroup(_phase == PHASE_3 ? GROUP_PHASE_3 : GROUP_PHASE_4); +                    me->LoadEquipment(0, true);                      DoCastSelf(SPELL_DEMON_TRANSFORM_1, true); -                    events.ScheduleEvent(EVENT_PHASE_4_DELAYED, Seconds(12), GROUP_PHASE_ALL); +                    events.ScheduleEvent(EVENT_DEMON_TEXT, Seconds(2), GROUP_PHASE_ALL); +                    specialEvents.ScheduleEvent(EVENT_CANCEL_DEMON_FORM, Minutes(1) + Seconds(12)); +                    events.ScheduleEvent(EVENT_SCHEDULE_DEMON_SPELLS, Seconds(15)); +                    break; +                case EVENT_SCHEDULE_DEMON_SPELLS: +                    ResetThreatList(); +                    ScheduleEvents(GROUP_PHASE_DEMON, GROUP_PHASE_DEMON); +                    break; +                case EVENT_DEMON_TEXT: +                    Talk(SAY_ILLIDAN_MORPH); +                    break; +                case EVENT_RESUME_COMBAT_DEMON: +                { +                    uint8 group = _phase == PHASE_3 ? GROUP_PHASE_3 : GROUP_PHASE_4; +                    ResetThreatList(); +                    ScheduleEvents(group, group); +                    me->LoadEquipment(1, true); +                    break;                  } -                else +                case EVENT_FLAME_BURST: +                    DoCastSelf(SPELL_FLAME_BURST); +                    events.Repeat(Seconds(22)); +                    break; +                case EVENT_SHADOW_DEMON: +                    DoCastSelf(SPELL_SUMMON_SHADOWDEMON); +                    break; +                case EVENT_SHADOW_BLAST: +                    DoCastVictim(SPELL_SHADOW_BLAST); +                    events.Repeat(Seconds(2)); +                    break; +                case EVENT_PHASE_4_DELAYED:                      DoAction(ACTION_START_PHASE_4); -            } -        } - -        void ExecuteSpecialEvents() -        { -            while (uint32 eventId = specialEvents.ExecuteEvent()) -            { -                switch (eventId) +                    break; +                case EVENT_SHADOW_PRISON_TEXT: +                    Talk(SAY_ILLIDAN_SHADOW_PRISON); +                    events.ScheduleEvent(EVENT_SUMMON_MAIEV, Seconds(9), GROUP_PHASE_ALL); +                    break; +                case EVENT_SUMMON_MAIEV: +                    DoCastSelf(SPELL_SUMMON_MAIEV); +                    if (Creature* maiev = instance->GetCreature(DATA_MAIEV)) +                        me->SetFacingToObject(maiev); +                    events.ScheduleEvent(EVENT_CONFRONT_MAIEV_TEXT, Seconds(9), GROUP_PHASE_ALL); +                    break; +                case EVENT_CONFRONT_MAIEV_TEXT: +                    Talk(SAY_ILLIDAN_CONFRONT_MAIEV); +                    events.ScheduleEvent(EVENT_RESUME_COMBAT_PHASE_4, Seconds(13), GROUP_PHASE_ALL); +                    break; +                case EVENT_RESUME_COMBAT_PHASE_4: +                    me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); +                    me->SetReactState(REACT_AGGRESSIVE); +                    ScheduleEvents(GROUP_PHASE_4, GROUP_PHASE_4); +                    summons.DoAction(ACTION_RESUME_COMBAT, EntryCheckPredicate(NPC_PARASITIC_SHADOWFIEND)); +                    break; +                case EVENT_FRENZY: +                    DoCastSelf(SPELL_FRENZY); +                    Talk(SAY_ILLIDAN_FRENZY); +                    events.Repeat(Seconds(40)); +                    break; +                case EVENT_TAUNT: +                    Talk(SAY_ILLIDAN_TAUNT); +                    events.Repeat(Seconds(30), Seconds(60)); +                    break; +                case EVENT_DEFEATED_TEXT: +                    Talk(SAY_ILLIDAN_DEFEATED); +                    if (GameObject* musicController = instance->GetGameObject(DATA_ILLIDAN_MUSIC_CONTROLLER)) +                        musicController->PlayDirectMusic(EVENT_BT_ARRIVAL_WALK_HERO_1_SOUND_ID); +                    events.ScheduleEvent(EVENT_QUIET_SUICIDE, Seconds(18)); +                    break; +                case EVENT_QUIET_SUICIDE:                  { -                    case EVENT_BERSERK: -                        Talk(SAY_ILLIDAN_ENRAGE); -                        DoCastSelf(SPELL_BERSERK, true); -                        break; -                    case EVENT_CANCEL_DEMON_FORM: -                        me->InterruptNonMeleeSpells(false); -                        me->SetControlled(false, UNIT_STATE_ROOT); -                        events.CancelEventGroup(GROUP_PHASE_DEMON); -                        DoCastSelf(SPELL_DEMON_TRANSFORM_1, true); -                        events.ScheduleEvent(EVENT_RESUME_COMBAT_DEMON, Seconds(12), GROUP_PHASE_ALL); -                        _isDemon = false; -                        break; -                    case EVENT_EVADE_CHECK: -                        EnterEvadeModeIfNeeded(); -                        specialEvents.Repeat(Seconds(10)); -                        break; -                    default: -                        break; +                    DoCastSelf(SPELL_QUIET_SUICIDE, true); +                    if (Creature* akama = instance->GetCreature(DATA_AKAMA)) +                        akama->AI()->DoAction(ACTION_START_OUTRO); +                    ObjectGuid _akamaGUID = instance->GetGuidData(DATA_AKAMA); +                    ObjectGuid _maievGUID = instance->GetGuidData(DATA_MAIEV); +                    summons.DespawnIf([_akamaGUID, _maievGUID](ObjectGuid unitGuid) +                    { +                        return unitGuid != _akamaGUID && unitGuid != _maievGUID; +                    }); +                    break;                  } +                default: +                    break;              } -        } - -        void UpdateAI(uint32 diff) override -        { -            if (!UpdateVictim() && !events.IsInPhase(PHASE_INTRO)) -                return; - -            specialEvents.Update(diff); - -            ExecuteSpecialEvents();              if (me->HasUnitState(UNIT_STATE_CASTING))                  return; +        } -            events.Update(diff); +        DoMeleeAttackIfReady(); +    } -            while (uint32 eventId = events.ExecuteEvent()) -            { -                switch (eventId) -                { -                    case EVENT_START_INTRO: -                        Talk(SAY_ILLIDAN_DUPLICITY); -                        break; -                    case EVENT_UNCONVINCED: -                        Talk(SAY_ILLIDAN_UNCONVINCED); -                        events.ScheduleEvent(EVENT_PREPARED, Seconds(14), GROUP_PHASE_ALL); -                        break; -                    case EVENT_PREPARED: -                        Talk(SAY_ILLIDAN_PREPARED); -                        me->SetSheath(SHEATH_STATE_MELEE); -                        events.ScheduleEvent(EVENT_ENCOUNTER_START, Seconds(3), GROUP_PHASE_ALL); -                        break; -                    case EVENT_ENCOUNTER_START: -                        me->SetImmuneToAll(false); -                        DoZoneInCombat(); -                        if (Creature* akama = instance->GetCreature(DATA_AKAMA)) -                            akama->AI()->DoAction(ACTION_START_ENCOUNTER); -                        break; -                    case EVENT_FLAME_CRASH: -                        DoCastVictim(SPELL_FLAME_CRASH); -                        events.Repeat(Seconds(30)); -                        break; -                    case EVENT_DRAW_SOUL: -                        DoCastAOE(SPELL_DRAW_SOUL); -                        events.Repeat(Seconds(34)); -                        break; -                    case EVENT_SHEAR: -                        DoCastVictim(SPELL_SHEAR); -                        events.Repeat(Seconds(12)); -                        break; -                    case EVENT_PARASITIC_SHADOWFIEND: -                        if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) -                            DoCast(target, SPELL_PARASITIC_SHADOWFIEND); -                        events.Repeat(Seconds(30)); -                        break; -                    case EVENT_MINIONS_WEAVE: -                        SummonMinions(); -                        events.Repeat(Seconds(30)); -                        break; -                    case EVENT_MOVE_TO_WARGLAIVE_POINT: -                    { -                        Position pos; -                        std::list<Creature*> triggers; -                        GetCreatureListWithEntryInGrid(triggers, me, NPC_GLAIVE_WORLD_TRIGGER, 150.0f); -                        triggers.remove_if([](WorldObject* unit) -                        { -                            return unit->GetPositionZ() < 355.0f || unit->GetPositionZ() > 365.0f; -                        }); +private: +    uint8 _minionsCount; +    uint8 _flameCount; +    float _orientation; +    uint8 _pillarIndex; +    uint8 _phase; +    bool _dead; +    bool _isDemon; +    EventMap specialEvents; +}; -                        if (triggers.empty()) -                            break; +struct npc_akama_illidan : public ScriptedAI +{ +    npc_akama_illidan(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), +        _orientation(0.0f), _isTeleportToMinions(false) { } -                        triggers.sort(Trinity::ObjectDistanceOrderPred(me)); -                        pos.Relocate(triggers.front()); -                        pos.SetOrientation(0.0f); -                        me->GetMotionMaster()->MovePoint(POINT_THROW_GLAIVE, pos); -                        if (GameObject* musicController = instance->GetGameObject(DATA_ILLIDAN_MUSIC_CONTROLLER)) -                            musicController->PlayDirectMusic(EVENT_BT_STORM_WALK_HERO_2_SOUND_ID); -                        break; -                    } -                    case EVENT_THROW_WARGLAIVE: -                        DoCastAOE(SPELL_THROW_GLAIVE); -                        events.ScheduleEvent(EVENT_THROW_WARGLAIVE_2, Seconds(1), GROUP_PHASE_ALL); -                        break; -                    case EVENT_THROW_WARGLAIVE_2: -                        DoCastAOE(SPELL_THROW_GLAIVE2); -                        me->SetSheath(SHEATH_STATE_UNARMED); -                        events.ScheduleEvent(EVENT_FLY_TO_RANDOM_PILLAR, Seconds(2), GROUP_PHASE_ALL); -                        break; -                    case EVENT_CHANGE_ORIENTATION: -                        me->SetFacingTo(_orientation); -                        break; -                    case EVENT_FLY: -                        ChangeOrientation(3.137039f); -                        events.ScheduleEvent(EVENT_MOVE_TO_WARGLAIVE_POINT, Seconds(6), GROUP_PHASE_ALL); -                        break; -                    case EVENT_FLY_TO_RANDOM_PILLAR: -                    { -                        events.CancelEventGroup(GROUP_PHASE_2); -                        _pillarIndex = urand(0, 3); -                        me->GetMotionMaster()->MovePoint(POINT_RANDOM_PILLAR, IllidanPhase2Positions[_pillarIndex]); -                        events.Repeat(Seconds(30)); -                        break; -                    } -                    case EVENT_FACE_MIDDLE: -                    { -                        float angle = me->GetAngle(IllidanMiddlePoint); -                        me->SetFacingTo(angle); -                        break; -                    } -                    case EVENT_EYE_BLAST: -                    { -                        events.CancelEvent(EVENT_DARK_BARRAGE); -                        Position pos = IllidanDBTargetSpawnPositions[_pillarIndex]; -                        if (TempSummon* dbTarget = me->SummonCreature(NPC_ILLIDAN_DB_TARGET, pos, TEMPSUMMON_MANUAL_DESPAWN)) -                        { -                            Talk(SAY_ILLIDAN_EYE_BLAST); -                            DoCast(dbTarget, SPELL_EYE_BLAST); -                            dbTarget->GetMotionMaster()->MovePoint(POINT_DB_TARGET, IllidanDBTargetPoints[_pillarIndex]); -                        } -                        break; -                    } -                    case EVENT_DARK_BARRAGE: -                    { -                        if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 150.0f, true)) -                            DoCast(target, SPELL_DARK_BARRAGE); -                        events.RescheduleEvent(EVENT_EYE_BLAST, Seconds(5), GROUP_PHASE_2); -                        uint32 currentTime = events.GetNextEventTime(EVENT_FLY_TO_RANDOM_PILLAR); -                        events.RescheduleEvent(EVENT_FLY_TO_RANDOM_PILLAR, Seconds(currentTime) + Seconds(30), GROUP_PHASE_2); -                        break; -                    } -                    case EVENT_FIREBALL: -                        if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 150.0f, true)) -                            DoCast(target, SPELL_FIREBALL); -                        events.Repeat(Seconds(2), Seconds(4)); -                        break; -                    case EVENT_GLAIVE_EMOTE: -                        me->SetDisableGravity(false); -                        me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); -                        me->SetSheath(SHEATH_STATE_MELEE); -                        events.ScheduleEvent(EVENT_RESUME_COMBAT, Seconds(3), GROUP_PHASE_ALL); -                        break; -                    case EVENT_RESUME_COMBAT: -                        me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); -                        me->SetReactState(REACT_AGGRESSIVE); -                        ScheduleEvents(GROUP_PHASE_3, GROUP_PHASE_3); -                        if (GameObject* musicController = instance->GetGameObject(DATA_ILLIDAN_MUSIC_CONTROLLER)) -                            musicController->PlayDirectMusic(EVENT_BT_STORM_WALK_UNI_3_SOUND_ID); -                        break; -                    case EVENT_AGONIZING_FLAMES: -                        DoCastSelf(SPELL_AGONIZING_FLAMES_SELECTOR); -                        events.Repeat(Seconds(53)); -                        break; -                    case EVENT_DEMON: -                        me->SetControlled(true, UNIT_STATE_ROOT); -                        _isDemon = true; -                        events.CancelEventGroup(_phase == PHASE_3 ? GROUP_PHASE_3 : GROUP_PHASE_4); -                        me->LoadEquipment(0, true); -                        DoCastSelf(SPELL_DEMON_TRANSFORM_1, true); -                        events.ScheduleEvent(EVENT_DEMON_TEXT, Seconds(2), GROUP_PHASE_ALL); -                        specialEvents.ScheduleEvent(EVENT_CANCEL_DEMON_FORM, Minutes(1) + Seconds(12)); -                        events.ScheduleEvent(EVENT_SCHEDULE_DEMON_SPELLS, Seconds(15)); -                        break; -                    case EVENT_SCHEDULE_DEMON_SPELLS: -                        ResetThreatList(); -                        ScheduleEvents(GROUP_PHASE_DEMON, GROUP_PHASE_DEMON); -                        break; -                    case EVENT_DEMON_TEXT: -                        Talk(SAY_ILLIDAN_MORPH); -                        break; -                    case EVENT_RESUME_COMBAT_DEMON: -                    { -                        uint8 group = _phase == PHASE_3 ? GROUP_PHASE_3 : GROUP_PHASE_4; -                        ResetThreatList(); -                        ScheduleEvents(group, group); -                        me->LoadEquipment(1, true); -                        break; -                    } -                    case EVENT_FLAME_BURST: -                        DoCastSelf(SPELL_FLAME_BURST); -                        events.Repeat(Seconds(22)); -                        break; -                    case EVENT_SHADOW_DEMON: -                        DoCastSelf(SPELL_SUMMON_SHADOWDEMON); -                        break; -                    case EVENT_SHADOW_BLAST: -                        DoCastVictim(SPELL_SHADOW_BLAST); -                        events.Repeat(Seconds(2)); -                        break; -                    case EVENT_PHASE_4_DELAYED: -                        DoAction(ACTION_START_PHASE_4); -                        break; -                    case EVENT_SHADOW_PRISON_TEXT: -                        Talk(SAY_ILLIDAN_SHADOW_PRISON); -                        events.ScheduleEvent(EVENT_SUMMON_MAIEV, Seconds(9), GROUP_PHASE_ALL); -                        break; -                    case EVENT_SUMMON_MAIEV: -                        DoCastSelf(SPELL_SUMMON_MAIEV); -                        if (Creature* maiev = instance->GetCreature(DATA_MAIEV)) -                            me->SetFacingToObject(maiev); -                        events.ScheduleEvent(EVENT_CONFRONT_MAIEV_TEXT, Seconds(9), GROUP_PHASE_ALL); -                        break; -                    case EVENT_CONFRONT_MAIEV_TEXT: -                        Talk(SAY_ILLIDAN_CONFRONT_MAIEV); -                        events.ScheduleEvent(EVENT_RESUME_COMBAT_PHASE_4, Seconds(13), GROUP_PHASE_ALL); -                        break; -                    case EVENT_RESUME_COMBAT_PHASE_4: -                        me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); -                        me->SetReactState(REACT_AGGRESSIVE); -                        ScheduleEvents(GROUP_PHASE_4, GROUP_PHASE_4); -                        break; -                    case EVENT_FRENZY: -                        DoCastSelf(SPELL_FRENZY); -                        Talk(SAY_ILLIDAN_FRENZY); -                        events.Repeat(Seconds(40)); -                        break; -                    case EVENT_TAUNT: -                        Talk(SAY_ILLIDAN_TAUNT); -                        events.Repeat(Seconds(30), Seconds(60)); -                        break; -                    case EVENT_DEFEATED_TEXT: -                        Talk(SAY_ILLIDAN_DEFEATED); -                        if (GameObject* musicController = instance->GetGameObject(DATA_ILLIDAN_MUSIC_CONTROLLER)) -                            musicController->PlayDirectMusic(EVENT_BT_ARRIVAL_WALK_HERO_1_SOUND_ID); -                        events.ScheduleEvent(EVENT_QUIET_SUICIDE, Seconds(18)); -                        break; -                    case EVENT_QUIET_SUICIDE: -                    { -                        DoCastSelf(SPELL_QUIET_SUICIDE, true); -                        if (Creature* akama = instance->GetCreature(DATA_AKAMA)) -                            akama->AI()->DoAction(ACTION_START_OUTRO); -                        ObjectGuid _akamaGUID = instance->GetGuidData(DATA_AKAMA); -                        ObjectGuid _maievGUID = instance->GetGuidData(DATA_MAIEV); -                        summons.DespawnIf([_akamaGUID, _maievGUID](ObjectGuid unitGuid) -                        { -                            return unitGuid != _akamaGUID && unitGuid != _maievGUID; -                        }); -                        break; -                    } -                    default: -                        break; -                } +    void Reset() override +    { +        _events.Reset(); +        _spiritOfUdaloGUID.Clear(); +        _spiritOfOlumGUID.Clear(); +        _isTeleportToMinions = false; +    } -                if (me->HasUnitState(UNIT_STATE_CASTING)) -                    return; -            } +    bool GossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override +    { +        if (gossipListId == GOSSIP_START_INTRO) +        { +            _instance->SetData(DATA_AKAMA, AKAMA_FIGHT); +            me->GetMotionMaster()->MoveAlongSplineChain(POINT_STAIRS, SPLINE_STAIRS, false); +            me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); +            if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE)) +                illidan->AI()->DoAction(ACTION_INTRO_DONE); +            CloseGossipMenuFor(player); -            DoMeleeAttackIfReady();          } +        else if (gossipListId == GOSSIP_START_FIGHT) +        { +            _events.SetPhase(PHASE_INTRO); +            me->GetMotionMaster()->MoveAlongSplineChain(POINT_FACE_ILLIDAN, SPLINE_FACE_ILLIDAN, false); +            me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); +            CloseGossipMenuFor(player); +        } +        return false; +    } -    private: -        uint8 _minionsCount; -        uint8 _flameCount; -        float _orientation; -        uint8 _pillarIndex; -        uint8 _phase; -        bool _dead; -        bool _isDemon; -        EventMap specialEvents; -    }; +    bool CanAIAttack(Unit const* who) const override +    { +        if (_events.IsInPhase(PHASE_MINIONS) && who->GetEntry() == NPC_ILLIDAN_STORMRAGE) +            return false; +        return ScriptedAI::CanAIAttack(who); +    } -    CreatureAI* GetAI(Creature* creature) const override +    uint32 GetData(uint32 /*data*/) const override      { -        return GetBlackTempleAI<boss_illidan_stormrageAI>(creature); +        return _isTeleportToMinions ? 1 : 0;      } -}; -class npc_akama : public CreatureScript -{ -public: -    npc_akama() : CreatureScript("npc_akama_illidan") { } +    void EnterEvadeMode(EvadeReason /*why*/) override { } -    struct npc_akamaAI : public ScriptedAI +    void JustSummoned(Creature* summon) override      { -        npc_akamaAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _orientation(0.0f), _isTeleportToMinions(false) { } - -        void Reset() override +        if (summon->GetEntry() == NPC_SPIRIT_OF_UDALO)          { -            _events.Reset(); -            _spiritOfUdaloGUID.Clear(); -            _spiritOfOlumGUID.Clear(); -            _isTeleportToMinions = false; +            _spiritOfUdaloGUID = summon->GetGUID(); +            summon->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);          } - -        bool GossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override +        else if (summon->GetEntry() == NPC_SPIRIT_OF_OLUM)          { -            if (gossipListId == GOSSIP_START_INTRO) -            { -                _instance->SetData(DATA_AKAMA, AKAMA_FIGHT); -                me->GetMotionMaster()->MoveAlongSplineChain(POINT_STAIRS, SPLINE_STAIRS, false); -                me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); -                if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE)) -                    illidan->AI()->DoAction(ACTION_INTRO_DONE); -                CloseGossipMenuFor(player); +            _spiritOfOlumGUID = summon->GetGUID(); +            summon->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); +        } +    } -            } -            else if (gossipListId == GOSSIP_START_FIGHT) -            { +    void DoAction(int32 actionId) override +    { +        switch (actionId) +        { +            case ACTION_ACTIVE_AKAMA_INTRO:                  _events.SetPhase(PHASE_INTRO); -                me->GetMotionMaster()->MoveAlongSplineChain(POINT_FACE_ILLIDAN, SPLINE_FACE_ILLIDAN, false);                  me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); -                CloseGossipMenuFor(player); -            } -            return false; +                _events.SetPhase(PHASE_INTRO); +                _events.ScheduleEvent(EVENT_TELEPORT, Seconds(1)); +                _events.ScheduleEvent(EVENT_MOVE_TO_ILLIDARI_ROOM, Seconds(1) + Milliseconds(500)); +                break; +            case ACTION_OPEN_DOOR: +                _instance->SetData(ACTION_OPEN_DOOR, 0); +                _events.ScheduleEvent(EVENT_AKAMA_THANKS, Seconds(2)); +                break; +            case ACTION_FREE: +                _events.ScheduleEvent(EVENT_FREE, Seconds(14)); +                break; +            case ACTION_START_ENCOUNTER: +                DoZoneInCombat(); +                _events.ScheduleEvent(EVENT_HEALING_POTION, Seconds(1)); +                break; +            case ACTION_START_MINIONS: +                _events.ScheduleEvent(EVENT_AKAMA_MINIONS, Seconds(8)); +                break; +            case ACTION_START_OUTRO: +                me->SetReactState(REACT_PASSIVE); +                me->AttackStop(); +                _events.Reset(); +                _events.ScheduleEvent(EVENT_AKAMA_MOVE_BACK, Seconds(2)); +                break; +            default: +                break;          } +    } -        bool CanAIAttack(Unit const* who) const override -        { -            if (_events.IsInPhase(PHASE_MINIONS) && who->GetEntry() == NPC_ILLIDAN_STORMRAGE) -                return false; -            return ScriptedAI::CanAIAttack(who); -        } +    void ChangeOrientation(float orientation) +    { +        _orientation = orientation; +        _events.ScheduleEvent(EVENT_CHANGE_ORIENTATION, Milliseconds(1)); +    } -        uint32 GetData(uint32 /*data*/) const override -        { -            return _isTeleportToMinions ? 1 : 0; +    void MovementInform(uint32 type, uint32 pointId) override +    { +        if (type != POINT_MOTION_TYPE && type != SPLINE_CHAIN_MOTION_TYPE) +            return; + +        switch (pointId) +        { +            case POINT_ILLIDARI_COUNCIL: +                Talk(SAY_AKAMA_FINISH); +                me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); +                break; +            case POINT_STAIRS: +                ChangeOrientation(6.265732f); +                _events.ScheduleEvent(EVENT_AKAMA_SAY_DOOR, Seconds(5)); +                break; +            case POINT_ILLIDAN_ROOM: +                ChangeOrientation(2.129302f); +                Talk(SAY_AKAMA_BETRAYER); +                me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); +                break; +            case POINT_FACE_ILLIDAN: +                ChangeOrientation(3.140537f); +                _events.ScheduleEvent(EVENT_START_ILLIDAN, Seconds(2)); +                break; +            case POINT_TELEPORT: +                DoCastSelf(SPELL_AKAMA_TELEPORT); +                _events.ScheduleEvent(EVENT_AKAMA_MINIONS_MOVE_2, Milliseconds(500)); +                break; +            case POINT_MINIONS: +                _events.SetPhase(PHASE_MINIONS); +                me->SetImmuneToNPC(false); +                me->SetReactState(REACT_AGGRESSIVE); +                if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE)) +                    illidan->AI()->DoAction(ACTION_START_MINIONS_WEAVE); +                _events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, Seconds(2)); +                break; +            case POINT_MOVE_BACK: +                _events.ScheduleEvent(EVENT_AKAMA_MOVE_TO_ILLIDAN, Milliseconds(1)); +                break; +            case POINT_ILLIDAN: +                _events.ScheduleEvent(EVENT_AKAMA_LIGHT_TEXT, Seconds(1)); +                break; +            default: +                break;          } +    } -        void EnterEvadeMode(EvadeReason /*why*/) override { } +    void DamageTaken(Unit* /*who*/, uint32 &damage) override +    { +        if (damage >= me->GetHealth()) +            damage = me->GetHealth() - 1; +    } -        void JustSummoned(Creature* summon) override -        { -            if (summon->GetEntry() == NPC_SPIRIT_OF_UDALO) -            { -                _spiritOfUdaloGUID = summon->GetGUID(); -                summon->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); -            } -            else if (summon->GetEntry() == NPC_SPIRIT_OF_OLUM) -            { -                _spiritOfOlumGUID = summon->GetGUID(); -                summon->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); -            } -        } +    void UpdateAI(uint32 diff) override +    { +        if (!UpdateVictim() && !_events.IsInPhase(PHASE_INTRO)) +            return; + +        _events.Update(diff); + +        if (me->HasUnitState(UNIT_STATE_CASTING)) +            return; -        void DoAction(int32 actionId) override +        while (uint32 eventId = _events.ExecuteEvent())          { -            switch (actionId) +            switch (eventId)              { -                case ACTION_ACTIVE_AKAMA_INTRO: -                    _events.SetPhase(PHASE_INTRO); -                    me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); -                    _events.SetPhase(PHASE_INTRO); -                    _events.ScheduleEvent(EVENT_TELEPORT, Seconds(1)); -                    _events.ScheduleEvent(EVENT_MOVE_TO_ILLIDARI_ROOM, Seconds(1) + Milliseconds(500)); +                case EVENT_TELEPORT: +                    DoCastSelf(SPELL_AKAMA_TELEPORT, true);                      break; -                case ACTION_OPEN_DOOR: -                    _instance->SetData(ACTION_OPEN_DOOR, 0); -                    _events.ScheduleEvent(EVENT_AKAMA_THANKS, Seconds(2)); +                case EVENT_MOVE_TO_ILLIDARI_ROOM: +                    me->GetMotionMaster()->MoveAlongSplineChain(POINT_ILLIDARI_COUNCIL, SPLINE_ILLIDARI_COUNCIL, false);                      break; -                case ACTION_FREE: -                    _events.ScheduleEvent(EVENT_FREE, Seconds(14)); +                case EVENT_AKAMA_SAY_DOOR: +                    Talk(SAY_AKAMA_DOOR); +                    _events.ScheduleEvent(EVENT_AKAMA_DOOR_FAIL, Seconds(4));                      break; -                case ACTION_START_ENCOUNTER: -                    DoZoneInCombat(); -                    _events.ScheduleEvent(EVENT_HEALING_POTION, Seconds(1)); +                case EVENT_AKAMA_DOOR_FAIL: +                    DoCastSelf(SPELL_AKAMA_DOOR_FAIL); +                    _events.ScheduleEvent(EVENT_AKAMA_SAY_ALONE, Seconds(10)); +                    break; +                case EVENT_AKAMA_SAY_ALONE: +                    Talk(SAY_AKAMA_ALONE); +                    _events.ScheduleEvent(EVENT_SUMMON_SPIRITS, Seconds(7)); +                    break; +                case EVENT_SUMMON_SPIRITS: +                    me->SummonCreatureGroup(SUMMON_GROUP); +                    _events.ScheduleEvent(EVENT_SPIRIT_SAY_1, Seconds(1)); +                    break; +                case EVENT_SPIRIT_SAY_1: +                    if (Creature* undalo = ObjectAccessor::GetCreature(*me, _spiritOfUdaloGUID)) +                        undalo->AI()->Talk(SAY_SPIRIT_ALONE); +                    _events.ScheduleEvent(EVENT_SPIRIT_SAY_2, Seconds(6)); +                    break; +                case EVENT_SPIRIT_SAY_2: +                    if (Creature* olum = ObjectAccessor::GetCreature(*me, _spiritOfOlumGUID)) +                        olum->AI()->Talk(SAY_SPIRIT_ALONE); +                    _events.ScheduleEvent(EVENT_AKAMA_DOOR_SUCCESS, Seconds(6)); +                    break; +                case EVENT_AKAMA_DOOR_SUCCESS: +                    DoCastSelf(SPELL_AKAMA_DOOR_CHANNEL); +                    if (Creature* undalo = ObjectAccessor::GetCreature(*me, _spiritOfUdaloGUID)) +                        undalo->CastSpell((Unit*) nullptr, SPELL_DEATHSWORN_DOOR_CHANNEL); +                    if (Creature* olum = ObjectAccessor::GetCreature(*me, _spiritOfOlumGUID)) +                        olum->CastSpell((Unit*) nullptr, SPELL_DEATHSWORN_DOOR_CHANNEL); +                    _events.ScheduleEvent(EVENT_AKAMA_START_SOUND, Seconds(5)); +                    break; +                case EVENT_AKAMA_START_SOUND: +                    if (GameObject* musicController = _instance->GetGameObject(DATA_ILLIDAN_MUSIC_CONTROLLER)) +                        musicController->PlayDirectMusic(EVENT_BT_SUMMIT_WALK_SOUND_ID);                      break; -                case ACTION_START_MINIONS: -                    _events.ScheduleEvent(EVENT_AKAMA_MINIONS, Seconds(8)); +                case EVENT_AKAMA_THANKS: +                    Talk(SAY_AKAMA_SALUTE); +                    _events.ScheduleEvent(EVENT_SPIRIT_SALUTE, Seconds(3)); +                    _events.ScheduleEvent(EVENT_RUN_FROM_ILLIDAN_ROOM, Seconds(7));                      break; -                case ACTION_START_OUTRO: +                case EVENT_SPIRIT_SALUTE: +                    if (Creature* undalo = ObjectAccessor::GetCreature(*me, _spiritOfUdaloGUID)) +                    { +                        undalo->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE); +                        undalo->DespawnOrUnsummon(Seconds(7)); +                    } +                    if (Creature* olum = ObjectAccessor::GetCreature(*me, _spiritOfOlumGUID)) +                    { +                        olum->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE); +                        olum->DespawnOrUnsummon(Seconds(7)); +                    } +                    break; +                case EVENT_RUN_FROM_ILLIDAN_ROOM: +                    me->GetMotionMaster()->MoveAlongSplineChain(POINT_ILLIDAN_ROOM, SPLINE_ILLIDAN_ROOM, false); +                    break; +                case EVENT_START_ILLIDAN: +                    if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE)) +                        illidan->AI()->DoAction(ACTION_START_ENCOUNTER); +                    break; +                case EVENT_FREE: +                    Talk(SAY_AKAMA_FREE); +                    _events.ScheduleEvent(EVENT_TIME_HAS_COME, Seconds(18)); +                    break; +                case EVENT_TIME_HAS_COME: +                    Talk(SAY_AKAMA_TIME_HAS_COME); +                    _events.ScheduleEvent(EVENT_ROAR, Seconds(2)); +                    break; +                case EVENT_ROAR: +                    me->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); +                    me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY1H); +                    break; +                case EVENT_CHANGE_ORIENTATION: +                    me->SetFacingTo(_orientation); +                    break; +                case EVENT_HEALING_POTION: +                    if (me->HealthBelowPct(20)) +                        DoCastSelf(SPELL_HEALING_POTION); +                    _events.Repeat(Seconds(1)); +                    break; +                case EVENT_AKAMA_MINIONS: +                    Talk(SAY_AKAMA_MINIONS); +                    _events.ScheduleEvent(EVENT_AKAMA_MINIONS_EMOTE, Seconds(2)); +                    break; +                case EVENT_AKAMA_MINIONS_EMOTE:                      me->SetReactState(REACT_PASSIVE);                      me->AttackStop(); -                    _events.Reset(); -                    _events.ScheduleEvent(EVENT_AKAMA_MOVE_BACK, Seconds(2)); +                    me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); +                    me->SetImmuneToNPC(true); +                    _events.ScheduleEvent(EVENT_AKAMA_MINIONS_MOVE, Seconds(4));                      break; -                default: +                case EVENT_AKAMA_MINIONS_MOVE: +                    _isTeleportToMinions = true; +                    me->GetMotionMaster()->MoveAlongSplineChain(POINT_TELEPORT, SPLINE_TELEPORT, false);                      break; -            } -        } - -        void ChangeOrientation(float orientation) -        { -            _orientation = orientation; -            _events.ScheduleEvent(EVENT_CHANGE_ORIENTATION, Milliseconds(1)); -        } - -        void MovementInform(uint32 type, uint32 pointId) override -        { -            if (type != POINT_MOTION_TYPE && type != SPLINE_CHAIN_MOTION_TYPE) -                return; - -            switch (pointId) -            { -                case POINT_ILLIDARI_COUNCIL: -                    Talk(SAY_AKAMA_FINISH); -                    me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); -                    break; -                case POINT_STAIRS: -                    ChangeOrientation(6.265732f); -                    _events.ScheduleEvent(EVENT_AKAMA_SAY_DOOR, Seconds(5)); -                    break; -                case POINT_ILLIDAN_ROOM: -                    ChangeOrientation(2.129302f); -                    Talk(SAY_AKAMA_BETRAYER); -                    me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); -                    break; -                case POINT_FACE_ILLIDAN: -                    ChangeOrientation(3.140537f); -                    _events.ScheduleEvent(EVENT_START_ILLIDAN, Seconds(2)); -                    break; -                case POINT_TELEPORT: -                    DoCastSelf(SPELL_AKAMA_TELEPORT); -                    _events.ScheduleEvent(EVENT_AKAMA_MINIONS_MOVE_2, Milliseconds(500)); -                    break; -                case POINT_MINIONS: -                    _events.SetPhase(PHASE_MINIONS); -                    me->SetImmuneToNPC(false); -                    me->SetReactState(REACT_AGGRESSIVE); +                case EVENT_AKAMA_MINIONS_MOVE_2: +                    me->GetMotionMaster()->MoveAlongSplineChain(POINT_MINIONS, SPLINE_MINIONS, false); +                    break; +                case EVENT_CHAIN_LIGHTNING: +                    DoCastVictim(SPELL_CHAIN_LIGHTNING); +                    _events.Repeat(Seconds(8) + Milliseconds(500)); +                    break; +                case EVENT_AKAMA_MOVE_BACK: +                    me->GetMotionMaster()->MoveAlongSplineChain(POINT_MOVE_BACK, SPLINE_MOVE_BACK, false); +                    break; +                case EVENT_AKAMA_MOVE_TO_ILLIDAN:                      if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE)) -                        illidan->AI()->DoAction(ACTION_START_MINIONS_WEAVE); -                    _events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, Seconds(2)); +                        me->GetMotionMaster()->MoveCloserAndStop(POINT_ILLIDAN, illidan, 5.0f); +                    break; +                case EVENT_AKAMA_LIGHT_TEXT: +                    Talk(SAY_AKAMA_LIGHT); +                    _events.ScheduleEvent(EVENT_FINAL_SALUTE, Seconds(4));                      break; -                case POINT_MOVE_BACK: -                    _events.ScheduleEvent(EVENT_AKAMA_MOVE_TO_ILLIDAN, Milliseconds(1)); +                case EVENT_FINAL_SALUTE: +                    me->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE); +                    _events.ScheduleEvent(EVENT_AKAMA_DESPAWN, Seconds(5));                      break; -                case POINT_ILLIDAN: -                    _events.ScheduleEvent(EVENT_AKAMA_LIGHT_TEXT, Seconds(1)); +                case EVENT_AKAMA_DESPAWN: +                    DoCastSelf(SPELL_AKAMA_DESPAWN, true);                      break;                  default:                      break;              } -        } - -        void DamageTaken(Unit* /*who*/, uint32 &damage) override -        { -            if (damage >= me->GetHealth()) -                damage = me->GetHealth() - 1; -        } - -        void UpdateAI(uint32 diff) override -        { -            if (!UpdateVictim() && !_events.IsInPhase(PHASE_INTRO)) -                return; - -            _events.Update(diff);              if (me->HasUnitState(UNIT_STATE_CASTING))                  return; - -            while (uint32 eventId = _events.ExecuteEvent()) -            { -                switch (eventId) -                { -                    case EVENT_TELEPORT: -                        DoCastSelf(SPELL_AKAMA_TELEPORT, true); -                        break; -                    case EVENT_MOVE_TO_ILLIDARI_ROOM: -                        me->GetMotionMaster()->MoveAlongSplineChain(POINT_ILLIDARI_COUNCIL, SPLINE_ILLIDARI_COUNCIL, false); -                        break; -                    case EVENT_AKAMA_SAY_DOOR: -                        Talk(SAY_AKAMA_DOOR); -                        _events.ScheduleEvent(EVENT_AKAMA_DOOR_FAIL, Seconds(4)); -                        break; -                    case EVENT_AKAMA_DOOR_FAIL: -                        DoCastSelf(SPELL_AKAMA_DOOR_FAIL); -                        _events.ScheduleEvent(EVENT_AKAMA_SAY_ALONE, Seconds(10)); -                        break; -                    case EVENT_AKAMA_SAY_ALONE: -                        Talk(SAY_AKAMA_ALONE); -                        _events.ScheduleEvent(EVENT_SUMMON_SPIRITS, Seconds(7)); -                        break; -                    case EVENT_SUMMON_SPIRITS: -                        me->SummonCreatureGroup(SUMMON_GROUP); -                        _events.ScheduleEvent(EVENT_SPIRIT_SAY_1, Seconds(1)); -                        break; -                    case EVENT_SPIRIT_SAY_1: -                        if (Creature* undalo = ObjectAccessor::GetCreature(*me, _spiritOfUdaloGUID)) -                            undalo->AI()->Talk(SAY_SPIRIT_ALONE); -                        _events.ScheduleEvent(EVENT_SPIRIT_SAY_2, Seconds(6)); -                        break; -                    case EVENT_SPIRIT_SAY_2: -                        if (Creature* olum = ObjectAccessor::GetCreature(*me, _spiritOfOlumGUID)) -                            olum->AI()->Talk(SAY_SPIRIT_ALONE); -                        _events.ScheduleEvent(EVENT_AKAMA_DOOR_SUCCESS, Seconds(6)); -                        break; -                    case EVENT_AKAMA_DOOR_SUCCESS: -                        DoCastSelf(SPELL_AKAMA_DOOR_CHANNEL); -                        if (Creature* undalo = ObjectAccessor::GetCreature(*me, _spiritOfUdaloGUID)) -                            undalo->CastSpell((Unit*) nullptr, SPELL_DEATHSWORN_DOOR_CHANNEL); -                        if (Creature* olum = ObjectAccessor::GetCreature(*me, _spiritOfOlumGUID)) -                            olum->CastSpell((Unit*) nullptr, SPELL_DEATHSWORN_DOOR_CHANNEL); -                        _events.ScheduleEvent(EVENT_AKAMA_START_SOUND, Seconds(5)); -                        break; -                    case EVENT_AKAMA_START_SOUND: -                        if (GameObject* musicController = _instance->GetGameObject(DATA_ILLIDAN_MUSIC_CONTROLLER)) -                            musicController->PlayDirectMusic(EVENT_BT_SUMMIT_WALK_SOUND_ID); -                        break; -                    case EVENT_AKAMA_THANKS: -                        Talk(SAY_AKAMA_SALUTE); -                        _events.ScheduleEvent(EVENT_SPIRIT_SALUTE, Seconds(3)); -                        _events.ScheduleEvent(EVENT_RUN_FROM_ILLIDAN_ROOM, Seconds(7)); -                        break; -                    case EVENT_SPIRIT_SALUTE: -                        if (Creature* undalo = ObjectAccessor::GetCreature(*me, _spiritOfUdaloGUID)) -                        { -                            undalo->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE); -                            undalo->DespawnOrUnsummon(Seconds(7)); -                        } -                        if (Creature* olum = ObjectAccessor::GetCreature(*me, _spiritOfOlumGUID)) -                        { -                            olum->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE); -                            olum->DespawnOrUnsummon(Seconds(7)); -                        } -                        break; -                    case EVENT_RUN_FROM_ILLIDAN_ROOM: -                        me->GetMotionMaster()->MoveAlongSplineChain(POINT_ILLIDAN_ROOM, SPLINE_ILLIDAN_ROOM, false); -                        break; -                    case EVENT_START_ILLIDAN: -                        if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE)) -                            illidan->AI()->DoAction(ACTION_START_ENCOUNTER); -                        break; -                    case EVENT_FREE: -                        Talk(SAY_AKAMA_FREE); -                        _events.ScheduleEvent(EVENT_TIME_HAS_COME, Seconds(18)); -                        break; -                    case EVENT_TIME_HAS_COME: -                        Talk(SAY_AKAMA_TIME_HAS_COME); -                        _events.ScheduleEvent(EVENT_ROAR, Seconds(2)); -                        break; -                    case EVENT_ROAR: -                        me->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); -                        me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY1H); -                        break; -                    case EVENT_CHANGE_ORIENTATION: -                        me->SetFacingTo(_orientation); -                        break; -                    case EVENT_HEALING_POTION: -                        if (me->HealthBelowPct(20)) -                            DoCastSelf(SPELL_HEALING_POTION); -                        _events.Repeat(Seconds(1)); -                        break; -                    case EVENT_AKAMA_MINIONS: -                        Talk(SAY_AKAMA_MINIONS); -                        _events.ScheduleEvent(EVENT_AKAMA_MINIONS_EMOTE, Seconds(2)); -                        break; -                    case EVENT_AKAMA_MINIONS_EMOTE: -                        me->SetReactState(REACT_PASSIVE); -                        me->AttackStop(); -                        me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); -                        me->SetImmuneToNPC(true); -                        _events.ScheduleEvent(EVENT_AKAMA_MINIONS_MOVE, Seconds(4)); -                        break; -                    case EVENT_AKAMA_MINIONS_MOVE: -                        _isTeleportToMinions = true; -                        me->GetMotionMaster()->MoveAlongSplineChain(POINT_TELEPORT, SPLINE_TELEPORT, false); -                        break; -                    case EVENT_AKAMA_MINIONS_MOVE_2: -                        me->GetMotionMaster()->MoveAlongSplineChain(POINT_MINIONS, SPLINE_MINIONS, false); -                        break; -                    case EVENT_CHAIN_LIGHTNING: -                        DoCastVictim(SPELL_CHAIN_LIGHTNING); -                        _events.Repeat(Seconds(8) + Milliseconds(500)); -                        break; -                    case EVENT_AKAMA_MOVE_BACK: -                        me->GetMotionMaster()->MoveAlongSplineChain(POINT_MOVE_BACK, SPLINE_MOVE_BACK, false); -                        break; -                    case EVENT_AKAMA_MOVE_TO_ILLIDAN: -                        if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE)) -                            me->GetMotionMaster()->MoveCloserAndStop(POINT_ILLIDAN, illidan, 5.0f); -                        break; -                    case EVENT_AKAMA_LIGHT_TEXT: -                        Talk(SAY_AKAMA_LIGHT); -                        _events.ScheduleEvent(EVENT_FINAL_SALUTE, Seconds(4)); -                        break; -                    case EVENT_FINAL_SALUTE: -                        me->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE); -                        _events.ScheduleEvent(EVENT_AKAMA_DESPAWN, Seconds(5)); -                        break; -                    case EVENT_AKAMA_DESPAWN: -                        DoCastSelf(SPELL_AKAMA_DESPAWN, true); -                        break; -                    default: -                        break; -                } - -                if (me->HasUnitState(UNIT_STATE_CASTING)) -                    return; -            } - -            DoMeleeAttackIfReady();          } -    private: -        InstanceScript* _instance; -        EventMap _events; -        ObjectGuid _spiritOfUdaloGUID; -        ObjectGuid _spiritOfOlumGUID; -        float _orientation; -        bool _isTeleportToMinions; -    }; - -    CreatureAI* GetAI(Creature* creature) const override -    { -        return GetBlackTempleAI<npc_akamaAI>(creature); +        DoMeleeAttackIfReady();      } + +private: +    InstanceScript* _instance; +    EventMap _events; +    ObjectGuid _spiritOfUdaloGUID; +    ObjectGuid _spiritOfOlumGUID; +    float _orientation; +    bool _isTeleportToMinions;  }; -class npc_parasitic_shadowfiend : public CreatureScript +struct npc_parasitic_shadowfiend : public ScriptedAI  { -public: -    npc_parasitic_shadowfiend() : CreatureScript("npc_parasitic_shadowfiend") { } +    npc_parasitic_shadowfiend(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } -    struct npc_parasitic_shadowfiendAI : public ScriptedAI +    void Reset() override      { -        npc_parasitic_shadowfiendAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } +        if (_instance->GetBossState(DATA_ILLIDAN_STORMRAGE) != IN_PROGRESS) +        { +            me->DespawnOrUnsummon(); +            return; +        } -        void Reset() override +        if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE)) +            illidan->AI()->JustSummoned(me); +        me->SetReactState(REACT_DEFENSIVE); +        _scheduler.Schedule(Seconds(2), [this](TaskContext /*context*/)          { -            if (_instance->GetBossState(DATA_ILLIDAN_STORMRAGE) != IN_PROGRESS) -            { -                me->DespawnOrUnsummon(); -                return; -            } +            me->SetReactState(REACT_AGGRESSIVE); +            me->SetInCombatWithZone(); +        }); +    } -            if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE)) -                illidan->AI()->JustSummoned(me); -            me->SetReactState(REACT_DEFENSIVE); +    void DoAction(int32 action) override +    { +        if (action == ACTION_START_PHASE_4) +        { +            me->SetReactState(REACT_PASSIVE); +            me->AttackStop(); +        } +        else if (action == ACTION_RESUME_COMBAT)              _scheduler.Schedule(Seconds(2), [this](TaskContext /*context*/)              {                  me->SetReactState(REACT_AGGRESSIVE);                  me->SetInCombatWithZone();              }); -        } - -        void UpdateAI(uint32 diff) override -        { -            if (!UpdateVictim()) -                return; - -            if (me->HasUnitState(UNIT_STATE_CASTING)) -                return; +    } -            _scheduler.Update(diff, [this] -            { -                DoMeleeAttackIfReady(); -            }); -        } +    void UpdateAI(uint32 diff) override +    { +        _scheduler.Update(diff); -    private: -        InstanceScript* _instance; -        TaskScheduler _scheduler; -    }; +        if (!UpdateVictim()) +            return; -    CreatureAI* GetAI(Creature* creature) const override -    { -        return GetBlackTempleAI<npc_parasitic_shadowfiendAI>(creature); +        DoMeleeAttackIfReady();      } + +private: +    InstanceScript* _instance; +    TaskScheduler _scheduler;  }; -class npc_blade_of_azzinoth : public CreatureScript +struct npc_blade_of_azzinoth : public NullCreatureAI  { -public: -    npc_blade_of_azzinoth() : CreatureScript("npc_blade_of_azzinoth") { } +    npc_blade_of_azzinoth(Creature* creature) : NullCreatureAI(creature), _instance(creature->GetInstanceScript()) { } -    struct npc_blade_of_azzinothAI : public NullCreatureAI +    void Reset() override      { -        npc_blade_of_azzinothAI(Creature* creature) : NullCreatureAI(creature), _instance(creature->GetInstanceScript()) { } - -        void Reset() override -        { -            if (_instance->GetBossState(DATA_ILLIDAN_STORMRAGE) != IN_PROGRESS) -            { -                me->DespawnOrUnsummon(); -                return; -            } - -            if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE)) -                illidan->AI()->JustSummoned(me); -            _flameGuid.Clear(); -            me->PlayDirectSound(WARGLAIVE_SPAWN_SOUND_ID); -            DoCastSelf(SPELL_BIRTH, true); -            _scheduler.Schedule(Seconds(3), [this](TaskContext /*context*/) -            { -                DoCastSelf(SPELL_SUMMON_TEAR_OF_AZZINOTH); -                _scheduler.Schedule(Milliseconds(500), [this](TaskContext /*context*/) -                { -                    if (Creature* flame = ObjectAccessor::GetCreature(*me, _flameGuid)) -                        DoCast(flame, SPELL_AZZINOTH_CHANNEL); -                }); -            }); -        } - -        void JustSummoned(Creature* summon) override +        if (_instance->GetBossState(DATA_ILLIDAN_STORMRAGE) != IN_PROGRESS)          { -            if (summon->GetEntry() == NPC_FLAME_OF_AZZINOTH) -                _flameGuid = summon->GetGUID(); +            me->DespawnOrUnsummon(); +            return;          } -        void UpdateAI(uint32 diff) override +        if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE)) +            illidan->AI()->JustSummoned(me); +        _flameGuid.Clear(); +        me->PlayDirectSound(WARGLAIVE_SPAWN_SOUND_ID); +        DoCastSelf(SPELL_BIRTH, true); +        _scheduler.Schedule(Seconds(3), [this](TaskContext /*context*/)          { -            _scheduler.Update(diff); -        } +            DoCastSelf(SPELL_SUMMON_TEAR_OF_AZZINOTH); +            _scheduler.Schedule(Milliseconds(500), [this](TaskContext /*context*/) +            { +                if (Creature* flame = ObjectAccessor::GetCreature(*me, _flameGuid)) +                    DoCast(flame, SPELL_AZZINOTH_CHANNEL); +            }); +        }); +    } -    private: -        InstanceScript* _instance; -        TaskScheduler _scheduler; -        ObjectGuid _flameGuid; -    }; +    void JustSummoned(Creature* summon) override +    { +        if (summon->GetEntry() == NPC_FLAME_OF_AZZINOTH) +            _flameGuid = summon->GetGUID(); +    } -    CreatureAI* GetAI(Creature* creature) const override +    void UpdateAI(uint32 diff) override      { -        return GetBlackTempleAI<npc_blade_of_azzinothAI>(creature); +        _scheduler.Update(diff);      } + +private: +    InstanceScript* _instance; +    TaskScheduler _scheduler; +    ObjectGuid _flameGuid;  }; -class npc_flame_of_azzinoth : public CreatureScript +struct npc_flame_of_azzinoth : public ScriptedAI  { -public: -    npc_flame_of_azzinoth() : CreatureScript("npc_flame_of_azzinoth") { } +    npc_flame_of_azzinoth(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) +    { +        SetBoundary(_instance->GetBossBoundary(DATA_ILLIDAN_STORMRAGE)); +    } -    struct npc_flame_of_azzinothAI : public ScriptedAI +    void Reset() override      { -        npc_flame_of_azzinothAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) +        if (_instance->GetBossState(DATA_ILLIDAN_STORMRAGE) != IN_PROGRESS)          { -            SetBoundary(_instance->GetBossBoundary(DATA_ILLIDAN_STORMRAGE)); +            me->DespawnOrUnsummon(); +            return;          } -        void Reset() override -        { -            if (_instance->GetBossState(DATA_ILLIDAN_STORMRAGE) != IN_PROGRESS) -            { -                me->DespawnOrUnsummon(); -                return; -            } +        if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE)) +            illidan->AI()->JustSummoned(me); +        DoCastSelf(SPELL_FLAME_TEAR_OF_AZZINOTH, true); // Idk what this spell should do +        me->SetReactState(REACT_PASSIVE); +        _events.ScheduleEvent(EVENT_ENGAGE, Seconds(3)); +        _events.ScheduleEvent(EVENT_FLAME_BLAST, Seconds(11)); +    } -            if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE)) -                illidan->AI()->JustSummoned(me); -            DoCastSelf(SPELL_FLAME_TEAR_OF_AZZINOTH, true); // Idk what this spell should do -            me->SetReactState(REACT_PASSIVE); -            _events.ScheduleEvent(EVENT_ENGAGE, Seconds(3)); -            _events.ScheduleEvent(EVENT_FLAME_BLAST, Seconds(11)); -        } +    void UpdateAI(uint32 diff) override +    { +        if (!UpdateVictim()) +            return; -        void UpdateAI(uint32 diff) override -        { -            if (!UpdateVictim()) -                return; +        if (me->HasUnitState(UNIT_STATE_CASTING)) +            return; -            if (me->HasUnitState(UNIT_STATE_CASTING)) -                return; - -            _events.Update(diff); +        _events.Update(diff); -            while (uint32 eventId = _events.ExecuteEvent()) +        while (uint32 eventId = _events.ExecuteEvent()) +        { +            switch (eventId)              { -                switch (eventId) -                { -                    case EVENT_ENGAGE: -                        me->SetReactState(REACT_AGGRESSIVE); -                        me->SetInCombatWithZone(); -                        _events.ScheduleEvent(EVENT_FLAME_CHARGE, Seconds(5)); -                        break; -                    case EVENT_FLAME_CHARGE: -                        if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, ChargeTargetSelector(me))) -                        { -                            DoCast(target, SPELL_CHARGE); -                            _events.Repeat(Seconds(5)); -                        } -                        else -                            _events.Repeat(Seconds(1)); -                        break; -                    case EVENT_FLAME_BLAST: -                        DoCastAOE(SPELL_FLAME_BLAST); -                        _events.Repeat(Seconds(12)); -                        break; -                    default: -                        break; -                } - -                if (me->HasUnitState(UNIT_STATE_CASTING)) -                    return; +                case EVENT_ENGAGE: +                    me->SetReactState(REACT_AGGRESSIVE); +                    me->SetInCombatWithZone(); +                    _events.ScheduleEvent(EVENT_FLAME_CHARGE, Seconds(5)); +                    break; +                case EVENT_FLAME_CHARGE: +                    if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, ChargeTargetSelector(me))) +                    { +                        DoCast(target, SPELL_CHARGE); +                        _events.Repeat(Seconds(5)); +                    } +                    else +                        _events.Repeat(Seconds(1)); +                    break; +                case EVENT_FLAME_BLAST: +                    DoCastAOE(SPELL_FLAME_BLAST); +                    _events.Repeat(Seconds(12)); +                    break; +                default: +                    break;              } -            DoMeleeAttackIfReady(); -        } - -        void JustDied(Unit* /*killer*/) override -        { -            if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE)) -                illidan->AI()->DoAction(ACTION_FLAME_DEAD); +            if (me->HasUnitState(UNIT_STATE_CASTING)) +                return;          } -    private: -        InstanceScript* _instance; -        EventMap _events; -    }; +        DoMeleeAttackIfReady(); +    } -    CreatureAI* GetAI(Creature* creature) const override +    void JustDied(Unit* /*killer*/) override      { -        return GetBlackTempleAI<npc_flame_of_azzinothAI>(creature); +        if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE)) +            illidan->AI()->DoAction(ACTION_FLAME_DEAD);      } + +private: +    InstanceScript* _instance; +    EventMap _events;  }; -class npc_illidan_db_target : public CreatureScript +struct npc_illidan_db_target : public NullCreatureAI  { -public: -    npc_illidan_db_target() : CreatureScript("npc_illidan_db_target") { } +    npc_illidan_db_target(Creature* creature) : NullCreatureAI(creature) { } -    struct npc_illidan_db_targetAI : public NullCreatureAI +    void Reset() override      { -        npc_illidan_db_targetAI(Creature* creature) : NullCreatureAI(creature) { } - -        void Reset() override -        { -            DoCastSelf(SPELL_EYE_BLAST_TRIGGER); -        } +        DoCastSelf(SPELL_EYE_BLAST_TRIGGER); +    } -        void JustSummoned(Creature* summon) override -        { -            if (summon->GetEntry() == NPC_DEMON_FIRE) -                summon->SetReactState(REACT_PASSIVE); -        } +    void JustSummoned(Creature* summon) override +    { +        if (summon->GetEntry() == NPC_DEMON_FIRE) +            summon->SetReactState(REACT_PASSIVE); +    } -        void MovementInform(uint32 type, uint32 pointId) override +    void MovementInform(uint32 type, uint32 pointId) override +    { +        if (type == POINT_MOTION_TYPE && pointId == POINT_DB_TARGET)          { -            if (type == POINT_MOTION_TYPE && pointId == POINT_DB_TARGET) -            { -                me->RemoveAurasDueToSpell(SPELL_EYE_BLAST_TRIGGER); -                me->RemoveAurasDueToSpell(SPELL_EYE_BLAST); -            } +            me->RemoveAurasDueToSpell(SPELL_EYE_BLAST_TRIGGER); +            me->RemoveAurasDueToSpell(SPELL_EYE_BLAST);          } -    }; - -    CreatureAI* GetAI(Creature* creature) const override -    { -        return GetBlackTempleAI<npc_illidan_db_targetAI>(creature);      }  }; -class npc_illidan_shadow_demon : public CreatureScript +struct npc_shadow_demon : public PassiveAI  { -public: -    npc_illidan_shadow_demon() : CreatureScript("npc_shadow_demon") { } +    npc_shadow_demon(Creature* creature) : PassiveAI(creature), _instance(creature->GetInstanceScript()) { } -    struct npc_illidan_shadow_demonAI : public PassiveAI +    void Reset() override      { -        npc_illidan_shadow_demonAI(Creature* creature) : PassiveAI(creature), _instance(creature->GetInstanceScript()) { } - -        void Reset() override +        if (_instance->GetBossState(DATA_ILLIDAN_STORMRAGE) != IN_PROGRESS)          { -            if (_instance->GetBossState(DATA_ILLIDAN_STORMRAGE) != IN_PROGRESS) -            { -                me->DespawnOrUnsummon(); -                return; -            } - -            DoCastSelf(SPELL_SHADOW_DEMON_PASSIVE); -            DoCastSelf(SPELL_FIND_TARGET); -            _scheduler.Schedule(Seconds(1), [this](TaskContext checkTarget) -            { -                if (Unit* target = ObjectAccessor::GetUnit(*me, _targetGUID)) -                { -                    if (!target->IsAlive()) -                        DoCastSelf(SPELL_FIND_TARGET); -                    else if (me->IsWithinMeleeRange(target)) -                    { -                        me->InterruptNonMeleeSpells(false); -                        DoCast(target, SPELL_CONSUME_SOUL, true); -                    } -                } -                checkTarget.Repeat(); -            }); +            me->DespawnOrUnsummon(); +            return;          } -        void SetGUID(ObjectGuid guid, int32 /*id*/) override +        DoCastSelf(SPELL_SHADOW_DEMON_PASSIVE); +        DoCastSelf(SPELL_FIND_TARGET); +        _scheduler.Schedule(Seconds(1), [this](TaskContext checkTarget)          { -            _targetGUID = guid;              if (Unit* target = ObjectAccessor::GetUnit(*me, _targetGUID)) -                me->GetMotionMaster()->MoveChase(target); -        } - -        void UpdateAI(uint32 diff) override -        { -            _scheduler.Update(diff); -        } +            { +                if (!target->IsAlive()) +                    DoCastSelf(SPELL_FIND_TARGET); +                else if (me->IsWithinMeleeRange(target)) +                { +                    me->InterruptNonMeleeSpells(false); +                    DoCast(target, SPELL_CONSUME_SOUL, true); +                } +            } +            checkTarget.Repeat(); +        }); +    } -    private: -        InstanceScript* _instance; -        TaskScheduler _scheduler; -        ObjectGuid _targetGUID; -    }; +    void SetGUID(ObjectGuid guid, int32 /*id*/) override +    { +        _targetGUID = guid; +        if (Unit* target = ObjectAccessor::GetUnit(*me, _targetGUID)) +            me->GetMotionMaster()->MoveChase(target); +    } -    CreatureAI* GetAI(Creature* creature) const override +    void UpdateAI(uint32 diff) override      { -        return GetBlackTempleAI<npc_illidan_shadow_demonAI>(creature); +        _scheduler.Update(diff);      } + +private: +    InstanceScript* _instance; +    TaskScheduler _scheduler; +    ObjectGuid _targetGUID;  }; -class npc_maiev : public CreatureScript +struct npc_maiev : public ScriptedAI  { -public: -    npc_maiev() : CreatureScript("npc_maiev") { } +    npc_maiev(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _canDown(true) { } -    struct npc_maievAI : public ScriptedAI +    void Reset() override      { -        npc_maievAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _canDown(true) { } +        if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE)) +            me->SetFacingToObject(illidan); +        me->SetReactState(REACT_PASSIVE); +        _events.SetPhase(PHASE_INTRO); +        _events.ScheduleEvent(EVENT_MAIEV_APPEAR, Seconds(1)); +        _events.ScheduleEvent(EVENT_MAIEV_EXCLAMATION, Seconds(2)); +        _events.ScheduleEvent(EVENT_MAIEV_JUSTICE_TEXT, Seconds(14)); +        _events.ScheduleEvent(EVENT_TAUNT, Seconds(20), Seconds(60)); +        _canDown = true; +    } + +    void EnterCombat(Unit* /*who*/) override +    { +        _events.SetPhase(PHASE_1); +        _events.ScheduleEvent(EVENT_CAGE_TRAP, Seconds(30)); +        _events.ScheduleEvent(EVENT_SHADOW_STRIKE, Seconds(50)); +        _events.ScheduleEvent(EVENT_THROW_DAGGER, Seconds(1)); +    } -        void Reset() override +    void DoAction(int32 actionId) override +    { +        if (actionId == ACTION_START_OUTRO)          { +            _events.Reset(); +            me->SetReactState(REACT_PASSIVE); +            me->AttackStop();              if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE))                  me->SetFacingToObject(illidan); -            me->SetReactState(REACT_PASSIVE); -            _events.SetPhase(PHASE_INTRO); -            _events.ScheduleEvent(EVENT_MAIEV_APPEAR, Seconds(1)); -            _events.ScheduleEvent(EVENT_MAIEV_EXCLAMATION, Seconds(2)); -            _events.ScheduleEvent(EVENT_MAIEV_JUSTICE_TEXT, Seconds(14)); -            _events.ScheduleEvent(EVENT_TAUNT, Seconds(20), Seconds(60)); -            _canDown = true; +            Talk(SAY_MAIEV_SHADOWSONG_FINISHED); +            _events.ScheduleEvent(EVENT_MAIEV_OUTRO_TEXT, Seconds(28));          } +        else if (actionId == ACTION_MAIEV_DOWN_FADE) +            _canDown = true; +    } -        void EnterCombat(Unit* /*who*/) override +    void DamageTaken(Unit* /*who*/, uint32 &damage) override +    { +        if (damage >= me->GetHealth() && _canDown)          { -            _events.SetPhase(PHASE_1); -            _events.ScheduleEvent(EVENT_CAGE_TRAP, Seconds(30)); -            _events.ScheduleEvent(EVENT_SHADOW_STRIKE, Seconds(50)); -            _events.ScheduleEvent(EVENT_THROW_DAGGER, Seconds(1)); +            damage = me->GetHealth() - 1; +            _canDown = false; +            DoCastSelf(SPELL_MAIEV_DOWN, true); +            Talk(SAY_MAIEV_SHADOWSONG_DOWN, me);          } +    } -        void DoAction(int32 actionId) override -        { -            if (actionId == ACTION_START_OUTRO) -            { -                _events.Reset(); -                me->SetReactState(REACT_PASSIVE); -                me->AttackStop(); -                if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE)) -                    me->SetFacingToObject(illidan); -                Talk(SAY_MAIEV_SHADOWSONG_FINISHED); -                _events.ScheduleEvent(EVENT_MAIEV_OUTRO_TEXT, Seconds(28)); -            } -            else if (actionId == ACTION_MAIEV_DOWN_FADE) -                _canDown = true; -        } +    void UpdateAI(uint32 diff) override +    { +        if (!UpdateVictim() && !_events.IsInPhase(PHASE_INTRO)) +            return; + +        if (me->HasUnitState(UNIT_STATE_CASTING)) +            return; -        void DamageTaken(Unit* /*who*/, uint32 &damage) override +        _events.Update(diff); + +        while (uint32 eventId = _events.ExecuteEvent())          { -            if (damage >= me->GetHealth() && _canDown) +            switch (eventId)              { -                damage = me->GetHealth() - 1; -                _canDown = false; -                DoCastSelf(SPELL_MAIEV_DOWN, true); -                Talk(SAY_MAIEV_SHADOWSONG_DOWN, me); +                case EVENT_MAIEV_APPEAR: +                    Talk(SAY_MAIEV_SHADOWSONG_APPEAR); +                    break; +                case EVENT_MAIEV_EXCLAMATION: +                    me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); +                    break; +                case EVENT_MAIEV_JUSTICE_TEXT: +                    Talk(SAY_MAIEV_SHADOWSONG_JUSTICE); +                    _events.ScheduleEvent(EVENT_MAIEV_YES, Seconds(2)); +                    break; +                case EVENT_MAIEV_YES: +                    me->HandleEmoteCommand(EMOTE_ONESHOT_YES); +                    _events.ScheduleEvent(EVENT_MAIEV_ROAR, Seconds(3)); +                    break; +                case EVENT_MAIEV_ROAR: +                    me->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); +                    _events.ScheduleEvent(EVENT_MAIEV_COMBAT, Seconds(3)); +                    break; +                case EVENT_MAIEV_COMBAT: +                    me->SetReactState(REACT_AGGRESSIVE); +                    if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE)) +                        AttackStart(illidan); +                    break; +                case EVENT_CAGE_TRAP: +                    if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE)) +                        illidan->CastSpell(illidan, SPELL_CAGED_TRAP_TELEPORT, true); +                    DoCastSelf(SPELL_CAGE_TRAP_SUMMON); +                    Talk(SAY_MAIEV_SHADOWSONG_TRAP); +                    _events.Repeat(Seconds(30)); +                    break; +                case EVENT_SHADOW_STRIKE: +                    DoCastVictim(SPELL_SHADOW_STRIKE); +                    _events.Repeat(Seconds(50)); +                    break; +                case EVENT_THROW_DAGGER: +                    if (Unit* target = me->GetVictim()) +                        if (!me->IsWithinMeleeRange(target)) +                        { +                            DoCastVictim(SPELL_THROW_DAGGER); +                            _events.Repeat(Seconds(5)); +                            break; +                        } +                    _events.Repeat(Seconds(1)); +                    break; +                case EVENT_TAUNT: +                    Talk(SAY_MAIEV_SHADOWSONG_TAUNT); +                    _events.Repeat(Seconds(30), Seconds(60)); +                    break; +                case EVENT_MAIEV_OUTRO_TEXT: +                    Talk(SAY_MAIEV_SHADOWSONG_OUTRO); +                    _events.ScheduleEvent(EVENT_MAIEV_FAREWELL_TEXT, Seconds(11)); +                    break; +                case EVENT_MAIEV_FAREWELL_TEXT: +                    Talk(SAY_MAIEV_SHADOWSONG_FAREWELL); +                    _events.ScheduleEvent(EVENT_MAIEV_TELEPORT_DESPAWN, Seconds(3)); +                    break; +                case EVENT_MAIEV_TELEPORT_DESPAWN: +                    DoCastSelf(SPELL_TELEPORT_VISUAL); +                    me->DespawnOrUnsummon(Seconds(1)); +                    break; +                default: +                    break;              } -        } - -        void UpdateAI(uint32 diff) override -        { -            if (!UpdateVictim() && !_events.IsInPhase(PHASE_INTRO)) -                return;              if (me->HasUnitState(UNIT_STATE_CASTING))                  return; +        } -            _events.Update(diff); - -            while (uint32 eventId = _events.ExecuteEvent()) -            { -                switch (eventId) -                { -                    case EVENT_MAIEV_APPEAR: -                        Talk(SAY_MAIEV_SHADOWSONG_APPEAR); -                        break; -                    case EVENT_MAIEV_EXCLAMATION: -                        me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); -                        break; -                    case EVENT_MAIEV_JUSTICE_TEXT: -                        Talk(SAY_MAIEV_SHADOWSONG_JUSTICE); -                        _events.ScheduleEvent(EVENT_MAIEV_YES, Seconds(2)); -                        break; -                    case EVENT_MAIEV_YES: -                        me->HandleEmoteCommand(EMOTE_ONESHOT_YES); -                        _events.ScheduleEvent(EVENT_MAIEV_ROAR, Seconds(3)); -                        break; -                    case EVENT_MAIEV_ROAR: -                        me->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); -                        _events.ScheduleEvent(EVENT_MAIEV_COMBAT, Seconds(3)); -                        break; -                    case EVENT_MAIEV_COMBAT: -                        me->SetReactState(REACT_AGGRESSIVE); -                        if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE)) -                            AttackStart(illidan); -                        break; -                    case EVENT_CAGE_TRAP: -                        if (Creature* illidan = _instance->GetCreature(DATA_ILLIDAN_STORMRAGE)) -                            illidan->CastSpell(illidan, SPELL_CAGED_TRAP_TELEPORT, true); -                        DoCastSelf(SPELL_CAGE_TRAP_SUMMON); -                        Talk(SAY_MAIEV_SHADOWSONG_TRAP); -                        _events.Repeat(Seconds(30)); -                        break; -                    case EVENT_SHADOW_STRIKE: -                        DoCastVictim(SPELL_SHADOW_STRIKE); -                        _events.Repeat(Seconds(50)); -                        break; -                    case EVENT_THROW_DAGGER: -                        if (Unit* target = me->GetVictim()) -                            if (!me->IsWithinMeleeRange(target)) -                            { -                                DoCastVictim(SPELL_THROW_DAGGER); -                                _events.Repeat(Seconds(5)); -                                break; -                            } -                        _events.Repeat(Seconds(1)); -                        break; -                    case EVENT_TAUNT: -                        Talk(SAY_MAIEV_SHADOWSONG_TAUNT); -                        _events.Repeat(Seconds(30), Seconds(60)); -                        break; -                    case EVENT_MAIEV_OUTRO_TEXT: -                        Talk(SAY_MAIEV_SHADOWSONG_OUTRO); -                        _events.ScheduleEvent(EVENT_MAIEV_FAREWELL_TEXT, Seconds(11)); -                        break; -                    case EVENT_MAIEV_FAREWELL_TEXT: -                        Talk(SAY_MAIEV_SHADOWSONG_FAREWELL); -                        _events.ScheduleEvent(EVENT_MAIEV_TELEPORT_DESPAWN, Seconds(3)); -                        break; -                    case EVENT_MAIEV_TELEPORT_DESPAWN: -                        DoCastSelf(SPELL_TELEPORT_VISUAL); -                        me->DespawnOrUnsummon(Seconds(1)); -                        break; -                    default: -                        break; -                } +        DoMeleeAttackIfReady(); +    } -                if (me->HasUnitState(UNIT_STATE_CASTING)) -                    return; -            } +private: +    EventMap _events; +    InstanceScript* _instance; +    bool _canDown; +}; -            DoMeleeAttackIfReady(); -        } +struct npc_cage_trap_trigger : public PassiveAI +{ +    npc_cage_trap_trigger(Creature* creature) : PassiveAI(creature) { } -    private: -        EventMap _events; -        InstanceScript* _instance; -        bool _canDown; -    }; +    void Reset() override +    { +        _scheduler.Schedule(Seconds(1), [this](TaskContext checkTarget) +        { +            DoCastSelf(SPELL_CAGE_TRAP_PERIODIC); +            checkTarget.Repeat(); +        }); +    } -    CreatureAI* GetAI(Creature* creature) const override +    void UpdateAI(uint32 diff) override      { -        return GetBlackTempleAI<npc_maievAI>(creature); +        _scheduler.Update(diff);      } + +private: +    TaskScheduler _scheduler;  }; -class npc_cage_trap_trigger : public CreatureScript +struct npc_illidari_elite : public ScriptedAI  { -public: -    npc_cage_trap_trigger() : CreatureScript("npc_cage_trap_trigger") { } +    npc_illidari_elite(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } -    struct npc_cage_trap_triggerAI : public PassiveAI +    void Reset() override      { -        npc_cage_trap_triggerAI(Creature* creature) : PassiveAI(creature) { } - -        void Reset() override -        { -            _scheduler.Schedule(Seconds(1), [this](TaskContext checkTarget) -            { -                DoCastSelf(SPELL_CAGE_TRAP_PERIODIC); -                checkTarget.Repeat(); -            }); -        } - -        void UpdateAI(uint32 diff) override +        if (Creature* akama = _instance->GetCreature(DATA_AKAMA))          { -            _scheduler.Update(diff); +            AttackStart(akama); +            AddThreat(akama, 1000.0f);          } +    } -    private: -        TaskScheduler _scheduler; -    }; - -    CreatureAI* GetAI(Creature* creature) const override +    bool CanAIAttack(Unit const* who) const override      { -        return GetBlackTempleAI<npc_cage_trap_triggerAI>(creature); +        if (who->GetEntry() == NPC_AKAMA) +            return true; +        return false;      } + +private: +    InstanceScript* _instance;  };  // 41077 - Akama Teleport -class spell_illidan_akama_teleport : public SpellScriptLoader +class spell_illidan_akama_teleport : public SpellScript  { -    public: -        spell_illidan_akama_teleport() : SpellScriptLoader("spell_illidan_akama_teleport") { } - -        class spell_illidan_akama_teleport_SpellScript : public SpellScript -        { -            PrepareSpellScript(spell_illidan_akama_teleport_SpellScript); - -            void SetDest(SpellDestination& dest) -            { -                if (Creature* caster = GetCaster()->ToCreature()) -                { -                    uint32 destination = caster->AI()->GetData(DATA_AKAMA_TELEPORT_POSITION); -                    dest.Relocate(AkamaTeleportPositions[destination]); -                } -            } +    PrepareSpellScript(spell_illidan_akama_teleport); -            void Register() override -            { -                OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_illidan_akama_teleport_SpellScript::SetDest, EFFECT_0, TARGET_DEST_NEARBY_ENTRY); -            } -        }; - -        SpellScript* GetSpellScript() const override +    void SetDest(SpellDestination& dest) +    { +        if (Creature* caster = GetCaster()->ToCreature())          { -            return new spell_illidan_akama_teleport_SpellScript(); +            uint32 destination = caster->AI()->GetData(DATA_AKAMA_TELEPORT_POSITION); +            dest.Relocate(AkamaTeleportPositions[destination]);          } +    } + +    void Register() override +    { +        OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_illidan_akama_teleport::SetDest, EFFECT_0, TARGET_DEST_NEARBY_ENTRY); +    }  };  // 41268 - Quest - Black Temple - Akama - Door Open -class spell_illidan_akama_door_channel : public SpellScriptLoader +class spell_illidan_akama_door_channel : public AuraScript  { -    public: -        spell_illidan_akama_door_channel() : SpellScriptLoader("spell_illidan_akama_door_channel") { } +    PrepareAuraScript(spell_illidan_akama_door_channel); -        class spell_illidan_akama_door_channel_AuraScript : public AuraScript -        { -            PrepareAuraScript(spell_illidan_akama_door_channel_AuraScript); - -            bool Validate(SpellInfo const* /*spell*/) override -            { -                return ValidateSpellInfo({ SPELL_ARCANE_EXPLOSION }); -            } - -            void OnRemoveDummy(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) -            { -                Unit* target = GetTarget(); -                target->CastSpell(target, SPELL_ARCANE_EXPLOSION, true); +    bool Validate(SpellInfo const* /*spell*/) override +    { +        return ValidateSpellInfo({ SPELL_ARCANE_EXPLOSION }); +    } -                if (InstanceScript* instance = target->GetInstanceScript()) -                    if (Creature* akama = instance->GetCreature(DATA_AKAMA)) -                        akama->AI()->DoAction(ACTION_OPEN_DOOR); -            } +    void OnRemoveDummy(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) +    { +        Unit* target = GetTarget(); +        target->CastSpell(target, SPELL_ARCANE_EXPLOSION, true); -            void Register() override -            { -                AfterEffectRemove += AuraEffectRemoveFn(spell_illidan_akama_door_channel_AuraScript::OnRemoveDummy, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); -            } -        }; +        if (InstanceScript* instance = target->GetInstanceScript()) +            if (Creature* akama = instance->GetCreature(DATA_AKAMA)) +                akama->AI()->DoAction(ACTION_OPEN_DOOR); +    } -        AuraScript* GetAuraScript() const override -        { -            return new spell_illidan_akama_door_channel_AuraScript(); -        } +    void Register() override +    { +        AfterEffectRemove += AuraEffectRemoveFn(spell_illidan_akama_door_channel::OnRemoveDummy, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); +    }  };  // 40904 - Draw Soul -class spell_illidan_draw_soul : public SpellScriptLoader +class spell_illidan_draw_soul : public SpellScript  { -    public: -        spell_illidan_draw_soul() : SpellScriptLoader("spell_illidan_draw_soul") { } - -        class spell_illidan_draw_soul_SpellScript : public SpellScript -        { -            PrepareSpellScript(spell_illidan_draw_soul_SpellScript); - -            bool Validate(SpellInfo const* /*spellInfo*/) override -            { -                return ValidateSpellInfo({ SPELL_DRAW_SOUL_HEAL }); -            } +    PrepareSpellScript(spell_illidan_draw_soul); -            void HandleScriptEffect(SpellEffIndex effIndex) -            { -                PreventHitDefaultEffect(effIndex); -                GetHitUnit()->CastSpell(GetCaster(), SPELL_DRAW_SOUL_HEAL, true); -            } +    bool Validate(SpellInfo const* /*spellInfo*/) override +    { +        return ValidateSpellInfo({ SPELL_DRAW_SOUL_HEAL }); +    } -            void Register() override -            { -                OnEffectHitTarget += SpellEffectFn(spell_illidan_draw_soul_SpellScript::HandleScriptEffect, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); -            } -        }; +    void HandleScriptEffect(SpellEffIndex effIndex) +    { +        PreventHitDefaultEffect(effIndex); +        GetHitUnit()->CastSpell(GetCaster(), SPELL_DRAW_SOUL_HEAL, true); +    } -        SpellScript* GetSpellScript() const override -        { -            return new spell_illidan_draw_soul_SpellScript(); -        } +    void Register() override +    { +        OnEffectHitTarget += SpellEffectFn(spell_illidan_draw_soul::HandleScriptEffect, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); +    }  };  /* 41917 - Parasitic Shadowfiend     41914 - Parasitic Shadowfiend */ -class spell_illidan_parasitic_shadowfiend : public SpellScriptLoader +class spell_illidan_parasitic_shadowfiend : public AuraScript  { -    public: -        spell_illidan_parasitic_shadowfiend() : SpellScriptLoader("spell_illidan_parasitic_shadowfiend") { } +    PrepareAuraScript(spell_illidan_parasitic_shadowfiend); -        class spell_illidan_parasitic_shadowfiend_AuraScript : public AuraScript -        { -            PrepareAuraScript(spell_illidan_parasitic_shadowfiend_AuraScript); +    bool Validate(SpellInfo const* /*spellInfo*/) override +    { +        return ValidateSpellInfo({ SPELL_SUMMON_PARASITIC_SHADOWFIENDS }); +    } -            bool Validate(SpellInfo const* /*spellInfo*/) override -            { -                return ValidateSpellInfo({ SPELL_SUMMON_PARASITIC_SHADOWFIENDS }); -            } +    void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) +    { +        AuraRemoveMode removeMode = GetTargetApplication()->GetRemoveMode(); +        if (removeMode != AURA_REMOVE_BY_EXPIRE && removeMode != AURA_REMOVE_BY_DEATH) +            return; -            void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) -            { -                Unit* target = GetTarget(); -                target->CastSpell(target, SPELL_SUMMON_PARASITIC_SHADOWFIENDS, true); -            } +        Unit* target = GetTarget(); +        target->CastSpell(target, SPELL_SUMMON_PARASITIC_SHADOWFIENDS, true); +    } -            void Register() override -            { -                AfterEffectRemove += AuraEffectRemoveFn(spell_illidan_parasitic_shadowfiend_AuraScript::HandleEffectRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL); -            } -        }; +    void Register() override +    { +        AfterEffectRemove += AuraEffectRemoveFn(spell_illidan_parasitic_shadowfiend::HandleEffectRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL); +    } +}; -        AuraScript* GetAuraScript() const override -        { -            return new spell_illidan_parasitic_shadowfiend_AuraScript(); -        } +// 41923 - Remove Parasitic Shadowfiends (SERVERSIDE) +class spell_illidan_remove_parasitic_shadowfiend : public AuraScript +{ +    PrepareAuraScript(spell_illidan_remove_parasitic_shadowfiend); + +    bool Validate(SpellInfo const* /*spellInfo*/) override +    { +        return ValidateSpellInfo({ SPELL_PARASITIC_SHADOWFIEND, SPELL_PARASITIC_SHADOWFIEND_2 }); +    } + +    void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) +    { +        GetTarget()->RemoveAurasDueToSpell(SPELL_PARASITIC_SHADOWFIEND); +        GetTarget()->RemoveAurasDueToSpell(SPELL_PARASITIC_SHADOWFIEND_2); +    } + +    void Register() override +    { +        AfterEffectApply += AuraEffectApplyFn(spell_illidan_remove_parasitic_shadowfiend::HandleApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); +    }  };  /* 39635 - Throw Glaive     39849 - Throw Glaive */ -class spell_illidan_throw_warglaive : public SpellScriptLoader +class spell_illidan_throw_warglaive : public SpellScript  { -    public: -        spell_illidan_throw_warglaive() : SpellScriptLoader("spell_illidan_throw_warglaive") { } - -        class spell_illidan_throw_warglaive_SpellScript : public SpellScript -        { -            PrepareSpellScript(spell_illidan_throw_warglaive_SpellScript); - -            void HandleDummy(SpellEffIndex /*effIndex*/) -            { -                Unit* target = GetHitUnit(); -                target->m_Events.AddEvent(new SummonWarglaiveEvent(target), target->m_Events.CalculateTime(1000)); -            } +    PrepareSpellScript(spell_illidan_throw_warglaive); -            void Register() override -            { -                OnEffectHitTarget += SpellEffectFn(spell_illidan_throw_warglaive_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); -            } -        }; +    void HandleDummy(SpellEffIndex /*effIndex*/) +    { +        Unit* target = GetHitUnit(); +        target->m_Events.AddEvent(new SummonWarglaiveEvent(target), target->m_Events.CalculateTime(1000)); +    } -        SpellScript* GetSpellScript() const override -        { -            return new spell_illidan_throw_warglaive_SpellScript(); -        } +    void Register() override +    { +        OnEffectHitTarget += SpellEffectFn(spell_illidan_throw_warglaive::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); +    }  };  // 39857 - Tear of Azzinoth Summon Channel -class spell_illidan_tear_of_azzinoth_channel : public SpellScriptLoader +class spell_illidan_tear_of_azzinoth_channel : public AuraScript  { -    public: -        spell_illidan_tear_of_azzinoth_channel() : SpellScriptLoader("spell_illidan_tear_of_azzinoth_channel") { } - -        class spell_illidan_tear_of_azzinoth_channel_AuraScript : public AuraScript -        { -            PrepareAuraScript(spell_illidan_tear_of_azzinoth_channel_AuraScript); - -            bool Validate(SpellInfo const* /*spellInfo*/) override -            { -                return ValidateSpellInfo({ SPELL_UNCAGED_WRATH }); -            } +    PrepareAuraScript(spell_illidan_tear_of_azzinoth_channel); -            void OnPeriodic(AuraEffect const* /*aurEff*/) -            { -                PreventDefaultAction(); -                if (Unit* caster = GetCaster()) -                { -                    Unit* target = GetTarget(); -                    if (caster->GetDistance2d(target) > 25.0f) -                    { -                        target->CastSpell(target, SPELL_UNCAGED_WRATH, true); -                        Remove(); -                    } -                } -            } +    bool Validate(SpellInfo const* /*spellInfo*/) override +    { +        return ValidateSpellInfo({ SPELL_UNCAGED_WRATH }); +    } -            void Register() override +    void OnPeriodic(AuraEffect const* /*aurEff*/) +    { +        PreventDefaultAction(); +        if (Unit* caster = GetCaster()) +        { +            Unit* target = GetTarget(); +            if (caster->GetDistance2d(target) > 25.0f)              { -                OnEffectPeriodic += AuraEffectPeriodicFn(spell_illidan_tear_of_azzinoth_channel_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); +                target->CastSpell(target, SPELL_UNCAGED_WRATH, true); +                Remove();              } -        }; - -        AuraScript* GetAuraScript() const override -        { -            return new spell_illidan_tear_of_azzinoth_channel_AuraScript();          } +    } + +    void Register() override +    { +        OnEffectPeriodic += AuraEffectPeriodicFn(spell_illidan_tear_of_azzinoth_channel::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); +    }  };  // 40631 - Flame Blast -class spell_illidan_flame_blast : public SpellScriptLoader +class spell_illidan_flame_blast : public SpellScript  { -    public: -        spell_illidan_flame_blast() : SpellScriptLoader("spell_illidan_flame_blast") { } +    PrepareSpellScript(spell_illidan_flame_blast); -        class spell_illidan_flame_blast_SpellScript : public SpellScript -        { -            PrepareSpellScript(spell_illidan_flame_blast_SpellScript); - -            bool Validate(SpellInfo const* /*spellInfo*/) override -            { -                return ValidateSpellInfo({ SPELL_BLAZE_SUMMON }); -            } - -            void HandleBlaze(SpellEffIndex /*effIndex*/) -            { -                Unit* target = GetHitUnit(); -                if (target->GetTypeId() == TYPEID_PLAYER) -                    target->CastSpell(target, SPELL_BLAZE_SUMMON, true); -            } +    bool Validate(SpellInfo const* /*spellInfo*/) override +    { +        return ValidateSpellInfo({ SPELL_BLAZE_SUMMON }); +    } -            void Register() override -            { -                OnEffectHitTarget += SpellEffectFn(spell_illidan_flame_blast_SpellScript::HandleBlaze, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); -            } -        }; +    void HandleBlaze(SpellEffIndex /*effIndex*/) +    { +        Unit* target = GetHitUnit(); +        if (target->GetTypeId() == TYPEID_PLAYER) +            target->CastSpell(target, SPELL_BLAZE_SUMMON, true); +    } -        SpellScript* GetSpellScript() const override -        { -            return new spell_illidan_flame_blast_SpellScript(); -        } +    void Register() override +    { +        OnEffectHitTarget += SpellEffectFn(spell_illidan_flame_blast::HandleBlaze, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); +    }  };  // 39873 - Glaive Returns -class spell_illidan_return_glaives : public SpellScriptLoader +class spell_illidan_return_glaives : public SpellScript  { -    public: spell_illidan_return_glaives() : SpellScriptLoader("spell_illidan_return_glaives") { } - -        class spell_illidan_return_glaives_SpellScript : public SpellScript -        { -            PrepareSpellScript(spell_illidan_return_glaives_SpellScript); - -            void HandleScriptEffect(SpellEffIndex /*effIndex*/) -            { -                GetHitUnit()->SendPlaySpellVisual(SPELL_GLAIVE_VISUAL_KIT); -                if (Creature* caster = GetCaster()->ToCreature()) -                    caster->DespawnOrUnsummon(); -            } +    PrepareSpellScript(spell_illidan_return_glaives); -            void Register() override -            { -                OnEffectHitTarget += SpellEffectFn(spell_illidan_return_glaives_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); -            } -        }; +    void HandleScriptEffect(SpellEffIndex /*effIndex*/) +    { +        GetHitUnit()->SendPlaySpellVisual(SPELL_GLAIVE_VISUAL_KIT); +        if (Creature* caster = GetCaster()->ToCreature()) +            caster->DespawnOrUnsummon(); +    } -        SpellScript* GetSpellScript() const override -        { -            return new spell_illidan_return_glaives_SpellScript(); -        } +    void Register() override +    { +        OnEffectHitTarget += SpellEffectFn(spell_illidan_return_glaives::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); +    }  };  // 40834 - Agonizing Flames -class spell_illidan_agonizing_flames : public SpellScriptLoader +class spell_illidan_agonizing_flames : public SpellScript  { -    public: -        spell_illidan_agonizing_flames() : SpellScriptLoader("spell_illidan_agonizing_flames") { } - -        class spell_illidan_agonizing_flames_SpellScript : public SpellScript -        { -            PrepareSpellScript(spell_illidan_agonizing_flames_SpellScript); +    PrepareSpellScript(spell_illidan_agonizing_flames); -            bool Validate(SpellInfo const* /*spellInfo*/) override -            { -                return ValidateSpellInfo({ SPELL_AGONIZING_FLAMES }); -            } - -            void FilterTargets(std::list<WorldObject*>& targets) -            { -                if (targets.empty()) -                    return; +    bool Validate(SpellInfo const* /*spellInfo*/) override +    { +        return ValidateSpellInfo({ SPELL_AGONIZING_FLAMES }); +    } -                WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); -                targets.clear(); -                targets.push_back(target); -            } +    void FilterTargets(std::list<WorldObject*>& targets) +    { +        if (targets.empty()) +            return; -            void HandleScript(SpellEffIndex /*effIndex*/) -            { -                GetCaster()->CastSpell(GetHitUnit(), SPELL_AGONIZING_FLAMES, true); -            } +        WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); +        targets.clear(); +        targets.push_back(target); +    } -            void Register() override -            { -                OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_illidan_agonizing_flames_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); -                OnEffectHitTarget += SpellEffectFn(spell_illidan_agonizing_flames_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY); -            } -        }; +    void HandleScript(SpellEffIndex /*effIndex*/) +    { +        GetCaster()->CastSpell(GetHitUnit(), SPELL_AGONIZING_FLAMES, true); +    } -        SpellScript* GetSpellScript() const override -        { -            return new spell_illidan_agonizing_flames_SpellScript(); -        } +    void Register() override +    { +        OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_illidan_agonizing_flames::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); +        OnEffectHitTarget += SpellEffectFn(spell_illidan_agonizing_flames::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY); +    }  };  // 40511 - Demon Transform 1 -class spell_illidan_demon_transform1 : public SpellScriptLoader +class spell_illidan_demon_transform1 : public AuraScript  { -    public: -        spell_illidan_demon_transform1() : SpellScriptLoader("spell_illidan_demon_transform1") { } - -        class spell_illidan_demon_transform1_AuraScript : public AuraScript -        { -            PrepareAuraScript(spell_illidan_demon_transform1_AuraScript); +    PrepareAuraScript(spell_illidan_demon_transform1); -            bool Validate(SpellInfo const* /*spellInfo*/) override -            { -                return ValidateSpellInfo({ SPELL_DEMON_TRANSFORM_2 }); -            } - -            void OnPeriodic(AuraEffect const* /*aurEff*/) -            { -                PreventDefaultAction(); -                GetTarget()->CastSpell(GetTarget(), SPELL_DEMON_TRANSFORM_2, true); -                Remove(); -            } +    bool Validate(SpellInfo const* /*spellInfo*/) override +    { +        return ValidateSpellInfo({ SPELL_DEMON_TRANSFORM_2 }); +    } -            void Register() override -            { -                OnEffectPeriodic += AuraEffectPeriodicFn(spell_illidan_demon_transform1_AuraScript::OnPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL); -            } -        }; +    void OnPeriodic(AuraEffect const* /*aurEff*/) +    { +        PreventDefaultAction(); +        GetTarget()->CastSpell(GetTarget(), SPELL_DEMON_TRANSFORM_2, true); +        Remove(); +    } -        AuraScript* GetAuraScript() const override -        { -            return new spell_illidan_demon_transform1_AuraScript(); -        } +    void Register() override +    { +        OnEffectPeriodic += AuraEffectPeriodicFn(spell_illidan_demon_transform1::OnPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL); +    }  }; +  // 40398 - Demon Transform 2 -class spell_illidan_demon_transform2 : public SpellScriptLoader +class spell_illidan_demon_transform2 : public AuraScript  { -    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 Validate(SpellInfo const* /*spellInfo*/) override -            { -                return ValidateSpellInfo({ SPELL_DEMON_FORM, SPELL_DEMON_TRANSFORM_3 }); -            } - -            void OnPeriodic(AuraEffect const* aurEff) -            { -                PreventDefaultAction(); -                Unit* target = GetTarget(); +    PrepareAuraScript(spell_illidan_demon_transform2); -                if (aurEff->GetTickNumber() == 1) -                { -                    if (target->GetDisplayId() == target->GetNativeDisplayId()) -                        target->CastSpell(target, SPELL_DEMON_FORM, true); -                    else -                        target->RemoveAurasDueToSpell(SPELL_DEMON_FORM); -                } -                else if (aurEff->GetTickNumber() == 2) -                { -                    target->CastSpell(target, SPELL_DEMON_TRANSFORM_3, true); -                    if (Aura* aura = GetUnitOwner()->GetAura(SPELL_DEMON_TRANSFORM_3)) -                        aura->SetDuration(4300); -                    Remove(); -                } -            } +    bool Validate(SpellInfo const* /*spellInfo*/) override +    { +        return ValidateSpellInfo({ SPELL_DEMON_FORM, SPELL_DEMON_TRANSFORM_3 }); +    } -            void Register() override -            { -                OnEffectPeriodic += AuraEffectPeriodicFn(spell_illidan_demon_transform2_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); -            } -        }; +    void OnPeriodic(AuraEffect const* aurEff) +    { +        PreventDefaultAction(); +        Unit* target = GetTarget(); -        AuraScript* GetAuraScript() const override +        if (aurEff->GetTickNumber() == 1) +        { +            if (target->GetDisplayId() == target->GetNativeDisplayId()) +                target->CastSpell(target, SPELL_DEMON_FORM, true); +            else +                target->RemoveAurasDueToSpell(SPELL_DEMON_FORM); +        } +        else if (aurEff->GetTickNumber() == 2)          { -            return new spell_illidan_demon_transform2_AuraScript(); +            target->CastSpell(target, SPELL_DEMON_TRANSFORM_3, true); +            if (Aura* aura = GetUnitOwner()->GetAura(SPELL_DEMON_TRANSFORM_3)) +                aura->SetDuration(4300); +            Remove();          } +    } + +    void Register() override +    { +        OnEffectPeriodic += AuraEffectPeriodicFn(spell_illidan_demon_transform2::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); +    }  };  // 41126 - Flame Burst -class spell_illidan_flame_burst : public SpellScriptLoader +class spell_illidan_flame_burst : public SpellScript  { -    public: -        spell_illidan_flame_burst() : SpellScriptLoader("spell_illidan_flame_burst") { } - -        class spell_illidan_flame_burst_SpellScript : public SpellScript -        { -            PrepareSpellScript(spell_illidan_flame_burst_SpellScript); +    PrepareSpellScript(spell_illidan_flame_burst); -            bool Validate(SpellInfo const* /*spellInfo*/) override -            { -                return ValidateSpellInfo({ SPELL_FLAME_BURST_EFFECT }); -            } - -            void HandleScriptEffect(SpellEffIndex /*effIndex*/) -            { -                GetHitUnit()->CastSpell(GetHitUnit(), SPELL_FLAME_BURST_EFFECT, true); -            } +    bool Validate(SpellInfo const* /*spellInfo*/) override +    { +        return ValidateSpellInfo({ SPELL_FLAME_BURST_EFFECT }); +    } -            void Register() override -            { -                OnEffectHitTarget += SpellEffectFn(spell_illidan_flame_burst_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); -            } -        }; +    void HandleScriptEffect(SpellEffIndex /*effIndex*/) +    { +        GetHitUnit()->CastSpell(GetHitUnit(), SPELL_FLAME_BURST_EFFECT, true); +    } -        SpellScript* GetSpellScript() const override -        { -            return new spell_illidan_flame_burst_SpellScript(); -        } +    void Register() override +    { +        OnEffectHitTarget += SpellEffectFn(spell_illidan_flame_burst::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); +    }  };  // 41081 - Find Target -class spell_illidan_find_target : public SpellScriptLoader +class spell_illidan_find_target : public SpellScript  { -    public: -        spell_illidan_find_target() : SpellScriptLoader("spell_illidan_find_target") { } - -        class spell_illidan_find_target_SpellScript : public SpellScript -        { -            PrepareSpellScript(spell_illidan_find_target_SpellScript); - -            bool Validate(SpellInfo const* /*spellInfo*/) override -            { -                return ValidateSpellInfo({ SPELL_PARALYZE }); -            } +    PrepareSpellScript(spell_illidan_find_target); -            void FilterTargets(std::list<WorldObject*>& targets) -            { -                targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_PARALYZE)); +    bool Validate(SpellInfo const* /*spellInfo*/) override +    { +        return ValidateSpellInfo({ SPELL_PARALYZE }); +    } -                if (targets.empty()) -                    return; +    void FilterTargets(std::list<WorldObject*>& targets) +    { +        targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_PARALYZE)); -                WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); -                targets.clear(); -                targets.push_back(target); -            } +        if (targets.empty()) +            return; -            void HandleScript(SpellEffIndex /*effIndex*/) -            { -                Unit* target = GetHitUnit(); -                if (Creature* caster = GetCaster()->ToCreature()) -                { -                    caster->CastSpell(target, SPELL_PARALYZE, true); -                    caster->AI()->SetGUID(target->GetGUID(), 0); -                } -            } - -            void Register() override -            { -                OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_illidan_find_target_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); -                OnEffectHitTarget += SpellEffectFn(spell_illidan_find_target_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY); -            } -        }; +        WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); +        targets.clear(); +        targets.push_back(target); +    } -        SpellScript* GetSpellScript() const override +    void HandleScript(SpellEffIndex /*effIndex*/) +    { +        Unit* target = GetHitUnit(); +        if (Creature* caster = GetCaster()->ToCreature())          { -            return new spell_illidan_find_target_SpellScript(); +            caster->CastSpell(target, SPELL_PARALYZE, true); +            caster->AI()->SetGUID(target->GetGUID(), 0);          } +    } + +    void Register() override +    { +        OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_illidan_find_target::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); +        OnEffectHitTarget += SpellEffectFn(spell_illidan_find_target::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY); +    }  };  // 39908 - Eye Blast -class spell_illidan_eye_blast : public SpellScriptLoader +class spell_illidan_eye_blast : public AuraScript  { -    public: -        spell_illidan_eye_blast() : SpellScriptLoader("spell_illidan_eye_blast") { } - -        class spell_illidan_eye_blast_AuraScript : public AuraScript -        { -            PrepareAuraScript(spell_illidan_eye_blast_AuraScript); - -            void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) -            { -                if (Creature* target = GetTarget()->ToCreature()) -                    target->DespawnOrUnsummon(); -            } +    PrepareAuraScript(spell_illidan_eye_blast); -            void Register() override -            { -                AfterEffectRemove += AuraEffectRemoveFn(spell_illidan_eye_blast_AuraScript::HandleEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); -            } -        }; +    void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) +    { +        if (Creature* target = GetTarget()->ToCreature()) +            target->DespawnOrUnsummon(); +    } -        AuraScript* GetAuraScript() const override -        { -            return new spell_illidan_eye_blast_AuraScript(); -        } +    void Register() override +    { +        AfterEffectRemove += AuraEffectRemoveFn(spell_illidan_eye_blast::HandleEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); +    }  };  // 40761 - Cage Trap -class spell_illidan_cage_trap : public SpellScriptLoader +class spell_illidan_cage_trap : public SpellScript  { -    public: -        spell_illidan_cage_trap() : SpellScriptLoader("spell_illidan_cage_trap") { } - -        class spell_illidan_cage_trap_SpellScript : public SpellScript -        { -            PrepareSpellScript(spell_illidan_cage_trap_SpellScript); - -            void HandleScriptEffect(SpellEffIndex /*effIndex*/) -            { -                Creature* target = GetHitCreature(); -                Creature* caster = GetCaster()->ToCreature(); - -                if (!target || !caster) -                    return; +    PrepareSpellScript(spell_illidan_cage_trap); -                if (caster->GetDistance2d(target) < 4.0f) -                { -                    target->AI()->DoAction(ACTION_ILLIDAN_CAGED); -                    caster->DespawnOrUnsummon(); -                    if (GameObject* trap = target->FindNearestGameObject(GO_ILLIDAN_CAGE_TRAP, 10.0f)) -                        trap->UseDoorOrButton(); -                } -            } +    void HandleScriptEffect(SpellEffIndex /*effIndex*/) +    { +        Creature* target = GetHitCreature(); +        Creature* caster = GetCaster()->ToCreature(); -            void Register() override -            { -                OnEffectHitTarget += SpellEffectFn(spell_illidan_cage_trap_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); -            } -        }; +        if (!target || !caster) +            return; -        SpellScript* GetSpellScript() const override +        if (caster->GetDistance2d(target) < 4.0f)          { -            return new spell_illidan_cage_trap_SpellScript(); +            target->AI()->DoAction(ACTION_ILLIDAN_CAGED); +            caster->DespawnOrUnsummon(); +            if (GameObject* trap = target->FindNearestGameObject(GO_ILLIDAN_CAGE_TRAP, 10.0f)) +                trap->UseDoorOrButton();          } +    } + +    void Register() override +    { +        OnEffectHitTarget += SpellEffectFn(spell_illidan_cage_trap::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); +    }  };  // 40760 - Cage Trap -class spell_illidan_caged : public SpellScriptLoader +class spell_illidan_caged : public AuraScript  { -    public: -        spell_illidan_caged() : SpellScriptLoader("spell_illidan_caged") { } - -        class spell_illidan_caged_AuraScript : public AuraScript -        { -            PrepareAuraScript(spell_illidan_caged_AuraScript); +    PrepareAuraScript(spell_illidan_caged); -            bool Validate(SpellInfo const* /*spellInfo*/) override -            { -                return ValidateSpellInfo({ SPELL_CAGED_DEBUFF }); -            } - -            void OnPeriodic(AuraEffect const* /*aurEff*/) -            { -                PreventDefaultAction(); -                Unit* target = GetTarget(); -                target->CastSpell(target, SPELL_CAGED_DEBUFF, true); -                Remove(); -            } +    bool Validate(SpellInfo const* /*spellInfo*/) override +    { +        return ValidateSpellInfo({ SPELL_CAGED_DEBUFF }); +    } -            void Register() override -            { -                OnEffectPeriodic += AuraEffectPeriodicFn(spell_illidan_caged_AuraScript::OnPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL); -            } -        }; +    void OnPeriodic(AuraEffect const* /*aurEff*/) +    { +        PreventDefaultAction(); +        Unit* target = GetTarget(); +        target->CastSpell(target, SPELL_CAGED_DEBUFF, true); +        Remove(); +    } -        AuraScript* GetAuraScript() const override -        { -            return new spell_illidan_caged_AuraScript(); -        } +    void Register() override +    { +        OnEffectPeriodic += AuraEffectPeriodicFn(spell_illidan_caged::OnPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL); +    }  };  // 40409 - Maiev Down -class spell_maiev_down : public SpellScriptLoader +class spell_maiev_down : public AuraScript  { -public: -    spell_maiev_down() : SpellScriptLoader("spell_maiev_down") { } +    PrepareAuraScript(spell_maiev_down); -    class spell_maiev_down_AuraScript : public AuraScript +    bool Load() override      { -        PrepareAuraScript(spell_maiev_down_AuraScript); - -        bool Load() override -        { -            return GetUnitOwner()->GetTypeId() == TYPEID_UNIT; -        } - -        void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) -        { -            GetTarget()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); -        } +        return GetUnitOwner()->GetTypeId() == TYPEID_UNIT; +    } -        void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) -        { -            GetTarget()->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); -            GetTarget()->GetAI()->DoAction(ACTION_MAIEV_DOWN_FADE); -        } +    void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) +    { +        GetTarget()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); +    } -        void Register() override -        { -            OnEffectApply += AuraEffectApplyFn(spell_maiev_down_AuraScript::HandleEffectApply, EFFECT_1, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL); -            AfterEffectRemove += AuraEffectRemoveFn(spell_maiev_down_AuraScript::HandleEffectRemove, EFFECT_1, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL); -        } -    }; +    void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) +    { +        GetTarget()->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); +        GetTarget()->GetAI()->DoAction(ACTION_MAIEV_DOWN_FADE); +    } -    AuraScript* GetAuraScript() const override +    void Register() override      { -        return new spell_maiev_down_AuraScript(); +        OnEffectApply += AuraEffectApplyFn(spell_maiev_down::HandleEffectApply, EFFECT_1, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL); +        AfterEffectRemove += AuraEffectRemoveFn(spell_maiev_down::HandleEffectRemove, EFFECT_1, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL);      }  };  //  40693 - Cage Trap -class spell_illidan_cage_teleport : public SpellScriptLoader +class spell_illidan_cage_teleport : public SpellScript  { -    public: -        spell_illidan_cage_teleport() : SpellScriptLoader("spell_illidan_cage_teleport") { } - -        class spell_illidan_cage_teleport_SpellScript : public SpellScript -        { -            PrepareSpellScript(spell_illidan_cage_teleport_SpellScript); - -            void SetDest(SpellDestination& dest) -            { -                Position offset = { 0.0f, 0.0f, GetCaster()->GetPositionZ(), 0.0f }; -                dest.RelocateOffset(offset); -            } +    PrepareSpellScript(spell_illidan_cage_teleport); -            void Register() override -            { -                OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_illidan_cage_teleport_SpellScript::SetDest, EFFECT_0, TARGET_DEST_CASTER_RADIUS); -            } -        }; +    void SetDest(SpellDestination& dest) +    { +        Position offset = { 0.0f, 0.0f, GetCaster()->GetPositionZ(), 0.0f }; +        dest.RelocateOffset(offset); +    } -        SpellScript* GetSpellScript() const override -        { -            return new spell_illidan_cage_teleport_SpellScript(); -        } +    void Register() override +    { +        OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_illidan_cage_teleport::SetDest, EFFECT_0, TARGET_DEST_CASTER_RADIUS); +    }  };  // 41242 - Akama Despawn -class spell_illidan_despawn_akama : public SpellScriptLoader +class spell_illidan_despawn_akama : public SpellScript  { -    public: -        spell_illidan_despawn_akama() : SpellScriptLoader("spell_illidan_despawn_akama") { } - -        class spell_illidan_despawn_akama_SpellScript : public SpellScript -        { -            PrepareSpellScript(spell_illidan_despawn_akama_SpellScript); +    PrepareSpellScript(spell_illidan_despawn_akama); -            void HandleDummy(SpellEffIndex /*effIndex*/) -            { -                if (Creature* target = GetHitCreature()) -                    target->DespawnOrUnsummon(Seconds(1)); -            } - -            void Register() override -            { -                OnEffectHitTarget += SpellEffectFn(spell_illidan_despawn_akama_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); -            } -        }; +    void HandleDummy(SpellEffIndex /*effIndex*/) +    { +        if (Creature* target = GetHitCreature()) +            target->DespawnOrUnsummon(Seconds(1)); +    } -        SpellScript* GetSpellScript() const override -        { -            return new spell_illidan_despawn_akama_SpellScript(); -        } +    void Register() override +    { +        OnEffectHitTarget += SpellEffectFn(spell_illidan_despawn_akama::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); +    }  };  void AddSC_boss_illidan()  { -    new boss_illidan_stormrage(); -    new npc_akama(); -    new npc_parasitic_shadowfiend(); -    new npc_blade_of_azzinoth(); -    new npc_flame_of_azzinoth(); -    new npc_illidan_db_target(); -    new npc_maiev(); -    new npc_illidan_shadow_demon(); -    new npc_cage_trap_trigger(); -    new spell_illidan_akama_teleport(); -    new spell_illidan_akama_door_channel(); -    new spell_illidan_draw_soul(); -    new spell_illidan_parasitic_shadowfiend(); -    new spell_illidan_throw_warglaive(); -    new spell_illidan_tear_of_azzinoth_channel(); -    new spell_illidan_flame_blast(); -    new spell_illidan_return_glaives(); -    new spell_illidan_agonizing_flames(); -    new spell_illidan_demon_transform1(); -    new spell_illidan_demon_transform2(); -    new spell_illidan_flame_burst(); -    new spell_illidan_find_target(); -    new spell_illidan_eye_blast(); -    new spell_illidan_cage_trap(); -    new spell_illidan_caged(); -    new spell_maiev_down(); -    new spell_illidan_cage_teleport(); -    new spell_illidan_despawn_akama(); +    RegisterBlackTempleCreatureAI(boss_illidan_stormrage); +    RegisterBlackTempleCreatureAI(npc_akama_illidan); +    RegisterBlackTempleCreatureAI(npc_parasitic_shadowfiend); +    RegisterBlackTempleCreatureAI(npc_blade_of_azzinoth); +    RegisterBlackTempleCreatureAI(npc_flame_of_azzinoth); +    RegisterBlackTempleCreatureAI(npc_illidan_db_target); +    RegisterBlackTempleCreatureAI(npc_maiev); +    RegisterBlackTempleCreatureAI(npc_shadow_demon); +    RegisterBlackTempleCreatureAI(npc_cage_trap_trigger); +    RegisterBlackTempleCreatureAI(npc_illidari_elite); +    RegisterSpellScript(spell_illidan_akama_teleport); +    RegisterAuraScript(spell_illidan_akama_door_channel); +    RegisterSpellScript(spell_illidan_draw_soul); +    RegisterAuraScript(spell_illidan_parasitic_shadowfiend); +    RegisterAuraScript(spell_illidan_remove_parasitic_shadowfiend); +    RegisterSpellScript(spell_illidan_throw_warglaive); +    RegisterAuraScript(spell_illidan_tear_of_azzinoth_channel); +    RegisterSpellScript(spell_illidan_flame_blast); +    RegisterSpellScript(spell_illidan_return_glaives); +    RegisterSpellScript(spell_illidan_agonizing_flames); +    RegisterAuraScript(spell_illidan_demon_transform1); +    RegisterAuraScript(spell_illidan_demon_transform2); +    RegisterSpellScript(spell_illidan_flame_burst); +    RegisterSpellScript(spell_illidan_find_target); +    RegisterAuraScript(spell_illidan_eye_blast); +    RegisterSpellScript(spell_illidan_cage_trap); +    RegisterAuraScript(spell_illidan_caged); +    RegisterAuraScript(spell_maiev_down); +    RegisterSpellScript(spell_illidan_cage_teleport); +    RegisterSpellScript(spell_illidan_despawn_akama);  } | 
