All pastes #793247 Raw Edit

Something

public text v1 · immutable
·published 2007-11-22 02:14 UTC
rendered paste body
/* Copyright (C) 2006,2007 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

/* ScriptData
SDName: boss_illidan_stormrage
SD%Complete: 80
SDComment: Need to do Eye Blast, Cage Traps, Enrage, Transform cosmetics and adjust timers.
EndScriptData */

/***************************************/
/* This script is still in development */
/*   by Wolfdragon and Moriquendu      */
/***************************************/

/******** Includes ************/
#include "../../sc_defines.h"
#include "../../../../../game/TargetedMovementGenerator.h"
#include "../../../../../shared/WorldPacket.h"
#include "../../../../../game/SpellAuras.h"
#include "../../../../../game/Player.h"
#include "../../../../../game/GossipDef.h"

/************* Quotes and Sounds ***********************/
// Gossip for when a player clicks Akama
#define GOSSIP_ITEM          "We are ready to face Illidan"

// Intro speech with Akama
#define SAY_INTRO_ILL1        "Akama... your duplicity is hardly surprising. I should have slaughtered you and your malformed brethren long ago."
#define SOUND_INTRO_ILL1    11463 // ~13 seconds
#define SAY_INTRO_AKA1        "We've come to end your reign, Illidan. My people and all of Outland shall be free!"
#define SOUND_INTRO_AKA1    11389 // ~12 seconds
#define SAY_INTRO_ILL2        "Boldly said. But I remain unconvinced."
#define SOUND_INTRO_ILL2    11464 // ~8 seconds
#define SAY_INTRO_AKA2        "The time has come! The moment is at hand!"
#define SOUND_INTRO_AKA2    11380 // ~5 seconds
#define SAY_INTRO_ILL3        "You are not prepared!" // He conjectures that your level of preparation could perhaps be improved somewhat
#define SOUND_INTRO_ILL3    11466

// Signal for Akama to leave
#define SAY_AKAMA_MINION    "Come, my minions. Deal with this traitor as he deserves!"
#define SOUND_AKAMA_MINION    11465

// Taunts?
#define SAY_HATRED          "I can feel your hatred"
#define SOUND_HATRED        11467
#define SAY_FEAR            "Give in to your fear!"
#define SOUND_FEAR          11468
#define SAY_POWER           "You know nothing of power!"
#define SOUND_POWER         11469
#define SAY_ARROGANCE       "Such..arrogance!"
#define SOUND_ARROGANCE     11471
#define SAY_RABBLE          "I will not be touched by rabble such as you!"
#define SOUND_RABBLE        11479

// Attacking Maeiv
#define SAY_ATT_MAIEV        "Feel the hatred of ten thousand years!"
#define SOUND_ATT_MAIEV        11470

// Self explanatory
#define SAY_KILL1            "Who shall be next to taste my blades?!"
#define SOUND_KILL1            11473
#define SAY_KILL2            "This is too easy!"
#define SOUND_KILL2            11472

// I think I'll fly now and let my subordinates take you on
#define SAY_PHASE2            "Behold the flames of Azzinoth!"
#define SOUND_PHASE2        11480

// When casting Eye Blast. Demon Fire will be appear on places that he casts this
#define SAY_EYE_BLAST      "Stare into the eyes of the Betrayer!"
#define SOUND_EYE_BLAST     11481

// kk, I go big, dark and demon on you.
#define SAY_MORPH            "Behold the power... of the demon within!"
#define SOUND_MORPH            11475

// I KILL!
#define SAY_ENRAGE            "You've wasted too much time mortals, now you shall fall!"
#define SOUND_ENRAGE        11474

// Speech when Maiev enters
#define SAY_SUMMON_MAIEV    "Is this it, mortals? Is this all the fury you can muster?"
#define SOUND_SUMMON_MAIEV    11476 // ~8 seconds
#define SAY_MAIEV1            "Their fury pales before mine, Illidan. We have some unsettled business between us."
#define SOUND_MAIEV1        11491 // ~9 seconds
#define SAY_MAIEV_ILL2        "Maiev... How is this even possible?"
#define SOUND_MAIEV_ILL2    11477 // ~7 seconds
#define SAY_MAIEV2            "Ah, my long hunt is finally over. Today, Justice will be done!"
#define SOUND_MAIEV2        11492 // ~10 seconds

