/*
REWRITTEN FROM SCRATCH BY PUSSYWIZARD, IT OWNS NOW!
*/

#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "trial_of_the_champion.h"
#include "ScriptedEscortAI.h"
#include "SpellScript.h"

enum EadricSpells
{
    //Eadric
    SPELL_EADRIC_ACHIEVEMENT            = 68197,
    ACHIEV_FACEROLLER                   = 3803,

    SPELL_RADIANCE                      = 66935,
    SPELL_VENGEANCE                     = 66865,
    SPELL_HAMMER_JUSTICE                = 66863,
    SPELL_HAMMER_RIGHTEOUS              = 66867,
    SPELL_HAMMER_RIGHTEOUS_DAMAGE       = 66903,
    SPELL_HAMMER_RIGHTEOUS_ACTION_BAR   = 66904,
    SPELL_HAMMER_RIGHTEOUS_THROW_BACK   = 66905,
};

enum EadricEvents
{
    EVENT_SPELL_RADIANCE = 1,
    EVENT_SPELL_HAMMER_RIGHTEOUS,
};

enum PaletressSpells
{
    SPELL_SMITE_N                       = 66536,
    SPELL_SMITE_H                       = 67674,
    SPELL_HOLY_FIRE_N                   = 66538,
    SPELL_HOLY_FIRE_H                   = 67676,
    SPELL_RENEW_N                       = 66537,
    SPELL_RENEW_H                       = 67675,

    SPELL_HOLY_NOVA                     = 66546,
    SPELL_SHIELD                        = 66515,
    SPELL_CONFESS                       = 66680,
    SPELL_SUMMON_MEMORY                 = 66545,

    //Memory
    SPELL_OLD_WOUNDS_N                  = 66620,
    SPELL_OLD_WOUNDS_H                  = 67679,
    SPELL_SHADOWS_PAST_N                = 66619,
    SPELL_SHADOWS_PAST_H                = 67678,
    SPELL_WAKING_NIGHTMARE_N            = 66552,
    SPELL_WAKING_NIGHTMARE_H            = 67677,
};

#define SPELL_SMITE                     DUNGEON_MODE(SPELL_SMITE_N, SPELL_SMITE_H)
#define SPELL_HOLY_FIRE                 DUNGEON_MODE(SPELL_HOLY_FIRE_N, SPELL_HOLY_FIRE_H)
#define SPELL_RENEW                     DUNGEON_MODE(SPELL_RENEW_N, SPELL_RENEW_H)
#define SPELL_OLD_WOUNDS                DUNGEON_MODE(SPELL_OLD_WOUNDS_N, SPELL_OLD_WOUNDS_H)
#define SPELL_SHADOWS_PAST              DUNGEON_MODE(SPELL_SHADOWS_PAST_N, SPELL_SHADOWS_PAST_H)
#define SPELL_WAKING_NIGHTMARE          DUNGEON_MODE(SPELL_WAKING_NIGHTMARE_N, SPELL_WAKING_NIGHTMARE_H)

enum PaletressEvents
{
    EVENT_SPELL_SMITE = 1,
    EVENT_SPELL_HOLY_FIRE,
    EVENT_SPELL_RENEW,

    EVENT_MEMORY_SCALE,
    EVENT_MEMORY_START_ATTACK,
    EVENT_SPELL_OLD_WOUNDS,
    EVENT_SPELL_SHADOWS_PAST,
    EVENT_SPELL_WAKING_NIGHTMARE,
};

#define TEXT_RADIATE                    "Eadric the Pure begins to radiate light. Shield your eyes!"

class boss_eadric : public CreatureScript
{
public:
    boss_eadric() : CreatureScript("boss_eadric") { }
    struct boss_eadricAI : public ScriptedAI
    {
        boss_eadricAI(Creature* pCreature) : ScriptedAI(pCreature)
        {
            pInstance = pCreature->GetInstanceScript();
        }

        InstanceScript* pInstance;
        EventMap events;

        void Reset()
        {
            events.Reset();
            me->SetReactState(REACT_PASSIVE);
            if( pInstance )
                pInstance->SetData(BOSS_ARGENT_CHALLENGE, NOT_STARTED);
        }
        
        void MovementInform(uint32 type, uint32 id)
        {
            if( type == POINT_MOTION_TYPE && id == 1 )
                me->SetFacingTo(3*M_PI/2);
        }

