Lich King Script Need help menu

Shout-Out

User Tag List

Results 1 to 2 of 2
  1. #1
    Nightman12's Avatar Private
    Reputation
    1
    Join Date
    Aug 2011
    Posts
    1
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Lich King Script Need help

    Code:
    /*
     * Copyright (C) 2008-2011 TrinityCore <http://www.trinitycore.org/>
     *
     * 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, see <http://www.gnu.org/licenses/>.
     */
    
    #include "ObjectMgr.h"
    #include "ScriptMgr.h"
    #include "ScriptedCreature.h"
    #include "SpellScript.h"
    #include "SpellAuraEffects.h"
    #include "icecrown_citadel.h"
    #include "Group.h"
    #include "MapManager.h"
    
    #define GOSSIP_MENU 10700
    #define GOSSIP_START_EVENT "We are prepared, Highlord. Let us battle for the fate of Azeroth! For the light of dawn!"
    
    enum eAchievements
    {
        ACHIEV_BEEN_WAITING_A_LONG_TIME_FOR_THIS_10    = 4601,
        ACHIEV_BEEN_WAITING_A_LONG_TIME_FOR_THIS_25    = 4621,
        ACHIEV_NECK_DEEP_IN_VILE_10                    = 4581,
        ACHIEV_NECK_DEEP_IN_VILE_25                    = 4622,
        ACHIEV_THE_FROZEN_THRONE_10                    = 4530,
        ACHIEV_THE_FROZEN_THRONE_25                    = 4597
    };
    
    enum eEnums
    {
        SOUND_ENDING_7_KING      = 17360,
        MOVIE_ID_ARTHAS_DEATH    = 16
    };
    
    enum Yells
    {
        SAY_INTRO_1_KING            = -1810001,
        SAY_INTRO_2_TIRION          = -1810002,
        SAY_INTRO_3_KING            = -1810003,
        SAY_INTRO_4_TIRION          = -1810004,
        SAY_INTRO_5_KING            = -1810005,
        SAY_AGGRO                   = -1810006,
        SAY_REMORSELESSS_WINTER     = -1810007,
        SAY_RANDOM_1                = -1810008,
        SAY_RANDOM_2                = -1810009,
        SAY_KILL_1                  = -1810010,
        SAY_KILL_2                  = -1810011,
        SAY_BERSERK                 = -1810012,
        SAY_ENDING_1_KING           = -1810013,
        SAY_ENDING_2_KING           = -1810014,
        SAY_ENDING_3_KING           = -1810015,
        SAY_ENDING_4_KING           = -1810016,
        SAY_ENDING_5_TIRION         = -1810017,
        SAY_ENDING_6_KING           = -1810018,
        SAY_ENDING_8_TIRION         = -1810020,
        SAY_ENDING_9_FATHER         = -1810021,
        SAY_ENDING_10_TIRION        = -1810022,
        SAY_ENDING_11_FATHER        = -1810023,
        SAY_ENDING_12_KING          = -1810024,
        SAY_DEATH_KING              = -1810025,
        SAY_ESCAPE_FROSTMOURNE      = -1810026,
        SAY_HARVEST_SOUL            = -1810027,
        SAY_DEVOURED_FROSTMOURNE    = -1810028,
        SAY_SUMMON_VALKYR           = -1810029,
        SAY_BROKEN_ARENA            = -1810030,
        SAY_10_PERCENT              = -1810031,
        SAY_EMOTE_DEFILE            = -1810032,
    };
    
    enum ePhases
    {
        PHASE_1 = 1,
        PHASE_2_TRANSITION,
        PHASE_3,
        PHASE_4_TRANSITION,
        PHASE_5,
        PHASE_6_ENDING
    };
    enum eEvents
    {
        // Lich King
        EVENT_SPEECH                              = 1,
        EVENT_BERSERK                             = 2,
        EVENT_CHECK_ALIVE_PLAYERS                 = 3,
        EVENT_SUMMON_SHAMBLING_HORROR             = 4,
        EVENT_SUMMON_DRUDGE_GHOULS                = 5,
        EVENT_INFEST                              = 6,
        EVENT_NECROTIC_PLAGUE                     = 7,
        EVENT_SHADOW_TRAP                         = 8,
        //Transition phase events
        EVENT_SUMMON_RAGING_SPIRIT                = 9,
        EVENT_SUMMON_ICE_SPHERE                   = 10,
        EVENT_TRANSITION_PHASE_END                = 11,
        EVENT_PAIN_AND_SUFFERING                  = 12,
        //Phase three events
        EVENT_SUMMON_VAL_KYR_SHADOWGUARD          = 13,
        EVENT_DEFILE                              = 14,
        EVENT_SOUL_REAPER                         = 15,
        //Phase five events
        EVENT_SUMMON_VILE_SPIRITS                 = 16,
        EVENT_HARVEST_SOUL                        = 17,
        EVENT_KILL_FROSTMOURNE_PLAYERS            = 18,
    
        // Valkyr Shadowguard
        EVENT_MOVE_TO_PLATFORM_EDGE               = 19,
        EVENT_SIPHON_LIFE                         = 20,
        EVENT_CHECK_AT_PLATFORM_EDGE              = 21,
        EVENT_CHARGE_PLAYER                       = 22,
    
        // Vile Spirit
        EVENT_BECOME_ACTIVE                       = 23,
        EVENT_DESPAWN                             = 24,
        EVENT_MOVE_RANDOM                         = 25,
        EVENT_CHECK_PLAYER_IN_FROSTMOURNE_ROOM    = 26,
    
        // Shambling Horror
        EVENT_ENRAGE                              = 27,
        EVENT_SHOCKWAVE                           = 28,
    
        // Raging Spirit
        EVENT_SOUL_SHRIEK                         = 29,
    
        // Ice Sphere
        EVENT_MOVE_FORWARD                        = 30,
        EVENT_ACTIVATE                            = 31,
    
        // Spirit Warden
        EVENT_SOUL_RIP                            = 32,
        EVENT_DESTROY_SOUL                        = 33,
        EVENT_CHECK_SOUL_RIP_DISPELLED            = 34,
    
        // Terenas Menethil
        EVENT_GREET_PLAYER                        = 35, //Yell "You have come to bring Arthas to justice? To see the Lich King destroyed?"
        EVENT_ENCOURAGE_PLAYER_TO_ESCAPE          = 36, //Yell "First, you must escape Frostmourne's hold or be damned as I am; trapped within this cursed blade for all eternity."
        EVENT_ASK_PLAYER_FOR_AID                  = 37, //Yell "Aid me in destroying these tortured souls! Together we will loosen Frostmourne's hold and weaken the Lich King from within!"
        EVENT_CHECK_SPIRIT_WARDEN_HEALTH          = 38,
    
        EVENT_RESTART_COMBAT_MOVEMENT             = 39,
    };
    
    enum Spells
    {
        SPELL_DEATH_GRIP                                       = 49560,
        SPELL_SUMMON_SHAMBLING_HORROR                          = 70372,
        SPELL_SUMMON_DRUDGE_GHOULS                             = 70358,
        SPELL_SUMMON_ICE_SPEHERE                               = 69104,
        SPELL_SUMMON_RAGING_SPIRIT                             = 69200,
        SPELL_SUMMON_VALKYR                                    = 74361,
        SPELL_SUMMON_DEFILE                                    = 72762,
        SPELL_SUMMON_VILE_SPIRIT                               = 70498,
        SPELL_SUMMON_BROKEN_FROSTMOURNE                        = 73017,
        SPELL_SUMMON_SHADOW_TRAP                               = 73539,
        SPELL_SHADOW_TRAP_INTRO                                = 73530,
        SPELL_SHADOW_TRAP_PERIODIC                             = 73525,
        SPELL_SHADOW_TRAP_EFFECT                               = 73529,
        SPELL_INFEST_10N                                       = 70541,
        SPELL_INFEST_10H                                       = 73780,
        SPELL_INFEST_25N                                       = 73779,
        SPELL_INFEST_25H                                       = 73781,
        SPELL_NECROTIC_PLAGUE_10N                              = 70337,
        SPELL_NECROTIC_PLAGUE_10H                              = 73913,
        SPELL_NECROTIC_PLAGUE_25N                              = 73912,
        SPELL_NECROTIC_PLAGUE_25H                              = 73914,
        SPELL_NECROTIC_PLAGUE_IMMUNITY                         = 72846,
        SPELL_NECROTIC_PLAGUE_EFFECT                           = 70338,
        SPELL_PLAGUE_SIPHON                                    = 74074,
        SPELL_REMORSELESS_WINTER_10N                           = 72259,
        SPELL_REMORSELESS_WINTER_10H                           = 74274,
        SPELL_REMORSELESS_WINTER_25N                           = 74273,
        SPELL_REMORSELESS_WINTER_25H                           = 74275,
        SPELL_REMORSELESS_WINTER_DAMAGE                        = 68983,
        SPELL_PAIN_AND_SUFFERING_10N                           = 72133,
        SPELL_PAIN_AND_SUFFERING_10H                           = 73789,
        SPELL_PAIN_AND_SUFFERING_25N                           = 73788,
        SPELL_PAIN_AND_SUFFERING_25H                           = 73790,
        SPELL_WINGS_OF_THE_DAMNED                              = 74352,
        SPELL_SOUL_REAPER_10N                                  = 69409,
        SPELL_SOUL_REAPER_10H                                  = 73798,
        SPELL_SOUL_REAPER_25N                                  = 73797,
        SPELL_SOUL_REAPER_25H                                  = 73799,
        SPELL_SOUL_REAPER_HASTE_AURA                           = 69410,
        SPELL_HARVEST_SOUL_TELEPORT                            = 71372,
        SPELL_HARVEST_SOULS_10N                                = 68980,
        SPELL_HARVEST_SOULS_10H                                = 74296,
        SPELL_HARVEST_SOULS_25N                                = 74325,
        SPELL_HARVEST_SOULS_25H                                = 74297,
        SPELL_HARVESTED_SOUL_NORMAL                            = 74321,
        SPELL_HARVESTED_SOUL_HEROIC                            = 74323,
        SPELL_HARVEST_SOUL_HEROIC_FROSTMOURNE_PLAYER_DEBUFF    = 73655,
        SPELL_HARVESTED_SOUL_FROSTMOURNE_PLAYER_BUFF           = 74322,
        SPELL_FROSTMOURNE_ROOM_TELEPORT_VISUAL                 = 73078,
        SPELL_QUAKE                                            = 72262,
        SPELL_RAISE_DEAD                                       = 71769,
        SPELL_RAISE_DEAD_EFFECT                                = 72376,
        SPELL_BROKEN_FROSTMOURNE                               = 72398,
        SPELL_BOOM_VISUAL                                      = 72726,
        SPELL_ICEBLOCK_TRIGGER                                 = 71614,
        SPELL_TIRION_LIGHT                                     = 71797,
        SPELL_FROSTMOURNE_TRIGGER                              = 72405,
        SPELL_DISENGAGE                                        = 61508,
        SPELL_FURY_OF_FROSTMOURNE                              = 72350,
        SPELL_REVIVE                                           = 72429,
        SPELL_REVIVE_EFFECT                                    = 72423,
        SPELL_CLONE_PLAYER                                     = 57507,
        SPELL_DEFILE                                           = 72743,
        SPELL_DEFILE_DAMAGE                                    = 72754,
        SPELL_DEFILE_INCREASE                                  = 72756,
        SPELL_ICE_PULSE                                        = 69091,
        SPELL_ICE_BURST                                        = 69108,
        SPELL_LIFE_SIPHON                                      = 73783,
        SPELL_SPIRIT_BURST                                     = 70503,
        SPELL_VILE_SPIRIT_DISTANCE_CHECK                       = 70502,
        SPELL_ICE_BURST_DISTANCE_CHECK                         = 69109,
        SPELL_VILE_SPIRIT_ACTIVE                               = 72130,
        SPELL_RAGING_VISUAL                                    = 69198,
        SPELL_REMOVE_WEAPON                                    = 72399,
        SPELL_DROP_FROSTMOURNE                                 = 73017,
        SPELL_SUMMON_FROSTMOURNE_TRIGGER                       = 72407,
        SPELL_WMO_INTACT                                       = 50176,
        SPELL_WMO_DESTROY                                      = 50177,
        SPELL_WMO_REBUILD                                      = 50178,
        SPELL_SUMMON_MENETHIL                                  = 72420,
        SPELL_MENETHIL_VISUAL                                  = 72372,
        SPELL_VALKYR_CARRY_CAN_CAST                            = 74506,
        SPELL_VALKYR_GRAB_PLAYER                               = 68985,
        SPELL_RIDE_VEHICLE                                     = 46598,
        SPELL_VALKYR_TARGET_SEARCH                             = 69030,
        SPELL_VALKYR_CHARGE                                    = 74399,
        SPELL_VALKYR_EJECT_PASSENGER                           = 68576,
        SPELL_LIGHTS_BLESSING                                  = 71773,
        SPELL_EMOTE_SHOUT                                      = 73213,
        SPELL_RAGING_GHOUL_VISUAL                              = 69636,
        SPELL_RISEN_WITCH_DOCTOR_SPAWN                         = 69639,
        SPELL_ICE_SPHERE_VISUAL                                = 69090,
        SPELL_TIRION_JUMP                                      = 71811,
        SPELL_CANT_RESSURECT_AURA                              = 72431,
        SPELL_FROSTMOURNE_DESPAWN                              = 72726,
        SPELL_SUMMON_FROSTMOURNE                               = 74081,
        SPELL_SOUL_EFFECT                                      = 72305,
        SPELL_IN_FROSTMOURNE_ROOM                              = 74276,
        SPELL_VILE_SPIRIT_TARGET_SEARCH                        = 70501,
        SPELL_SOUL_RIP                                         = 69397, 
        SPELL_DESTROY_SOUL                                     = 74086,
        SPELL_DARK_HUNGER                                      = 69383,
        SPELL_DARK_HUNGER_HEAL_EFFECT                          = 69384,
        SPELL_LIGHT_S_FAVOR                                    = 69382,
        SPELL_RESTORE_SOUL                                     = 72595,
        SPELL_FEIGN_DEATH                                      = 5384,
        SPELL_SHOCKWAVE                                        = 72149,
        SPELL_ENRAGE                                           = 72143,
        SPELL_FRENZY                                           = 28747,
        SPELL_SOUL_SHRIEK                                      = 69242,
        SPELL_FURY_OF_FROSTMOURNE_NORES                        = 72351,
        SPELL_KNOCKDOWN                                        = 68848,
    };
    
    enum eActions
    {
        ACTION_PHASE_SWITCH_1        = 1, //phase 1 and 3
        ACTION_PHASE_SWITCH_2,            //phase 2 and 4
        ACTION_START_EVENT,
        ACTION_RESET,
        ACTION_CANCEL_ALL_TRANSITION_EVENTS,
        ACTION_DESPAWN,
        ACTION_CHARGE_PLAYER,
        ACTION_PREPARE_FROSTMOURNE_ROOM,
        ACTION_ATTACK_SPIRIT_WARDEN,
        ACTION_ATTACK_TERENAS_FIGHTER,
    };
    
    enum eSetGuid
    {
        TYPE_VICTIM = 1
    };
    
    enum ePoints
    {
        POINT_MOVE_NEAR_RANDOM           = 1,
        POINT_START_EVENT_1              = 3659700,
        POINT_PLATFORM_CENTER            = 3659701,
        POINT_PLATFORM_END               = 3659702,
        POINT_VALKYR_END                 = 3659703,
        POINT_VALKYR_ZET                 = 3659704,
        POINT_VALKYR_CONTINUE_FLYING     = 3659705
    };
    
    enum eLKData
    {
        DATA_PHASE = 2
    };
    
    struct Position StartEvent[]=
    {
        {465.0731f, -2123.473f, 1040.8569f},
        {462.8351f, -2123.673f, 1040.9082f},
        {461.5851f, -2123.673f, 1041.4082f},
        {445.5851f, -2123.673f, 1056.1582f},
        {436.0851f, -2123.673f, 1064.6582f}
    };
    
    struct Position MovePos[]=
    {
        {459.039f, -2124.21f, 1040.860f, 0.0f}, // move
        {503.156f, -2124.51f, 1040.860f, 0.0f}, // move center X: 505.2118 Y: -2124.353 Z: 840.9403
        {490.110f, -2124.98f, 1040.860f, 0.0f}, // move tirion frostmourne
        {467.069f, -2123.58f, 1040.857f, 0.0f}, // move tirion attack
        {498.004f, 2201.57f, 1046.093f, 0.0f},  // move valkyr
        {489.297f, -2124.84f, 1040.857f, 0.0f}, //start event tirion move 1
        {503.682f, -2126.63f, 1040.940f, 0.0f}, //boss escapes after wipe
        {508.989f, -2124.55f, 1045.356f, 0.0f}, //boss levitates above the frostmourne
        {505.212f, -2124.35f, 1040.94f, 3.14159f},
        {491.759f, -2124.86f, 1040.86f, 0.0f},  // tirion talk position
        {517.482f, -2124.91f, 1040.86f, 0.0f}, // Jump position
        {529.413f, -2124.94f, 1040.86f, 0.0f}, // Knockback position
    };
    struct Position FrostmourneRoom[] = 
    {
        {520.0f, -2524.0f, 1051.0f, 0.0f}, //Place where player is teleported to
        {539.1f, -2513.0f, 1042.6f, 2.8f}, //Home position of the Spirit Warden
        {508.4f, -2506.2f, 1042.6f, 6.0f}, //Home position of Terenas Menethil
    };
    
    Player* SelectRandomPlayerFromList(TPlayerList& players)
    {
        if (players.empty())
            return NULL;
    
        TPlayerList::iterator it = players.begin();
        std::advance(it, urand(0, players.size()-1));
        return* it;
    }
    
    Player* SelectRandomPlayerInTheMap(Map* map)
    {
        TPlayerList players = GetPlayersInTheMap(map);
        return SelectRandomPlayerFromList(players);
    }
    
    Player* SelectRandomAttackablePlayerInTheMap(Map* map)
    {
        TPlayerList players = GetAttackablePlayersInTheMap(map);
        return SelectRandomPlayerFromList(players);
    }
    
    class boss_the_lich_king : public CreatureScript
    {
        public:
            boss_the_lich_king() : CreatureScript("boss_the_lich_king") { }
    
            struct boss_the_lich_kingAI : public BossAI
            {
                boss_the_lich_kingAI(Creature* creature) : BossAI(creature, DATA_THE_LICH_KING), summons(me)
                {
                    instance = me->GetInstanceScript();
                }
    
                uint32 GetData(uint32 dataId)
                {
                    if (dataId == DATA_PHASE)
                        return GetPhase(events);
    
                    return BossAI::GetData(dataId);
                }
    
                void Reset()
                {
                    me->SetReactState(REACT_PASSIVE);
                    me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                    SetEquipmentSlots(false, 49706, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE);
    
                    if(me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE)
                        me->GetMotionMaster()->MovementExpired();
    
                    if (SpellEntry* spellDefile = GET_SPELL(SPELL_SUMMON_DEFILE))
                        spellDefile->DurationIndex = 3;
    
                    if (SpellEntry* lock = GET_SPELL(SPELL_ICEBLOCK_TRIGGER))
                        lock->Targets = 6; //target chain damage
    
                    if (SpellEntry* reaper = GET_SPELL(SPELL_SOUL_REAPER_HASTE_AURA))
                        reaper->Targets = 1;
    
                    if (SpellEntry* plague = GET_SPELL(SPELL_PLAGUE_SIPHON)) //hack
                        plague->Targets = 18;
    
                    if (SpellEntry *shadowEffect = GET_SPELL(SPELL_SHADOW_TRAP_EFFECT))
                        shadowEffect->EffectRadiusIndex[1] = 13;
    
                    if (SpellEntry* raging = GET_SPELL(SPELL_SUMMON_RAGING_SPIRIT))
                    {
                        raging->DurationIndex = 28;
                        raging->Effect[0] = 6;
                    }
    
                    if (SpellEntry* furyOfFrostmourne = GET_SPELL(SPELL_FURY_OF_FROSTMOURNE))
                    {
                        furyOfFrostmourne->Effect[0] = SPELL_EFFECT_APPLY_AURA;
                        furyOfFrostmourne->Effect[1] = SPELL_EFFECT_INSTAKILL;
                        furyOfFrostmourne->EffectRadiusIndex[0] = 22;
                        furyOfFrostmourne->EffectRadiusIndex[1] = 22;
                        furyOfFrostmourne->EffectImplicitTargetA[0] = TARGET_SRC_CASTER;
                        furyOfFrostmourne->EffectImplicitTargetB[0] = TARGET_UNIT_AREA_ENEMY_SRC;
                        furyOfFrostmourne->EffectAmplitude[0] = 50000;
                    }
                    if (SpellEntry *furyOfFrostmournenores = GET_SPELL(SPELL_FURY_OF_FROSTMOURNE_NORES))
                    {
                        furyOfFrostmournenores->EffectRadiusIndex[0] = 22;
                    }
                    if(SpellEntry* spellRaiseDead = GET_SPELL(SPELL_RAISE_DEAD_EFFECT))
                    {
                        spellRaiseDead->EffectRadiusIndex[0] = 22;
                    }
                    if (SpellEntry* massResurrection = GET_SPELL(SPELL_REVIVE))
                    {
                        massResurrection->EffectRadiusIndex[0] = 4;
                        massResurrection->AttributesEx3 |= SPELL_ATTR3_REQUIRE_DEAD_TARGET;
                    }
    
                    if (SpellEntry* defileDamage = GET_SPELL(SPELL_DEFILE_DAMAGE))
                    {
                        defileDamage->EffectImplicitTargetA[0] = TARGET_UNIT_TARGET_ENEMY;
                        defileDamage->EffectImplicitTargetB[1] = TARGET_UNIT_TARGET_ENEMY;
                    }
    
                    if (SpellEntry* remorselessWinter = GET_SPELL(SPELL_REMORSELESS_WINTER_10N || SPELL_REMORSELESS_WINTER_10H || SPELL_REMORSELESS_WINTER_25N || SPELL_REMORSELESS_WINTER_25H))
                        remorselessWinter->Effect[2] = 0;
    
                    if (instance)
                        instance->SetBossState(DATA_THE_LICH_KING, NOT_STARTED);
    
                    me->SetReactState(REACT_PASSIVE);
                    me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                    if (Creature* tirion = Unit::GetCreature(*me, uiTirionGUID))
                    {
                        tirion->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
                    }
    
                    uiStage = 1;
                }
    
                void EnterEvadeMode()
                {
                    events.Reset();
                    BossAI::EnterEvadeMode();
                    me->SetReactState(REACT_PASSIVE);
                    me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                    if (Creature* tirion = Unit::GetCreature(*me, uiTirionGUID))
                    {
                        tirion->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
                    }
                }
    
                void EnterCombat(Unit* /*pWho*/)
                {
                    if (uiStage > 1)
                        return;
    
                    instance->SetData(DATA_BEEN_WAITING_ACHIEVEMENT, NOT_STARTED);
                    instance->SetData(DATA_NECK_DEEP_ACHIEVEMENT, DONE);
    
                    uiEndingTimer = 1000;
                    uiTirionGUID = 0;
                    isSwitching = false;
                    imSummoning = false;
                    isAboutToDie = false;
                    events.Reset();
                    events.SetPhase(PHASE_1);
                    events.ScheduleEvent(EVENT_BERSERK, 900000, PHASE_1);
                    events.ScheduleEvent(EVENT_BERSERK, 900000, PHASE_2_TRANSITION);
                    events.ScheduleEvent(EVENT_BERSERK, 900000, PHASE_3);
                    events.ScheduleEvent(EVENT_BERSERK, 900000, PHASE_4_TRANSITION);
                    events.ScheduleEvent(EVENT_BERSERK, 900000, PHASE_5);
    
                    events.ScheduleEvent(EVENT_CHECK_ALIVE_PLAYERS, 5000, PHASE_1);
                    events.ScheduleEvent(EVENT_CHECK_ALIVE_PLAYERS, 5000, PHASE_2_TRANSITION);
                    events.ScheduleEvent(EVENT_CHECK_ALIVE_PLAYERS, 5000, PHASE_3);
                    events.ScheduleEvent(EVENT_CHECK_ALIVE_PLAYERS, 5000, PHASE_4_TRANSITION);
                    events.ScheduleEvent(EVENT_CHECK_ALIVE_PLAYERS, 5000, PHASE_5);
    
                    events.ScheduleEvent(EVENT_SUMMON_DRUDGE_GHOULS, 10000, 0, PHASE_1);
                    events.ScheduleEvent(EVENT_INFEST, 5000, 0, PHASE_1);
                    events.ScheduleEvent(EVENT_SUMMON_SHAMBLING_HORROR, 20000, 0, PHASE_1);
                    events.ScheduleEvent(EVENT_NECROTIC_PLAGUE, 30000, 0, PHASE_1);
    
                    if (IsHeroic())
                        events.ScheduleEvent(EVENT_SHADOW_TRAP, 10000, 0, PHASE_1);
    
                    //DoScriptText(SAY_AGGRO, me);
                    DoCast(me, SPELL_NECROTIC_PLAGUE_IMMUNITY);
    
                    if (instance)
                        uiTirionGUID = instance->GetData64(DATA_TIRION);
    
                    if (instance)
                    {
                        instance->SetBossState(DATA_THE_LICH_KING, IN_PROGRESS);
                        instance->SetData(DATA_THE_LICH_KING, IN_PROGRESS);
                    }
                }
    
                void Cleanup()
                {
                    instance->DoRemoveAurasDueToSpellOnPlayers(RAID_MODE(SPELL_INFEST_10N, SPELL_INFEST_25N, SPELL_INFEST_10H, SPELL_INFEST_25H));
                    instance->DoCastSpellOnPlayers(FROZEN_THRONE_TELEPORT);
                    instance->DoRemoveAurasDueToSpellOnPlayers(RAID_MODE(SPELL_NECROTIC_PLAGUE_10N, SPELL_NECROTIC_PLAGUE_25N, SPELL_NECROTIC_PLAGUE_10H, SPELL_NECROTIC_PLAGUE_25H));
                    instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_NECROTIC_PLAGUE_EFFECT);
                    instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_ICE_PULSE);
                    instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_IN_FROSTMOURNE_ROOM);
                    summons.DespawnAll();
                }
    
                void JustDied(Unit* /*killer*/)
                {
                    if (!instance)
                        return;
    
                    instance->SetBossState(DATA_THE_LICH_KING, DONE);
                    instance->SetData(DATA_THE_LICH_KING, DONE);
                    //instance->DoCompleteAchievement(RAID_MODE<uint32>(ACHIEV_THE_FROZEN_THRONE_10, ACHIEV_BANE_OF_THE_FALLEN_KING, ACHIEV_THE_FROZEN_THRONE_25, ACHIEV_THE_LIGHT_OF_DAWN));
    
                    if (instance->GetData(DATA_BEEN_WAITING_ACHIEVEMENT) == DONE)
                        instance->DoCompleteAchievement(RAID_MODE(ACHIEV_BEEN_WAITING_A_LONG_TIME_FOR_THIS_10,ACHIEV_BEEN_WAITING_A_LONG_TIME_FOR_THIS_25));
    
                    if (instance->GetData(DATA_NECK_DEEP_ACHIEVEMENT) == DONE)
                        instance->DoCompleteAchievement(RAID_MODE(ACHIEV_NECK_DEEP_IN_VILE_10,ACHIEV_NECK_DEEP_IN_VILE_25));
    
                    Cleanup();
    
                    TPlayerList players = GetPlayersInTheMap(me->GetMap());
    
                    for (TPlayerList::iterator it = players.begin(); it != players.end(); ++it)
                        if ((*it)->isAlive())
                            (*it)->SendMovieStart(MOVIE_ID_ARTHAS_DEATH);
    
                    if (Creature* father = me->FindNearestCreature(NPC_TERENAS_MENETHIL, 25.0f, true))
                        father->SetVisible(false);
    
                    if (Creature* tirion = Unit::GetCreature(*me, uiTirionGUID))
                    {
                        tirion->GetMotionMaster()->MovePoint(0, MovePos[1]);
                        tirion->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE);
                        tirion->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
                        tirion->SetReactState(REACT_PASSIVE);
                        tirion->RemoveAllAuras();
                    }
                }
    
                void MovementInform(uint32 type, uint32 id)
                {
                    if (type != POINT_MOTION_TYPE)
                        return;
    
                    if (instance->GetBossState(DATA_THE_LICH_KING) == DONE)
                        return;
    
                    switch(id)
                    {
                        case POINT_PLATFORM_CENTER:
                        {
                            me->GetMotionMaster()->MovementExpired();
                            uint32 curPhase = GetPhase(events);
                            events.ScheduleEvent(EVENT_PAIN_AND_SUFFERING, 2500 + 2000, 0, curPhase);
                            events.ScheduleEvent(EVENT_SUMMON_ICE_SPHERE, 2500 + 7000, 0, curPhase);
                            events.ScheduleEvent(EVENT_SUMMON_RAGING_SPIRIT, 6000, 0, curPhase);
                            events.ScheduleEvent(EVENT_TRANSITION_PHASE_END, 60000, 0, curPhase);
                            DoScriptText(SAY_REMORSELESSS_WINTER, me);
                            DoCast(me, RAID_MODE(SPELL_REMORSELESS_WINTER_10N, SPELL_REMORSELESS_WINTER_25N, SPELL_REMORSELESS_WINTER_10H, SPELL_REMORSELESS_WINTER_25H));
                            break;
                        }
                    }
                }
    
                void JustReachedHome()
                {
                    if (!instance)
                        return;
    
                    instance->SetBossState(DATA_THE_LICH_KING, FAIL);
                    instance->SetData(DATA_THE_LICH_KING, FAIL);
                    Cleanup();
    
                    if (Creature* tirion = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_TIRION)))
                        tirion->AI()->DoAction(ACTION_RESET);
    
                    events.Reset();
                }
    
                void KilledUnit(Unit* victim)
                {
                    if (GetPhase(events) != PHASE_6_ENDING && victim->GetTypeId() == TYPEID_PLAYER)
                        DoScriptText(RAND(SAY_KILL_1, SAY_KILL_2), me);
                }
    
                void JustSummoned(Creature* summoned)
                {
                    summons.Summon(summoned);
                    switch(summoned->GetEntry())
                    {
                        case NPC_RAGING_SPIRIT:
                            summoned->CastSpell(summoned, SPELL_NECROTIC_PLAGUE_IMMUNITY, true);
                            if (Unit *target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
                            {
                                target->CastSpell(summoned, SPELL_RAGING_VISUAL, true);
                                summoned->AI()->AttackStart(target);
    
                                // Hack Fix: If we cloned a non player unit, the model would be wrong
                                // so set it to a generic one
                                if(target->GetTypeId() != TYPEID_PLAYER)
                                    target->SetDisplayId(278);
                            }
                            break;
                        case NPC_DEFILE:
                        {
                            Position pos;
                            summoned->GetPosition(&pos);
                            pos.m_positionZ += 0.75f;
                            summoned->SetPosition(pos, true);
                            summoned->SetInCombatWithZone();
                            break;
                        }
                        case NPC_TRIGGER:
                            summoned->AI()->AttackStart(me);
                            summoned->SetVisible(false);
                            summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                            break;
                        case NPC_FROSTMOURNE_TRIGGER:
                        {
                            summoned->CastSpell(summoned, SPELL_BROKEN_FROSTMOURNE, false);
                            summoned->CastSpell(summoned, SPELL_FROSTMOURNE_TRIGGER, false);
                            //summoned->SetVisible(false);
                            break;
                        }
                        /*case NPC_TERENAS_MENETHIL:
                        {
                            DoScriptText(SAY_ENDING_9_FATHER, summoned);
                            summoned->CastSpell(summoned, SPELL_MENETHIL_VISUAL, true);
                            summoned->CastSpell(summoned, SPELL_REVIVE, true);
                            TPlayerList players = GetPlayersInTheMap(me->GetMap());
    
                            for (TPlayerList::iterator it = players.begin(); it != players.end(); ++it)
                                summoned->CastSpell(*it, SPELL_REVIVE_EFFECT, true);
                            break;
                        }*/
                        case NPC_VALKYR:
                        {
                            if (Unit *valkyrTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true))
                                summoned->AI()->SetGUID(valkyrTarget->GetGUID(), TYPE_VICTIM);
                            else
                            {
                                //There is no target - unsummon valkyr
                                summoned->Kill(summoned);
                                summoned->DespawnOrUnsummon();
                            }
                            break;
                        }
                        case NPC_DRUDGE_GHOUL:
                            summoned->CastSpell(summoned, SPELL_RAGING_GHOUL_VISUAL, true);
    
                            if (Unit* pVictim = SelectTarget(SELECT_TARGET_RANDOM))
                                summoned->AI()->AttackStart(pVictim);
                            break;
                        case NPC_SHAMBLING_HORROR:
                            summoned->CastSpell(summoned, SPELL_RISEN_WITCH_DOCTOR_SPAWN, true);
    
                            if (Unit* pVictim = SelectTarget(SELECT_TARGET_RANDOM))
                                summoned->AI()->AttackStart(pVictim);
                            break;
                    }
                }
    
                void DoAction(const int32 action)
                {
                    switch(action)
                    {
                        case ACTION_PREPARE_FROSTMOURNE_ROOM:
                        {
                            Creature* terenasFighter = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_TERENAS_FIGHTER));
                            Creature* spiritWarden = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_SPIRIT_WARDEN));
    
                            if (terenasFighter && spiritWarden)
                            {
                                terenasFighter->Respawn();
                                spiritWarden->Respawn();
                                terenasFighter->AI()->DoAction(ACTION_ATTACK_SPIRIT_WARDEN);
                                spiritWarden->AI()->DoAction(ACTION_ATTACK_TERENAS_FIGHTER);
                                events.ScheduleEvent(EVENT_KILL_FROSTMOURNE_PLAYERS, 60000, 0, PHASE_5);
                            }
                            break;
                        }
                        case ACTION_CANCEL_ALL_TRANSITION_EVENTS:
                        {
                            events.CancelEvent(EVENT_PAIN_AND_SUFFERING);
                            events.CancelEvent(EVENT_SUMMON_ICE_SPHERE);
                            events.CancelEvent(EVENT_SUMMON_RAGING_SPIRIT);
                            events.CancelEvent(EVENT_TRANSITION_PHASE_END);
                            break;
                        }
                        case ACTION_PHASE_SWITCH_1:
                        {
                            uint32 nextPhase = PHASE_2_TRANSITION;
    
                            if (GetPhase(events) == PHASE_3)
                                nextPhase = PHASE_4_TRANSITION;
    
                            events.SetPhase(nextPhase);
                            me->SetReactState(REACT_PASSIVE);
                            me->AttackStop();
                            me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE);
                            SetCombatMovement(false);
                            me->SetInCombatWithZone();
                            me->GetMotionMaster()->MovePoint(POINT_PLATFORM_CENTER, MovePos[1]);
                            break;
                        }
                        case ACTION_PHASE_SWITCH_2:
                        {
                        if (GetPhase(events) == PHASE_2_TRANSITION)
                        {
                            events.SetPhase(PHASE_3);
                            events.ScheduleEvent(EVENT_SUMMON_VAL_KYR_SHADOWGUARD, 13000, 0, PHASE_3);
                            events.ScheduleEvent(EVENT_SOUL_REAPER, 35000, 0, PHASE_3);
                            events.ScheduleEvent(EVENT_DEFILE, 32000, 0, PHASE_3);
                            events.ScheduleEvent(EVENT_INFEST, 8000, 0, PHASE_3);
                        }
    
                        if (GetPhase(events) == PHASE_4_TRANSITION)
                        {
                            events.SetPhase(PHASE_5);
                            events.ScheduleEvent(EVENT_SUMMON_VILE_SPIRITS, 15000, 0, PHASE_5);
                            events.ScheduleEvent(EVENT_SOUL_REAPER, 35000, 0, PHASE_5);
                            events.ScheduleEvent(EVENT_DEFILE, 32000, 0, PHASE_5);
                            events.ScheduleEvent(EVENT_HARVEST_SOUL, 7000, 0, PHASE_5);
                        }
    
                            me->SetReactState(REACT_AGGRESSIVE);
                            me->RemoveAurasDueToSpell(RAID_MODE(SPELL_PAIN_AND_SUFFERING_10N, SPELL_PAIN_AND_SUFFERING_25N, SPELL_PAIN_AND_SUFFERING_10H, SPELL_PAIN_AND_SUFFERING_25H));
                            DoZoneInCombat(me);
                            SetCombatMovement(true);
                            me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE);
                            isSwitching = false;
                            break;
                        }
                    }
                }
    
                void DamageTaken(Unit* /*done_by*/, uint32& /*damage*/)
                {
                    switch(GetPhase(events))
                    {
                        case PHASE_1:
                            if (!HealthAbovePct(71) && !isSwitching)
                            {
                                isSwitching = true;
                                DoAction(ACTION_PHASE_SWITCH_1);
                                break;
                            }
                        case PHASE_3:
                            if (!HealthAbovePct(41) && !isSwitching)
                            {
                                isSwitching = true;
                                DoAction(ACTION_PHASE_SWITCH_1);
                                break;
                            }
                        case PHASE_5:
                            if (!HealthAbovePct(11) && !isSwitching)
                            {
                                isSwitching = true;
                                me->SummonCreature(NPC_TRIGGER, MovePos[6], TEMPSUMMON_CORPSE_DESPAWN, 900000);
                                summons.DespawnAll();
                                events.Reset();
                                events.SetPhase(PHASE_6_ENDING);
                            }
                            break;
                        case PHASE_6_ENDING:
                            if(HealthBelowPct(1) && !isAboutToDie)
                            {
                                if (Creature* tirion = Unit::GetCreature(*me, uiTirionGUID))
                                {
                                    isAboutToDie = true;
                                    me->RemoveAurasDueToSpell(34873);
                                    me->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), tirion->GetPositionZ());
                                    me->SetPosition(me->GetPositionX(), me->GetPositionY(), tirion->GetPositionZ(), me->GetOrientation(), true);
                                }
                            }
                            break;
                    }
                }
    
                void UpdateAI(const uint32 diff)
                {
                    if (GetPhase(events) != PHASE_6_ENDING && (!UpdateVictim() || !CheckInRoom()))
                        return;
    
                    events.Update(diff);
    
                    if (me->HasUnitState(UNIT_STAT_CASTING))
                        return;
    
                    while (uint32 eventId = events.ExecuteEvent())
                    {
                        //Remove players from threat list if they fall down
                        if (eventId == EVENT_CHECK_ALIVE_PLAYERS)
                        {
                            if (Creature* pTirion = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_TIRION)))
                            {
                                TPlayerList players = GetPlayersInTheMap(me->GetMap());
                                for (TPlayerList::iterator it = players.begin(); it != players.end(); ++it)
                                    if ((*it)->GetDistanceZ(pTirion) > 10.0f && !(*it)->HasAura(SPELL_IN_FROSTMOURNE_ROOM))
                                    {
                                        (*it)->RemoveAllAuras();
                                        me->DealDamage(*it, (*it)->GetHealth());
                                        pTirion->CastSpell(*it, FROZEN_THRONE_TELEPORT, true);
                                    }
                            }
    
                            events.ScheduleEvent(EVENT_CHECK_ALIVE_PLAYERS, 5000);
                        }
    
                        switch (GetPhase(events))
                        {
                            case PHASE_1:
                            {
                                switch (eventId)
                                {
                                    case EVENT_SPEECH:
                                    {
                                        DoScriptText(RAND(SAY_RANDOM_1, SAY_RANDOM_2), me);
                                        events.ScheduleEvent(EVENT_SPEECH, 33000, 0, PHASE_1);
                                        break;
                                    }
                                    case EVENT_SUMMON_SHAMBLING_HORROR:
                                    {
                                        DoCast(SPELL_SUMMON_SHAMBLING_HORROR);
                                        events.ScheduleEvent(EVENT_SUMMON_SHAMBLING_HORROR, 35000, 0, PHASE_1);
                                        break;
                                    }
                                    case EVENT_SUMMON_DRUDGE_GHOULS:
                                    {
                                        PauseForSummoning(true);
                                        DoCast(SPELL_SUMMON_DRUDGE_GHOULS);
                                        events.ScheduleEvent(EVENT_RESTART_COMBAT_MOVEMENT, 4100, 0, PHASE_1);
                                        events.ScheduleEvent(EVENT_SUMMON_DRUDGE_GHOULS, 30000, 0, PHASE_1);
                                        break;
                                    }
                                    case EVENT_INFEST:
                                    {
                                        if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true, -RAID_MODE(SPELL_INFEST_10N, SPELL_INFEST_25N, SPELL_INFEST_10H, SPELL_INFEST_25H)))
                                            DoCast(target, RAID_MODE(SPELL_INFEST_10N, SPELL_INFEST_10H, SPELL_INFEST_25N, SPELL_INFEST_25H));
    
                                        events.ScheduleEvent(EVENT_INFEST, 20000, 0, PHASE_1);
                                        break;
                                    }
                                    case EVENT_NECROTIC_PLAGUE:
                                    {
                                        if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true, -EVENT_NECROTIC_PLAGUE))
                                            DoCast(target, RAID_MODE<uint32>(SPELL_NECROTIC_PLAGUE_10N, SPELL_NECROTIC_PLAGUE_25N, SPELL_NECROTIC_PLAGUE_10H, SPELL_NECROTIC_PLAGUE_25H));
    
                                        events.ScheduleEvent(EVENT_NECROTIC_PLAGUE, 25000, 0, PHASE_1);
                                        break;
                                    }
                                    case EVENT_SHADOW_TRAP:
                                    {
                                        ASSERT(IsHeroic());
                                        //First, try to select somebody far away from the boss
                                        Unit* target = NULL;
                                        target = SelectTarget(SELECT_TARGET_RANDOM, 0, -5.0f, true);
    
                                        if (!target)
                                            target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true);
    
                                        DoCast(target, SPELL_SUMMON_SHADOW_TRAP, true);
                                        events.ScheduleEvent(EVENT_SHADOW_TRAP, 30000, 0, PHASE_1);
                                        break;
                                    }
                                    case EVENT_RESTART_COMBAT_MOVEMENT:
                                    {
                                        PauseForSummoning(false);
                                        break;
                                    }
                                }
                                break;
                            }
                            case PHASE_2_TRANSITION:
                            case PHASE_4_TRANSITION:
                            {
                                switch (eventId)
                                {
                                    case EVENT_PAIN_AND_SUFFERING:
                                    {
                                        if (Player* randomPlayer = SelectRandomAttackablePlayerInTheMap(me->GetMap()))
                                        {
                                            me->SetFacingToObject(randomPlayer);
                                            DoCast(randomPlayer, RAID_MODE(SPELL_PAIN_AND_SUFFERING_10N, SPELL_PAIN_AND_SUFFERING_25N, SPELL_PAIN_AND_SUFFERING_10H, SPELL_PAIN_AND_SUFFERING_25H), true);
                                        }
    
                                        events.ScheduleEvent(EVENT_PAIN_AND_SUFFERING, 1500, 0, GetPhase(events));
                                        break;
                                    }
                                    case EVENT_SUMMON_RAGING_SPIRIT:
                                    {
                                        if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
                                            DoCast(target, SPELL_SUMMON_RAGING_SPIRIT);
    
                                        events.RescheduleEvent(EVENT_PAIN_AND_SUFFERING, 3000, 0, PHASE_2_TRANSITION);
                                        events.ScheduleEvent(EVENT_SUMMON_RAGING_SPIRIT, RAID_MODE(20000, 15000, 20000, 15000), 0, GetPhase(events));
                                        break;
                                    }
                                    case EVENT_SUMMON_ICE_SPHERE:
                                    {
                                        events.RescheduleEvent(EVENT_PAIN_AND_SUFFERING, 3000, 0, GetPhase(events));
                                        DoCast(SPELL_SUMMON_ICE_SPEHERE);
                                        events.ScheduleEvent(EVENT_SUMMON_ICE_SPHERE, urand(6000, 8000), 0, GetPhase(events));
                                        break;
                                    }
                                    case EVENT_BERSERK:
                                    {
                                        events.Reset();
                                        DoScriptText(SAY_BERSERK, me);
                                        DoCast(me, SPELL_BERSERK2);
                                        break;
                                    }
                                }
                                break;
                            }
                            case PHASE_3:
                            {
                                switch (eventId)
                                {
                                    case EVENT_SUMMON_VAL_KYR_SHADOWGUARD:
                                    {
                                        DoScriptText(SAY_SUMMON_VALKYR, me);
                                        DoCast(me, SPELL_SUMMON_VALKYR);
                                        events.ScheduleEvent(EVENT_SUMMON_VAL_KYR_SHADOWGUARD, urand(40000, 45000), 0, PHASE_3);
                                        break;
                                    }
                                    case EVENT_DEFILE:
                                    {
                                        DoScriptText(SAY_EMOTE_DEFILE, me);
    
                                        if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
                                            DoCast(target, SPELL_SUMMON_DEFILE);
    
                                        events.ScheduleEvent(EVENT_DEFILE, 35000, 0, PHASE_3);
                                        break;
                                    }
                                    case EVENT_SOUL_REAPER:
                                    {
                                        DoCastVictim(RAID_MODE(SPELL_SOUL_REAPER_10N, SPELL_SOUL_REAPER_25N, SPELL_SOUL_REAPER_10H, SPELL_SOUL_REAPER_25H));
                                        DoCast(SPELL_SOUL_REAPER_HASTE_AURA);
                                        events.ScheduleEvent(EVENT_SOUL_REAPER, 30000, 0, PHASE_3);
                                        break;
                                    }
                                    case EVENT_INFEST:
                                    {
                                        if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true, -RAID_MODE(SPELL_INFEST_10N, SPELL_INFEST_25N, SPELL_INFEST_10H, SPELL_INFEST_25H)))
                                            DoCast(target, RAID_MODE(SPELL_INFEST_10N, SPELL_INFEST_25N, SPELL_INFEST_10H, SPELL_INFEST_25H));
    
                                        events.ScheduleEvent(EVENT_INFEST, 20000, 0, PHASE_3);
                                        break;
                                    }
                                    case EVENT_BERSERK:
                                    {
                                        DoScriptText(SAY_BERSERK, me);
                                        DoCast(me, SPELL_BERSERK2);
                                        break;
                                    }
                                }
                                break;
                            }
                            case PHASE_5:
                            {
                                switch (eventId)
                                {
                                    case EVENT_DEFILE:
                                    {
                                        DoScriptText(SAY_EMOTE_DEFILE, me);
    
                                        if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
                                            DoCast(target, SPELL_SUMMON_DEFILE);
    
                                        events.ScheduleEvent(EVENT_DEFILE, 35000, 0, PHASE_5);
                                        break;
                                    }
                                    case EVENT_SOUL_REAPER:
                                    {
                                        DoCastVictim(RAID_MODE(SPELL_SOUL_REAPER_10N, SPELL_SOUL_REAPER_25N, SPELL_SOUL_REAPER_10H, SPELL_SOUL_REAPER_25H));
                                        DoCast(SPELL_SOUL_REAPER_HASTE_AURA);
                                        events.ScheduleEvent(EVENT_SOUL_REAPER, 30000, 0, PHASE_5);
                                        break;
                                    }
                                    case EVENT_SUMMON_VILE_SPIRITS:
                                    {
                                        PauseForSummoning(true);
                                        DoCast(me, SPELL_SUMMON_VILE_SPIRIT);
                                        events.ScheduleEvent(EVENT_RESTART_COMBAT_MOVEMENT, 5700, 0, PHASE_5);
                                        events.ScheduleEvent(EVENT_SUMMON_VILE_SPIRITS, 30000, 0, PHASE_5);
                                        break;
                                    }
                                    case EVENT_HARVEST_SOUL:
                                    {
                                        DoScriptText(SAY_HARVEST_SOUL, me);
    
                                        if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true))
                                            DoCast(target, RAID_MODE(SPELL_HARVEST_SOULS_10N, SPELL_HARVEST_SOULS_25N, SPELL_HARVEST_SOULS_10H, SPELL_HARVEST_SOULS_25H));
    
                                        events.ScheduleEvent(EVENT_HARVEST_SOUL, 75000, 0, PHASE_5);
                                        break;
                                    }
                                    case EVENT_BERSERK:
                                    {
                                        DoScriptText(SAY_BERSERK, me);
                                        DoCast(me, SPELL_BERSERK2);
                                        break;
                                    }
                                    case EVENT_RESTART_COMBAT_MOVEMENT:
                                    {
                                        PauseForSummoning(false);
                                        break;
                                    }
                                }
                                break;
                            }
                        }
                    }
    
                    if (GetPhase(events) == PHASE_6_ENDING)
                    {
                        if (uiStage > 25)
                            return;
    
                        if (uiEndingTimer <= diff)
                        {
                            switch(uiStage)
                            {
                                case 1:
                                {
                                    //Teleport all players who are inside Frostmourne back to Frozen Throne platform
                                    TPlayerList players = GetPlayersInTheMap(me->GetMap());
    
                                    for (TPlayerList::iterator it = players.begin(); it != players.end(); ++it)
                                        if ((*it)->HasAura(SPELL_IN_FROSTMOURNE_ROOM))
                                            TeleportPlayerToFrozenThrone(*it);
    
                                    if (Creature* terenasFighter = ObjectAccessor::GetCreature(*me, DATA_TERENAS_FIGHTER))
                                        terenasFighter->AI()->DoAction(ACTION_DESPAWN);
    
                                    if (Creature* spiritWarden = ObjectAccessor::GetCreature(*me, DATA_SPIRIT_WARDEN))
                                        spiritWarden->AI()->DoAction(ACTION_DESPAWN);
    
                                    me->GetMotionMaster()->MoveIdle();
                                    me->SetReactState(REACT_PASSIVE);
                                    me->AttackStop();
                                    me->CastStop();
                                    me->SetInCombatWithZone();
    
                                    if (Creature* tirion = Unit::GetCreature(*me, uiTirionGUID))
                                        me->SetInCombatWith(tirion);
    
                                    DoScriptText(SAY_10_PERCENT, me);
                                    //Wait for everyone who is inside the Frostmourne Room to get teleported to the Platform
                                    uiEndingTimer = 4000;
                                    break;
                                }
                                case 2:
                                {
                                    DoCast(me, SPELL_FURY_OF_FROSTMOURNE);
                                    uiEndingTimer = 12000;
                                    break;
                                }
                                case 3:
                                {
                                    DoScriptText(SAY_ENDING_1_KING, me);
                                    uiEndingTimer = 30000;
                                    break;
                                }
                                case 4:
                                {
                                    if (Creature* tirion = Unit::GetCreature(*me, uiTirionGUID))
                                        me->SetFacingToObject(tirion);
                                    DoScriptText(SAY_ENDING_2_KING, me);
                                    uiEndingTimer = 25000;
                                    break;
                                }
                                case 5:
                                {
                                    me->GetMotionMaster()->MovePoint(0, MovePos[1]);
                                    uiEndingTimer = 4000;
                                    break;
                                }
                                case 6:
                                {
                                    DoScriptText(SAY_ENDING_3_KING, me);
                                    if (Creature* trigger = me->FindNearestCreature(37882, 50.0f, true))
                                        me->SetFacingToObject(trigger);
                                    //DoCast(me, SPELL_RAISE_DEAD);
                                    // Temp fix for visual rising sword on spellcast
                                    me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 468);
                                    me->HandleEmoteCommand(EMOTE_ONESHOT_SPELLCAST_OMNI);
                                    uiEndingTimer = 28000;
                                    break;
                                }
                                case 7:
                                {
                                    DoScriptText(SAY_ENDING_4_KING, me);
                                    uiEndingTimer = 8000;
                                    break;
                                }
                                case 8:
                                {
                                    if (uiTirionGUID)
                                        if (Creature* tirion = Unit::GetCreature(*me, uiTirionGUID))
                                            DoScriptText(SAY_ENDING_5_TIRION, tirion);
    
                                    uiEndingTimer = 11000;
                                    break;
                                }
                                case 9:
                                {
                                    if (uiTirionGUID)
                                        if (Creature* tirion = Unit::GetCreature(*me, uiTirionGUID))
                                        {
                                            tirion->CastSpell(tirion, SPELL_TIRION_LIGHT, true);
                                            tirion->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
                                        }
    
                                    uiEndingTimer = 7000;
                                    break;
                                }
                                case 10:
                                {
                                    if (uiTirionGUID)
                                        if (Creature* tirion = Unit::GetCreature(*me, uiTirionGUID))
                                        {
                                            tirion->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2H);
                                            tirion->GetMotionMaster()->MovePoint(0, MovePos[2]);
                                        }
    
                                    uiEndingTimer = 3000;
                                    break;
                                }
                                case 11:
                                {
                                    if (uiTirionGUID)
                                    {
                                        if (Creature* tirion = Unit::GetCreature(*me, uiTirionGUID))
                                        {
                                            tirion->GetMotionMaster()->MoveJump(MovePos[10].GetPositionX(), MovePos[10].GetPositionY(), MovePos[10].GetPositionZ(), 10.0f, 15.0f);
                                            tirion->SetPosition(MovePos[10]);
                                        }
                                    }
                                    me->RemoveAura(SPELL_RAISE_DEAD);
    
                                    uiEndingTimer = 600;
                                    break;
                                }
                                case 12:
                                {
                                    if (uiTirionGUID)
                                        if (Creature* tirion = Unit::GetCreature(*me, uiTirionGUID))
                                            tirion->HandleEmoteCommand(EMOTE_ONESHOT_ATTACK2HTIGHT);
    
                                    DoPlaySoundToSet(me, SOUND_ENDING_7_KING);
                                    //Equip broken Frostmourne
                                    SetEquipmentSlots(false, 50840, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE);
                                    me->CastSpell(me, SPELL_BOOM_VISUAL, false);
                                    me->HandleEmoteCommand(EMOTE_STATE_CUSTOM_SPELL_01);
                                    uiEndingTimer = 3000;
                                    break;
                                }
                                case 13:
                                {
                                    me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_CUSTOM_SPELL_02);
                                    uiEndingTimer = 1000;
                                    break;
                                }
                                case 14:
                                {
                                    if (Creature* tirion = Unit::GetCreature(*me, uiTirionGUID))
                                        tirion->SetFacingToObject(me);
                                    uiEndingTimer = 1000;
                                    break;
                                }
                                case 15:
                                {
                                    me->CastSpell(me, SPELL_DROP_FROSTMOURNE, false);
                                    SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE);
                                    uiEndingTimer = 500;
                                    break;
                                }
                                case 16:
                                {
                                    // Here Tirion is knocked back to the teleport circle
                                    if (Creature* tirion = Unit::GetCreature(*me, uiTirionGUID))
                                        tirion->GetMotionMaster()->MoveJump(MovePos[11].GetPositionX(), MovePos[11].GetPositionY(), MovePos[11].GetPositionZ(), 11.0f, 9.0f);
    
                                    uiEndingTimer = 800;
                                    break;
                                }
                                case 17:
                                {
                                    if (Creature* tirion = Unit::GetCreature(*me, uiTirionGUID))
                                        tirion->CastSpell(tirion, SPELL_KNOCKDOWN, true);
    
                                    DoScriptText(SAY_ENDING_6_KING, me);
                                    uiEndingTimer = 5000;
                                    break;
                                }
                                case 18:
                                {
                                    me->CastSpell(me, SPELL_SOUL_EFFECT, true);
                                    if (Creature* frostmourne = me->FindNearestCreature(NPC_FROSTMOURNE_TRIGGER, 25.0f, true))
                                    {
                                        me->GetMotionMaster()->MovePoint(0, frostmourne->GetPositionX(),frostmourne->GetPositionY(), frostmourne->GetPositionZ() + 3.0f);
                                        me->SetPosition(frostmourne->GetPositionX(),frostmourne->GetPositionY(), frostmourne->GetPositionZ() + 3.0f, me->GetOrientation());
                                    }
    
                                    uiEndingTimer = 5000;
                                    break;
                                }
                                case 19:
                                {
                                    if (uiTirionGUID)
                                        if (Creature* tirion = Unit::GetCreature(*me, uiTirionGUID))
                                            DoScriptText(SAY_ENDING_8_TIRION, tirion);
    
                                    uiEndingTimer = 6000;
                                    break;
                                }
                                case 20:
                                {
                                    if (Creature* frostmourne = me->FindNearestCreature(NPC_FROSTMOURNE_TRIGGER, 25.0f, true))
                                        frostmourne->CastSpell(frostmourne, SPELL_SUMMON_MENETHIL, true);
    
                                    uiEndingTimer = 500;
                                    break;
                                }
                                case 21:
                                {
                                    if (Creature* father = me->FindNearestCreature(NPC_TERENAS_MENETHIL, 25.0f, true))
                                    {
                                        DoScriptText(SAY_ENDING_9_FATHER, father);
                                        father->SetFacingToObject(me);
                                    }
                                    uiEndingTimer = 11000;
                                    break;
                                }
                                case 22:
                                {
                                    if (Creature* father = me->FindNearestCreature(NPC_TERENAS_MENETHIL, 25.0f, true))
                                    {
                                        DoScriptText(SAY_ENDING_11_FATHER, father);
                                        instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_FURY_OF_FROSTMOURNE_NORES);
                                        father->CastSpell(father, SPELL_MENETHIL_VISUAL, true);
                                        father->CastSpell(father, SPELL_REVIVE, true);
                                    }
    
                                    uiEndingTimer = 6000;
                                    break;
                                }
                                case 23:
                                {
                                    if (uiTirionGUID)
                                        if (Creature* tirion = Unit::GetCreature(*me, uiTirionGUID))
                                            DoScriptText(SAY_ENDING_10_TIRION, tirion);
    
                                    uiEndingTimer = 5000;
                                    break;
                                }
                                case 24:
                                {
                                    DoScriptText(SAY_ENDING_12_KING, me);
                                    if (uiTirionGUID)
                                        if (Creature* tirion = Unit::GetCreature(*me, uiTirionGUID))
                                        {
                                            if(Creature* frostmourne = me->FindNearestCreature(NPC_FROSTMOURNE_TRIGGER, 25.0f, true))
                                                tirion->GetMotionMaster()->MoveChase(frostmourne, 2.0f, 1.5f);
    
                                            tirion->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID());
                                        }
    
                                    if (Creature* father = me->FindNearestCreature(NPC_TERENAS_MENETHIL, 25.0f, true))
                                    {
                                        if(Creature* frostmourne = me->FindNearestCreature(NPC_FROSTMOURNE_TRIGGER, 25.0f, true))
                                            father->GetMotionMaster()->MoveChase(frostmourne, 3.0f, 0.0f);
                                        father->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID());
                                    }
    
                                    uiEndingTimer = 10000;
                                    break;
                                }
                                case 25:
                                {
                                    DoScriptText(SAY_DEATH_KING, me);
                                    break;
                                }
                            }
    
                            ++uiStage;
                        } else uiEndingTimer -= diff;
                    }
    
                    switch (GetPhase(events))
                    {
                        case PHASE_1:
                        case PHASE_3:
                        case PHASE_5:
                            if(!imSummoning)
                                DoMeleeAttackIfReady();
                            break;
                    }
                }
    
                void PauseForSummoning(bool on)
                {
                    imSummoning = on;
    
                    if(on)
                        me->GetMotionMaster()->MoveIdle();
                    else
                        me->GetMotionMaster()->MoveChase(me->getVictim());
                }
    
                // JUST FOR TESTING PROPUSES!!!!
                void SpellHit(Unit* /*caster*/, const SpellEntry * spell)
                {
                    if (spell->Id == 72400)
                        events.SetPhase(PHASE_6_ENDING);
                }
    
            private:
                InstanceScript* instance;
                uint8 uiStage;
                uint8 uiPhase;
                uint32 uiEndingTimer;
                uint32 uiSummonShamblingHorrorTimer;
                uint32 uiSummonDrudgeGhoulsTimer;
                uint32 uiSummonShadowTrap;
                uint32 uiInfestTimer;
                uint32 uiNecroticPlagueTimer;
                uint32 uiSummonValkyrTimer;
                uint32 uiSoulReaperTimer;
                uint32 uiDefileTimer;
                uint32 uiHarvestSoulTimer;
                uint32 uiSummonVileSpiritTimer;
                uint32 uiIcePulsSummonTimer;
                uint32 uiSummonSpiritTimer;
                uint64 uiTirionGUID;
                bool isSwitching;
                bool imSummoning;
                bool isAboutToDie;
                SummonList summons;
                EventMap events;
            };
    
            CreatureAI* GetAI(Creature* creature) const
            {
                return GetIcecrownCitadelAI<boss_the_lich_kingAI>(creature);
            }
    };
    
    class npc_tirion_icc : public CreatureScript
    {
        public:
            npc_tirion_icc() : CreatureScript("npc_tirion_icc") { }
    
            struct npc_tirion_iccAI : public ScriptedAI
            {
                npc_tirion_iccAI(Creature* creature) : ScriptedAI(creature)
                {
                    instance = creature->GetInstanceScript();
                }
    
                void Reset()
                {
                    uiIntroTimer = 1000;
                    uiStage = 1;
                    uiLichKingGUID = 0;
                    bIntro = false;
    
                    me->RemoveAllAuras();
                    me->SetReactState(REACT_PASSIVE);
                    me->SetSpeed(MOVE_RUN, 1.8f);
                    me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
                    me->GetMotionMaster()->MovePoint(POINT_PLATFORM_CENTER, MovePos[8]);
                    DoCast(me, SPELL_REVIVE, true);
                    DoCast(SPELL_WMO_INTACT);
    
                    //Rebuilding ice shards
                    if (GameObject* go = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_ICE_SHARD_1)))
                        go->SetGoState(GO_STATE_READY);
    
                    if (GameObject* go = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_ICE_SHARD_2)))
                        go->SetGoState(GO_STATE_READY);
    
                    if (GameObject* go = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_ICE_SHARD_3)))
                        go->SetGoState(GO_STATE_READY);
    
                    if (GameObject* go = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_ICE_SHARD_4)))
                        go->SetGoState(GO_STATE_READY);
    
                    if (GameObject* go = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_EDGE_DESTROY_WARNING)))
                        go->SetGoState(GO_STATE_READY);
    
                    if (GameObject* go = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_FROSTY_EDGE_INNER)))
                        go->SetGoState(GO_STATE_READY);
    
                    if (GameObject* go = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_FROSTY_EDGE_OUTER)))
                        go->SetGoState(GO_STATE_ACTIVE);
                }
    
                void MovementInform(uint32 type, uint32 id)
                {
                    if (type != POINT_MOTION_TYPE)
                        return;
    
                    switch (id)
                    {
                        case POINT_PLATFORM_CENTER:
                        {
                            if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE)
                                me->GetMotionMaster()->MovementExpired();
    
                            me->SetPosition(MovePos[8]);
                            me->SetOrientation(3.1416f);
                            me->SetFacing(3.1416f);
                            break;
                        }
                    }
                }
    
                void DoAction(const int32 action)
                {
                    switch (action)
                    {
                        case ACTION_START_EVENT:
                        {
                            bIntro = true;
    
                            if (instance)
                                uiLichKingGUID = instance->GetData64(DATA_THE_LICH_KING);
    
                            break;
                        }
                        case ACTION_RESET:
                        {
                            Reset();
                            break;
                        }
                    }
                }
    
                void SpellHit(Unit* /*caster*/, const SpellEntry * spell)
                {
                    if (spell->Id == SPELL_LIGHTS_BLESSING)
                        me->RemoveAurasDueToSpell(SPELL_ICEBLOCK_TRIGGER);
                }
    
                void UpdateAI(const uint32 diff)
                {
                    if (!bIntro || !uiLichKingGUID)
                        return;
    
                    if (uiStage > 12)
                        return;
    
                    if (uiIntroTimer <= diff)
                    {
                        switch(uiStage)
                        {
                            case 1:
                            {
                                // IntroStarts. Tirion moves to talk position
                                me->SetUnitMovementFlags(MOVEMENTFLAG_WALKING);
                                me->GetMotionMaster()->MovePoint(0, MovePos[9]);
                                uiIntroTimer = 8000;
                                break;
                            }
                            case 2:
                            {
                                // Tirion reaches talk position, Arthas stands up
                                if (Creature* lich = Unit::GetCreature(*me, uiLichKingGUID))
                                    lich->SetStandState(UNIT_STAND_STATE_STAND);
    
                                me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2H);
                                uiIntroTimer = 1000;
                                break;
                            }
                            case 3:
                            {
                                // Arthas talks
                                if (Creature* lich = Unit::GetCreature(*me, uiLichKingGUID))
                                    DoScriptText(SAY_INTRO_1_KING, lich);
                                uiIntroTimer = 2000;
                                break;
                            }
                            case 4:
                            {
                                // Arthas walks downstair
                                if (Creature* lich = Unit::GetCreature(*me, uiLichKingGUID))
                                {
                                    lich->SetUnitMovementFlags(MOVEMENTFLAG_WALKING);
                                    lich->GetMotionMaster()->MovePoint(POINT_START_EVENT_1, MovePos[0]);
                                }
                                uiIntroTimer = 13500;
                                break;
                            }
                            case 5:
                            {
                                // Arthas has reached bottom of stairs, Tirion talks
                                if (Creature* lich = Unit::GetCreature(*me, uiLichKingGUID))
                                    lich->SetFacingToObject(me);
    
                                DoScriptText(SAY_INTRO_2_TIRION, me);
                                uiIntroTimer = 8000;
                                break;
                            }
                            case 6:
                            {
                                if (Creature* lich = Unit::GetCreature(*me, uiLichKingGUID))
                                {
                                    lich->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_LAUGH);
                                    DoScriptText(SAY_INTRO_3_KING, lich);
                                }
    
                                uiIntroTimer = 3000;
                                break;
                            }
                            case 7:
                            {
                                if (Creature* lich = Unit::GetCreature(*me, uiLichKingGUID))
                                    lich->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_POINT_NOSHEATHE);
    
                                uiIntroTimer = 2000;
                                break;
                            }
                            case 8:
                            {
                                if (Creature* lich = Unit::GetCreature(*me, uiLichKingGUID))
                                    lich->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
    
                                uiIntroTimer = 18000;
                                break;
                            }
                            case 9:
                                me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_POINT_NOSHEATHE);
                                DoScriptText(SAY_INTRO_4_TIRION, me);
                                uiIntroTimer = 2000;
                                break;
                            case 10:
                                // Tirion runs to Arthas
                                me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
                                me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
                                me->GetMotionMaster()->MovePoint(0, MovePos[3]);
                                uiIntroTimer = 1600;
                                break;
                            case 11:
                                // Arthas freezes Tirion
                                if(Creature* lich = Unit::GetCreature(*me, uiLichKingGUID))
                                {
                                    lich->CastSpell(me, SPELL_ICEBLOCK_TRIGGER, true);
                                    me->GetMotionMaster()->MoveIdle();
                                    me->SetFacingToObject(lich);
                                }
                                me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
    
                                // From here, Arthas is attackable
                                if(Creature* lich = Unit::GetCreature(*me, uiLichKingGUID))
                                {
                                    lich->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
                                    lich->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE);
                                    lich->SetReactState(REACT_AGGRESSIVE);
                                }
                                uiIntroTimer = 2000;
                                break;
                            case 12:
                            {
                                if (Creature* lich = Unit::GetCreature(*me, uiLichKingGUID))
                                {
                                    DoScriptText(SAY_INTRO_5_KING, lich);
    
                                    // If Arthas stills not in combat, find nearest player and attack him
                                    if(!lich->isInCombat())
                                    {
                                        if (Unit* target = lich->FindNearestPlayer(100.0f))
                                            lich->AI()->AttackStart(target);
                                    }
                                }
                                break;
                            }
                        }
    
                        ++uiStage;
                    } else uiIntroTimer -= diff;
                }
                private:
                    InstanceScript* instance;
                    uint64 uiLichKingGUID;
                    uint32 uiIntroTimer;
                    uint8 uiStage;
                    bool bIntro;
            };
    
            bool OnGossipHello(Player* player, Creature* creature)
            {
                InstanceScript* instance = creature->GetInstanceScript();
    
                if (!instance)
                    return false;
    
                if (instance->GetBossState(DATA_THE_LICH_KING) == DONE)
                {
                    player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "The Lich King was already defeated here. Teleport me back to the Light's Hammer", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
                    player->SEND_GOSSIP_MENU(GOSSIP_MENU, creature->GetGUID());
                    return true;
                }
    
                player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_START_EVENT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
                player->SEND_GOSSIP_MENU(GOSSIP_MENU, creature->GetGUID());
    
                return true;
            }
    
            bool OnGossipSelect(Player* player, Creature* creature, uint32 /*uiSender*/, uint32 uiAction)
            {
                switch (uiAction)
                {
                    case GOSSIP_ACTION_INFO_DEF + 4:
                        creature->CastSpell(player, LIGHT_S_HAMMER_TELEPORT, true);
                        break;
                    case GOSSIP_ACTION_INFO_DEF + 3:
                        CAST_AI(npc_tirion_icc::npc_tirion_iccAI, creature->AI())->DoAction(ACTION_START_EVENT);
                        creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
                        player->CLOSE_GOSSIP_MENU();
                        break;
                    default:
                        creature->MonsterSay("You've just found a bug. Contact server admin and explain what to do to reproduce this bug", LANG_UNIVERSAL, player->GetGUID());
                        break;
                }
                return true;
            }
    
            CreatureAI* GetAI(Creature* creature) const
            {
                return GetIcecrownCitadelAI<npc_tirion_iccAI>(creature);
            }
    };
    
    class npc_valkyr_shadowguard : public CreatureScript
    {
        public:
            static const float Z_FLY;
            npc_valkyr_shadowguard() : CreatureScript("npc_valkyr_shadowguard") { }
    
            struct npc_valkyr_shadowguardAI : public ScriptedAI
            {
                npc_valkyr_shadowguardAI(Creature* creature) : ScriptedAI(creature), vehicle(creature->GetVehicleKit()), m_victimGuid(0)
                {
                    ASSERT(vehicle);
                }
    
                void Reset()
                {
                    SetCombatMovement(false);
                    me->SetReactState(REACT_PASSIVE);
                    m_moveUpdatePeriod = 100;
                    events.Reset();
                    me->SetFlying(true);
                    me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
                    me->GetPosition(&m_pos);
                    m_pos.m_positionZ = Z_FLY + 6.0f;
                    me->SetPosition(m_pos);
                    bCanCast = false;
                    m_victimGuid = 0;
    
                    if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE)
                        me->GetMotionMaster()->MovementExpired();
    
                    events.ScheduleEvent(EVENT_CHARGE_PLAYER, 2000);
                    DoCast(me, SPELL_WINGS_OF_THE_DAMNED, true);
                    //summoned->AI()->AttackStart(*it);
                    //summoned->CastSpell(*it, SPELL_VALKYR_TARGET_SEARCH, true);
                }
    
                void DamageTaken(Unit* /*done_by*/, uint32& /*damage*/)
                {
                    if (!HealthAbovePct(50) && IsHeroic() && !bCanCast)
                    {
                        vehicle->RemoveAllPassengers();
                        me->RemoveAllAuras();
                        me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
                        me->GetMotionMaster()->MovePoint(POINT_VALKYR_ZET, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 10);
                        events.Reset();
                    }
                }
    
                void SetGUID(const uint64& guid, int32 type = 0)
                {
                    if (type == TYPE_VICTIM)
                        m_victimGuid = guid;
                }
    
                void DoAction(const int32 action)
                {
                    switch(action)
                    {
                        case ACTION_CHARGE_PLAYER:
                        {
                            events.ScheduleEvent(EVENT_CHARGE_PLAYER, 2000);
                            break;
                        }
                    }
                }
    
                void SpellHitTarget(Unit* victim, SpellEntry const* spellEntry)
                {
                    if (spellEntry->Id == SPELL_VALKYR_CHARGE)
                        if (Player *player = ObjectAccessor::GetPlayer(*me, m_victimGuid))
                            DoCast(player, SPELL_VALKYR_CARRY_CAN_CAST, true);
    
                    ScriptedAI::SpellHitTarget(victim, spellEntry);
                }
    
                void SpellHit(Unit* attacker, const SpellEntry* spellEntry)
                {
                    if (spellEntry)
                        switch (spellEntry->Id)
                        {
                            case SPELL_VALKYR_GRAB_PLAYER:
                            {
                                float speedRate = me->GetSpeedRate(MOVE_RUN);
                                speedRate = 0.25f;
                                me->SetSpeed(MOVE_FLIGHT, speedRate);
                                me->SetSpeed(MOVE_RUN, speedRate);
    
                                float x, y, z;
                                me->GetPosition(x, y, z);
                                me->SetPosition(x, y, Z_FLY, 0.0f, true);
    
                                me->SetReactState(REACT_PASSIVE);
                                me->AttackStop();
                                SetCombatMovement(false);
                                me->SetInCombatWithZone();
                        
                                me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
                                me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true);
                                me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_CHARM, true);
                                me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_FEAR, true);
                                me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_ROOT, true);
                                me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_PACIFY, true);
                                me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_SILENCE, true);
                                me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_TRANSFORM, true);
                                me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_SCALE, true);
                                me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_DISARM, true);
                                me->ApplySpellImmune(0, IMMUNITY_ID, SPELL_DEATH_GRIP, true);
                                //The Val'kyrs always choose the closest edge of the platform).
                                std::list<Creature*> allEdgeStalkers;
                                GetCreatureListWithEntryInGrid(allEdgeStalkers, me, NPC_PLATFORM_DESTRUCTIBLE_EDGE_STALKER, 1000.0f);
    
                                if (allEdgeStalkers.empty())
                                {
                                    me->Kill(me);
                                    me->DespawnOrUnsummon();
                                }
                                else
                                {
                                    Creature *nearestEdgeStalker = allEdgeStalkers.front();
    
                                    for (std::list<Creature*>::iterator it = allEdgeStalkers.begin(); it != allEdgeStalkers.end(); ++it)
                                        if (me->GetDistance2d(nearestEdgeStalker) > me->GetDistance2d(*it))
                                            nearestEdgeStalker = *it;
    
                                    //Position edgePos;
                                    me->GetPosition(&m_pos);
                                    m_pos.m_positionZ = Z_FLY;
                                    me->SetPosition(m_pos, true);
                                    float ex, ey, ez;
                                    nearestEdgeStalker->GetPosition(ex, ey, ez);
                                    float distanceToEdge = m_pos.GetExactDist2d(ex, ey);
                                    distanceToEdge += 10.0f;
                                    m_angle = m_pos.GetAngle(ex, ey);
                                    me->GetNearPoint2D(ex, ey, distanceToEdge, m_angle);
                                    me->SetFacingToObject(nearestEdgeStalker);
                                    me->GetMotionMaster()->MovePoint(POINT_PLATFORM_END, ex, ey, Z_FLY);
                                    //events.ScheduleEvent(EVENT_MOVE_TO_PLATFORM_EDGE, 1000);
                                    //events.ScheduleEvent(EVENT_CHECK_AT_PLATFORM_EDGE, 1000);
                                }
    
                                //me->GetMotionMaster()->MovePoint(POINT_PLATFORM_END, MovePos[4]);
                            }
                        }
                    ScriptedAI::SpellHit(attacker, spellEntry);
                }
    
                void MovementInform(uint32 type, uint32 id)
                {
                    if (type != POINT_MOTION_TYPE)
                        return;
    
                    if (bCanCast)
                        me->GetMotionMaster()->Clear();
    
                    switch(id)
                    {
                        case POINT_PLATFORM_END:
                        {
                            DoCast(me, SPELL_VALKYR_EJECT_PASSENGER);
                            //Fly 15 feet upward, then despawn
                            me->GetPosition(&m_pos);
                            m_pos.m_positionZ = 1055.0f;
                            me->GetMotionMaster()->MovePoint(POINT_VALKYR_END, m_pos);
                            break;
                        }
                        case POINT_VALKYR_END:
                        {
                            me->DespawnOrUnsummon();
                            break;
                        }
                        case POINT_VALKYR_ZET:
                        {
                            events.ScheduleEvent(EVENT_SIPHON_LIFE, 3000);
                            bCanCast = true;
                            break;
                        }
                        case POINT_VALKYR_CONTINUE_FLYING:
                        {
                            me->SetPosition(m_pos);
                            events.ScheduleEvent(EVENT_MOVE_TO_PLATFORM_EDGE, m_moveUpdatePeriod);
                            break;
                        }
                    }
                }
    
                void UpdateAI(const uint32 diff)
                {
                    if (!me->isAlive() || me->HasUnitState(UNIT_STAT_CASTING))
                        return;
    
                    events.Update(diff);
    
                    while (uint32 eventId = events.ExecuteEvent())
                    {
                        switch (eventId)
                        {
                            case EVENT_CHARGE_PLAYER:
                            {
                                if (Player* player = ObjectAccessor::GetPlayer(*me, m_victimGuid))
                                    DoCast(player, SPELL_VALKYR_CHARGE, true);
                                else
                                    me->DespawnOrUnsummon();
                                break;
                            }
                            case EVENT_CHECK_AT_PLATFORM_EDGE:
                            {
                                if (me->GetDistance2d(MovePos[1].m_positionX, MovePos[1].m_positionY) > 55.0f)
                                {
                                    events.Reset();
                                    DoCast(me, SPELL_VALKYR_EJECT_PASSENGER);
                                    //Fly 15 feet upward, then despawn
                                    me->GetPosition(&m_pos);
                                    m_pos.m_positionZ = 1055.0f;
                                    me->GetMotionMaster()->MovePoint(POINT_VALKYR_END, m_pos);
                                }
                                else
                                    events.ScheduleEvent(EVENT_CHECK_AT_PLATFORM_EDGE, 1000);
                            }
                            case EVENT_MOVE_TO_PLATFORM_EDGE:
                            {
                                me->GetPosition(&m_pos);
    
                                if (!me->HasAuraType(SPELL_AURA_MOD_STUN))
                                {
                                    float flySpeed = me->GetSpeed(MOVE_RUN) * m_moveUpdatePeriod / 10000;
                                    m_pos.m_positionX += flySpeed * cosf(m_angle);
                                    m_pos.m_positionY += flySpeed * sinf(m_angle);
                                    m_pos.m_positionZ = Z_FLY;
                                }
    
                                me->SetFacing(m_angle);
                                me->GetMotionMaster()->Clear();
                                me->GetMotionMaster()->MovePoint(POINT_VALKYR_CONTINUE_FLYING, m_pos);
                                me->SetPosition(m_pos);
                                break;
                            }
                            case EVENT_SIPHON_LIFE:
                            {
                                DoCastVictim(SPELL_LIFE_SIPHON);
                                events.ScheduleEvent(EVENT_SIPHON_LIFE, 3000);
                            }
                        }
                    }
                }
            private:
                bool bCanCast;
                EventMap events;
                Position m_pos;
                float m_angle;
                uint32 m_moveUpdatePeriod;
                Vehicle* vehicle;
                uint64 m_victimGuid;
            };
    
            CreatureAI* GetAI(Creature* creature) const
            {
                return GetIcecrownCitadelAI<npc_valkyr_shadowguardAI>(creature);
            }
    };
    
    const float npc_valkyr_shadowguard::Z_FLY = 1045.0f;
    
    class npc_vile_spirit : public CreatureScript
    {
        public:
            static const float Z_VILE_SPIRIT;
            npc_vile_spirit() : CreatureScript("npc_vile_spirit") { }
    
            struct npc_vile_spiritAI : public ScriptedAI
            {
                npc_vile_spiritAI(Creature* creature) : ScriptedAI(creature) { }
    
                void Reset()
                {
                    events.ScheduleEvent(EVENT_BECOME_ACTIVE, 15000);
                    //If they don't reach that player within around 30 seconds, they will despawn harmlessly.
                    events.ScheduleEvent(EVENT_DESPAWN, 45000);
                    SetCombatMovement(false);
                    me->SetReactState(REACT_PASSIVE);
                    me->SetFlying(true);
                    float x, y, z;
                    me->GetPosition(x, y, z);
                    me->SetPosition(x, y, npc_vile_spirit::Z_VILE_SPIRIT, true);
                    Position randomPos;
                    float dist = 1.0f * (float)rand_norm() * 10.0f;
                    me->GetRandomNearPosition(randomPos, dist);
                    randomPos.m_positionZ = Z_VILE_SPIRIT;
                    me->GetMotionMaster()->MovePoint(POINT_MOVE_NEAR_RANDOM, randomPos);
                    bActive = false;
                }
    
                void MovementInform(uint32 type, uint32 id)
                {
                    if (type != POINT_MOTION_TYPE)
                        return;
    
                    if (id == POINT_MOVE_NEAR_RANDOM)
                    {
                        me->GetMotionMaster()->MovementExpired();
    
                        if (!bActive)
                            events.ScheduleEvent(EVENT_MOVE_RANDOM, 1000);
                    }
                }
    
                void DoAction(const int32 action)
                {
                    switch(action)
                    {
                        case ACTION_DESPAWN:
                        {
                            me->RemoveAura(SPELL_VILE_SPIRIT_DISTANCE_CHECK);
                            events.ScheduleEvent(EVENT_DESPAWN, 1000);
                            me->SetReactState(REACT_PASSIVE);
                            SetCombatMovement(false);
                            break;
                        }
                    }
                }
    
                void UpdateAI(const uint32 diff)
                {
                    events.Update(diff);
    
                    while (uint32 eventId = events.ExecuteEvent())
                    {
                        switch (eventId)
                        {
                            case EVENT_MOVE_RANDOM:
                            {
                                Position randomPos;
                                float dist = 1.0f * (float)rand_norm() * 10.0f;
                                me->GetRandomNearPosition(randomPos, dist);
                                randomPos.m_positionZ = Z_VILE_SPIRIT;
                                me->GetMotionMaster()->MovePoint(POINT_MOVE_NEAR_RANDOM, randomPos);
                                break;
                            }
                            case EVENT_BECOME_ACTIVE:
                            {
                                events.CancelEvent(EVENT_MOVE_RANDOM);
                                bActive = true;
                                SetCombatMovement(true);
                                me->SetReactState(REACT_AGGRESSIVE);
                                me->GetMotionMaster()->MovementExpired();
                                DoCast(me, SPELL_VILE_SPIRIT_ACTIVE, true);
                                //DoCast(me, SPELL_VILE_SPIRIT_TARGET_SEARCH, true);
                                DoCast(me, SPELL_VILE_SPIRIT_DISTANCE_CHECK, true);
                                events.ScheduleEvent(EVENT_CHECK_PLAYER_IN_FROSTMOURNE_ROOM, 1000);
                                break;
                            }
                            case EVENT_CHECK_PLAYER_IN_FROSTMOURNE_ROOM:
                            {
                                Unit* curVictim = me->getVictim();
    
                                if (!curVictim)
                                    curVictim = SelectRandomAttackablePlayerInTheMap(me->GetMap());
    
                                if (!curVictim)
                                {
                                    me->DespawnOrUnsummon();
                                    return;
                                }
    
                                if (!curVictim->isAlive() || curVictim->GetTypeId() != TYPEID_PLAYER)
                                {
                                    Player* player = curVictim->ToPlayer();
                                    uint8 count = 0;
    
                                    while ((!player->isTargetableForAttack() || !player->HasAura(SPELL_IN_FROSTMOURNE_ROOM)) && count++ < 20)
                                        player = SelectRandomAttackablePlayerInTheMap(me->GetMap());
    
                                    EnterEvadeMode();
                                    AttackStart(player);
                                }
    
                                events.ScheduleEvent(EVENT_CHECK_PLAYER_IN_FROSTMOURNE_ROOM, 2000);
                                break;
                            }
                            case EVENT_DESPAWN:
                            {
                                me->DespawnOrUnsummon();
                                break;
                            }
                            default:
                                break;
                        }
                    }
                }
        private:
            EventMap events;
            bool bActive;
        };
    
        CreatureAI* GetAI(Creature* creature) const
        {
            return GetIcecrownCitadelAI<npc_vile_spiritAI>(creature);
        }
    };
    
    const float npc_vile_spirit::Z_VILE_SPIRIT = 1050.0f;
    
    class npc_shambling_horror: public CreatureScript
    {
        public:
            npc_shambling_horror(): CreatureScript("npc_shambling_horror") { }
    
            struct npc_shambling_horrorAI: public ScriptedAI
            {
                npc_shambling_horrorAI(Creature* creature): ScriptedAI(creature)
                {
                    instance = creature->GetInstanceScript();
                }
            
                void EnterCombat(Unit* /*who*/)
                {
                    events.Reset();
                    events.ScheduleEvent(EVENT_ENRAGE, 15000);
                    events.ScheduleEvent(EVENT_SHOCKWAVE, 10000);
                    isFrenzied = false;
                }
    
                void DamageTaken(Unit* /*done_by*/, uint32& /*damage*/)
                {
                    if (IsHeroic())
                        if (HealthBelowPct(20) && !isFrenzied)
                        {
                            isFrenzied = true;
                            DoCast(me, SPELL_FRENZY);
                        }
                }
    
                void UpdateAI(const uint32 diff)
                {
                    if (!UpdateVictim())
                        return;
    
                    if (me->HasUnitState(UNIT_STAT_CASTING))
                        return;
    
                    events.Update(diff);
    
                    while (uint32 eventId = events.ExecuteEvent())
                    {
                        switch (eventId)
                        {
                            case EVENT_ENRAGE:
                            {
                                DoCast(me, SPELL_ENRAGE);
                                events.ScheduleEvent(EVENT_ENRAGE, urand(20000, 30000));
                                break;
                            }
                            case EVENT_SHOCKWAVE:
                            {
                                DoCast(me->getVictim(), SPELL_SHOCKWAVE);
                                events.ScheduleEvent(EVENT_SHOCKWAVE, 20000);
                                break;
                            }
                            default:
                                break;
                        }
                    }
    
                    DoMeleeAttackIfReady();
                }
        private:
            bool isFrenzied;
            InstanceScript* instance;
            EventMap events;
        };
    
        CreatureAI* GetAI(Creature* creature) const
        {
            return GetIcecrownCitadelAI<npc_shambling_horrorAI>(creature);
        }
    };
    
    class npc_shadow_trap : public CreatureScript
    {
    enum eEvents
    {
        EVENT_BECOME_ACTIVE = 1,
        EVENT_ACTIVE,
        EVENT_CHECK,
        EVENT_DESPAWN
    };
    
    public:
    
        npc_shadow_trap() : CreatureScript("npc_shadow_trap") { }
    
        struct npc_shadow_trapAI : public Scripted_NoMovementAI
        {
            npc_shadow_trapAI(Creature* creature) : Scripted_NoMovementAI(creature) { }
    
            void Reset()
            {
                events.ScheduleEvent(EVENT_BECOME_ACTIVE, 500);
                events.ScheduleEvent(EVENT_DESPAWN, 60000);
                SetCombatMovement(false);
                active = false;
            }
    
            //void MoveInLineOfSight(Unit* who)
            //{
            //    if (active && me->IsWithinDistInMap(who, 4.0f))
            //    {
            //        if (who->GetTypeId() == TYPEID_PLAYER)
            //            me->CastSpell(who, SPELL_SHADOW_TRAP_EFFECT, true);
            //    }
            //}
    
            void UpdateAI(const uint32 uiDiff)
            {
                events.Update(uiDiff);
                while (uint32 eventId = events.ExecuteEvent())
                {
                    switch (eventId)
                    {
                        case EVENT_BECOME_ACTIVE:
                        {
                            DoCast(me, SPELL_SHADOW_TRAP_INTRO, true);
                            me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
                            events.ScheduleEvent(EVENT_ACTIVE, 1500);
                            break;
                        }
                        case EVENT_ACTIVE:
                        {
                            me->RemoveAura(SPELL_SHADOW_TRAP_INTRO);
                            DoCast(me, SPELL_SHADOW_TRAP_PERIODIC, true);
                            //If they don't reach that player within around 45 seconds, they will despawn harmlessly.
                            events.ScheduleEvent(EVENT_DESPAWN, 45000);
                            events.ScheduleEvent(EVENT_CHECK, 500);
                            active = true;
                            break;
                        }
                        case EVENT_CHECK:
                        {
                            if(Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 4.0f, true))
                            {
                                if (target->GetTypeId() == TYPEID_PLAYER)
                                    me->CastSpell(target, SPELL_SHADOW_TRAP_EFFECT, true);
                            }
                            else if(Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 4.0f, true))
                            {
                                if (target->GetTypeId() == TYPEID_PLAYER)
                                    me->CastSpell(target, SPELL_SHADOW_TRAP_EFFECT, true);
                            }
                            events.ScheduleEvent(EVENT_CHECK, 1500);
                            break;
                        }
                        case EVENT_DESPAWN:
                        {
                            DoCast(me, SPELL_SHADOW_TRAP_INTRO, true);
                            me->RemoveAura(SPELL_SHADOW_TRAP_PERIODIC);
                            me->DespawnOrUnsummon(2000);
                            break;
                        }
                        default:
                            break;
                    }
                }
            }
        private:
            EventMap events;
            bool active;
        };
    
        CreatureAI* GetAI(Creature* creature) const
        {
            return GetIcecrownCitadelAI<npc_shadow_trapAI>(creature);
        }
    };
    
    class npc_raging_spirit: public CreatureScript
    {
        public:
            npc_raging_spirit(): CreatureScript("npc_raging_spirit") { }
    
            struct npc_raging_spiritAI: public ScriptedAI
            {
                npc_raging_spiritAI(Creature* creature): ScriptedAI(creature) { }
    
                void EnterCombat(Unit* /*who*/)
                {
                    events.Reset();
                    events.ScheduleEvent(EVENT_SOUL_SHRIEK, 15000);
                }
    
                void UpdateAI(const uint32 diff)
                {
                    if (!UpdateVictim())
                        return;
    
                    if (me->HasUnitState(UNIT_STAT_CASTING))
                        return;
    
                    events.Update(diff);
    
                    while (uint32 eventId = events.ExecuteEvent())
                    {
                        switch (eventId)
                        {
                            case EVENT_SOUL_SHRIEK:
                            {
                                DoCast(me->getVictim(), SPELL_SOUL_SHRIEK);
                                events.ScheduleEvent(EVENT_SOUL_SHRIEK, 10000);
                                break;
                            }
                            default:
                                break;
                        }
                    }
    
                    DoMeleeAttackIfReady();
                }
        private:
            EventMap events;
        };
    
        CreatureAI* GetAI(Creature* creature) const
        {
            return GetIcecrownCitadelAI<npc_raging_spiritAI>(creature);
        }
    };
    
    class npc_ice_sphere : public CreatureScript
    {
        public:
            npc_ice_sphere() : CreatureScript("npc_ice_sphere") { }
    
            struct npc_ice_sphereAI : public ScriptedAI
            {
                npc_ice_sphereAI(Creature* creature) : ScriptedAI(creature), m_victimGuid(0) { }
    
                void Reset()
                {
                    //events.ScheduleEvent(EVENT_MOVE_FORWARD, 2000);
                    SetCombatMovement(false);
                    me->SetReactState(REACT_PASSIVE);
                    me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
                    me->ApplySpellImmune(0, IMMUNITY_ID, SPELL_REMORSELESS_WINTER_DAMAGE, true);
                    me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true);
                    me->ApplySpellImmune(0, IMMUNITY_ID, SPELL_DEATH_GRIP, true);
                    events.ScheduleEvent(EVENT_ACTIVATE, 2500);
                }
    
                void SetGUID(const uint64& guid, int32 type = 0)
                {
                    if (type == TYPE_VICTIM)
                    {
                        m_victimGuid = guid;
                        if (Unit* victim = ObjectAccessor::GetUnit(*me, m_victimGuid))
                            me->GetMotionMaster()->MoveChase(victim);
                    }
                }
    
                void JustDied(Unit* /*killer*/)
                {
                    if (Unit* victim = ObjectAccessor::GetUnit(*me, m_victimGuid))
                        victim->RemoveAurasDueToSpell(SPELL_ICE_PULSE, me->GetGUID());
                    me->DespawnOrUnsummon();
                }
    
                void KilledUnit(Unit* victim)
                {
                    victim->RemoveAurasDueToSpell(SPELL_ICE_PULSE, me->GetGUID());
                    me->DespawnOrUnsummon();
                }
    
                void UpdateAI(const uint32 diff)
                {
                    events.Update(diff);
    
                    while (uint32 eventId = events.ExecuteEvent())
                    {
                        switch (eventId)
                        {
                            case EVENT_ACTIVATE:
                            {
                                me->CastSpell(me, SPELL_ICE_SPHERE_VISUAL, true);
                                me->SetDisplayId(30243); //Make sphere visible
                                me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
                                me->CastSpell(me, SPELL_ICE_BURST_DISTANCE_CHECK, true);
                                me->SetReactState(REACT_AGGRESSIVE);
    
                                if (Player* target = SelectRandomAttackablePlayerInTheMap(me->GetMap()))
                                {
                                    me->AI()->AttackStart(target);
                                    me->AI()->SetGUID(target->GetGUID(), TYPE_VICTIM);
                                    me->CastSpell(target, SPELL_ICE_PULSE, true);
                                }
                                else
                                me->DespawnOrUnsummon();
                                break;
                            }
                            case EVENT_MOVE_FORWARD:
                            {
                                if (Unit* pVictim = ObjectAccessor::GetUnit(*me, m_victimGuid))
                                    if (pVictim->isAlive() && pVictim->isTargetableForAttack())
                                    {
                                        me->SetFacingToObject(pVictim);
                                        pVictim->GetPosition(&m_victimPos);
                                        me->GetPosition(&m_newPos);
                                        me->MovePosition(m_newPos, 0.20f, 0.0f);
                                        me->SetPosition(m_newPos);
                                    }
                                    else
                                    {
                                        if (Player* newVictim = SelectRandomPlayerInTheMap(me->GetMap()))
                                        {
                                            m_victimGuid = newVictim->GetGUID();
                                            AttackStart(newVictim);
                                            me->CastSpell(newVictim, SPELL_ICE_PULSE, true);
                                        }
                                        else
                                            me->DespawnOrUnsummon();
                                    }
                                events.ScheduleEvent(EVENT_MOVE_FORWARD, 100);
                            }
                            default:
                                break;
                        }
                    }
                }
        private:
            EventMap events;
            Position m_victimPos, m_newPos;
            uint64 m_victimGuid;
        };
    
        CreatureAI* GetAI(Creature* creature) const
        {
            return GetIcecrownCitadelAI<npc_ice_sphereAI>(creature);
        }
    };
    
    class npc_defile : public CreatureScript
    {
        public:
            npc_defile() : CreatureScript("npc_defile") { }
    
            struct npc_defileAI : public Scripted_NoMovementAI
            {
                npc_defileAI(Creature* creature) : Scripted_NoMovementAI(creature), alreadyReset(false), m_hitNumber(0) { }
    
                void JustRespawned()
                {
                    me->SetInCombatWithZone();
                    me->SetReactState(REACT_PASSIVE);
                }
    
                /*void UpdateDefileAura()
                {
                    ++m_hitNumber;
                    m_radiusMod = (int32)(((float)m_hitNumber / 60) * 0.9f + 0.1f) * 10000 * 2 / 3;
    
                    if (SpellEntry const* defileAuraSpellEntry = sSpellMgr->GetSpellForDifficultyFromSpell(sSpellStore.LookupEntry(SPELL_DEFILE), me))
                        me->CastCustomSpell(defileAuraSpellEntry->Id, SPELLVALUE_RADIUS_MOD, m_radiusMod, me, true, NULL, NULL, me->GetGUID()); 
                }*/
    
                void Reset()
                {
                    if (!alreadyReset)
                    {
                        if (SpellEntry const* defileAuraSpellEntry = sSpellMgr->GetSpellForDifficultyFromSpell(sSpellStore.LookupEntry(SPELL_DEFILE), me))
                            DoCast(me, defileAuraSpellEntry->Id, true);
                        //UpdateDefileAura();
                        me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
                        alreadyReset = true;
                    }
                }
    
                /*void SpellHitTarget(Unit* target, SpellEntry const* spell)
                {
                    if (spell->Id == SPELL_DEFILE_DAMAGE)
                    {
                        AttackStart(target);
    
                        if (SpellEntry const* defileIncrease = sSpellMgr->GetSpellForDifficultyFromSpell(sSpellStore.LookupEntry(SPELL_DEFILE_INCREASE), me))
                            DoCast(me, defileIncrease->Id, true);
                        UpdateDefileAura();
                    }
                }*/
    
                void UpdateAI(const uint32 diff) {}
        private:
            bool alreadyReset;
            int32 m_hitNumber, m_radiusMod;
        };
    
        CreatureAI* GetAI(Creature* creature) const
        {
            return GetIcecrownCitadelAI<npc_defileAI>(creature);
        }
    };
    
    class npc_spirit_warden : public CreatureScript
    {
        public:
            npc_spirit_warden() : CreatureScript("npc_spirit_warden") { }
    
            struct npc_spirit_wardenAI : public ScriptedAI
            {
                npc_spirit_wardenAI(Creature* creature) : ScriptedAI(creature) {}
    
                void Reset()
                {
                    me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
                    me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true);
                    me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_CHARM, true);
                    me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_SILENCE, true);
                    me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_TRANSFORM, true);
                    me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_SCALE, true);
                    DoCast(me, SPELL_DARK_HUNGER, true);
                    me->SetReactState(REACT_PASSIVE);
                }
    
                void DamageDealt(Unit* /*target*/, uint32& damage, DamageEffectType /*damageType*/)
                {
                    me->CastCustomSpell(SPELL_DARK_HUNGER_HEAL_EFFECT, SPELLVALUE_BASE_POINT0, damage, me, true, NULL, NULL, me->GetGUID());
                }
                
                void JustDied(Unit* /*killer*/)
                {
                    if (Player* player = me->FindNearestPlayer(80.0f, true))
                    {
                        if (Creature* terenasFighter = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetData64(DATA_TERENAS_FIGHTER)))
                            terenasFighter->CastSpell(player, SPELL_RESTORE_SOUL, true);
    
                        TeleportPlayerToFrozenThrone(player);
                        player->RemoveAurasDueToSpell(SPELL_IN_FROSTMOURNE_ROOM);
                        events.Reset();
                    }
                }
    
                void DoAction(const int32 action)
                {
                    switch(action)
                    {
                        case ACTION_DESPAWN:
                        {
                            me->DespawnOrUnsummon();
                            break;
                        }
                        case ACTION_ATTACK_TERENAS_FIGHTER:
                        {
                            events.Reset();
                            me->NearTeleportTo(FrostmourneRoom[1].m_positionX, FrostmourneRoom[1].m_positionY, FrostmourneRoom[1].m_positionZ, FrostmourneRoom[1].m_orientation); 
    
                            if (Creature* terenasFighter = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetData64(DATA_TERENAS_FIGHTER)))
                                AttackStart(terenasFighter);
    
                            me->SetHealth(me->GetMaxHealth());
                            events.ScheduleEvent(EVENT_SOUL_RIP, 5000);
                            events.ScheduleEvent(EVENT_DESTROY_SOUL, 60000);
                            events.ScheduleEvent(EVENT_CHECK_SOUL_RIP_DISPELLED, 1000);
                            break;
                        }
                    }
                }
    
                void UpdateAI(const uint32 diff)
                {
                    if (!me->isAlive() || me->HasUnitState(UNIT_STAT_CASTING))
                        return;
    
                    events.Update(diff);
    
                    while (uint32 eventId = events.ExecuteEvent())
                    {
                        switch (eventId)
                        {
                            case EVENT_CHECK_SOUL_RIP_DISPELLED:
                            {
                                if (Creature* terenasFighter = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetData64(DATA_TERENAS_FIGHTER)))
                                    if (!terenasFighter->HasAura(SPELL_SOUL_RIP, me->GetGUID()))
                                    {
                                        me->InterruptNonMeleeSpells(false);
                                        me->InterruptSpell(CURRENT_CHANNELED_SPELL, false);
                                    }
    
                                events.ScheduleEvent(EVENT_CHECK_SOUL_RIP_DISPELLED, 1000);
                                break;
                            }
                            case EVENT_SOUL_RIP:
                            {
                                if (Creature* terenasFighter = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetData64(DATA_TERENAS_FIGHTER)))
                                    DoCast(terenasFighter, SPELL_SOUL_RIP, true);
    
                                events.ScheduleEvent(EVENT_SOUL_RIP, 20000);
                                break;
                            }
                            case EVENT_DESTROY_SOUL:
                            {
                                //Player failed to help Terenas to defeat Spirit Warden within 60 seconds - kill Player forcibly
                                if (Creature* lichKing = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetData64(DATA_THE_LICH_KING)))
                                    DoCast(lichKing, IsHeroic() ? SPELL_HARVESTED_SOUL_HEROIC : SPELL_HARVESTED_SOUL_NORMAL, true);
    
                                if (Player *player = me->FindNearestPlayer(80.0f, true))
                                {
                                    player->CastSpell(player, SPELL_DESTROY_SOUL, true);
                                    TeleportPlayerToFrozenThrone(player);
                                    player->RemoveAurasDueToSpell(SPELL_IN_FROSTMOURNE_ROOM);
                                }
                                events.Reset();
                                break;
                            }
                        }
                    }
                    DoMeleeAttackIfReady();
                }
            private:
                EventMap events;
            };
    
            CreatureAI* GetAI(Creature* creature) const
            {
                return GetIcecrownCitadelAI<npc_spirit_wardenAI>(creature);
            }
    };
    
    class npc_terenas_menethil : public CreatureScript
    {
        public:
            npc_terenas_menethil() : CreatureScript("npc_terenas_menethil") { }
    
            struct npc_terenas_menethilAI : public ScriptedAI
            {
                npc_terenas_menethilAI(Creature* creature) : ScriptedAI(creature) {}
    
                void Reset()
                {
                    DoCast(me, SPELL_LIGHT_S_FAVOR, true);
                    me->SetReactState(REACT_PASSIVE);
                    me->SetHealth(me->GetMaxHealth() / 2);
                }
    
                void DoAction(const int32 action)
                {
                    switch(action)
                    {
                        case ACTION_DESPAWN:
                        {
                            me->DespawnOrUnsummon();
                            break;
                        }
                        case ACTION_ATTACK_SPIRIT_WARDEN:
                        {
                            me->NearTeleportTo(FrostmourneRoom[2].m_positionX, FrostmourneRoom[2].m_positionY, FrostmourneRoom[2].m_positionZ, FrostmourneRoom[2].m_orientation); 
    
                            if (Creature* spiritWarden = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetData64(DATA_SPIRIT_WARDEN)))
                                AttackStart(spiritWarden);
    
                            me->SetHealth(me->GetMaxHealth() / 2);
                            events.ScheduleEvent(EVENT_GREET_PLAYER, 1000);
                            break;
                        }
                    }
                }
    
                void DamageDealt(Unit* /*target*/, uint32& damage, DamageEffectType /*damageType*/)
                {
                    //Damage scales with Terenas' health
                    damage = damage * (100 + (uint32)me->GetHealthPct()) / 100;
                }
    
                void JustDied(Unit* /*killer*/)
                {
                    Player* player = me->FindNearestPlayer(80.0f, true);
                    player->CastSpell(player, SPELL_DESTROY_SOUL, true);
    
                    if (Creature* lichKing = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetData64(DATA_THE_LICH_KING)))
                        DoCast(lichKing, IsHeroic() ? SPELL_HARVESTED_SOUL_HEROIC : SPELL_HARVESTED_SOUL_NORMAL, true);
    
                    TeleportPlayerToFrozenThrone(player);
                    events.Reset();
                }
    
                void UpdateAI(const uint32 diff)
                {
                    if (!me->isAlive() || me->HasUnitState(UNIT_STAT_CASTING))
                        return;
    
                    events.Update(diff);
    
                    while (uint32 eventId = events.ExecuteEvent())
                    {
                        switch (eventId)
                        {
                            case EVENT_GREET_PLAYER:
                            {
                                me->MonsterYell("You have come to bring Arthas to justice? To see the Lich King destroyed?", LANG_UNIVERSAL, 0);
                                me->PlayDirectSound(17394);
                                events.ScheduleEvent(EVENT_ENCOURAGE_PLAYER_TO_ESCAPE, 10000);
                                break;
                            }
                            case EVENT_ENCOURAGE_PLAYER_TO_ESCAPE:
                            {
                                me->MonsterYell("First, you must escape Frostmourne's hold or be damned as I am; trapped within this cursed blade for all eternity.", LANG_UNIVERSAL, 0);
                                 me->PlayDirectSound(17395);
                                events.ScheduleEvent(EVENT_ASK_PLAYER_FOR_AID, 10000);
                                break;
                            }
                            case EVENT_ASK_PLAYER_FOR_AID:
                            {
                                me->MonsterYell("Aid me in destroying these tortured souls! Together we will loosen Frostmourne's hold and weaken the Lich King from within!", LANG_UNIVERSAL, 0);
                                 me->PlayDirectSound(17396);
                                break;
                            }
                            case EVENT_CHECK_SPIRIT_WARDEN_HEALTH:
                            {
                                if (Creature* spiritWarden = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetData64(DATA_SPIRIT_WARDEN)))
                                {
                                    if (!spiritWarden->isAlive())
                                        KilledUnit(spiritWarden);
                                }
                                break;
                            }
                        }
                    }
                    DoMeleeAttackIfReady();
                }
            private:
                EventMap events;
            };
    
            CreatureAI* GetAI(Creature* creature) const
            {
                return GetIcecrownCitadelAI<npc_terenas_menethilAI>(creature);
            }
    };
    
    /*class spell_lich_king_pain_and_suffering : public SpellScriptLoader
    {
        public:
            spell_lich_king_pain_and_suffering() : SpellScriptLoader("spell_lich_king_pain_and_suffering") { }
    
            class spell_lich_king_pain_and_suffering_AuraScript : public AuraScript
            {
                PrepareAuraScript(spell_lich_king_pain_and_suffering_AuraScript)
    
                class AnyAlivePetOrPlayerInObjectFrontalConeCheck
                {
                    public:
                        AnyAlivePetOrPlayerInObjectFrontalConeCheck(WorldObject const* obj) : i_obj(obj) {}
                        bool operator()(Unit* u)
                        {
                            if (u->GetTypeId() != TYPEID_PLAYER)
                                return false;
    
                            if (!u->isTargetableForAttack())
                                return false;
    
                            if (!u->isAlive())
                                return false;
    
                            Position myPos, uPos;
                            i_obj->GetPosition(&myPos);
                            u->GetPosition(&uPos);
                            float orientation = i_obj->GetOrientation();
                            float angle = myPos.GetAngle(&uPos);
                            float coneAngle = M_PI / 180 * 1.0f;
                            angle = MapManager::NormalizeOrientation(orientation - angle);
    
                            if ((0.0f <= angle) && (angle <= coneAngle / 2) ||
                                ((2 * M_PI - coneAngle / 2) <= angle) && (angle <= (2 * M_PI)))
                                return true;
                            return false;
                        }
                    private:
                        WorldObject const* i_obj;
                };
    
                void OnPeriodic(AuraEffect const*aurEff)
                {
                    PreventDefaultAction();
                    Unit *caster = GetCaster();
    
                    if (!caster || !caster->isAlive() || caster->HasUnitState(UNIT_STAT_CASTING))
                        return;
    
                    AnyAlivePetOrPlayerInObjectFrontalConeCheck checker(caster);
                    std::list<Unit *> targets;
                    Trinity::UnitListSearcher<AnyAlivePetOrPlayerInObjectFrontalConeCheck> searcher(caster, targets, checker);
    
                    TypeContainerVisitor<Trinity::UnitListSearcher<AnyAlivePetOrPlayerInObjectFrontalConeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
                    TypeContainerVisitor<Trinity::UnitListSearcher<AnyAlivePetOrPlayerInObjectFrontalConeCheck>, GridTypeMapContainer >  grid_unit_searcher(searcher);
    
                    CellPair p(Trinity::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY()));
                    Cell cell(p);
                    cell.data.Part.reserved = ALL_DISTRICT;
                    cell.SetNoCreate();
    
                    cell.Visit(p, world_unit_searcher, *GetTarget()->GetMap(), *GetTarget(), 100.0f);
                    cell.Visit(p, grid_unit_searcher, *GetTarget()->GetMap(), *GetTarget(), 100.0f);
    
                    for (std::list<Unit*>::iterator it = targets.begin(); it != targets.end(); ++it)
                        caster->CastSpell((*it), SPELL_PAIN_AND_SUFFERING_DAMAGE, true);
                    //Next time try to target somebody else
    
                    if (Player *randomTarget = SelectRandomPlayerInTheMap(caster->GetMap()))
                        caster->SetFacingToObject(randomTarget);
                }
    
                void Register()
                {
                    OnEffectPeriodic += AuraEffectPeriodicFn(spell_lich_king_pain_and_suffering_AuraScript::OnPeriodic, EFFECT_2, SPELL_AURA_PERIODIC_TRIGGER_SPELL); //74117
                }
            };
    
            AuraScript* GetAuraScript() const
            {
                return new spell_lich_king_pain_and_suffering_AuraScript();
            }
    };*/
    
    class spell_lich_king_pain_and_suffering_effect : public SpellScriptLoader
    {
        public:
            spell_lich_king_pain_and_suffering_effect() : SpellScriptLoader("spell_lich_king_pain_and_suffering_effect") { }
    
            class spell_lich_king_pain_and_suffering_effect_SpellScript : public SpellScript
            {
                PrepareSpellScript(spell_lich_king_pain_and_suffering_effect_SpellScript);
    
                /*void HandleScript(SpellEffIndex effIndex)
                {
                    Unit *caster = GetCaster();
                    if (!caster || !caster->isAlive())
                    {
                        PreventHitDefaultEffect(effIndex);
                        return;
                    }
                    //Next time try to target random player
                    if (Player *randomTarget = SelectRandomPlayerInTheMap(caster->GetMap()))
                        caster->SetFacingToObject(randomTarget);
                }*/
    
                class AnyAlivePetOrPlayerInObjectFrontalConeCheck
                {
                    public:
                        AnyAlivePetOrPlayerInObjectFrontalConeCheck(WorldObject const* obj) : i_obj(obj) {}
                        bool operator()(Unit* u)
                        {
                            if (u->GetTypeId() != TYPEID_PLAYER)
                                return true;
    
                            if (!u->isTargetableForAttack())
                                return true;
    
                            if (!u->isAlive())
                                return true;
    
                            Position myPos, uPos;
                            i_obj->GetPosition(&myPos);
                            u->GetPosition(&uPos);
                            float orientation = i_obj->GetOrientation();
                            float angle = myPos.GetAngle(&uPos);
                            float coneAngle = M_PI / 180 * 15.0f;
                            angle = MapManager::NormalizeOrientation(orientation - angle);
    
                            if ((0.0f <= angle) && (angle <= coneAngle / 2) ||
                                ((2 * M_PI - coneAngle / 2) <= angle) && (angle <= (2 * M_PI)))
                                return false;
                            return true;
                        }
                    private:
                        WorldObject const* i_obj;
                };
    
                void FilterTargets(std::list<Unit*>& unitList)
                {
                    Unit *caster = GetCaster();
    
                    if (!caster || !caster->isAlive())
                        return;
    
                    unitList.remove_if (AnyAlivePetOrPlayerInObjectFrontalConeCheck(caster)); 
                }
    
                void Register()
                {
                    OnUnitTargetSelect += SpellUnitTargetFn(spell_lich_king_pain_and_suffering_effect_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_TARGET_ENEMY);
                    OnUnitTargetSelect += SpellUnitTargetFn(spell_lich_king_pain_and_suffering_effect_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_AREA_PATH);
                    OnUnitTargetSelect += SpellUnitTargetFn(spell_lich_king_pain_and_suffering_effect_SpellScript::FilterTargets, EFFECT_2, TARGET_UNIT_AREA_PATH);
                    //OnEffect += SpellEffectFn(spell_lich_king_pain_and_suffering_effect_SpellScript::HandleScript, EFFECT_1, SPELL_EFFECT_SCHOOL_DAMAGE);
                }
            };
    
            SpellScript* GetSpellScript() const
            {
                return new spell_lich_king_pain_and_suffering_effect_SpellScript();
            }
    };
    
    class spell_lich_king_necrotic_plague : public SpellScriptLoader
    {
        public:
            spell_lich_king_necrotic_plague() : SpellScriptLoader("spell_lich_king_necrotic_plague") { }
    
            class spell_lich_king_necrotic_plague_AuraScript : public AuraScript
            {
                PrepareAuraScript(spell_lich_king_necrotic_plague_AuraScript)
    
                class AnyAliveCreatureOrPlayerInObjectRangeCheck
                {
                    public:
                        AnyAliveCreatureOrPlayerInObjectRangeCheck(WorldObject const* obj, float range) : i_obj(obj), i_range(range) {}
                        bool operator()(Unit* u)
                        {
                            if (!u->isTargetableForAttack())
                                return false;
    
                            if (u->GetGUID() == i_obj->GetGUID())
                                return false;
    
                            if (!(u->isAlive() && i_obj->IsWithinDistInMap(u, i_range)))
                                return false;
    
                            if (u->GetTypeId() == TYPEID_PLAYER)
                                return true;
    
                            if (u->GetTypeId() != TYPEID_UNIT)
                                return false;
    
                            if (((Creature*)u)->isTotem())
                                return false;
    
                            if (u->GetOwner() && u->GetOwner()->GetTypeId() == TYPEID_PLAYER)
                                return false;
    
                            uint32 entry = u->ToCreature()->GetEntry();
    
                            if (entry == NPC_THE_LICH_KING || entry == NPC_TIRION || entry == NPC_RAGING_SPIRIT)
                                return false;
                            return true;
                        }
                    private:
                        WorldObject const* i_obj;
                        float i_range;
                };
    
                /*void OnPeriodic(AuraEffect const*aurEff)
                {
                    PreventDefaultAction();
                    if (!(GetTarget() && GetTarget()->isAlive() && GetCaster() && GetCaster()->isAlive()))
                        return;
                    m_stackAmount = GetStackAmount();
                    GetCaster()->DealDamage(GetTarget(), (uint32)aurEff->GetBaseAmount() * m_stackAmount, 0, SPELL_DIRECT_DAMAGE, SPELL_SCHOOL_MASK_SHADOW, aurEff->GetSpellProto(), true);
                    //if (GetTarget() && GetTarget()->isAlive() && GetCaster() && GetCaster()->isAlive())
                    //    GetCaster()->CastSpell(GetTarget(), SPELL_NECROTIC_PLAGUE_EFFECT, true);
                }*/
    
                void OnRemove(AuraEffect const * aurEff, AuraEffectHandleModes mode)
                {
                    Unit* target = GetTarget();
    
                    if (!target)
                        return;
    
                    if (GetStackAmount() >= 30)
                        if (InstanceScript *instance = target->GetInstanceScript())
                            instance->SetData(DATA_BEEN_WAITING_ACHIEVEMENT, DONE);
    
                    CellPair p(Trinity::ComputeCellPair(target->GetPositionX(), target->GetPositionY()));
                    Cell cell(p);
                    cell.data.Part.reserved = ALL_DISTRICT;
                    cell.SetNoCreate();
    
                    Unit* anyPlayerOrCreatureInRange = NULL;
                    float dist = 10.0f;
                    AnyAliveCreatureOrPlayerInObjectRangeCheck checker(target, dist);
                    Unit* newTarget = NULL;
                    Trinity::UnitLastSearcher<AnyAliveCreatureOrPlayerInObjectRangeCheck> searcher(target, newTarget, checker);
    
                    TypeContainerVisitor<Trinity::UnitLastSearcher<AnyAliveCreatureOrPlayerInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
                    TypeContainerVisitor<Trinity::UnitLastSearcher<AnyAliveCreatureOrPlayerInObjectRangeCheck>, GridTypeMapContainer >  grid_unit_searcher(searcher);
    
                    cell.Visit(p, world_unit_searcher, *target->GetMap(), *target, dist);
                    cell.Visit(p, grid_unit_searcher, *target->GetMap(), *target, dist);
    
                    uint32 stacksTransferred = GetStackAmount();
                    //If target is still alive and it's a player, it means that this spell was dispelled - increase stack amount then
                    //I don't know the way to find out whether it's dispelled or not
                    if (!target->isAlive())
                        ++stacksTransferred;
                    else
                    {
                        //Player was a target and is still alive - assume that the spell was dispelled
                        if (target->GetTypeId() == TYPEID_PLAYER)
                            if (stacksTransferred > 1)
                                --stacksTransferred;
                    }
    
                    if (stacksTransferred < 1)
                        stacksTransferred = 1;
    
                    uint32 spellId = aurEff->GetSpellProto()->Id;
                    InstanceScript* instance = target->GetInstanceScript();
    
                    if (instance)
                    {
                        Unit* lichKing = ObjectAccessor::GetCreature(*target, instance->GetData64(DATA_THE_LICH_KING));
    
                        if (lichKing)
                        {
                            if (newTarget)
                            {
                                Aura* appAura = newTarget->GetAura(spellId);
                                if (!appAura)
                                {
                                    Unit* newCaster = lichKing;
                                    newCaster->CastSpell(newTarget, spellId, true);
                                    appAura = newTarget->GetAura(spellId);
                                    --stacksTransferred; //One stack is already transferred
                                }
                                if (appAura)
                                {
                                    appAura->SetStackAmount(appAura->GetStackAmount() + stacksTransferred);
                                    appAura->RefreshDuration();
                                }
                            }
    
                            Aura* plagueSiphon = lichKing->GetAura(SPELL_PLAGUE_SIPHON);
    
                            if (!plagueSiphon)
                            {
                                lichKing->CastSpell(lichKing, SPELL_PLAGUE_SIPHON, true);
                                plagueSiphon = lichKing->GetAura(SPELL_PLAGUE_SIPHON);
                            }
    
                            if (plagueSiphon)
                            {
                                plagueSiphon->ModStackAmount(1);
                                plagueSiphon->RefreshDuration();
                            }
                        }
                    }
                }
    
                void Register()
                {
                    //OnEffectPeriodic += AuraEffectPeriodicFn(spell_lich_king_necrotic_plague_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
                    //OnEffectApply += AuraEffectApplyFn(spell_lich_king_necrotic_plague_AuraScript::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL);
                    OnEffectRemove += AuraEffectRemoveFn(spell_lich_king_necrotic_plague_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL);
                }
            private:
                uint8 m_stackAmount;
            };
    
            AuraScript* GetAuraScript() const
            {
                return new spell_lich_king_necrotic_plague_AuraScript();
            }
    };
    
    class spell_lich_king_defile : public SpellScriptLoader
    {
        public:
            spell_lich_king_defile() : SpellScriptLoader("spell_lich_king_defile") { } 
    
            class spell_lich_king_defile_AuraScript : public AuraScript
            {
                PrepareAuraScript(spell_lich_king_defile_AuraScript)
    
                void OnPeriodic(AuraEffect const* aurEff)
                {
                    PreventDefaultAction();
                    Unit* caster = GetCaster();
    
                    if (!(caster && caster->isAlive()) && caster->GetAI())
                        return;
    
                    Map* map = caster->GetMap();
                    //Radius increases by 10% per hit on heroic and by 5% if it's normal
                    m_radius = 8.0f + m_hitCount;
                    //Find targest
                    std::list<Unit *> targets;
                    Trinity::AnyUnfriendlyAttackableVisibleUnitInObjectRangeCheck checker(caster, m_radius); 
                    Trinity::UnitListSearcher<Trinity::AnyUnfriendlyAttackableVisibleUnitInObjectRangeCheck> searcher(caster, targets, checker);
                    TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyUnfriendlyAttackableVisibleUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
                    TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyUnfriendlyAttackableVisibleUnitInObjectRangeCheck>, GridTypeMapContainer >  grid_unit_searcher(searcher);
                    CellPair p(Trinity::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY()));
                    Cell cell(p);
                    cell.data.Part.reserved = ALL_DISTRICT;
                    cell.SetNoCreate();
                    cell.Visit(p, world_unit_searcher, *map, *caster, 100.0f);
                    cell.Visit(p, grid_unit_searcher, *map, *caster, 100.0f);
    
                    if (targets.empty())
                        return;
    
                    uint32 triggeredSpellId = SPELL_DEFILE_DAMAGE;
                    int32 triggeredSpellBaseDamage = 3000;
    
                    if (SpellEntry const* defileDamage = sSpellMgr->GetSpellForDifficultyFromSpell(sSpellStore.LookupEntry(SPELL_DEFILE_DAMAGE), caster))
                    {
                        triggeredSpellId = defileDamage->Id;
                        triggeredSpellBaseDamage = (int32)(defileDamage->EffectBasePoints[EFFECT_0] * (1.0f + (map->IsHeroic() ? 0.1f : 0.05f) * m_hitCount));
                    }
    
                    values.AddSpellMod(SPELLVALUE_BASE_POINT0, ((int32)(triggeredSpellBaseDamage)));
                    values.AddSpellMod(SPELLVALUE_RADIUS_MOD, ((int32)(m_radius * 50)));
                    //values.AddSpellMod(SPELLVALUE_MAX_TARGETS, 1);
    
                    bool increaseRadius = false;
                    uint64 ownerGuid = (caster->GetOwner() ? caster->GetOwner()->GetGUID() : 0);
                    Unit* curVictim = NULL;
    
                    for (std::list<Unit*>::iterator it = targets.begin(); it != targets.end(); ++it)
                    {
                        curVictim = *it;
                        if (curVictim->GetGUID() == ownerGuid)
                            continue;
    
                        if (curVictim->GetTypeId() != TYPEID_PLAYER)
                            continue;
    
                        if (curVictim->GetDistance2d(caster) > m_radius)
                            continue;
    
                        caster->CastCustomSpell(triggeredSpellId, values, curVictim, true, NULL, NULL, GetCasterGUID());
                        increaseRadius = true;
                    }
    
                    if (!increaseRadius)
                        return;
    
                    if (SpellEntry const* defileIncrease = sSpellMgr->GetSpellForDifficultyFromSpell(sSpellStore.LookupEntry(SPELL_DEFILE_INCREASE), caster))
                    {
                        caster->CastSpell(caster, defileIncrease->Id, true);
    
                        if (Aura* defileIncreaseAura = caster->GetAura(defileIncrease->Id))
                            m_hitCount = defileIncreaseAura->GetStackAmount();
                        else
                            ++m_hitCount;
                    }
                }
    
                void Register()
                {
                    m_hitCount = 0;
                    m_radius = 0.0f;
                    OnEffectPeriodic += AuraEffectPeriodicFn(spell_lich_king_defile_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
                }
            private:
                uint32 m_hitCount;
                float m_radius;
                CustomSpellValues values;
            };
    
            AuraScript* GetAuraScript() const
            {
                return new spell_lich_king_defile_AuraScript();
            }
    };
    
    class spell_lich_king_infection : public SpellScriptLoader
    {
        public:
            spell_lich_king_infection() : SpellScriptLoader("spell_lich_king_infection") { } //70541
    
            class spell_lich_king_infection_AuraScript : public AuraScript
            {
                PrepareAuraScript(spell_lich_king_infection_AuraScript)
    
                void HandleTick(AuraEffect const* aurEff)
                {
                    if (!GetTarget()->isAlive() || GetTarget()->GetHealthPct() >= 90)
                    {
                        //Aura::ApplicationMap &apmap = const_cast<Aura::ApplicationMap&>(aurEff->GetBase()->GetApplicationMap());
                        //Aura::ApplicationMap::iterator it = apmap.find(GetTarget()->GetGUID());
                        //if (it != apmap.end())
                        //    apmap.erase(it);
                        PreventDefaultAction();
                        GetTarget()->RemoveAurasDueToSpell(aurEff->GetSpellProto()->Id);
                    }
                }
    
                void OnCalcAmount(AuraEffect const* aurEff, int32 & amount, bool & canBeRecalculated)
                {
                    amount = (int32)(1000.0f * powf(1.15f, (float)aurEff->GetTickNumber()));
                }
    
                void Register()
                {
                    OnEffectPeriodic += AuraEffectPeriodicFn(spell_lich_king_infection_AuraScript::HandleTick, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
                    DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_lich_king_infection_AuraScript::OnCalcAmount, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
                }
            };
    
            AuraScript* GetAuraScript() const
            {
                return new spell_lich_king_infection_AuraScript();
            }
    };
    
    class spell_lich_king_valkyr_summon : public SpellScriptLoader
    {
        public:
            spell_lich_king_valkyr_summon() : SpellScriptLoader("spell_lich_king_valkyr_summon") { } //74361
    
            class spell_lich_king_valkyr_summon_AuraScript : public AuraScript
            {
                PrepareAuraScript(spell_lich_king_valkyr_summon_AuraScript);
    
                void OnApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
                {
                    if (Unit* caster = GetCaster())
                    {
                        uint32 spawnMod = caster->GetMap()->GetSpawnMode();
                        GetTargetApplication()->GetBase()->SetDuration(spawnMod == 1 || spawnMod == 3 ? 3000 : 1000);
                    }
                }
    
                void HandleTriggerSpell(AuraEffect const* aurEff)
                {
                    PreventDefaultAction();
    
                    if (Unit* caster = GetCaster())
                    {
                        Position randomPos;
                        caster->GetRandomNearPosition(randomPos, 10.0f);
                        uint32 triggerSpellId = GetSpellProto()->EffectTriggerSpell[aurEff->GetEffIndex()];
                        randomPos.m_positionZ = caster->GetPositionZ() + 6.0f;
                        caster->CastSpell(randomPos.GetPositionX(), randomPos.GetPositionY(), randomPos.GetPositionZ(), triggerSpellId, true, NULL, NULL, GetCasterGUID(), caster);
                    }
                }
    
                void Register()
                {
                    OnEffectPeriodic += AuraEffectPeriodicFn(spell_lich_king_valkyr_summon_AuraScript::HandleTriggerSpell, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
                    OnEffectApply += AuraEffectApplyFn(spell_lich_king_valkyr_summon_AuraScript::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
                }
            };
    
            AuraScript* GetAuraScript() const
            {
                return new spell_lich_king_valkyr_summon_AuraScript();
            }
    };
    
    class spell_lich_king_vile_spirit_summon : public SpellScriptLoader
    {
        public:
            spell_lich_king_vile_spirit_summon() : SpellScriptLoader("spell_lich_king_vile_spirit_summon") { }
    
            class spell_lich_king_vile_spirit_summon_AuraScript : public AuraScript
            {
                PrepareAuraScript(spell_lich_king_vile_spirit_summon_AuraScript);
    
                void OnPeriodic(AuraEffect const* aurEff)
                {
                    PreventDefaultAction();
                    Unit* caster = GetCaster();
    
                    if (!caster || !caster->isAlive())
                        return;
    
                    InstanceScript* instance = caster->GetInstanceScript();
    
                    if (instance)
                    {
                        uint32 spawnMod = caster->GetMap()->GetSpawnMode();
                        uint32 maxSummoned;
                        if (spawnMod == 1 || spawnMod == 3)
                            maxSummoned = 10;
                        else
                            maxSummoned = 8;
                        if (aurEff->GetTickNumber() >= maxSummoned)
                            return;
                    }
    
                    Position pos;
                    caster->GetRandomNearPosition(pos, 13.0f);
                    pos.m_positionZ = npc_vile_spirit::Z_VILE_SPIRIT;
                    uint32 triggeredSpell = aurEff->GetSpellProto()->EffectTriggerSpell[aurEff->GetEffIndex()];
                    caster->CastSpell(pos.m_positionX, pos.m_positionY, pos.m_positionZ, triggeredSpell, true);
                }
    
                void Register()
                {
                    OnEffectPeriodic += AuraEffectPeriodicFn(spell_lich_king_vile_spirit_summon_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
                    OnEffectPeriodic += AuraEffectPeriodicFn(spell_lich_king_vile_spirit_summon_AuraScript::OnPeriodic, EFFECT_1, SPELL_AURA_LINKED);
                }
            };
    
            AuraScript* GetAuraScript() const
            {
                return new spell_lich_king_vile_spirit_summon_AuraScript();
            }
    };
    
    class spell_lich_king_vile_spirit_summon_visual : public SpellScriptLoader
    {
        public:
            spell_lich_king_vile_spirit_summon_visual() : SpellScriptLoader("spell_lich_king_vile_spirit_summon_visual") { }
    
            class spell_lich_king_vile_spirit_summon_visual_AuraScript : public AuraScript
            {
                PrepareAuraScript(spell_lich_king_vile_spirit_summon_visual_AuraScript);
    
                void OnPeriodic(AuraEffect const* aurEff)
                {
                    PreventDefaultAction();
                    Unit* caster = GetCaster();
    
                    if (!caster || !caster->isAlive())
                        return;
    
                    Position pos;
                    caster->GetRandomNearPosition(pos, 13.0f);
                    pos.m_positionZ = npc_vile_spirit::Z_VILE_SPIRIT;
                    uint32 triggeredSpell = aurEff->GetSpellProto()->EffectTriggerSpell[aurEff->GetEffIndex()];
                    caster->CastSpell(pos.m_positionX, pos.m_positionY, pos.m_positionZ, triggeredSpell, true);
                }
    
                void Register()
                {
                    OnEffectPeriodic += AuraEffectPeriodicFn(spell_lich_king_vile_spirit_summon_visual_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
                }
            };
    
            AuraScript* GetAuraScript() const
            {
                return new spell_lich_king_vile_spirit_summon_visual_AuraScript();
            }
    };
    
    
    class spell_lich_king_winter : public SpellScriptLoader
    {
        public:
            spell_lich_king_winter() : SpellScriptLoader("spell_lich_king_winter") { } //68981
    
            class spell_lich_king_winter_AuraScript : public AuraScript
            {
                PrepareAuraScript(spell_lich_king_winter_AuraScript)
    
                void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
                {
                    if (Unit* caster = GetCaster())
                    {
                        if (UnitAI* pBossAI = caster->GetAI())
                            pBossAI->DoAction(ACTION_CANCEL_ALL_TRANSITION_EVENTS);
    
                        caster->CastSpell(caster, SPELL_QUAKE, true);
                        DoScriptText(SAY_BROKEN_ARENA, caster);
                        InstanceScript* instance = caster->GetInstanceScript();
    
                        if (!instance)
                            return;
                    }
                }
    
                void OnApply(AuraEffect const* aurEff, AuraEffectHandleModes mode)
                {
                    Unit* caster = GetCaster();
    
                    if (!caster || !caster->isAlive())
                        return;
    
                    InstanceScript* instance = caster->GetInstanceScript();
    
                    if (!instance)
                        return;
    
                    //Rebuild platform's edge only in second transition phase
                    if (UnitAI* pAI = caster->GetAI())
                        if (pAI->GetData(DATA_PHASE) == PHASE_4_TRANSITION)
                        {
                            //Two spells should be casted in this very sequence to get working animation
                            caster->CastSpell(caster, SPELL_WMO_INTACT, true);
                            caster->CastSpell(caster, SPELL_WMO_REBUILD, true);
                        }
                    //Destroying ice shards
                    if (GameObject* go = ObjectAccessor::GetGameObject(*caster, instance->GetData64(DATA_ICE_SHARD_1)))
                        go->SetGoState(GO_STATE_ACTIVE);
    
                    if (GameObject* go = ObjectAccessor::GetGameObject(*caster, instance->GetData64(DATA_ICE_SHARD_2)))
                        go->SetGoState(GO_STATE_ACTIVE);
    
                    if (GameObject* go = ObjectAccessor::GetGameObject(*caster, instance->GetData64(DATA_ICE_SHARD_3)))
                        go->SetGoState(GO_STATE_ACTIVE);
    
                    if (GameObject* go = ObjectAccessor::GetGameObject(*caster, instance->GetData64(DATA_ICE_SHARD_4)))
                        go->SetGoState(GO_STATE_ACTIVE);
    
                    if (GameObject* go = ObjectAccessor::GetGameObject(*caster, instance->GetData64(DATA_EDGE_DESTROY_WARNING)))
                        go->SetGoState(GO_STATE_READY);
    
                    if (GameObject* go = ObjectAccessor::GetGameObject(*caster, instance->GetData64(DATA_FROSTY_EDGE_INNER)))
                        go->SetGoState(GO_STATE_READY);
    
                    if (GameObject* go = ObjectAccessor::GetGameObject(*caster, instance->GetData64(DATA_FROSTY_EDGE_OUTER)))
                        go->SetGoState(GO_STATE_ACTIVE);
                }
    
                void Register()
                {
                    OnEffectApply += AuraEffectApplyFn(spell_lich_king_winter_AuraScript::OnApply, EFFECT_1, SPELL_AURA_MOD_ROOT, AURA_EFFECT_HANDLE_REAL);
                    OnEffectRemove += AuraEffectRemoveFn(spell_lich_king_winter_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
                }
            };
    
            AuraScript* GetAuraScript() const
            {
                return new spell_lich_king_winter_AuraScript();
            }
    };
    
    class spell_lich_king_quake : public SpellScriptLoader
    {
        public:
            spell_lich_king_quake() : SpellScriptLoader("spell_lich_king_quake") { } //72262
    
            class spell_lich_king_quake_AuraScript : public AuraScript
            {
                PrepareAuraScript(spell_lich_king_quake_AuraScript)
    
                void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
                {
                    Unit* caster = GetCaster();
    
                    if (!caster)
                        return;
    
                    caster->CastSpell(caster, SPELL_WMO_INTACT, true);
                    caster->CastSpell(caster, SPELL_WMO_DESTROY, true);
    
                    if (InstanceScript* instance = GetTarget()->GetInstanceScript())
                    {
                        if (Creature* lichKing = Unit::GetCreature(*GetTarget(), instance->GetData64(DATA_THE_LICH_KING)))
                            lichKing->AI()->DoAction(ACTION_PHASE_SWITCH_2);
    
                        if (GameObject* go = ObjectAccessor::GetGameObject(*caster, instance->GetData64(DATA_EDGE_DESTROY_WARNING)))
                            go->SetGoState(GO_STATE_READY);
    
                        if (GameObject* go = ObjectAccessor::GetGameObject(*caster, instance->GetData64(DATA_FROSTY_EDGE_INNER)))
                            go->SetGoState(GO_STATE_ACTIVE);
    
                        if (GameObject* go = ObjectAccessor::GetGameObject(*caster, instance->GetData64(DATA_FROSTY_EDGE_OUTER)))
                            go->SetGoState(GO_STATE_READY);
                    }
                }
    
                void OnApply(AuraEffect const* aurEff, AuraEffectHandleModes mode)
                {
                    Unit* caster = GetCaster();
    
                    if (!caster || !caster->isAlive())
                        return;
    
                    InstanceScript* instance = caster->GetInstanceScript();
    
                    if (!instance)
                        return;
    
                    if (GameObject* go = ObjectAccessor::GetGameObject(*caster, instance->GetData64(DATA_EDGE_DESTROY_WARNING)))
                        go->SetGoState(GO_STATE_ACTIVE);
                }
    
                void Register()
                {
                    OnEffectApply += AuraEffectApplyFn(spell_lich_king_quake_AuraScript::OnApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
                    OnEffectRemove += AuraEffectRemoveFn(spell_lich_king_quake_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
                }
            };
    
            AuraScript* GetAuraScript() const
            {
                return new spell_lich_king_quake_AuraScript();
            }
    };
    
    class spell_vile_spirit_distance_check : public SpellScriptLoader
    {
        public:
            spell_vile_spirit_distance_check() : SpellScriptLoader("spell_vile_spirit_distance_check") { }
    
            class spell_vile_spirit_distance_check_SpellScript : public SpellScript
            {
                PrepareSpellScript(spell_vile_spirit_distance_check_SpellScript);
    
                void HandleScript(SpellEffIndex /*effIndex*/)
                {
                    if (!(GetHitUnit() && GetHitUnit()->isAlive()))
                        return;
    
                    if (Unit* caster = GetCaster())
                    {
                        caster->CastSpell(caster, SPELL_SPIRIT_BURST, true);
    
                        if (InstanceScript* instance = caster->GetInstanceScript())
                            instance->SetData(DATA_NECK_DEEP_ACHIEVEMENT, FAIL);
    
                        caster->GetAI()->DoAction(ACTION_DESPAWN);
                    }
                }
    
                void Register()
                {
                    OnEffect += SpellEffectFn(spell_vile_spirit_distance_check_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
                }
            };
    
            SpellScript* GetSpellScript() const
            {
                return new spell_vile_spirit_distance_check_SpellScript();
            }
    };
    
    class spell_ice_burst_distance_check : public SpellScriptLoader
    {
        public:
            spell_ice_burst_distance_check() : SpellScriptLoader("spell_ice_burst_distance_check") { }
    
            class spell_ice_burst_distance_check_SpellScript : public SpellScript
            {
                PrepareSpellScript(spell_ice_burst_distance_check_SpellScript);
    
                void HandleScript(SpellEffIndex effIndex)
                {
                    PreventHitDefaultEffect(effIndex);
    
                    if (!(GetHitUnit() && GetHitUnit()->isAlive()))
                        return;
    
                    if (GetHitUnit()->GetTypeId() != TYPEID_PLAYER)
                        return;
    
                    if (Unit* caster = GetCaster())
                        caster->CastSpell(caster, SPELL_ICE_BURST, true);
                }
    
                void Register()
                {
                    OnEffect += SpellEffectFn(spell_ice_burst_distance_check_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
                }
            };
    
            SpellScript* GetSpellScript() const
            {
                return new spell_ice_burst_distance_check_SpellScript();
            }
    };
    
    class spell_valkyr_carry_can_cast : public SpellScriptLoader
    {
        public:
            spell_valkyr_carry_can_cast() : SpellScriptLoader("spell_valkyr_carry_can_cast") { }
    
            class spell_valkyr_carry_can_cast_SpellScript : public SpellScript
            {
                PrepareSpellScript(spell_valkyr_carry_can_cast_SpellScript);
    
                void HandleScript(SpellEffIndex /*effIndex*/)
                {
                    Unit* caster = GetCaster(), *target = GetHitUnit();
    
                    if (!(target && target->isAlive() && caster))
                        return;
    
                    if (target->GetTypeId() == TYPEID_PLAYER)
                        target->CastSpell(caster, SPELL_VALKYR_GRAB_PLAYER, true);
                }
    
                void Register()
                {
                    OnEffect += SpellEffectFn(spell_valkyr_carry_can_cast_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
                }
            };
    
            SpellScript* GetSpellScript() const
            {
                return new spell_valkyr_carry_can_cast_SpellScript();
            }
    };
    
    class spell_valkyr_target_search : public SpellScriptLoader
    {
        public:
            spell_valkyr_target_search() : SpellScriptLoader("spell_valkyr_target_search") { }
    
            class spell_valkyr_target_search_SpellScript : public SpellScript
            {
                PrepareSpellScript(spell_valkyr_target_search_SpellScript);
    
                void HandleScript(SpellEffIndex /*effIndex*/)
                {
                    Unit* target = GetHitUnit(), *caster = GetCaster();
    
                    if (!(target && target->isAlive() && caster))
                        return;
    
                    if (target->GetTypeId() == TYPEID_PLAYER)
                    {
                        if (UnitAI* pAI = caster->GetAI())
                        {
                            pAI->SetGUID(target->GetGUID(), TYPE_VICTIM);
                            pAI->DoAction(ACTION_CHARGE_PLAYER);
                        }
                    }
                }
    
                void FilterTargets(std::list<Unit*>& unitList)
                {
                    LeaveOnlyPlayers(unitList);
                }
    
                void Register()
                {
                    OnUnitTargetSelect += SpellUnitTargetFn(spell_valkyr_target_search_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_AREA_ENEMY_SRC);
                    OnEffect += SpellEffectFn(spell_valkyr_target_search_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
                }
            };
    
            SpellScript* GetSpellScript() const
            {
                return new spell_valkyr_target_search_SpellScript();
            }
    };
    
    class spell_valkyr_eject_passenger : public SpellScriptLoader
    {
        public:
            spell_valkyr_eject_passenger() : SpellScriptLoader("spell_valkyr_eject_passenger") { }
    
    
            class spell_valkyr_eject_passenger_SpellScript : public SpellScript
            {
                PrepareSpellScript(spell_valkyr_eject_passenger_SpellScript);
    
                void HandleScript(SpellEffIndex /*effIndex*/)
                {
                    if (!(GetCaster() && GetCaster()->IsVehicle()))
                        return;
    
                    if (Vehicle* vehicle = GetCaster()->GetVehicleKit())
                        vehicle->RemoveAllPassengers();
                }
    
                void Register()
                {
                    OnEffect += SpellEffectFn(spell_valkyr_eject_passenger_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
                }
            };
    
            SpellScript* GetSpellScript() const
            {
                return new spell_valkyr_eject_passenger_SpellScript();
            }
    };
    
    class spell_vile_spirit_target_search : public SpellScriptLoader
    {
        public:
            spell_vile_spirit_target_search() : SpellScriptLoader("spell_vile_spirit_target_search") { }
    
            class spell_vile_spirit_target_search_SpellScript : public SpellScript
            {
                PrepareSpellScript(spell_vile_spirit_target_search_SpellScript);
    
                void HandleScript(SpellEffIndex /*effIndex*/)
                {
                    if (!(GetHitUnit() && GetHitUnit()->isAlive() && GetCaster()))
                        return;
    
                    if (GetHitUnit()->GetTypeId() == TYPEID_PLAYER)
                        GetCaster()->AddThreat(GetHitUnit(), 1000.0f);
                }
    
                void Register()
                {
                    OnEffect += SpellEffectFn(spell_vile_spirit_target_search_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
                }
            };
    
            SpellScript* GetSpellScript() const
            {
                return new spell_vile_spirit_target_search_SpellScript();
            }
    };
    
    class spell_lich_king_tirion_mass_resurrection : public SpellScriptLoader
    {
        public:
            spell_lich_king_tirion_mass_resurrection() : SpellScriptLoader("spell_lich_king_tirion_mass_resurrection") { } 
    
            class spell_lich_king_tirion_mass_resurrection_SpellScript : public SpellScript
            {
                PrepareSpellScript(spell_lich_king_tirion_mass_resurrection_SpellScript)
    
                /*void MassResurrect(SpellEffIndex effIndex)
                {
                    PreventHitDefaultEffect(effIndex);
                    InstanceScript *instance = GetCaster()->GetInstanceScript();
    
                    if (!instance)
                        return;
    
                    instance->DoCastSpellOnPlayers(SPELL_REVIVE_EFFECT);
                }*/
    
                void FilterTargets(std::list<Unit*>& unitList)
                {
                    unitList.clear();
                    const Map::PlayerList &PlayerList = GetCaster()->GetMap()->GetPlayers();
    
                    if (!PlayerList.isEmpty())
                        for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
                            if (Player* player = i->getSource())
                                unitList.push_back(player);
                }
    
                void Register()
                {
                    OnUnitTargetSelect += SpellUnitTargetFn(spell_lich_king_tirion_mass_resurrection_SpellScript::FilterTargets, EFFECT_0, TARGET_SRC_CASTER);
                    //OnEffect += SpellEffectFn(spell_lich_king_tirion_mass_resurrection_SpellScript::MassResurrect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
                }
            };
    
            SpellScript* GetSpellScript() const
            {
                return new spell_lich_king_tirion_mass_resurrection_SpellScript();
            }
    };
    
    class spell_lich_king_harvest_soul : public SpellScriptLoader
    {
        public:
            spell_lich_king_harvest_soul() : SpellScriptLoader("spell_lich_king_harvest_soul") { }
    
            class spell_lich_king_harvest_soul_AuraScript : public AuraScript
            {
                PrepareAuraScript(spell_lich_king_harvest_soul_AuraScript)
    
                class TeleportToFrostmourneRoom : public BasicEvent
                {
                    public:
                        TeleportToFrostmourneRoom(Player* player, uint8 attempts): pPlayer(player), attemptsLeft(attempts) { }
    
                        bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/)
                        {
                            pPlayer->NearTeleportTo(FrostmourneRoom[0].m_positionX, FrostmourneRoom[0].m_positionY, FrostmourneRoom[0].m_positionZ, FrostmourneRoom[0].m_orientation);
                            pPlayer->RemoveAurasDueToSpell(SPELL_FEIGN_DEATH);
    
                            if (--attemptsLeft)
                                pPlayer->m_Events.AddEvent(new TeleportToFrostmourneRoom(pPlayer, attemptsLeft), pPlayer->m_Events.CalculateTime(uint64(1000)));
                            else
                                pPlayer->CastSpell(pPlayer, SPELL_FROSTMOURNE_ROOM_TELEPORT_VISUAL, true);
    
                            return true;
                        }
                    private:
                        Player* pPlayer;
                        uint8 attemptsLeft;
                };
    
                void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes mode)
                {
                    Unit* target = GetTarget(), *caster = GetCaster();
    
                    if (target->GetTypeId() != TYPEID_PLAYER || !caster)
                        return;
    
                    Player* player = target->ToPlayer();
                    bool isHeroic = caster->GetMap()->IsHeroic();
    
                    if (!player || !player->isAlive())
                        caster->CastSpell(caster, isHeroic ? SPELL_HARVESTED_SOUL_HEROIC : SPELL_HARVESTED_SOUL_NORMAL, true);
    
                    player->CastSpell(player, SPELL_HARVESTED_SOUL_FROSTMOURNE_PLAYER_BUFF, true);
    
                    if (isHeroic)
                        player->CastSpell(player, SPELL_HARVEST_SOUL_HEROIC_FROSTMOURNE_PLAYER_DEBUFF, true);
    
                    player->CastSpell(player, SPELL_IN_FROSTMOURNE_ROOM, true);
    
                    //Should use Feign death to emulate player's death
                    player->CastSpell(player, SPELL_FEIGN_DEATH, true);
    
                    player->getThreatManager().clearReferences();
                    player->GetMap()->LoadGrid(FrostmourneRoom[0].m_positionX, FrostmourneRoom[0].m_positionY);
                    player->m_Events.AddEvent(new TeleportToFrostmourneRoom(player, 2), player->m_Events.CalculateTime(uint64(2000)));
                    InstanceScript* instance = player->GetInstanceScript();
    
                    if (instance)
                        if (Creature* lichKing = ObjectAccessor::GetCreature(*caster, instance->GetData64(DATA_THE_LICH_KING)))
                            lichKing->AI()->DoAction(ACTION_PREPARE_FROSTMOURNE_ROOM);
                }
    
                void Register()
                {
                    OnEffectRemove += AuraEffectRemoveFn(spell_lich_king_harvest_soul_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL);
                }
            };
    
            AuraScript* GetAuraScript() const
            {
                return new spell_lich_king_harvest_soul_AuraScript();
            }
    };
    
    class spell_lich_king_fury_of_frostmourne : public SpellScriptLoader
    {
        public:
            spell_lich_king_fury_of_frostmourne() : SpellScriptLoader("spell_lich_king_fury_of_frostmourne") { }
    
            class spell_lich_king_fury_of_frostmourneSpellScript : public SpellScript
            {
                PrepareSpellScript(spell_lich_king_fury_of_frostmourneSpellScript);
    
                // function called on server startup
                // checks if script has data required for it to work
                bool Validate(SpellEntry const* /*spellEntry*/)
                {
                    if (!sSpellStore.LookupEntry(SPELL_FURY_OF_FROSTMOURNE_NORES))
                        return false;
                    return true;
                }
    
                void HandleDummy(SpellEffIndex /*effIndex*/)
                {
                    if (Unit* target = GetHitUnit())
                        GetCaster()->AddAura(SPELL_FURY_OF_FROSTMOURNE_NORES, target);
                }
    
                void Register()
                {
                    OnEffect += SpellEffectFn(spell_lich_king_fury_of_frostmourneSpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_APPLY_AURA);
                }
            };
    
            SpellScript* GetSpellScript() const
            {
                return new spell_lich_king_fury_of_frostmourneSpellScript();
            }
    };
    
    void AddSC_boss_lichking()
    {
        new boss_the_lich_king();
        new npc_tirion_icc();
        new npc_valkyr_shadowguard();
        new npc_vile_spirit();
        new npc_shambling_horror();
        new npc_raging_spirit();
        new npc_ice_sphere();
        new npc_defile();
        new npc_spirit_warden();
        new npc_terenas_menethil();
        new npc_shadow_trap();
    
        new spell_lich_king_necrotic_plague();
        new spell_lich_king_infection();
        new spell_lich_king_valkyr_summon();
        new spell_lich_king_vile_spirit_summon();
        new spell_lich_king_vile_spirit_summon_visual();
        new spell_lich_king_winter();
        new spell_vile_spirit_distance_check();
        new spell_lich_king_pain_and_suffering_effect();
        new spell_ice_burst_distance_check();
        new spell_lich_king_quake();
        new spell_valkyr_carry_can_cast();
        new spell_valkyr_target_search();
        new spell_valkyr_eject_passenger();
        new spell_vile_spirit_target_search();
        new spell_lich_king_defile();
        new spell_lich_king_tirion_mass_resurrection();
        new spell_lich_king_harvest_soul();
        new spell_lich_king_fury_of_frostmourne();
    }
    Stoneharry can you help me some fixes?like:when the lich king casts quake after the casts finish he holds down hes sword (a visual bugg) and can u add some of your custom fixes because i have seen your emu with lich king (perfect script i think :P) so plsss if u can fix it i would be happy and the others too...
    one more question how to summon the Frostmourne chamber to the right place?

    Lich King Script Need help
  2. #2
    stoneharry's Avatar Moderator Harry


    Reputation
    1618
    Join Date
    Sep 2007
    Posts
    4,564
    Thanks G/R
    151/150
    Trade Feedback
    0 (0%)
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)
    You shouldn't request me specifically, or if you do need me specifically for some reason then you should take it to private messages. There are many more who are much better than me at emulation, and my first version of the Lich King script was very poor.

    The quake I would assume is because you need to switch to the kneeling bytes or emote after casting the spell, perhaps using a hacky fix like freezing a the animation for a while.

    The frostmourne chamber is part of the main gameobjects, so if they are positioned correctly then the frostmourne chamber will be there correctly. You may need to change the view distance of the object so that it loads at a greater distance, otherwise it won't appear there even if it is there.

Similar Threads

  1. [lua help] my lich king script wont work
    By bomsemann in forum WoW EMU Questions & Requests
    Replies: 4
    Last Post: 01-31-2009, 09:17 PM
  2. Boss Lua Script Need help
    By David2222 in forum World of Warcraft General
    Replies: 0
    Last Post: 01-25-2009, 04:22 PM
  3. Yell script need help will +rep
    By Padlockcode in forum WoW EMU Questions & Requests
    Replies: 1
    Last Post: 08-08-2008, 07:31 PM
  4. Booty bay - Scripting **Need help**
    By Ganoran in forum World of Warcraft Emulator Servers
    Replies: 2
    Last Post: 11-05-2007, 04:26 PM
  5. GM - Command scripts -need help-
    By Ganoran in forum World of Warcraft Emulator Servers
    Replies: 3
    Last Post: 11-03-2007, 02:32 PM
All times are GMT -5. The time now is 02:45 PM. Powered by vBulletin® Version 4.2.3
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Google Authenticator verification provided by Two-Factor Authentication (Free) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search