// Death speech
#define SAY_DEATH_MAIEV1    "Ahh... It is finished. You are beaten."
#define SOUND_DEATH_MAIEV1    11496 // ~6 seconds
#define SAY_DEATH_ILL        "You have won... Maiev. But the huntress... is nothing without the hunt. You... are nothing... without me."
#define SOUND_DEATH_ILL        11478 // ~22 seconds
#define SAY_DEATH_MAIEV2    "He's right. I feel nothing. I am nothing. Farewell, champions."
#define SOUND_DEATH_MAIEV2    11497 // ~9 seconds
#define SAY_DEATH_AKA        "The Light will fill these dismal halls once again. I swear it."
#define SOUND_DEATH_AKA        11387 // ~8 seconds

/************** Spells *************/
// Normal Form
#define SPELL_SHEAR                     41032 // Reduces Max. Health by 60% for 7 seconds. Can stack 19 times. 1.5 second cast
#define SPELL_FLAME_CRASH               40832 // Summons an invis/unselect passive mob that has an aura of flame in a circle around him.
#define SPELL_DRAW_SOUL                 40904 // 5k Shadow Damage in front of him. Heals Illidan for 100k health (script effect)
#define SPELL_PARASITIC_SHADOWFIEND     41917 // DoT of 3k Shadow every 2 seconds. Lasts 10 seconds. (Script effect: Summon 2 parasites once the debuff has ticked off)
#define SPELL_AGONIZING_FLAMES          40932 // 4k fire damage initial to target and anyone w/i 5 yards. PHASE 3 ONLY
// Flying (Phase 2)
#define SPELL_FIREBALL                  40598 // 2.5k-3.5k damage in 10 yard radius. 2 second cast time.
#define SPELL_EYE_BLAST                 39908 // Fiery blue beam across platform. Deals ~20k fire damage, spawns Demon Fire on ground for 1 minute.
#define SPELL_DEMON_FIRE                40029 // Blue fire trail left by Eye Blast. Deals 2k per second if players stand on it.
#define SPELL_DARK_BARRAGE              40585 // 10 second channeled spell, 3k shadow damage per second.
// Demon Form
#define SPELL_DEMON_FORM                40506 // Transforms into Demon Illidan. Has an Aura of Dread on him.
#define SPELL_SHADOW_BLAST              41078 // 8k - 11k Shadow Damage. Targets highest threat. Has a splash effect, damaging anyone in 20 yards of the target.
#define SPELL_FLAME_BURST               41126 // Hurls fire at entire raid for ~3.5k damage every 10 seconds. Resistable. (Does not work: Script effect)
// Other Illidan spells
#define SPELL_KNEEL                     39656 // Before beginning encounter, this is how he appears (talking to skully).
#define SPELL_SHADOW_PRISON             40647 // Illidan casts this spell to immobilize entire raid when he summons Maiev.
#define SPELL_DEATH                     40220 // This spell doesn't do anything except stun Illidan and set him on his knees.

// Non-Illidan spells
#define SPELL_HEALING_POTION            40535 // Akama uses this to heal himself to full.
#define SPELL_GREEN_BEAM                39165 // Glaives cast it on Flames. Not sure if this is the right spell.

/***** Locations *******/
// Locations for spawning glaives.
#define X_GLAIVE1                       695.105
#define X_GLAIVE2                       659.338
#define Y_GLAIVE                        305.303
#define Z_GLAIVE                        354.256

/******* The AI *******/
struct MANGOS_DLL_SPEC boss_illidan_stormrageAI : public ScriptedAI
{
    boss_illidan_stormrageAI(Creature* c) : ScriptedAI(c)
    {
        SetVariables();
    }

    /** Generic **/
    bool InCombat;
    bool IsTalking;
    uint32 Phase;
    uint32 GlobalTimer;
    uint32 TalkCount;

    /** GUIDs **/
    uint64 FlameGUID[1];
    uint64 GlaiveGUID[1];
    uint64 AkamaGUID;
    uint64 MaievGUID;

    /** Timers **/
    uint32 ShearTimer;
    uint32 DrawSoulTimer;
    uint32 FlameCrashTimer;
    uint32 ParasiticShadowFiendTimer;
    uint32 FireballTimer;
    uint32 EyeBlastTimer;
    uint32 DarkBarrageTimer;
    uint32 AgonizingFlamesTimer;
    uint32 ShadowBlastTimer;
    uint32 FlameBurstTimer;
    uint32 ShadowDemonTimer;
    uint32 SummonTimer;
    uint32 TalkTimer;
    uint32 TransformTimer;
    uint32 EnrageTimer;