        void KilledUnit(Unit* who)
        {
            if( who->GetTypeId() == TYPEID_PLAYER )
            {
                if( urand(0,1) )
                    Talk(TEXT_EADRIC_SLAIN_1);
                else
                    Talk(TEXT_EADRIC_SLAIN_2);
            }
        }

        void EnterCombat(Unit* who)
        {
            events.Reset();
            events.ScheduleEvent(EVENT_SPELL_RADIANCE, 16000);
            events.ScheduleEvent(EVENT_SPELL_HAMMER_RIGHTEOUS, 25000);
            Talk(TEXT_EADRIC_AGGRO);
            me->CastSpell(me, SPELL_VENGEANCE, false);
            if( pInstance )
                pInstance->SetData(BOSS_ARGENT_CHALLENGE, IN_PROGRESS);
        }

        void SpellHit(Unit* caster, const SpellInfo* spell)
        {
            if (spell->Id == 66905 && me->GetHealth() == 1) // hammer throw back damage (15k)
                me->CastSpell(me, 68197, true);
        }

        void DamageTaken(Unit*, uint32 &damage, DamageEffectType, SpellSchoolMask)
        {
            if( damage >= me->GetHealth() )
            {
                damage = me->GetHealth() - 1;
                if( me->getFaction() != 35 )
                {
                    me->CastSpell((Unit*)NULL, 68575, true); // achievements
                    me->GetMap()->UpdateEncounterState(ENCOUNTER_CREDIT_CAST_SPELL, 68574, me); // paletress' spell credits encounter, but shouldn't credit achievements
                    me->setFaction(35);
                    events.Reset();
                    Talk(TEXT_EADRIC_DEATH);
                    me->getThreatManager().clearReferences();
                    me->SetRegeneratingHealth(false);
                    _EnterEvadeMode();
                    me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                    if( pInstance )
                        pInstance->SetData(BOSS_ARGENT_CHALLENGE, DONE);
                }
            }
        }

        void UpdateAI(uint32 diff)
        {
            if( !UpdateVictim() )
                return;

            events.Update(diff);

            if( me->HasUnitState(UNIT_STATE_CASTING) )
                return;

            switch( events.GetEvent() )
            {
                case 0:
                    break;
                case EVENT_SPELL_RADIANCE:
                    me->CastSpell((Unit*)NULL, SPELL_RADIANCE, false);
                    me->MonsterTextEmote(TEXT_RADIATE, 0, true);
                    events.RepeatEvent(16000);
                    break;
                case EVENT_SPELL_HAMMER_RIGHTEOUS:
                    if( Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 55.0f, true) )
                    {
                        char buffer[100];
                        sprintf(buffer, "Eadric the Pure targets %s with the Hammer of the Righteous!", target->GetName().c_str());
                        me->MonsterTextEmote(buffer, 0, true);
                        Talk(TEXT_EADRIC_HAMMER);
                        me->CastSpell(target, SPELL_HAMMER_JUSTICE, true);
                        me->CastSpell(target, SPELL_HAMMER_RIGHTEOUS, false);
                    }
                    events.RepeatEvent(25000);
                    break;
            }

            DoMeleeAttackIfReady();
        }
    };

    CreatureAI* GetAI(Creature* pCreature) const
    {
        return new boss_eadricAI(pCreature);
    }
};

class boss_paletress : public CreatureScript
{
public:
    boss_paletress() : CreatureScript("boss_paletress") { }

    struct boss_paletressAI : public ScriptedAI
    {
        boss_paletressAI(Creature* pCreature) : ScriptedAI(pCreature)
        {
            pInstance = pCreature->GetInstanceScript();
        }

        InstanceScript* pInstance;
        EventMap events;
        bool summoned;
        uint64 MemoryGUID;

        void Reset()
        {
            events.Reset();
            summoned = false;
            if( MemoryGUID )
            {
                if( Creature* memory = ObjectAccessor::GetCreature(*me, MemoryGUID) )
                    memory->DespawnOrUnsummon();
                MemoryGUID = 0;
            }
            me->SetReactState(REACT_PASSIVE);
            if( pInstance )
                pInstance->SetData(BOSS_ARGENT_CHALLENGE, NOT_STARTED);
        }
        
