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

            if (TargetTimer <= diff && Enslaved == false)
            {
                EnslaveTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
                TargetTimer = 1000;
            } else TargetTimer -= diff;

            if (EnslaveEndTimer <= diff && Enslaved == true)
            {
                me->SetReactState(REACT_AGGRESSIVE);
                EnslaveTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
                EnslaveTarget->RemoveAurasDueToSpell(SPELL_ENSLAVE);
                EnslaveTarget->RemoveAurasDueToSpell(SPELL_ENSLAVE_BUFF);
                me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                Enslaved = false;
                EnslaveTimer = 30000;
                AbsorbMagicTimer = 20000;
                MindFogTimer = urand(6000,12000);
                UnrelentingAgonyTimer = 10000;
                EnslaveEndTimer = 90000;
            } else EnslaveEndTimer -= diff;

            if (EnslaveTimer <= diff && Enslaved == false)
            {
                if (EnslaveTarget)
                {
                    DoZoneInCombat();
                    me->SetReactState(REACT_PASSIVE);
                    DoCast(EnslaveTarget, SPELL_ENSLAVE);
                    DoCast(EnslaveTarget, SPELL_ENSLAVE_BUFF);
                    me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                    DoScriptText(RAND(SAY_MIND_CONTROL_1,SAY_MIND_CONTROL_2,SAY_MIND_CONTROL_3), me);
                    Enslaved = true;
                    EnslaveTimer = 180000;
                    AbsorbMagicTimer = 180000;
                    MindFogTimer = 180000;
                    UnrelentingAgonyTimer = 180000;
                    EnslaveEndTimer = DUNGEON_MODE(60000,30000);
                    CastTimer = 2000;
                }
                EnslaveTimer = 1000;
            } else EnslaveTimer -= diff;

            if (EnslaveTarget && Enslaved == true)
                if (EnslaveTarget->HealthBelowPct(50))
                {
                    me->SetReactState(REACT_AGGRESSIVE);
                    EnslaveTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
                    EnslaveTarget->RemoveAurasDueToSpell(SPELL_ENSLAVE);
                    EnslaveTarget->RemoveAurasDueToSpell(SPELL_ENSLAVE_BUFF);
                    me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                    Enslaved = false;
                    EnslaveTimer = 30000;
                    AbsorbMagicTimer = 20000;
                    MindFogTimer = urand(6000,12000);
                    UnrelentingAgonyTimer = 10000;
                }

            if (CastTimer <= diff && Enslaved == true)
            {
                if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, NotCharmedTargetSelector()))
                {
                    switch(EnslaveTarget->getClass())
                    {
                        case CLASS_DRUID:
                            if (urand(0,1))
                                EnslaveTarget->CastSpell(pTarget, 8921, false);
                            else
                                EnslaveTarget->CastSpell(me, 774, false);
                            break;
                        case CLASS_HUNTER:
                            EnslaveTarget->CastSpell(pTarget, RAND(2643, 1978), false);
                            break;
                        case CLASS_MAGE:
                            EnslaveTarget->CastSpell(pTarget, RAND(44614, 30455), false);
                            break;
                        case CLASS_WARLOCK:
                            EnslaveTarget->CastSpell(pTarget, RAND(980, 686), true);
                            break;
                        case CLASS_WARRIOR:
                            EnslaveTarget->CastSpell(pTarget, RAND(46924, 845), false);
                            break;
                        case CLASS_PALADIN:
                            if (urand(0,1))
                                EnslaveTarget->CastSpell(pTarget, 853, false);
                            else
                                EnslaveTarget->CastSpell(me, 20473, false);
                            break;
                        case CLASS_PRIEST:
                            if (urand(0,1))
                                EnslaveTarget->CastSpell(pTarget, 34914, false);
                            else
                                EnslaveTarget->CastSpell(me, 139, false);
                            break;
                        case CLASS_SHAMAN:
                            if (urand(0,1))
                                EnslaveTarget->CastSpell(pTarget, 421, false);
                            else
                                EnslaveTarget->CastSpell(me, 61295, false);
                            break;
                        case CLASS_ROGUE:
                            EnslaveTarget->CastSpell(pTarget, RAND(16511, 1329), false);
                            break;
                        case CLASS_DEATH_KNIGHT:
                            if (urand(0,1))
                                EnslaveTarget->CastSpell(pTarget, 45462, true);
                            else
                                EnslaveTarget->CastSpell(pTarget, 49184, true);
                            break;
                    }
                }
                CastTimer = 3000;
            } else CastTimer -= diff;

            if (AbsorbMagicTimer <= diff && Enslaved == false)
            {
                DoCast(me, SPELL_ABSORB_MAGIC);
                AbsorbMagicTimer = urand(15000,20000);
            } else AbsorbMagicTimer -= diff;

            if (MindFogTimer <= diff && Enslaved == false)
            {
                DoCast(me, SPELL_MIND_FOG_SUMMON);
                DoScriptText(SAY_MIND_FOG, me);
                MindFogTimer = 18000;
            } else MindFogTimer -= diff;

            if (UnrelentingAgonyTimer <= diff && Enslaved == false)
            {
                DoCastAOE(SPELL_UNRELENTING_AGONY);
                UnrelentingAgonyTimer = 20000;
            } else UnrelentingAgonyTimer -= diff;

            DoMeleeAttackIfReady();
        }