    void SetVariables()
    {
        Phase = 1;
        /*   1 = Normal form
             2 = Flying. Raid attacks Flames of Azzinoth
             3 = Normal form, casts Agonizing Flames + can transform to Demon form
             4 = Demon Form.
             5 = Normal form with Agonizing Flames + Demon form + Maiev
        */

        // If in combat, check if any flames/glaives are alive/existing. Kill if alive and set GUIDs to 0
        for(uint8 i = 0; i < 2; i++)
        {
            if(FlameGUID[i])
            {
                if(InCombat)
                {
                    Unit* Flame = Unit::GetUnit((*m_creature), FlameGUID[i]);
                    if(Flame) Flame->DealDamage(Flame, Flame->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_NORMAL, NULL, 0, false);
                }
                FlameGUID[i] = 0;
            }

            if(GlaiveGUID[i])
            {
                if(InCombat)
                {
                    Unit* Glaive = Unit::GetUnit((*m_creature), GlaiveGUID[i]);
                    if(Glaive) Glaive->DealDamage(Glaive, Glaive->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_NORMAL, NULL, 0, false);
                }
                GlaiveGUID[i] = 0;
            }
        }

        InCombat = false;
        IsTalking = false;
        AkamaGUID = 0;
        MaievGUID = 0;
        GlobalTimer = 0;
        TalkCount = 0;
        TalkTimer = 0;

        // Kneel when not in combat
        //DoCast(m_creature, SPELL_KNEEL);

        /** Normal Form **/
        ShearTimer = 20000 + (rand()%10 * 100); // 20 to 30 seconds
        FlameCrashTimer = 30000; //30 seconds
        ParasiticShadowFiendTimer = 25000; // 25 seconds
        DrawSoulTimer = 35000; // 35 seconds

        /** Phase 2 **/
        SummonTimer = 10000; // Phase 2 timers may be incorrect
        FireballTimer = 5000;
        DarkBarrageTimer = 45000;
        EyeBlastTimer = 30000;

        /** Phase 3+ **/
        AgonizingFlamesTimer = 35000; // Phase 3+ timers may be incorrect
        ShadowBlastTimer = 3000;
        FlameBurstTimer = 30000;
        ShadowDemonTimer = 35000;
        TransformTimer = 60000;
        EnrageTimer = 15000;


        m_creature->setFaction(35); // Start him off as friendly.
       // m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); // Do not be attacked (use this instead of UNIT_FLAG_NOT_ATTACK since AoEs still target him)
    }

    void EnterEvadeMode()
    {
        SetVariables();

        m_creature->RemoveAllAuras();
        m_creature->DeleteThreatList();
        m_creature->CombatStop();
        DoGoHome();
    }

    void AttackStart(Unit *who)
    {
        if(!who || IsTalking)
            return;
        
        if (who->isTargetableForAttack() && who!= m_creature)
        {
            //Begin melee attack if we are within range
            DoStartMeleeAttack(who);

            if (!InCombat) InCombat = true;
        }
    }