        void MovementInform(uint32 type, uint32 id)
        {
            if( type == POINT_MOTION_TYPE && id == 1 )
                me->SetFacingTo(3*M_PI/2);
        }

        void KilledUnit(Unit* who)
        {
            if( who->GetTypeId() == TYPEID_PLAYER )
            {
                if( urand(0,1) )
                    Talk(TEXT_PALETRESS_SLAIN_1);
                else
                    Talk(TEXT_PALETRESS_SLAIN_2);
            }
        }

        void EnterCombat(Unit* who)
        {
            events.Reset();
            events.ScheduleEvent(EVENT_SPELL_HOLY_FIRE, urand(9000,12000));
            events.ScheduleEvent(EVENT_SPELL_SMITE, urand(2000,3000));
            me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
            Talk(TEXT_PALETRESS_AGGRO);
            if( pInstance )
                pInstance->SetData(BOSS_ARGENT_CHALLENGE, IN_PROGRESS);
        }

        void DoAction(int32 param)
        {
            if( param == 1 )
            {
                MemoryGUID = 0;
                me->RemoveAura(SPELL_SHIELD);
                Talk(TEXT_PALETRESS_MEMORY_DEFEATED);
            }
            else if( param == (-1) )
            {
                if( MemoryGUID )
                    if( Creature* memory = ObjectAccessor::GetCreature(*me, MemoryGUID) )
                    {
                        memory->DespawnOrUnsummon();
                        MemoryGUID = 0;
                    }
            }
        }

        void DamageTaken(Unit*, uint32 &damage, DamageEffectType, SpellSchoolMask)
        {
            //if( me->HasAura(SPELL_SHIELD) )
            //  return;

            if( damage >= me->GetHealth() )
            {
                damage = me->GetHealth() - 1;

                if( me->getFaction() != 35 )
                {
                    me->CastSpell((Unit*)NULL, 68574, true); // achievements
                    me->setFaction(35);
                    events.Reset();
                    Talk(TEXT_PALETRESS_DEATH);
                    me->getThreatManager().clearReferences();
                    me->SetRegeneratingHealth(false);
                    _EnterEvadeMode();
                    me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                    if( pInstance )
                    {
                        pInstance->SetData(BOSS_ARGENT_CHALLENGE, DONE);
                        pInstance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, 68206);
                    }
                }
            }
        }

        void JustSummoned(Creature* summon)
        {
            if( pInstance )
                pInstance->SetData(DATA_MEMORY_ENTRY, summon->GetEntry());
            MemoryGUID = summon->GetGUID();
        }

        void SummonMemory()
        {
            uint8 uiRandom = urand(0,25);
            uint32 uiSpells[26] = {66704,66705,66706,66707,66709,66710,66711,66712,66713,66714,66715,66708,66708,66691,66692,66694,66695,66696,66697,66698,66699,66700,66701,66702,66703,66543};
            me->CastSpell(me, uiSpells[uiRandom], true);
        }

        void UpdateAI(uint32 diff)
        {
            if( !UpdateVictim() )
                return;

            events.Update(diff);

            if( !summoned && HealthBelowPct(25) )
            {
                me->InterruptNonMeleeSpells(true);
                Talk(TEXT_PALETRESS_MEMORY_SUMMON);
                me->CastSpell((Unit*)NULL, SPELL_HOLY_NOVA, false);
                me->CastSpell(me, SPELL_SHIELD, false);
                me->CastSpell((Unit*)NULL, SPELL_SUMMON_MEMORY, false);
                SummonMemory();
                me->CastSpell((Unit*)NULL, SPELL_CONFESS, false);
                events.ScheduleEvent(EVENT_SPELL_RENEW, urand(6000,8000));
                summoned = true;
                return;
            }

            if( me->HasUnitState(UNIT_STATE_CASTING) )
                return;

            switch( events.GetEvent() )
            {
                case 0:
                    break;
                case EVENT_SPELL_SMITE:
                    if( Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f, true) )
                        me->CastSpell(target, SPELL_SMITE, false);
                    events.RepeatEvent(urand(3000,4000));
                    break;
                case EVENT_SPELL_HOLY_FIRE:
                    if( Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 30.0f, true) )
                        me->CastSpell(target, SPELL_HOLY_FIRE, false);
                    events.RepeatEvent(urand(9000,12000));
                    break;
                case EVENT_SPELL_RENEW:
                    if( !MemoryGUID )
                    {
                        events.PopEvent();
                        break;
                    }
                    if( urand(0,1) )
                        me->CastSpell(me, SPELL_RENEW, false);
                    else if( Creature* memory = ObjectAccessor::GetCreature(*me, MemoryGUID) )
                        if( memory->IsAlive() )
                            me->CastSpell(memory, SPELL_RENEW, false);
                    events.RepeatEvent(urand(15000,17000));
                    break;
            }

            DoMeleeAttackIfReady();
        }
    };

    CreatureAI* GetAI(Creature* pCreature) const
    {
        return new boss_paletressAI(pCreature);
    }
};