Ejemplo n.º 2
0
        void UpdateAI(const uint32 diff)
        {
            if (!UpdateVictim())
                return;

            events.Update(diff);

            if (Phase == 1)
            {
                while (uint32 eventId = events.GetEvent())
                {
                    switch (eventId)
                    {
                        case EVENT_WASTE:
                            DoSummon(NPC_WASTE, Pos[RAND(0, 3, 6, 9)]);
                            events.RepeatEvent(urand(2000, 5000));
                            break;
                        case EVENT_ABOMIN:
                            if (nAbomination < 8)
                            {
                                DoSummon(NPC_ABOMINATION, Pos[RAND(1, 4, 7, 10)]);
                                nAbomination++;
                                events.RepeatEvent(20000);
                            }
                            else
                                events.PopEvent();
                            break;
                        case EVENT_WEAVER:
                            if (nWeaver < 8)
                            {
                                DoSummon(NPC_WEAVER, Pos[RAND(0, 3, 6, 9)]);
                                nWeaver++;
                                events.RepeatEvent(25000);
                            }
                            else
                                events.PopEvent();
                            break;
                        case EVENT_TRIGGER:
                            if (GameObject* pKTTrigger = me->GetMap()->GetGameObject(KTTriggerGUID))
                                pKTTrigger->SetPhaseMask(2, true);
                            events.PopEvent();
                            break;
                        case EVENT_PHASE:
                            events.Reset();
                            DoScriptText(RAND(SAY_AGGRO_1, SAY_AGGRO_2, SAY_AGGRO_3), me);
                            spawns.DespawnAll();
                            me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE);
                            me->CastStop();

                            DoStartMovement(me->getVictim());
                            events.ScheduleEvent(EVENT_BOLT, urand(5000, 10000));
                            events.ScheduleEvent(EVENT_NOVA, 15000);
                            events.ScheduleEvent(EVENT_DETONATE, urand(30000, 40000));
                            events.ScheduleEvent(EVENT_FISSURE, urand(10000, 30000));
                            events.ScheduleEvent(EVENT_BLAST, urand(60000, 120000));
                            if (GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL)
                                events.ScheduleEvent(EVENT_CHAIN, urand(30000, 60000));
                            Phase = 2;
                            break;
                        default:
                            events.PopEvent();
                            break;
                    }
                }
            }
            else
            {
                //start phase 3 when we are 45% health
                if (Phase != 3)
                {
                    if (HealthBelowPct(45))
                    {
                        Phase = 3;
                        DoScriptText(SAY_REQUEST_AID, me);
                        //here Lich King should respond to KelThuzad but I don't know which Creature to make talk
                        //so for now just make Kelthuzad says it.
                        DoScriptText(SAY_ANSWER_REQUEST, me);

                        for (uint8 i = 0; i <= 3; ++i)
                        {
                            if (GameObject* pPortal = me->GetMap()->GetGameObject(PortalsGUID[i]))
                            {
                                if (pPortal->getLootState() == GO_READY)
                                    pPortal->UseDoorOrButton();
                            }
                        }
                    }
                }
                else if (nGuardiansOfIcecrownCount < RAID_MODE(2, 4))
                {
                    if (uiGuardiansOfIcecrownTimer <= diff)
                    {
                        // TODO : Add missing text
                        if (Creature* pGuardian = DoSummon(NPC_ICECROWN, Pos[RAND(2, 5, 8, 11)]))
                            pGuardian->SetFloatValue(UNIT_FIELD_COMBATREACH, 2);
                        ++nGuardiansOfIcecrownCount;
                        uiGuardiansOfIcecrownTimer = 5000;
                    }
                    else uiGuardiansOfIcecrownTimer -= diff;
                }

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

                if (uint32 eventId = events.GetEvent())
                {
                    switch (eventId)
                    {
                        case EVENT_BOLT:
                            DoCastVictim(RAID_MODE(SPELL_FROST_BOLT, H_SPELL_FROST_BOLT));
                            events.RepeatEvent(urand(5000, 10000));
                            break;
                        case EVENT_NOVA:
                            DoCastAOE(RAID_MODE(SPELL_FROST_BOLT_AOE, H_SPELL_FROST_BOLT_AOE));
                            events.RepeatEvent(urand(15000, 30000));
                            break;
                        case EVENT_CHAIN:
                        {
                            uint32 count = urand(1, 3);
                            for (uint8 i = 1; i <= count; i++)
                            {
                                Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 200, true);
                                if (target && !target->isCharmed() && (chained.find(target->GetGUID()) == chained.end()))
                                {
                                    DoCast(target, SPELL_CHAINS_OF_KELTHUZAD);
                                    float scale = target->GetFloatValue(OBJECT_FIELD_SCALE_X);
                                    chained.insert(std::make_pair(target->GetGUID(), scale));
                                    target->SetFloatValue(OBJECT_FIELD_SCALE_X, scale * 2);
                                    events.ScheduleEvent(EVENT_CHAINED_SPELL, 2000); //core has 2000ms to set unit flag charm
                                }
                            }
                            if (!chained.empty())
                                DoScriptText(RAND(SAY_CHAIN_1, SAY_CHAIN_2), me);
                            events.RepeatEvent(urand(100000, 180000));
                            break;
                        }
                        case EVENT_CHAINED_SPELL:
                        {
                            std::map<uint64, float>::iterator itr;
                            for (itr = chained.begin(); itr != chained.end();)
                            {
                                if (Unit* player = Unit::GetPlayer(*me, (*itr).first))
                                {
                                    if (!player->isCharmed())
                                    {
                                        player->SetFloatValue(OBJECT_FIELD_SCALE_X, (*itr).second);
                                        std::map<uint64, float>::iterator next = itr;
                                        ++next;
                                        chained.erase(itr);
                                        itr = next;
                                        continue;
                                    }

                                    if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0, NotCharmedTargetSelector()))
                                    {
                                        switch (player->getClass())
                                        {
                                            case CLASS_DRUID:
                                                if (urand(0, 1))
                                                    player->CastSpell(target, SPELL_MOONFIRE, false);
                                                else
                                                    player->CastSpell(me, SPELL_LIFEBLOOM, false);
                                                break;
                                            case CLASS_HUNTER:
                                                player->CastSpell(target, RAND(SPELL_MULTI_SHOT, SPELL_VOLLEY), false);
                                                break;
                                            case CLASS_MAGE:
                                                player->CastSpell(target, RAND(SPELL_FROST_FIREBOLT, SPELL_ARCANE_MISSILES), false);
                                                break;
                                            case CLASS_WARLOCK:
                                                player->CastSpell(target, RAND(SPELL_CURSE_OF_AGONY, SPELL_SHADOW_BOLT), true);
                                                break;
                                            case CLASS_WARRIOR:
                                                player->CastSpell(target, RAND(SPELL_BLADESTORM, SPELL_CLEAVE), false);
                                                break;
                                            case CLASS_PALADIN:
                                                if (urand(0, 1))
                                                    player->CastSpell(target, SPELL_HAMMER_OF_JUSTICE, false);
                                                else
                                                    player->CastSpell(me, SPELL_HOLY_SHOCK, false);
                                                break;
                                            case CLASS_PRIEST:
                                                if (urand(0, 1))
                                                    player->CastSpell(target, SPELL_VAMPIRIC_TOUCH, false);
                                                else
                                                    player->CastSpell(me, SPELL_RENEW, false);
                                                break;
                                            case CLASS_SHAMAN:
                                                if (urand(0, 1))
                                                    player->CastSpell(target, SPELL_EARTH_SHOCK, false);
                                                else
                                                    player->CastSpell(me, SPELL_HEALING_WAVE, false);
                                                break;
                                            case CLASS_ROGUE:
                                                player->CastSpell(target, RAND(SPELL_HEMORRHAGE, SPELL_MUTILATE), false);
                                                break;
                                            case CLASS_DEATH_KNIGHT:
                                                if (urand(0, 1))
                                                    player->CastSpell(target, SPELL_PLAGUE_STRIKE, true);
                                                else
                                                    player->CastSpell(target, SPELL_HOWLING_BLAST, true);
                                                break;
                                        }
                                    }
                                }
                                ++itr;
                            }

                            if (chained.empty())
                                events.PopEvent();
                            else
                                events.RepeatEvent(5000);

                            break;
                        }
                        case EVENT_DETONATE:
                        {
                            std::vector<Unit*> unitList;
                            std::list<HostileReference*> *threatList = &me->getThreatManager().getThreatList();
                            for (std::list<HostileReference*>::const_iterator itr = threatList->begin(); itr != threatList->end(); ++itr)
                            {
                                if ((*itr)->getTarget()->GetTypeId() == TYPEID_PLAYER
                                    && (*itr)->getTarget()->getPowerType() == POWER_MANA
                                    && (*itr)->getTarget()->GetPower(POWER_MANA))
                                    unitList.push_back((*itr)->getTarget());
                            }

                            if (!unitList.empty())
                            {
                                std::vector<Unit*>::const_iterator itr = unitList.begin();
                                advance(itr, rand()%unitList.size());
                                DoCast(*itr, SPELL_MANA_DETONATION);
                                DoScriptText(RAND(SAY_SPECIAL_1, SAY_SPECIAL_2, SAY_SPECIAL_3), me);
                            }

                            events.RepeatEvent(urand(20000, 50000));
                            break;
                        }
                        case EVENT_FISSURE:
                            if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
                                DoCast(target, SPELL_SHADOW_FISURE);
                            events.RepeatEvent(urand(10000, 45000));
                            break;
                        case EVENT_BLAST:
                            if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, RAID_MODE(1, 0), 0, true))
                                DoCast(target, SPELL_FROST_BLAST);
                            if (rand()%2)
                                DoScriptText(SAY_FROST_BLAST, me);
                            events.RepeatEvent(urand(30000, 90000));
                            break;
                        default:
                            events.PopEvent();
                            break;
                    }
                }

                DoMeleeAttackIfReady();
            }
        }