    void MoveInLineOfSight(Unit *who)
    {
        if (!who || m_creature->getVictim())
            return;

        if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who))
        {
            float attackRadius = m_creature->GetAttackDistance(who);
            if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who))
            {
                if(who->HasStealthAura())
                    who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);

                if (!InCombat) InCombat = true;

                DoStartMeleeAttack(who);
            }
        }
    }

    void JustDied(Unit *killer)
    {
        SetVariables(); // Reset variables for respawn.
    }

    /** This will handle the cast of eye blast **/
    void CastEyeBlast()
    {
        DoYell(SAY_EYE_BLAST, LANG_UNIVERSAL, NULL);
        DoPlaySoundToSet(m_creature, SOUND_EYE_BLAST);
    }

    void SetGUID(char *Identifier, uint64 guid)
    {
        if(!Identifier || !guid) return;
        if(Identifier == "Akama") DoYell("AKAMA!", LANG_UNIVERSAL, NULL); AkamaGUID = guid;
        if(Identifier == "Maiev") DoYell("MAIEV", LANG_UNIVERSAL, NULL); MaievGUID = guid;
    }

    void UpdateAI(const uint32 diff)
    {

        /*** This section will handle the conversations ***/
        if(IsTalking) // Is there a better way to do this without a long switch statement?
        {
            if(TalkTimer < diff)
            {
                switch(TalkCount)
                {
                    case 0:
                        DoYell(SAY_INTRO_ILL1, LANG_UNIVERSAL, NULL);
                        DoPlaySoundToSet(m_creature, SOUND_INTRO_ILL1);
                        TalkTimer = 13000;
                        TalkCount = 1;
                        break;
                    case 1:
                        if(AkamaGUID)
                        {
                            Creature* Akama = ((Creature*)Unit::GetUnit((*m_creature), AkamaGUID));
                            if(Akama)
                            {
                                Akama->Yell(SAY_INTRO_AKA1, LANG_UNIVERSAL, NULL);
                                DoPlaySoundToSet(Akama, SOUND_INTRO_AKA1);
                                TalkTimer = 12000;
                                TalkCount = 2;
                            }
                        }
                        break;
                    case 2:
                        DoYell(SAY_INTRO_ILL2, LANG_UNIVERSAL, NULL);
                        DoPlaySoundToSet(m_creature, SOUND_INTRO_ILL2);
                        TalkTimer = 8000;
                        TalkCount = 3;
                        break;
                    case 3:
                        if(AkamaGUID)
                        {
                            Creature* Akama = ((Creature*)Unit::GetUnit((*m_creature), AkamaGUID));
                            if(Akama)
                            {
                                Akama->Yell(SAY_INTRO_AKA2, LANG_UNIVERSAL, NULL);
                                DoPlaySoundToSet(Akama, SOUND_INTRO_AKA2);
                                TalkTimer = 5000;
                                TalkCount = 4;
                            }
                        }
                        break;
                    case 4:
                        DoYell(SAY_INTRO_ILL3, LANG_UNIVERSAL, NULL);
                        DoPlaySoundToSet(m_creature, SOUND_INTRO_ILL3);
                        m_creature->setFaction(14); // Hostile
                        IsTalking = false;
                        break;
                    case 5:
                        DoYell(SAY_SUMMON_MAIEV, LANG_UNIVERSAL, NULL);
                        DoPlaySoundToSet(m_creature, SOUND_SUMMON_MAIEV);
                        TalkTimer = 8000;
                        TalkCount = 6;
                        break;
                    case 6:
                        if(MaievGUID)
                        {
                            Creature* Maiev = ((Creature*)Unit::GetUnit((*m_creature), MaievGUID));
                            if(Maiev)
                            {
                                Maiev->Yell(SAY_MAIEV1, LANG_UNIVERSAL, NULL);
                                DoPlaySoundToSet(Maiev, SOUND_MAIEV1);
                                TalkTimer = 9000;
                                TalkCount = 7;
                            }
                        }
                        break;
                    case 7:
                        DoYell(SAY_MAIEV_ILL2, LANG_UNIVERSAL, NULL);
                        DoPlaySoundToSet(m_creature, SOUND_MAIEV_ILL2);
                        TalkTimer = 7000;
                        TalkCount = 8;
                        break;
                    case 8:
                        if(MaievGUID)
                        {
                            Creature* Maiev = ((Creature*)Unit::GetUnit((*m_creature), MaievGUID));
                            if(Maiev)
                            {
                                Maiev->Yell(SAY_MAIEV2, LANG_UNIVERSAL, NULL);
                                DoPlaySoundToSet(Maiev, SOUND_MAIEV2);
                                TalkTimer = 10000;
                                TalkCount = 9;
                            }
                        }
                        break;
                    case 9:
                        DoYell(SAY_ATT_MAIEV, LANG_UNIVERSAL, NULL);
                        DoPlaySoundToSet(m_creature, SOUND_ATT_MAIEV);
                        if(MaievGUID)
                            m_creature->Attack(Unit::GetUnit((*m_creature), MaievGUID));
                        IsTalking = false;
                        break;
                    case 10:
                        if(MaievGUID)
                        {
                            Creature* Maiev = ((Creature*)Unit::GetUnit((*m_creature), MaievGUID));
                            if(Maiev && Maiev->isAlive())
                            {
                                Maiev->Yell(SAY_DEATH_MAIEV1, LANG_UNIVERSAL, NULL);
                                DoPlaySoundToSet(Maiev, SOUND_DEATH_MAIEV1);
                                TalkTimer = 6000;
                                TalkCount = 11;
                            }
                        }
                        break;
                    case 11:
                        DoYell(SAY_DEATH_ILL, LANG_UNIVERSAL, NULL);
                        DoPlaySoundToSet(m_creature, SOUND_DEATH_ILL);
                        TalkTimer = 22000;
                        TalkCount = 12;
                        break;
                    case 12:
                        if(MaievGUID)
                        {
                            Creature* Maiev = ((Creature*)Unit::GetUnit((*m_creature), MaievGUID));
                            if(Maiev && Maiev->isAlive())
                            {
                                Maiev->Yell(SAY_DEATH_MAIEV2, LANG_UNIVERSAL, NULL);                            
                                DoPlaySoundToSet(Maiev, SOUND_DEATH_MAIEV2);                            
                                TalkTimer = 9000;                            
                                TalkCount = 13;
                            }
                        }
                        break;
                    case 13:
                        if(AkamaGUID)
                        {
                            Creature* Akama = ((Creature*)Unit::GetUnit((*m_creature), AkamaGUID));
                            if(Akama && Akama->isAlive())
                            {
                                Akama->Relocate(m_creature->GetPositionX()+5, m_creature->GetPositionY()+5, m_creature->GetPositionZ());
                                Akama->SendMonsterMove(m_creature->GetPositionX()+5, m_creature->GetPositionY()+5, m_creature->GetPositionZ(), 0, false, 100);
                                m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
                                Akama->Yell(SAY_DEATH_AKA, LANG_UNIVERSAL, NULL);
                                DoPlaySoundToSet(Akama, SOUND_DEATH_AKA);
                                m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_NORMAL, NULL, 0, false);
                            }
                        }
                        break;
                }
            }else TalkTimer -= diff;
        }

        // If we don't have a target, return.
        if(!m_creature->SelectHostilTarget() || !m_creature->getVictim() || IsTalking) return;

        // Remove Kneel spell if in combat
        if(InCombat && m_creature->HasAura(SPELL_KNEEL, 0)) m_creature->RemoveAllAuras();

        /** Signal to change to phase 2 **/
        if(((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 65) && (Phase == 1))
        {
            SummonTimer = 10000;
            Phase = 2;
            m_creature->SetHover(true);
            m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
            (*m_creature).GetMotionMaster()->Clear();
        }

        /** Signal to summon Maiev **/
        if(((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 30) && (!MaievGUID))
        {
            Creature* Maiev = NULL;
            //TODO: FIND EXACT LOCATIONS
            Maiev = m_creature->SummonCreature(23197, m_creature->GetPositionX() + 10, m_creature->GetPositionY() + 5, m_creature->GetPositionZ(), 0, TEMPSUMMON_DEAD_DESPAWN, 0);
            if(Maiev)
            {
                DoCast(m_creature, SPELL_SHADOW_PRISON);
                IsTalking = true;
                TalkCount = 5;
                MaievGUID = Maiev->GetGUID();
            }
        }

        /** Time for the death speech **/
        if((m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 3) && (!IsTalking))
        {
            DoCast(m_creature, SPELL_DEATH);
            m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
            IsTalking = true;
            TalkCount = 10;
        }


        /***** Spells for Phase 1, 3 and 5 (Normal Form) ******/
        if(Phase == 1 || Phase == 3 || Phase == 5)
        {
            if(GlobalTimer < diff) // Global Timer so that spells do not overlap.
            {
                if(ShearTimer < diff)
                {
                    DoCast(m_creature->getVictim(), SPELL_SHEAR);
                    ShearTimer = 20000 + (rand()%10 * 100);
                    GlobalTimer += 2000;
                }else ShearTimer -= diff;

                if(FlameCrashTimer < diff)
                {
                    DoCast(m_creature->getVictim(), SPELL_FLAME_CRASH);
                    FlameCrashTimer = 30000;
                    GlobalTimer += 2000;
                }else FlameCrashTimer -= diff;

                if(ParasiticShadowFiendTimer < diff)
                {
                    DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_PARASITIC_SHADOWFIEND);
                    ParasiticShadowFiendTimer = 25000;
                }else ParasiticShadowFiendTimer -= diff;

                if(DrawSoulTimer < diff)
                {
                    DoCast(m_creature->getVictim(), SPELL_DRAW_SOUL);
                    DrawSoulTimer = 35000;
                    GlobalTimer = 3000;
                }else DrawSoulTimer -= diff;
            }else GlobalTimer -= diff;

            DoMeleeAttackIfReady();
        }

        /*** Phase 2 ***/
        if(Phase == 2)
        {
            // Check if Summon Timer is not 0 or null.
            if(SummonTimer)
                if(SummonTimer < diff)
                {
                    Creature* Flame1 = NULL;
                    Creature* Flame2 = NULL;
                    Creature* Glaive1 = NULL;
                    Creature* Glaive2 = NULL;

                    // Summon Glaives.
                    Glaive1 = m_creature->SummonCreature(22824, X_GLAIVE1, Y_GLAIVE, Z_GLAIVE, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
                    Glaive2 = m_creature->SummonCreature(22824, X_GLAIVE2, Y_GLAIVE, Z_GLAIVE, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);

                    // Summon Flames near the Glaives and have the Glaives channel a green beam on the flames
                    if(Glaive1)
                    {
                        GlaiveGUID[0] = Glaive1->GetGUID();
                        Flame1 = m_creature->SummonCreature(22997, X_GLAIVE1-5, Y_GLAIVE, Z_GLAIVE, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 2000);
                        if(Flame1)
                        {
                            FlameGUID[0] = Flame1->GetGUID();
                            Glaive1->CastSpell(Flame1, SPELL_GREEN_BEAM, true);
                        }
                    }

                    if(Glaive2)
                    {
                        GlaiveGUID[1] = Glaive2->GetGUID();
                        Flame2 = m_creature->SummonCreature(22997, X_GLAIVE2+5, Y_GLAIVE, Z_GLAIVE, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 2000);
                        if(Flame2)
                        {
                            FlameGUID[1] = Flame2->GetGUID();
                            Glaive2->CastSpell(Flame2, SPELL_GREEN_BEAM, true);
                        }
                    }
                    SummonTimer = 0;
                }else SummonTimer -= diff;

            //  Check if we are hovering. Recast if we are not.
            if(!m_creature->isHover()) m_creature->SetHover(true);

            // Check if flames are dead or non-existant. If so, set GUID to 0.
            for(uint8 i = 0; i < 2; i++)
            {
                if(FlameGUID[i])
                {
                    Unit* Flame = NULL;
                    Flame = Unit::GetUnit((*m_creature), FlameGUID[i]);

                    if(!Flame || !Flame->isAlive())
                        FlameGUID[i] = 0;
                }
            }

            // If both flames are dead/non-existant, kill glaives and change to phase 3.
            if(!FlameGUID[0] && !FlameGUID[1])
            {
                for(uint8 i = 0; i < 2; i++)
                {
                    if(GlaiveGUID[i])
                    {
                        Unit* Glaive = NULL;
                        Glaive = Unit::GetUnit((*m_creature), GlaiveGUID[i]);
                        if(Glaive)
                            Glaive->DealDamage(Glaive, Glaive->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_NORMAL, NULL, 0, false);
                        GlaiveGUID[i] = 0;
                    }
                }
                m_creature->SetHover(false);
                Phase = 3;
                m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
                (*m_creature).GetMotionMaster()->Mutate(new TargetedMovementGenerator<Creature>(*m_creature->getVictim()));
            }

            if(GlobalTimer < diff)
            {
                if(FireballTimer < diff)
                {
                    DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_FIREBALL);
                    FireballTimer = 5000;
                    GlobalTimer += 1500;
                }else FireballTimer -= diff;

                if(DarkBarrageTimer < diff)
                {
                    DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DARK_BARRAGE);
                    DarkBarrageTimer = 45000;
                    GlobalTimer += 11000;
                }else DarkBarrageTimer -= diff;

                if(EyeBlastTimer < diff)
                {
                    CastEyeBlast();
                    EyeBlastTimer = 30000;
                    GlobalTimer += 40000;
                }else EyeBlastTimer -= diff;
            }else GlobalTimer -= diff;
        }

        /** Phase 3,5 spells only**/
        if(Phase == 3 || Phase == 5)
        {
            if(GlobalTimer < diff)
            {
                if(AgonizingFlamesTimer < diff)
                {
                    DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_AGONIZING_FLAMES);
                    AgonizingFlamesTimer = 35000;
                    GlobalTimer += 1500;
                }else AgonizingFlamesTimer -= diff;
            }else GlobalTimer -= diff;
           
            if(TransformTimer < diff)
            {
                //TODO: Transformation scene
                DoYell(SAY_MORPH, LANG_UNIVERSAL, NULL);
                DoPlaySoundToSet(m_creature, SOUND_MORPH);
                DoCast(m_creature, SPELL_DEMON_FORM);
                TransformTimer = 60000;
                Phase = 4;
                (*m_creature).GetMotionMaster()->Clear(); // Stop moving
            }else TransformTimer -= diff;
        }

        /** Phase 4 spells only (Demon Form) **/
        if(Phase == 4)
        {
            // Stop moving if we are by clearing movement generators.
            if(!m_creature->GetMotionMaster()->empty())
                (*m_creature).GetMotionMaster()->Clear();

            if(TransformTimer < diff)
            {
                //TODO: Transformation scene
                m_creature->RemoveAurasDueToSpell(SPELL_DEMON_FORM);
                if(!MaievGUID) Phase = 3; // Maiev has not yet been summoned, go back to phase 3
                else Phase = 5; // Maiev has been summoned, go to phase 5.
                (*m_creature).GetMotionMaster()->Mutate(new TargetedMovementGenerator<Creature>(*m_creature->getVictim()));
                TransformTimer = 60000;
            }else TransformTimer -= diff;

            if(ShadowDemonTimer < diff)
            {
                Creature* ShadowDemon = NULL;
                for(uint8 i = 0; i < 4; i++)
                {
                    Unit* target = NULL;
                    if(target)
                    {
                        ShadowDemon = m_creature->SummonCreature(23375, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
                        if(ShadowDemon)
                        {
                            ShadowDemon->Attack(target);
                            ShadowDemon->AddThreat(target, 5000000.0f);
                            //ShadowDemon->CastSpell(target, SPELL_PURPLE_BEAM);
                            //ShadowDemon->CastSpell(target, SPELL_PARALYZE);
                        }
                    }
                }
                ShadowDemonTimer = 35000;
            }else ShadowDemonTimer -= diff;

            if(GlobalTimer < diff)
            {
                if(ShadowBlastTimer < diff)
                {
                    DoCast(m_creature->getVictim(), SPELL_SHADOW_BLAST);
                    ShadowBlastTimer = 3000;
                    GlobalTimer += 1500;
                }else ShadowBlastTimer -= diff;
            }else GlobalTimer -= diff;
        }

        /** Phase 5 timers. Enrage spell **/
        if(Phase == 5)
        {
            if(EnrageTimer < diff)
            {
                // DoCast(m_creature, SPELL_ENRAGE);
                EnrageTimer = 15000;
            }else EnrageTimer -= diff;
        }
    }
};