class npc_memory : public CreatureScript
{
public:
    npc_memory() : CreatureScript("npc_memory") { }

    struct npc_memoryAI : public ScriptedAI
    {
        npc_memoryAI(Creature* pCreature) : ScriptedAI(pCreature)
        {
            pInstance = pCreature->GetInstanceScript();
            events.Reset();
            me->SetReactState(REACT_PASSIVE);
            me->SetObjectScale(0.01f);
            events.ScheduleEvent(EVENT_MEMORY_SCALE, 500);
        }

        InstanceScript* pInstance;
        EventMap events;

        void Reset() {}

        void JustDied(Unit* /*killer*/)
        {
            me->DespawnOrUnsummon(20000);
            if( pInstance )
                if( Creature* paletress = ObjectAccessor::GetCreature(*me, pInstance->GetData64(DATA_PALETRESS)) )
                    paletress->AI()->DoAction(1);
        }

        void UpdateAI(uint32 diff)
        {
            UpdateVictim();

            events.Update(diff);

            if( me->HasUnitState(UNIT_STATE_CASTING) )
                return;

            switch( events.GetEvent() )
            {
                case 0:
                    break;
                case EVENT_MEMORY_SCALE:
                    me->SetObjectScale(1.0f);
                    events.ScheduleEvent(EVENT_MEMORY_START_ATTACK, 5000);
                    events.PopEvent();
                    break;
                case EVENT_MEMORY_START_ATTACK:
                    me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                    if( Unit* target = me->SelectNearestTarget(200.0f) )
                    {
                        AttackStart(target);
                        DoZoneInCombat();
                    }
                    me->SetReactState(REACT_AGGRESSIVE);
                    events.ScheduleEvent(EVENT_SPELL_OLD_WOUNDS, 8000);
                    events.ScheduleEvent(EVENT_SPELL_SHADOWS_PAST, 4000);
                    events.ScheduleEvent(EVENT_SPELL_WAKING_NIGHTMARE, urand(20000,30000));
                    events.PopEvent();
                    break;
                case EVENT_SPELL_OLD_WOUNDS:
                    if( Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 10.0f, true) )
                        me->CastSpell(target, SPELL_OLD_WOUNDS, true);
                    events.RepeatEvent(12000);
                    break;
                case EVENT_SPELL_SHADOWS_PAST:
                    if( Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40.0f, true) )
                        me->CastSpell(target, SPELL_SHADOWS_PAST, false);
                    events.RepeatEvent(urand(15000,20000));
                    break;
                case EVENT_SPELL_WAKING_NIGHTMARE:
                    me->CastSpell(me, SPELL_WAKING_NIGHTMARE, false);
                    events.RepeatEvent(35000);
                    break;
            }

            DoMeleeAttackIfReady();
        }
    };

    CreatureAI* GetAI(Creature* pCreature) const
    {
        return new npc_memoryAI(pCreature);
    }
};


enum ArgentSoldierSpells
{
    // monk
    SPELL_FLURRY_OF_BLOWS               = 67233,
    SPELL_PUMMEL                        = 67235,
    SPELL_DIVINE_SHIELD_H               = 67251, 
    SPELL_FINAL_MEDITATION_H            = 67255,

    // priestess
    SPELL_HOLY_SMITE_N                  = 36176,
    SPELL_HOLY_SMITE_H                  = 67289,
    SPELL_FOUNTAIN_OF_LIGHT             = 67194,
    NPC_FOUNTAIN_OF_LIGHT               = 35311,
    SPELL_SHADOW_WORD_PAIN_N            = 34941,
    SPELL_SHADOW_WORD_PAIN_H            = 34942,
    SPELL_MIND_CONTROL_H                = 67229,

