void UpdateAI(uint32 diff)
        {
            if (!UpdateVictim() || me->HasUnitState(UNIT_STATE_CASTING))
                return;

            if (!phase)
                return;

            if (m_uiPowerTimer <= diff)
            {
               instance->NormaliseAltPower();
            }
            else m_uiPowerTimer -= diff;

            events.Update(diff);

            if (phase == PHASE_GROUND) // Ground phase
            {
                ThreatContainer::StorageType const &threatlist = me->getThreatManager().getThreatList();

                while (uint32 eventId = events.ExecuteEvent())
                {
                    switch (eventId)
                    {
                        case EVENT_AGGRO_NEF:
                            if (Creature* nefarianHelperheroic = me->FindNearestCreature(NPC_NEFARIAN_HELPER_HEROIC, 150.0f, true))
                            nefarianHelperheroic->AI()->Talk(28);
                            return;

                        case EVENT_SONAR_PULSE:
                            DoCast(me, SPELL_SONAR_PULSE);
                            me->SummonCreature(NPC_SONAR_PULSES, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 1.5f, TEMPSUMMON_TIMED_DESPAWN, 30000);
                            me->SummonCreature(NPC_SONAR_PULSES, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 3.0f, TEMPSUMMON_TIMED_DESPAWN, 30000);
                            me->SummonCreature(NPC_SONAR_PULSES, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 4.5f, TEMPSUMMON_TIMED_DESPAWN, 30000);
                            me->SummonCreature(NPC_SONAR_PULSES, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 6.0f, TEMPSUMMON_TIMED_DESPAWN, 30000);   
                            events.ScheduleEvent(EVENT_SONAR_PULSE, 50000);
                            break;

                        case EVENT_MODULATION:
                            DoCast(me, SPELL_MODULATION);
                            for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr)
                                if (Unit* unit = Unit::GetUnit(*me, (*itr)->getUnitGuid()))
                                    unit->SetPower(POWER_ALTERNATE_POWER, unit->GetPower(POWER_ALTERNATE_POWER) + 7);

                            events.ScheduleEvent(EVENT_MODULATION, 20000);
                            break;

                        case EVENT_SONIC_BREATH:
                             if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
                            {
                                target->AddAura(SPELL_TRACKING, target);
                                DoCast(target, SPELL_SONIC_BREATH);
                            }
                            events.ScheduleEvent(EVENT_REMOVE_TRACKING, 8500);                            
                            events.ScheduleEvent(EVENT_SONIC_BREATH, 40000);
                            break;

                        case EVENT_REMOVE_TRACKING:
                            if(instance)
                                instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_TRACKING);
                            return;

                        case EVENT_SEARING_FLAMES:
                            Talk(SAY_SEARING);
                            DoCast(me, SPELL_SEARING_FLAMES);                       
                            events.ScheduleEvent(EVENT_SEARING_FLAMES, 50000);
                            break;

                        case EVENT_LIFTOFF:
                            Talk(SAY_AIR_PHASE);
                            me->HandleEmote(EMOTE_ONESHOT_LIFTOFF);
                            me->SetDisableGravity(true);
                            events.ScheduleEvent(EVENT_FLIGHT, 1500);
                            events.ScheduleEvent(EVENT_AIR, 2000);
                            return;
                            
                        case EVENT_FLIGHT:
                            me->SetReactState(REACT_PASSIVE);
                            me->AttackStop();
                            me->GetMotionMaster()->MovePoint(1, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 20.0f);
                            return;

                        case EVENT_AIR:
                            EnterPhaseAir();
                            return;

                        case EVENT_FIEND:
                            me->SummonCreature(NPC_OBNOXIOUS_FIEND, 93.767f, -224.105f, 74.911f, 6.26f, TEMPSUMMON_CORPSE_DESPAWN, 3000);
                            if (Creature* nefarianHelperheroic = me->FindNearestCreature(NPC_NEFARIAN_HELPER_HEROIC, 150.0f, true))
                                nefarianHelperheroic->AI()->Talk(27);                                
                            events.ScheduleEvent(EVENT_FIEND, 38500);
                            break;
                    }
                }

                DoMeleeAttackIfReady();
            }
            else if (phase == PHASE_FLIGHT) // Air phase
            {
                std::list<Unit*> targets;
                ThreatContainer::StorageType const &m_threatlist = me->getThreatManager().getThreatList();

                // if has vertigo, remove all roaring flame npc's wait 8 sec then get player who rang gong.
                if (me->HasAura(SPELL_VERTIGO))
                    events.ScheduleEvent(EVENT_ROARING_FLAME_SUMMON, 8000, PHASE_FLIGHT);

                if (uint32 eventId = events.ExecuteEvent())
                {
                    switch (eventId)
                    {
                        case EVENT_ROARING_FLAME_SUMMON:
                            for (ThreatContainer::StorageType::const_iterator i = m_threatlist.begin(); i != m_threatlist.end(); ++i)
                            {
                                Unit* unit = Unit::GetUnit(*me, (*i)->getUnitGuid());
                                if (unit && unit->HasAura(SPELL_NOISY)) // You rang? :)
                                {
                                    me->SummonCreature(NPC_ROARING_FLAME_TARGET, unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 30000);
                                }
                                else
                                {                                
                                     if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
                                        me->SummonCreature(NPC_ROARING_FLAME_TARGET, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 30000);
                                }
                            }        
                            events.ScheduleEvent(EVENT_ROARING_FLAME, 500);
                            return;

                        case EVENT_ROARING_FLAME:
                            if (Unit* roaring = me->FindNearestCreature(NPC_ROARING_FLAME_TARGET, 100.0f))
                                DoCast(roaring, SPELL_ROARING_FLAME_BREATH_DUMMY);
                            return;

                        case EVENT_SONAR_BOMB:
                            SelectTargetList(targets, RAID_MODE(3, 6), SELECT_TARGET_RANDOM, 100.0f, true);
                            if (!targets.empty())
                                for (std::list<Unit*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
                                    DoCast(*itr, SPELL_SONAR_BOMB);                     
                            events.ScheduleEvent(EVENT_SONAR_BOMB, 18000);
                            break;

                        case EVENT_LAND:
                            me->HandleEmote(EMOTE_ONESHOT_LAND);
                            me->SetDisableGravity(false);
                            events.ScheduleEvent(EVENT_RETURN, 1000);
                            events.ScheduleEvent(EVENT_GROUND, 1500);
                            return;

                        case EVENT_RETURN:
                            me->SetReactState(REACT_PASSIVE);
                            me->AttackStop();
                            me->GetMotionMaster()->MovePoint(1, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() - 20.0f);
                            return;
                            
                        case EVENT_GROUND:
                            EnterPhaseGround();
                            return;
                    }
                }
            }            
        }
        void UpdateAI(const uint32 diff)
        {
            if (!UpdateVictim() || me->HasUnitState(UNIT_STATE_CASTING))
                return;

            if (Creature* Onyxia = me->FindNearestCreature(NPC_ONYXIA, 150.0f, true))
                if (Onyxia && !Onyxia->isInCombat() && said == false)
                {
                    Talk(SAY_AVOID_WIPE);
                    said = true;
                }

            if (phase == PHASE_GROUND && m_uiDistanceCheckTimer <= diff)
            {
                if (me->FindNearestCreature(NPC_ONYXIA, 50.0f, true) && onyxiaAlive && !me->HasAura(SPELL_CHILDREN_OF_DEATHWING_ONY))
                    me->AddAura(SPELL_CHILDREN_OF_DEATHWING_ONY, me);
                else if (!me->FindNearestCreature(NPC_ONYXIA, 50.0f, true) && onyxiaAlive)
                    if(me->HasAura(SPELL_CHILDREN_OF_DEATHWING_ONY))
                       me->RemoveAura(SPELL_CHILDREN_OF_DEATHWING_ONY);

                m_uiDistanceCheckTimer = 5000;
            }
            else m_uiDistanceCheckTimer -= diff;

            if (phase == PHASE_GROUND && m_uiOnyxiaCheckTimer <= diff && !secondPhase)
            {
                if (me->FindNearestCreature(NPC_ONYXIA, 150.0f, true))
                    onyxiaAlive = true;
                else
                {
                    onyxiaAlive = false;
                    Talk(SAY_AIR_PHASE);
                    if(me->HasAura(SPELL_CHILDREN_OF_DEATHWING_ONY))
                       me->RemoveAura(SPELL_CHILDREN_OF_DEATHWING_ONY);
                    events.ScheduleEvent(EVENT_LIFTOFF, 5000, PHASE_GROUND);
                    secondPhase = true;
                }

                m_uiOnyxiaCheckTimer = 5000;
            }
            else m_uiOnyxiaCheckTimer -= diff;

            if (phase == PHASE_FLIGHT && m_uiChromaticCheckTimer <= diff && !finalPhase)
            {
                if (!me->FindNearestCreature(NPC_CHROMATIC_PROTO, 150.0f, true))
                    events.ScheduleEvent(EVENT_LAND, 2000, PHASE_FLIGHT);
                finalPhase = true;

                m_uiChromaticCheckTimer = 5000;
            }
            else m_uiChromaticCheckTimer -= diff;

            events.Update(diff);

            while (uint32 eventId = events.ExecuteEvent())
            {
                switch (eventId)
                {
                    case EVENT_ELECTROCUTE:
                        if(electrocute == true)
                        {
                            DoCast(me, SPELL_ELECTROCUTE);
                            electrocute = false;
                        }
                        break;

                    case EVENT_INTRO:
                        me->HandleEmote(EMOTE_ONESHOT_LIFTOFF);
                        me->SetDisableGravity(true);
                        me->SendMovementFlagUpdate();
                        me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, 0x02);
                        me->GetMotionMaster()->MovePoint(1, -126.518f, -233.342f, 36.358f); // Position on top of raid.
                        break;

                    case EVENT_INTRO2:
                        Talk(SAY_AGGRO);
                        events.ScheduleEvent(EVENT_HAIL_OF_BONES, 100);
                        break;

                    case EVENT_HAIL_OF_BONES:
                        DoCast(me, SPELL_HAIL_OF_BONES);
                        break;

                    case EVENT_MOVE:
                        me->GetMotionMaster()->MovePoint(1, -100.123f, -221.522f, 7.156f); // Move down.
                        events.ScheduleEvent(EVENT_LANDING, 8000);                        
                        break;
            
                    case EVENT_LANDING:
                        me->HandleEmote(EMOTE_ONESHOT_LAND);
                        me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, 0x02);
                        me->SetDisableGravity(false);
                        me->SendMovementFlagUpdate();
                        EnterPhaseGround();
                        me->GetMotionMaster()->MoveChase(me->GetVictim());
                        me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                        break;

                    case EVENT_SHADOWFLAME_BREATH:
                        Talk(SAY_SHADOWFLAME);
                        DoCastVictim(SPELL_SHADOWFLAME_BREATH);   
                        events.ScheduleEvent(EVENT_SHADOWFLAME_BREATH, urand(10000, 12000));
                        break;
                         
                    case EVENT_SHADOW_COWARDICE:
                        if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
                            DoCast(target, SPELL_SHADOW_COWARDICE);                 
                        events.ScheduleEvent(EVENT_SHADOW_COWARDICE, urand(9000, 10000));
                        break;

                    case EVENT_LIFTOFF:
                        Talk(SAY_AIR_PHASE_2);
                        if(GameObject* elevator = me->FindNearestGameObject(207834, 200.0f))
                            elevator->SetGoState(GO_STATE_READY);

                        me->HandleEmote(EMOTE_ONESHOT_LIFTOFF);
                        me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, 0x02);
                        me->SetDisableGravity(true);
                        me->SendMovementFlagUpdate();
                        events.ScheduleEvent(EVENT_FLIGHT, 1500);
                        events.ScheduleEvent(EVENT_AIR, 2000);
                        break;

                    case EVENT_FLIGHT:
                        me->SetReactState(REACT_PASSIVE);
                        me->AttackStop();
                        me->GetMotionMaster()->MovePoint(1, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 30.0f);
                        break;

                    case EVENT_AIR:
                        EnterPhaseAir();
                        break;

                    case EVENT_SUMMON_CHROMATIC:
                        me->SummonCreature(NPC_CHROMATIC_PROTO, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_MANUAL_DESPAWN);
                        break;

                    case EVENT_SHADOWFLAME_BARRAGE:
                        if(Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 200.0f, true))
                            DoCast(target, SPELL_SHADOWFLAME_BARRAGE);
                        events.ScheduleEvent(EVENT_SHADOWFLAME_BARRAGE, urand(8000, 11000));
                        break;

                    case EVENT_LAND:
                        me->HandleEmote(EMOTE_ONESHOT_LAND);
                        me->SetDisableGravity(false);
                        me->SendMovementFlagUpdate();
                        me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, 0x02);
                        events.ScheduleEvent(EVENT_RETURN, 1000);
                        events.ScheduleEvent(EVENT_GROUND, 1500);
                        break;

                    case EVENT_RETURN:
                        me->SetReactState(REACT_PASSIVE);
                        me->AttackStop();
                        me->GetMotionMaster()->MovePoint(1, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() - 30.0f);
                        break;
            
                    case EVENT_GROUND:
                        EnterPhaseFinal();
                        me->SetReactState(REACT_AGGRESSIVE);
                        AttackStart(me->GetVictim());
                        me->GetMotionMaster()->MoveChase(me->GetVictim());
                        if(GameObject* elevator = me->FindNearestGameObject(207834, 200.0f))
                            elevator->SetGoState(GO_STATE_ACTIVE);

                        Talk(SAY_FINAL_PHASE);
                        break;

                    case EVENT_TAIL_LASH:
                        DoCast(me, SPELL_TAIL_LASH);
                        events.ScheduleEvent(EVENT_TAIL_LASH, urand(8000, 11000));
                        break;

                    case EVENT_SHADOWBLAZE:
                        if(Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 200.0f, true))
                            DoCast(target, SPELL_SHADOWBLAZE_SPARK);
                        events.ScheduleEvent(EVENT_TAIL_LASH, urand(18000, 21000));
                        break;

                    case EVENT_REVIVE_SKELETONS:
                    {
                        std::list<Creature*> creatures;
                        GetCreatureListWithEntryInGrid(creatures, me, 41918, 200.0f);

                        if (!creatures.empty())
                        for (std::list<Creature*>::iterator iter = creatures.begin(); iter != creatures.end(); ++iter)
                        {
                            DoCast((*iter), SPELL_ANIMATE_BONES, true);
                            (*iter)->SetReactState(REACT_AGGRESSIVE);
                            (*iter)->RemoveAura(SPELL_DIE_VISUAL);
                        }
                    }
                        break;
                }
            }

            if (phase == PHASE_GROUND || phase == PHASE_FINAL)
                DoMeleeAttackIfReady();
        }