struct MANGOS_DLL_SPEC npc_akama_illidanAI : public ScriptedAI
{
    npc_akama_illidanAI(Creature* c) : ScriptedAI(c)
    {
        pInstance = ((ScriptedInstance*)c->GetInstanceData());
        SetVariables();
    }

    /* Instance Data */
    ScriptedInstance* pInstance;

    /* GUIDs */
    uint64 IllidanGUID;

    /* Generic */
    bool InCombat;
    bool IsTalking;

    void SetVariables()
    {
        if(pInstance) pInstance->SetData("IllidanStormrageEvent", 0); // Not started
        IllidanGUID = 0;

        InCombat = false;
        IsTalking = false;

        m_creature->SetUInt32Value(UNIT_NPC_FLAGS, 1); // Gossip flag
    }
    
    void EnterEvadeMode()
    {
        SetVariables();

        m_creature->DeleteThreatList();
        m_creature->RemoveAllAuras();
        m_creature->CombatStop();
        DoGoHome();
    }

    void BeginEvent()
    {
        InCombat = true;

        if(pInstance)
            IllidanGUID = pInstance->GetData64("IllidanStormrage");

        if(IllidanGUID)
        {
            Creature* Illidan = ((Creature*)Unit::GetUnit((*m_creature), IllidanGUID));
            if(Illidan)
            {
                // Start walking towards Illidan. Get exact positions and time later
                //m_creature->Relocate(Illidan->GetPositionX() + 20, Illidan->GetPositionY(), Illidan->GetPositionZ());
                //m_creature->SendMonsterMove(Illidan->GetPositionX() + 20, Illidan->GetPositionY(), Illidan->GetPositionZ(), 0, false, 20000);
                Illidan->RemoveAurasDueToSpell(SPELL_KNEEL); // Time for Illidan to stand up.
                Illidan->SetInCombat(); // Get ready to begin attacking
                m_creature->SetInCombat();
                ((boss_illidan_stormrageAI*)Illidan->AI())->TalkCount = 0; // First line of Akama-Illidan convo
                uint32 TalkCount = ((boss_illidan_stormrageAI*)Illidan->AI())->TalkCount;
                ((boss_illidan_stormrageAI*)Illidan->AI())->IsTalking = true; // Begin Talking
                ((boss_illidan_stormrageAI*)Illidan->AI())->SetGUID("Akama", m_creature->GetGUID()); // Allow communication between Akama and Illidan scripts
                IsTalking = true; // Prevent Akama from starting to attack him
                Illidan->SetInFront(m_creature); // Face each other
                DoFaceTarget(Illidan);
                m_creature->SetUInt32Value(UNIT_NPC_FLAGS, 0); // Prevent players from talking again
            }
        }
    }
    