    // lightwielder
    SPELL_BLAZING_LIGHT_N               = 67247,
    SPELL_BLAZING_LIGHT_H               = 67290,
    SPELL_CLEAVE                        = 15284,
    SPELL_UNBALANCING_STRIKE_H          = 67237,
};

#define SPELL_HOLY_SMITE                DUNGEON_MODE(SPELL_HOLY_SMITE_N, SPELL_HOLY_SMITE_H)
#define SPELL_SHADOW_WORD_PAIN          DUNGEON_MODE(SPELL_SHADOW_WORD_PAIN_N, SPELL_SHADOW_WORD_PAIN_H)
#define SPELL_BLAZING_LIGHT             DUNGEON_MODE(SPELL_BLAZING_LIGHT_N, SPELL_BLAZING_LIGHT_H)

enum ArgentSoldierEvents
{
    EVENT_MONK_SPELL_FLURRY_OF_BLOWS = 1,
    EVENT_MONK_SPELL_PUMMEL,
    EVENT_PRIESTESS_SPELL_HOLY_SMITE,
    EVENT_PRIESTESS_SPELL_SHADOW_WORD_PAIN,
    EVENT_PRIESTESS_SPELL_FOUNTAIN_OF_LIGHT,
    EVENT_PRIESTESS_SPELL_MIND_CONTROL_H,
    EVENT_LIGHTWIELDER_SPELL_BLAZING_LIGHT,
    EVENT_LIGHTWIELDER_SPELL_CLEAVE,
    EVENT_LIGHTWIELDER_SPELL_UNBALANCING_STRIKE_H,
};

class npc_argent_soldier : public CreatureScript
{
public:
    npc_argent_soldier() : CreatureScript("npc_argent_soldier") { }

    struct npc_argent_soldierAI : public npc_escortAI
    {
        npc_argent_soldierAI(Creature* pCreature) : npc_escortAI(pCreature)
        {
            pInstance = pCreature->GetInstanceScript();
            me->SetReactState(REACT_PASSIVE);
            SetDespawnAtEnd(false);
            uiWaypoint = 0;
        }

        InstanceScript* pInstance;
        EventMap events;
        uint8 uiWaypoint;
        bool bCheck;

        void Reset()
        {
            events.Reset();
            bCheck = false;
        }

        void WaypointReached(uint32 uiPoint)
        {
            if( uiPoint == 1 )
            {
                switch( uiWaypoint )
                {
                    case 0:
                        me->SetFacingTo(5.4f);
                        break;
                    case 1:
                        me->SetFacingTo(4.6f);
                        break;
                    case 2:
                        me->SetFacingTo(4.0f);
                        break;
                }
            }
        }

        void SetData(uint32 uiType, uint32 /*uiData*/)
        {
            AddWaypoint(0, me->GetPositionX(), 660.0f, 411.80f);
            switch( me->GetEntry() )
            {
                case NPC_ARGENT_LIGHTWIELDER:
                    switch( uiType )
                    {
                        case 0:
                            AddWaypoint(1,716.321f,647.047f,411.93f);
                            break;
                        case 1:
                            AddWaypoint(1,742.44f,650.29f,411.79f);
                            break;
                        case 2:
                            AddWaypoint(1,772.6314f,651.7f,411.93f);
                            break;
                    }
                    break;
                case NPC_ARGENT_MONK:
                    switch( uiType )
                    {
                        case 0:
                            AddWaypoint(1,717.86f,649.0f,411.923f);
                            break;
                        case 1:
                            AddWaypoint(1,746.73f,650.24f,411.56f);
                            break;
                        case 2:
                            AddWaypoint(1,775.567f,648.26f,411.93f);
                            break;
                    }
                    break;
                case NPC_PRIESTESS:
                    switch( uiType )
                    {
                        case 0:
                            AddWaypoint(1,719.872f,650.94f,411.93f);
                            break;
                        case 1:
                            AddWaypoint(1,750.72f,650.20f,411.77f);
                            break;
                        case 2:
                            AddWaypoint(1,777.78f,645.70f,411.93f);
                            break;
                    }
                    break;
            }

            Start(false,true,0);
            uiWaypoint = uiType;
        }

        void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask)
        {
            if( bCheck && damage >= me->GetHealth() )
            {
                bCheck = false;
                damage = me->GetHealth()-1;
                events.DelayEvents(10000);
                me->CastSpell(me, SPELL_DIVINE_SHIELD_H, true);
                me->CastSpell((Unit*)NULL, SPELL_FINAL_MEDITATION_H, true);
            }
        }

        void EnterCombat(Unit* /*who*/)
        {
            switch( me->GetEntry() )
            {
                case NPC_ARGENT_MONK:
                    events.RescheduleEvent(EVENT_MONK_SPELL_FLURRY_OF_BLOWS, 5000);
                    events.RescheduleEvent(EVENT_MONK_SPELL_PUMMEL, 7000);
                    if( IsHeroic() )
                        bCheck = true;
                    break;
                case NPC_PRIESTESS:
                    events.RescheduleEvent(EVENT_PRIESTESS_SPELL_HOLY_SMITE, urand(5000,8000));
                    events.RescheduleEvent(EVENT_PRIESTESS_SPELL_SHADOW_WORD_PAIN, urand(3000,6000));
                    events.RescheduleEvent(EVENT_PRIESTESS_SPELL_FOUNTAIN_OF_LIGHT, urand(8000,15000));
                    if( IsHeroic() )
                        events.RescheduleEvent(EVENT_PRIESTESS_SPELL_MIND_CONTROL_H, 12000);
                    break;
                case NPC_ARGENT_LIGHTWIELDER:
                    events.RescheduleEvent(EVENT_LIGHTWIELDER_SPELL_BLAZING_LIGHT, urand(12000,15000));
                    events.RescheduleEvent(EVENT_LIGHTWIELDER_SPELL_CLEAVE, urand(3000,5000));
                    if( IsHeroic() )
                        events.RescheduleEvent(EVENT_LIGHTWIELDER_SPELL_UNBALANCING_STRIKE_H, urand(8000,12000));
                    break;
            }               
        }

        void UpdateAI(uint32 diff)
        {
            npc_escortAI::UpdateAI(diff);

            if( !UpdateVictim() )
                return;

            events.Update(diff);

            if( me->HasUnitState(UNIT_STATE_CASTING) )
                return;

            switch( events.GetEvent() )
            {
                case 0:
                    break;

                case EVENT_MONK_SPELL_FLURRY_OF_BLOWS:
                    me->CastSpell(me, SPELL_FLURRY_OF_BLOWS, false);
                    events.RepeatEvent(urand(12000,18000));
                    break;
                case EVENT_MONK_SPELL_PUMMEL:
                    if( me->GetVictim() )
                        me->CastSpell(me->GetVictim(), SPELL_PUMMEL, false);
                    events.RepeatEvent(urand(8000,11000));
                    break;

                case EVENT_PRIESTESS_SPELL_HOLY_SMITE:
                    if( me->GetVictim() )
                        me->CastSpell(me->GetVictim(), SPELL_HOLY_SMITE, false);
                    events.RepeatEvent(urand(6000,8000));
                    break;
                case EVENT_PRIESTESS_SPELL_SHADOW_WORD_PAIN:
                    if( me->GetVictim() )
                        me->CastSpell(me->GetVictim(), SPELL_SHADOW_WORD_PAIN, false);
                    events.RepeatEvent(urand(12000,15000));
                    break;
                case EVENT_PRIESTESS_SPELL_FOUNTAIN_OF_LIGHT:
                    me->CastSpell((Unit*)NULL, SPELL_FOUNTAIN_OF_LIGHT, false);
                    events.RepeatEvent(urand(35000,45000));
                    break;
                case EVENT_PRIESTESS_SPELL_MIND_CONTROL_H:
                    if( Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 30.0f, true) )
                        me->CastSpell(target, SPELL_MIND_CONTROL_H, false);
                    events.RepeatEvent(urand(22000,30000));
                    break;

                case EVENT_LIGHTWIELDER_SPELL_BLAZING_LIGHT:
                    {
                        Unit* target = DoSelectLowestHpFriendly(40.0f);
                        if( !target )
                            target = me;
                        me->CastSpell(target, SPELL_BLAZING_LIGHT, false);
                        events.RepeatEvent(urand(8000,12000));
                    }
                    break;
                case EVENT_LIGHTWIELDER_SPELL_CLEAVE:
                    if( me->GetVictim() )
                        me->CastSpell(me->GetVictim(), SPELL_CLEAVE, false);
                    events.RepeatEvent(urand(6000,8000));
                    break;
                case EVENT_LIGHTWIELDER_SPELL_UNBALANCING_STRIKE_H:
                    if( me->GetVictim() )
                        me->CastSpell(me->GetVictim(), SPELL_UNBALANCING_STRIKE_H, false);
                    events.RepeatEvent(urand(12000,15000));
                    break;
            }