    void AttackStart(Unit *who)
    {
        if((!who) || IsTalking)
            return;

        if(who->isTargetableForAttack() && who!= m_creature)
        {
            DoStartMeleeAttack(who);

            if(!InCombat)
            {
                InCombat = true;
            }
        }
    }

    void DamageTaken(Unit *done_by, uint32 &damage)
    {
        if(damage > m_creature->GetHealth())
        {
            damage = 0;
            m_creature->SetHealth(1);
        }
    }

    void UpdateAI(const uint32 diff)
    {   
        if(IllidanGUID)
        {
            Creature* Illidan = ((Creature*)Unit::GetUnit((*m_creature), IllidanGUID));
            if(Illidan)
            {
                if(!((boss_illidan_stormrageAI*)Illidan->AI())->IsTalking)
                    IsTalking = false;
            }
        }

        // If we don't have a target, return.
        if(!m_creature->SelectHostilTarget() || !m_creature->getVictim() || IsTalking) return;
        
        if((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 30)
            DoCast(m_creature, SPELL_HEALING_POTION);

        DoMeleeAttackIfReady();
    }
};

bool GossipSelect_npc_akama_at_illidan(Player *player, Creature *_Creature, uint32 sender, uint32 action)
{
    if(action == GOSSIP_ACTION_INFO_DEF) // Time to begin the event
    {
        player->PlayerTalkClass->CloseGossip();
        ((npc_akama_illidanAI*)_Creature->AI())->BeginEvent();
    }
    return true;
}

bool GossipHello_npc_akama_at_illidan(Player *player, Creature *_Creature)
{
    uint32 acctid = player->GetSession()->GetAccountId();
    if((acctid == 6) || (acctid == 91) || (acctid == 480) || (acctid == 7421))
    {
        player->ADD_GOSSIP_ITEM(0, GOSSIP_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
        player->PlayerTalkClass->SendGossipMenu(10465, _Creature->GetGUID());
    }else player->DealDamage(player, player->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_NORMAL, NULL, 0, true);

    return true;
}

CreatureAI* GetAI_boss_illidan_stormrage(Creature *_Creature)
{
    return new boss_illidan_stormrageAI (_Creature);
}

CreatureAI* GetAI_npc_akama_at_illidan(Creature *_Creature)
{
    return new npc_akama_illidanAI (_Creature);
}

void AddSC_boss_illidan_stormrage()
{
    Script* newscript;

    newscript = new Script;
    newscript->Name = "boss_illidan_stormrage";
    newscript->GetAI = GetAI_boss_illidan_stormrage;
    m_scripts[nrscripts++] = newscript;

    newscript = new Script;
    newscript->Name = "boss_akama_illidan";
    newscript->GetAI = GetAI_npc_akama_at_illidan;
    newscript->pGossipHello = GossipHello_npc_akama_at_illidan;
    newscript->pGossipSelect = GossipSelect_npc_akama_at_illidan;
    m_scripts[nrscripts++] = newscript;
}