            DoMeleeAttackIfReady();
        }

        void JustDied(Unit* /*pKiller*/)
        {
            me->DespawnOrUnsummon(10000);
            if( pInstance )
                pInstance->SetData(DATA_ARGENT_SOLDIER_DEFEATED, 0);
        }
    };

    CreatureAI* GetAI(Creature* pCreature) const
    {
        return new npc_argent_soldierAI(pCreature);
    }
};

class spell_eadric_radiance : public SpellScriptLoader
{
    public:
        spell_eadric_radiance() : SpellScriptLoader("spell_eadric_radiance") { }

        class spell_eadric_radiance_SpellScript : public SpellScript
        {
            PrepareSpellScript(spell_eadric_radiance_SpellScript);

            void FilterTargets(std::list<WorldObject*>& targets)
            {
                std::list<WorldObject*> tmplist;
                for( std::list<WorldObject*>::const_iterator itr = targets.begin(); itr != targets.end(); ++itr)
                    if( (*itr)->ToUnit()->HasInArc(M_PI, GetCaster()) )
                        tmplist.push_back(*itr);

                 targets.clear();
                 for( std::list<WorldObject*>::iterator itr = tmplist.begin(); itr != tmplist.end(); ++itr )
                     targets.push_back(*itr);
            }

            void Register()
            {
                OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_eadric_radiance_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
                OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_eadric_radiance_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY);
            }
        };

        SpellScript* GetSpellScript() const
        {
            return new spell_eadric_radiance_SpellScript();
        }
};

class spell_toc5_light_rain : public SpellScriptLoader
{
    public:
        spell_toc5_light_rain() : SpellScriptLoader("spell_toc5_light_rain") { }

        class spell_toc5_light_rain_SpellScript : public SpellScript
        {
            PrepareSpellScript(spell_toc5_light_rain_SpellScript);

            void FilterTargets(std::list<WorldObject*>& targets)
            {
                for( std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); )
                {
                    if ((*itr)->GetTypeId() == TYPEID_UNIT)
                        if ((*itr)->ToCreature()->GetEntry() == NPC_FOUNTAIN_OF_LIGHT)
                        {
                            targets.erase(itr);
                            itr = targets.begin();
                            continue;
                        }
                    ++itr;
                }
            }

            void Register()
            {
                OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_toc5_light_rain_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY);
            }
        };

        SpellScript* GetSpellScript() const
        {
            return new spell_toc5_light_rain_SpellScript();
        }
};

class spell_reflective_shield : public SpellScriptLoader
{
    public:
        spell_reflective_shield() : SpellScriptLoader("spell_reflective_shield") { }

        class spell_reflective_shield_AuraScript : public AuraScript
        {
            PrepareAuraScript(spell_reflective_shield_AuraScript)

            void HandleAfterEffectAbsorb(AuraEffect * aurEff, DamageInfo & dmgInfo, uint32 & absorbAmount)
            {
                if( Unit* attacker = dmgInfo.GetAttacker() )
                    if( GetOwner() && attacker->GetGUID() != GetOwner()->GetGUID() )
                    {
                        int32 damage = (int32)(absorbAmount*0.25f);
                        GetOwner()->ToUnit()->CastCustomSpell(attacker, 33619, &damage, NULL, NULL, true);
                    }
            }

            void Register()
            {
                AfterEffectAbsorb += AuraEffectAbsorbFn(spell_reflective_shield_AuraScript::HandleAfterEffectAbsorb, EFFECT_0);
            }
        };

        AuraScript *GetAuraScript() const
        {
            return new spell_reflective_shield_AuraScript();
        }
};

void AddSC_boss_argent_challenge()
{
    new boss_eadric();
    new boss_paletress();
    new npc_memory();
    new npc_argent_soldier();
    new spell_eadric_radiance();
    new spell_toc5_light_rain();
    new spell_reflective_shield();
}
