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

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

                while (uint32 eventId = events.ExecuteEvent())
                {
                    switch (eventId)
                    {
                        case EVENT_POUNDING:
                            DoCastVictim(SPELL_POUNDING);
                            Talk(SAY_POUNDING);
                            events.ScheduleEvent(EVENT_POUNDING, 15000);
                            break;
                        case EVENT_ARCANE_ORB:
                        {
                            Unit* target = NULL;
                            std::list<HostileReference*> t_list = me->getThreatManager().getThreatList();
                            std::vector<Unit*> target_list;
                            for (std::list<HostileReference*>::const_iterator itr = t_list.begin(); itr != t_list.end(); ++itr)
                            {
                                target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid());
                                if (!target)
                                    continue;
                                // exclude pets & totems, 18 yard radius minimum
                                if (target->GetTypeId() == TYPEID_PLAYER && target->IsAlive() && !target->IsWithinDist(me, 18, false))
                                    target_list.push_back(target);
                                target = NULL;
                            }

                            if (!target_list.empty())
                                target = *(target_list.begin() + rand32() % target_list.size());
                            else
                                target = me->GetVictim();

                            if (target)
                                me->CastSpell(target, SPELL_ARCANE_ORB, false, NULL, NULL);

                            events.ScheduleEvent(EVENT_ARCANE_ORB, 3000);
                            break;
                        }
                        case EVENT_KNOCK_AWAY:
                            DoCastVictim(SPELL_KNOCK_AWAY);
                            // Drop 25% aggro
                            if (DoGetThreat(me->GetVictim()))
                                DoModifyThreatPercent(me->GetVictim(), -25);

                            events.ScheduleEvent(EVENT_KNOCK_AWAY, 30000);
                            break;
                        case EVENT_BERSERK:
                            if (!Enraged)
                            {
                                DoCast(me, SPELL_BERSERK);
                                Enraged = true;
                            }
                            break;
                        default:
                            break;
                    }
                }

                DoMeleeAttackIfReady();

                EnterEvadeIfOutOfCombatArea(diff);
            }
        void UpdateAI(uint32 diff)
        {
            if (!UpdateVictim())
                return;
            if (uiPhaseTimer <= diff)
            {
                switch (Phase)
                {
                    case CASTING_FLAME_SPHERES:
                    {
                        Creature* pSpheres[3];

                        //DoCast(me, SPELL_FLAME_SPHERE_SUMMON_1);
                        pSpheres[0] = DoSpawnCreature(CREATURE_FLAME_SPHERE, 0, 0, 5, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10*IN_MILLISECONDS);
                        Unit* pSphereTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
                        if (pSphereTarget && pSpheres[0])
                        {
                            float angle, x, y;
                            angle = pSpheres[0]->GetAngle(pSphereTarget);
                            x = pSpheres[0]->GetPositionX() + DATA_SPHERE_DISTANCE * std::cos(angle);
                            y = pSpheres[0]->GetPositionY() + DATA_SPHERE_DISTANCE * std::sin(angle);
                            pSpheres[0]->GetMotionMaster()->MovePoint(0, x, y, pSpheres[0]->GetPositionZ());
                        }
                        if (IsHeroic())
                        {
                            //DoCast(me, H_SPELL_FLAME_SPHERE_SUMMON_1);
                            pSpheres[1] = DoSpawnCreature(H_CREATURE_FLAME_SPHERE_1, 0, 0, 5, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10*IN_MILLISECONDS);
                            //DoCast(me, H_SPELL_FLAME_SPHERE_SUMMON_2);
                            pSpheres[2] = DoSpawnCreature(H_CREATURE_FLAME_SPHERE_2, 0, 0, 5, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10*IN_MILLISECONDS);
                            if (pSphereTarget && pSpheres[1] && pSpheres[2])
                            {
                                float angle, x, y;
                                angle = pSpheres[1]->GetAngle(pSphereTarget) + DATA_SPHERE_ANGLE_OFFSET;
                                x = pSpheres[1]->GetPositionX() + DATA_SPHERE_DISTANCE/2 * std::cos(angle);
                                y = pSpheres[1]->GetPositionY() + DATA_SPHERE_DISTANCE/2 * std::sin(angle);
                                pSpheres[1]->GetMotionMaster()->MovePoint(0, x, y, pSpheres[1]->GetPositionZ());
                                angle = pSpheres[2]->GetAngle(pSphereTarget) - DATA_SPHERE_ANGLE_OFFSET;
                                x = pSpheres[2]->GetPositionX() + DATA_SPHERE_DISTANCE/2 * std::cos(angle);
                                y = pSpheres[2]->GetPositionY() + DATA_SPHERE_DISTANCE/2 * std::sin(angle);
                                pSpheres[2]->GetMotionMaster()->MovePoint(0, x, y, pSpheres[2]->GetPositionZ());
                            }
                        }

                        Phase = NORMAL;
                        uiPhaseTimer = 0;
                        break;
                    }
                    case JUST_VANISHED:
                        if (Unit* pEmbraceTarget = GetEmbraceTarget())
                        {
                            me->GetMotionMaster()->Clear();
                            me->SetSpeed(MOVE_WALK, 2.0f, true);
                            me->GetMotionMaster()->MoveChase(pEmbraceTarget);
                        }
                        Phase = VANISHED;
                        uiPhaseTimer = 1300;
                        break;
                    case VANISHED:
                        if (Unit* pEmbraceTarget = GetEmbraceTarget())
                            DoCast(pEmbraceTarget, DUNGEON_MODE(SPELL_EMBRACE_OF_THE_VAMPYR, H_SPELL_EMBRACE_OF_THE_VAMPYR));
                        Talk(SAY_FEED);
                        me->GetMotionMaster()->Clear();
                        me->SetSpeed(MOVE_WALK, 1.0f, true);
                        me->GetMotionMaster()->MoveChase(me->GetVictim());
                        Phase = FEEDING;
                        uiPhaseTimer = 20*IN_MILLISECONDS;
                        break;
                    case FEEDING:
                        Phase = NORMAL;
                        uiPhaseTimer = 0;
                        uiEmbraceTarget = 0;
                        break;
                    case NORMAL:
                        if (uiBloodthirstTimer <= diff)
                        {
                            DoCast(me, SPELL_BLOODTHIRST);
                            uiBloodthirstTimer = 10*IN_MILLISECONDS;
                        } else uiBloodthirstTimer -= diff;

                        if (uiFlamesphereTimer <= diff)
                        {
                            // because TARGET_UNIT_TARGET_ENEMY we need a target selected to cast
                            DoCastVictim(SPELL_CONJURE_FLAME_SPHERE);
                            Phase = CASTING_FLAME_SPHERES;
                            uiPhaseTimer = 3*IN_MILLISECONDS + diff;
                            uiFlamesphereTimer = 15*IN_MILLISECONDS;
                        } else uiFlamesphereTimer -= diff;

                        if (uiVanishTimer <= diff)
                        {
                            //Count alive players
                            Unit* target = NULL;
                            std::list<HostileReference*> t_list = me->getThreatManager().getThreatList();
                            std::vector<Unit*> target_list;
                            for (std::list<HostileReference*>::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr)
                            {
                                target = Unit::GetUnit(*me, (*itr)->getUnitGuid());
                                // exclude pets & totems
                                if (target && target->GetTypeId() == TYPEID_PLAYER && target->IsAlive())
                                    target_list.push_back(target);
                                target = NULL;
                            }
                            //He only vanishes if there are 3 or more alive players
                            if (target_list.size() > 2)
                            {
                                Talk(SAY_VANISH);
                                DoCast(me, SPELL_VANISH);
                                Phase = JUST_VANISHED;
                                uiPhaseTimer = 500;
                                if (Unit* pEmbraceTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
                                    uiEmbraceTarget = pEmbraceTarget->GetGUID();

                            }
                            uiVanishTimer = urand(25*IN_MILLISECONDS, 35*IN_MILLISECONDS);
                        } else uiVanishTimer -= diff;

                        DoMeleeAttackIfReady();
                    break;
                }
            } else uiPhaseTimer -= diff;
        }
        void UpdateAI(uint32 diff) override
        {
            if (!UpdateVictim())
                return;

            events.Update(diff);

            while (uint32 eventId = events.ExecuteEvent())
            {
                switch (eventId)
                {
                    case EVENT_HATEFUL:
                    {
                        // Hateful Strike targets the highest non-MT threat in melee range on 10man
                        // and the higher HP target out of the two highest non-MT threats in melee range on 25man
                        float MostThreat = 0.0f;
                        Unit* secondThreatTarget = NULL;
                        Unit* thirdThreatTarget = NULL;

                        std::list<HostileReference*>::const_iterator i = me->getThreatManager().getThreatList().begin();
                        for (; i != me->getThreatManager().getThreatList().end(); ++i)
                        { // find second highest
                            Unit* target = (*i)->getTarget();
                            if (target->IsAlive() && target != me->GetVictim() && (*i)->getThreat() >= MostThreat && me->IsWithinMeleeRange(target))
                            {
                                MostThreat = (*i)->getThreat();
                                secondThreatTarget = target;
                            }
                        }

                        if (secondThreatTarget && Is25ManRaid())
                        { // find third highest
                            MostThreat = 0.0f;
                            i = me->getThreatManager().getThreatList().begin();
                            for (; i != me->getThreatManager().getThreatList().end(); ++i)
                            {
                                Unit* target = (*i)->getTarget();
                                if (target->IsAlive() && target != me->GetVictim() && target != secondThreatTarget && (*i)->getThreat() >= MostThreat && me->IsWithinMeleeRange(target))
                                {
                                    MostThreat = (*i)->getThreat();
                                    thirdThreatTarget = target;
                                }
                            }
                        }

                        Unit* pHatefulTarget = NULL;
                        if (!thirdThreatTarget)
                            pHatefulTarget = secondThreatTarget;
                        else if (secondThreatTarget)
                            pHatefulTarget = (secondThreatTarget->GetHealth() < thirdThreatTarget->GetHealth()) ? thirdThreatTarget : secondThreatTarget;

                        if (!pHatefulTarget)
                            pHatefulTarget = me->GetVictim();

                        DoCast(pHatefulTarget, SPELL_HATEFUL_STRIKE, true);

                        // add threat to highest threat targets
                        if (me->GetVictim() && me->IsWithinMeleeRange(me->GetVictim()))
                            me->getThreatManager().addThreat(me->GetVictim(), HATEFUL_THREAT_AMT);
                        if (secondThreatTarget)
                            me->getThreatManager().addThreat(secondThreatTarget, HATEFUL_THREAT_AMT);
                        if (thirdThreatTarget)
                            me->getThreatManager().addThreat(thirdThreatTarget, HATEFUL_THREAT_AMT); // this will only ever be used in 25m

                        events.ScheduleEvent(EVENT_HATEFUL, 1 * IN_MILLISECONDS);
                        break;
                    }
                    case EVENT_BERSERK:
                        DoCast(me, SPELL_BERSERK, true);
                        Talk(EMOTE_BERSERK);
                        events.ScheduleEvent(EVENT_SLIME, 2 * IN_MILLISECONDS);
                        break;
                    case EVENT_SLIME:
                        DoCastVictim(SPELL_SLIME_BOLT, true);
                        events.ScheduleEvent(EVENT_SLIME, 2 * IN_MILLISECONDS);
                        break;
                }
            }

            if (!Enraged && HealthBelowPct(5))
            {
                DoCast(me, SPELL_FRENZY, true);
                Talk(EMOTE_ENRAGE);
                Enraged = true;
            }

            DoMeleeAttackIfReady();
        }
    void UpdateAI(const uint32 diff)
    {
        //Only if not incombat check if the event is started
        if (!me->IsInCombat() && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT))
        {
            Unit* pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER));

            if (pTarget)
                AttackStart(pTarget);
        }

        //Return since we have no target
        if (!UpdateVictim())
            return;

        //someone evaded!
        if (pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT))
        {
            EnterEvadeMode();
            return;
        }

        //WaterBoltVolley_Timer
        if (WaterBoltVolley_Timer <= diff)
        {
            DoCastVictim( SPELL_WATER_BOLT_VOLLEY);
            WaterBoltVolley_Timer = 30000;
        }
        else WaterBoltVolley_Timer -= diff;

        //TidalSurge_Timer
        if (TidalSurge_Timer <= diff)
        {
            DoCastVictim( SPELL_TIDAL_SURGE);
            // Hacky way to do it - won't trigger elseways
            me->GetVictim()->CastSpell(me->GetVictim(), SPELL_TIDAL_SURGE_FREEZE, true);
            TidalSurge_Timer = 15000 + rand() % 5000;
        }
        else TidalSurge_Timer -= diff;

        //Cyclone_Timer
        if (Cyclone_Timer <= diff)
        {
            //DoCast(me, SPELL_SUMMON_CYCLONE); // Doesn't work
            Cyclone_Timer = 30000 + rand() % 10000;
            Creature* Cyclone = me->SummonCreature(CREATURE_CYCLONE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), float(rand() % 5), TEMPSUMMON_TIMED_DESPAWN, 15000);
            if (Cyclone)
            {
                CAST_CRE(Cyclone)->SetObjectScale(3.0f);
                Cyclone->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
                Cyclone->SetFaction(me->GetFaction());
                Cyclone->CastSpell(Cyclone, SPELL_CYCLONE_CYCLONE, true);
                Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0);
                if (pTarget)
                    Cyclone->AI()->AttackStart(pTarget);
            }
        }
        else Cyclone_Timer -= diff;

        //Heal_Timer
        if (Heal_Timer <= diff)
        {
            // It can be cast on any of the mobs
            Unit* pUnit = NULL;

            while (pUnit == NULL || !pUnit->IsAlive())
                pUnit = selectAdvisorUnit();

            if (pUnit && pUnit->IsAlive())
                DoCast(pUnit, SPELL_HEAL);
            Heal_Timer = 60000;
        }
        else Heal_Timer -= diff;

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

            if (!DrainingCrystal)
            {
                uint32 maxPowerMana = me->GetMaxPower(POWER_MANA);
                if (maxPowerMana && ((me->GetPower(POWER_MANA)*100 / maxPowerMana) < 10))
                {
                    if (DrainLifeTimer <= diff)
                    {
                        DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0), SPELL_DRAIN_LIFE);
                        DrainLifeTimer = 10000;
                    } else DrainLifeTimer -= diff;

                    // Heroic only
                    if (IsHeroic())
                    {
                        if (DrainManaTimer <= diff)
                        {
                            DoCast(SelectTarget(SELECT_TARGET_RANDOM, 1), SPELL_DRAIN_MANA);
                            DrainManaTimer = 10000;
                        } else DrainManaTimer -= diff;
                    }
                }

                if (FelExplosionTimer <= diff)
                {
                    if (!me->IsNonMeleeSpellCasted(false))
                    {
                        DoCast(me, SPELL_FEL_EXPLOSION);
                        FelExplosionTimer = 2000;
                    }
                } else FelExplosionTimer -= diff;

                // If below 10% mana, start recharging
                maxPowerMana = me->GetMaxPower(POWER_MANA);
                if (maxPowerMana && ((me->GetPower(POWER_MANA)*100 / maxPowerMana) < 10))
                {
                    if (DrainCrystalTimer <= diff)
                    {
                        SelectNearestCrystal();
                        if (IsHeroic())
                            DrainCrystalTimer = urand(10000, 15000);
                        else
                            DrainCrystalTimer = urand(20000, 25000);
                    } else DrainCrystalTimer -= diff;
                }
            }else
            {
                if (IsDraining)
                {
                    if (EmpowerTimer <= diff)
                    {
                        IsDraining = false;
                        DrainingCrystal = false;

                        Talk(SAY_EMPOWERED);

                        Unit* CrystalChosen = Unit::GetUnit(*me, CrystalGUID);
                        if (CrystalChosen && CrystalChosen->IsAlive())
                            // Use Deal Damage to kill it, not setDeathState.
                            CrystalChosen->Kill(CrystalChosen);

                        CrystalGUID = 0;

                        me->GetMotionMaster()->Clear();
                        me->GetMotionMaster()->MoveChase(me->GetVictim());
                    } else EmpowerTimer -= diff;
                }
            }

            DoMeleeAttackIfReady();                             // No need to check if we are draining crystal here, as the spell has a stun.
        }
Example #6
0
void hyjalAI::UpdateAI(uint32 diff)
{
    if (IsDummy)
    {
        if (MassTeleportTimer < diff && DoMassTeleport)
        {
            DoCast(me, SPELL_MASS_TELEPORT, false);
            DoMassTeleport = false;
        }
        else
            MassTeleportTimer -= diff;
        return;
    }
    if (DoHide)
    {
        DoHide = false;
        switch (me->GetEntry())
        {
            case JAINA:
                if (instance->GetData(DATA_ALLIANCE_RETREAT))
                {
                    me->SetVisible(false);
                    HideNearPos(me->GetPositionX(), me->GetPositionY());
                    HideNearPos(5037.76f, -1889.71f);
                    for (uint8 i = 0; i < 92; ++i)//summon fires
                        me->SummonGameObject(GO_ROARING_FLAME, AllianceFirePos[i][0], AllianceFirePos[i][1], AllianceFirePos[i][2], AllianceFirePos[i][3], G3D::Quat(AllianceFirePos[i][4], AllianceFirePos[i][5], AllianceFirePos[i][6], AllianceFirePos[i][7]), 0);

                }
                else me->SetVisible(true);
                break;
            case THRALL: //thrall
                if (instance->GetData(DATA_HORDE_RETREAT))
                {
                    me->SetVisible(false);
                    HideNearPos(me->GetPositionX(), me->GetPositionY());
                    HideNearPos(5563, -2763.19f);
                    HideNearPos(5542.2f, -2629.36f);
                    for (uint8 i = 0; i < 65; ++i)//summon fires
                        me->SummonGameObject(GO_ROARING_FLAME, HordeFirePos[i][0], HordeFirePos[i][1], HordeFirePos[i][2], HordeFirePos[i][3], G3D::Quat(HordeFirePos[i][4], HordeFirePos[i][5], HordeFirePos[i][6], HordeFirePos[i][7]), 0);

                }
                else me->SetVisible(true);
                break;
        }
    }
    if (DoRespawn)
    {
        if (RespawnTimer <= diff)
        {
            DoRespawn = false;
            RespawnNearPos(me->GetPositionX(), me->GetPositionY());
            if (Faction == 0)
            {
                RespawnNearPos(5037.76f, -1889.71f);
            } else if (Faction == 1)
            {
                RespawnNearPos(5563, -2763.19f);
                RespawnNearPos(5542.2f, -2629.36f);
            }
            me->SetVisible(true);
        }else{
            RespawnTimer -= diff;
            me->SetVisible(false);
        }
        return;
    }
    if (Overrun)
        DoOverrun(Faction, diff);
    if (bRetreat)
    {
        if (RetreatTimer <= diff)
        {
            IsDummy = true;
            bRetreat = false;
            HideNearPos(me->GetPositionX(), me->GetPositionY());
            switch (me->GetEntry())
            {
                case JAINA://jaina
                    HideNearPos(5037.76f, -1889.71f);
                    break;
                case THRALL://thrall
                    HideNearPos(5563, -2763.19f);
                    HideNearPos(5542.2f, -2629.36f);
                    HideNearPos(5603.75f, -2853.12f);
                    break;
            }
            me->SetVisible(false);
        } else RetreatTimer -= diff;
    }

    if (!EventBegun)
        return;

    if (Summon)
    {
        if (EnemyCount)
        {
            EnemyCount = instance->GetData(DATA_TRASH);
            if (!EnemyCount)
                NextWaveTimer = 5000;
        }

        if (NextWaveTimer <= diff)
        {
            if (Faction == 0)
                SummonNextWave(AllianceWaves, WaveCount, AllianceBase);
            else if (Faction == 1)
                SummonNextWave(HordeWaves, WaveCount, HordeBase);
            ++WaveCount;
        } else NextWaveTimer -= diff;
    }

    if (CheckTimer <= diff)
    {
        for (uint8 i = 0; i < 2; ++i)
        {
            if (BossGUID[i])
            {
                Unit* unit = ObjectAccessor::GetUnit(*me, BossGUID[i]);
                if (unit && (!unit->IsAlive()))
                {
                    if (BossGUID[i] == BossGUID[0])
                    {
                        Talk(INCOMING);
                        FirstBossDead = true;
                    }
                    else if (BossGUID[i] == BossGUID[1])
                    {
                        Talk(SUCCESS);
                        SecondBossDead = true;
                    }
                    EventBegun = false;
                    CheckTimer = 0;
                    me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
                    BossGUID[i].Clear();
                    instance->DoUpdateWorldState(WORLD_STATE_ENEMY, 0); // Reset world state for enemies to disable it
                }
            }
        }
        CheckTimer = 5000;
    } else CheckTimer -= diff;

    if (!UpdateVictim())
        return;

    for (uint8 i = 0; i < HYJAL_AI_MAX_SPELLS; ++i)
    {
        if (Spells[i].SpellId)
        {
            if (SpellTimer[i] <= diff)
            {
                if (me->IsNonMeleeSpellCast(false))
                    me->InterruptNonMeleeSpells(false);

                Unit* target = NULL;

                switch (Spells[i].TargetType)
                {
                    case TARGETTYPE_SELF:
                        target = me;
                        break;

                    case TARGETTYPE_RANDOM:
                        target = SelectTarget(SELECT_TARGET_RANDOM, 0);
                        break;

                    case TARGETTYPE_VICTIM:
                        target = me->GetVictim();
                        break;
                }

                if (target && target->IsAlive())
                {
                    DoCast(target, Spells[i].SpellId);
                    SpellTimer[i] = Spells[i].Cooldown;
                }
            } else SpellTimer[i] -= diff;
        }
    }

    DoMeleeAttackIfReady();
}
Example #7
0
        void UpdateAI(uint32 diff) override
        {
            if (!UpdateVictim())
                return;

            if (HealthBelowPct(10) && !Enraged)
            {
                Enraged = true;
                DoCast(me, SPELL_ENRAGE, true);
                Talk(SAY_ENRAGE);
            }

            //Randomly cast one beam.
            if (BeamTimer <= diff)
            {
                Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0);
                if (!target || !target->IsAlive())
                    return;

                BeamTimer = 9000;

                switch (CurrentBeam)
                {
                    case 0:
                        DoCast(target, SPELL_BEAM_SINISTER);
                        break;
                    case 1:
                        DoCast(target, SPELL_BEAM_VILE);
                        break;
                    case 2:
                        DoCast(target, SPELL_BEAM_WICKED);
                        break;
                    case 3:
                        DoCast(target, SPELL_BEAM_SINFUL);
                        break;
                }
                ++BeamCount;
                uint32 Beam = CurrentBeam;
                if (BeamCount > 3)
                    while (CurrentBeam == Beam)
                        CurrentBeam = rand32() % 3;

            } else BeamTimer -= diff;

            // Random Prismatic Shield every 15 seconds.
            if (PrismaticShieldTimer <= diff)
            {
                uint32 random = rand32() % 6;
                if (PrismaticAuras[random])
                    DoCast(me, PrismaticAuras[random]);
                PrismaticShieldTimer = 15000;
            } else PrismaticShieldTimer -= diff;

            // Select 3 random targets (can select same target more than once), teleport to a random location then make them cast explosions until they get away from each other.
            if (FatalAttractionTimer <= diff)
            {
                ExplosionCount = 0;

                TeleportPlayers();

                Talk(SAY_SPELL);
                FatalAttractionExplodeTimer = 2000;
                FatalAttractionTimer = urand(40, 71) * 1000;
            } else FatalAttractionTimer -= diff;

            if (FatalAttractionExplodeTimer <= diff)
            {
                // Just make them explode three times... they're supposed to keep exploding while they are in range, but it'll take too much code. I'll try to think of an efficient way for it later.
                if (ExplosionCount < 3)
                {
                    for (uint8 i = 0; i < 3; ++i)
                    {
                        if (TargetGUID[i])
                        {
                            if (Unit* unit = ObjectAccessor::GetUnit(*me, TargetGUID[i]))
                                unit->CastSpell(unit, SPELL_ATTRACTION, true);
                            TargetGUID[i] = 0;
                        }
                    }

                    ++ExplosionCount;
                    FatalAttractionExplodeTimer = 1000;
                }
                else
                {
                    FatalAttractionExplodeTimer = FatalAttractionTimer + 2000;
                    ExplosionCount = 0;
                }
            } else FatalAttractionExplodeTimer -= diff;

            if (ShriekTimer <= diff)
            {
                DoCastVictim(SPELL_SILENCING_SHRIEK);
                ShriekTimer = 25000 + rand32() % 10 * 1000;
            } else ShriekTimer -= diff;

            if (SaberTimer <= diff)
            {
                DoCastVictim(SPELL_SABER_LASH);
                SaberTimer = 25000 + rand32() % 10 * 1000;
            } else SaberTimer -= diff;

            //Enrage
            if (!me->HasAura(SPELL_BERSERK))
            {
                if (EnrageTimer <= diff)
                {
                    DoCast(me, SPELL_BERSERK);
                    Talk(SAY_ENRAGE);
                } else EnrageTimer -= diff;
            }

            //Random taunts
            if (RandomYellTimer <= diff)
            {
                Talk(SAY_TAUNT);
                RandomYellTimer = urand(60, 151) * 1000;
            } else RandomYellTimer -= diff;

            DoMeleeAttackIfReady();
        }
Example #8
0
    void UpdateAI(const uint32 diff)
    {
        if (!UpdateVictim())
            return;

        if (!me->HasAura(SPELL_BERSERK, 0))
        {
            if (EnrageTimer <= diff)
            {
                DoCast(me, SPELL_BERSERK);
                switch (rand() % 2)
                {
                case 0:
                    DoScriptText(SAY_ENRAGE1, me);
                    break;
                case 1:
                    DoScriptText(SAY_ENRAGE2, me);
                    break;
                }
            }
            else EnrageTimer -= diff;
        }

        if (ArcingSmashTimer <= diff)
        {
            DoCastVictim(Phase1 ? SPELL_ARCING_SMASH_1 : SPELL_ARCING_SMASH_2);
            ArcingSmashTimer = 10000;
        }
        else ArcingSmashTimer -= diff;

        if (FelBreathTimer <= diff)
        {
            DoCastVictim(Phase1 ? SPELL_FELBREATH_1 : SPELL_FELBREATH_2);
            FelBreathTimer = 25000;
        }
        else FelBreathTimer -= diff;

        if (EjectTimer <= diff)
        {
            DoCastVictim(Phase1 ? SPELL_EJECT_1 : SPELL_EJECT_2);
            EjectTimer = 15000;
        }
        else EjectTimer -= diff;


        if (Charge_Timer <= diff)
        {
            if (me->GetDistance2d(me->GetVictim()) > 15)
                DoCastVictim(SPELL_CHARGE);
            Charge_Timer = 10000;
        }
        else Charge_Timer -= diff;

        if (Phase1)
        {
            if (BewilderingStrikeTimer <= diff)
            {
                DoCastVictim( SPELL_BEWILDERING_STRIKE);
                BewilderingStrikeTimer = 20000;
            }
            else BewilderingStrikeTimer -= diff;

            if (BloodboilTimer <= diff)
            {
                if (BloodboilCount < 5)                      // Only cast it five times.
                {
                    CastBloodboil(); // Causes issues on windows, so is commented out.
                    //DoCastVictim( SPELL_BLOODBOIL);
                    ++BloodboilCount;
                    BloodboilTimer = 10000;
                }
            }
            else BloodboilTimer -= diff;
        }

        if (!Phase1)
        {
            if (FelGeyserTimer <= diff)
            {
                DoCastVictim( SPELL_FEL_GEYSER);
                FelGeyserTimer = 30000;
            }
            else FelGeyserTimer -= diff;

            if (me->GetVictim() && me->GetVictim()->IsImmunedToDamage(SPELL_SCHOOL_MASK_ALL, true))
                me->getThreatManager().modifyThreatPercent(me->GetVictim(), -100);
        }

        if (PhaseChangeTimer <= diff)
        {
            if (Phase1)
            {
                Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0);
                if (pTarget && pTarget->IsAlive())
                {
                    Phase1 = false;

                    TargetThreat = DoGetThreat(pTarget);
                    TargetGUID = pTarget->GetGUID();
                    if (DoGetThreat(pTarget))
                        DoModifyThreatPercent(pTarget, -100);
                    me->AddThreat(pTarget, 50000000.0f);
                    pTarget->CastSpell(me, SPELL_TAUNT_GURTOGG, true);
                    me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true);
                    me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true);

                    // If VMaps are disabled, this spell can call the whole instance
                    DoCast(me, SPELL_INSIGNIFIGANCE, true);
                    DoCast(pTarget, SPELL_FEL_RAGE_1, true);
                    DoCast(pTarget, SPELL_FEL_RAGE_2, true);
                    DoCast(pTarget, SPELL_FEL_RAGE_3, true);
                    DoCast(pTarget, SPELL_FEL_RAGE_SCALE, true);

                    //Cast this without triggered so that it appears in combat logs and shows visual.
                    DoCast(me, SPELL_FEL_RAGE_SELF);

                    DoScriptText(RAND(SAY_SPECIAL1, SAY_SPECIAL2), me);

                    FelGeyserTimer = 1000;
                    PhaseChangeTimer = 30000;
                }
            }
            else                                             // Encounter is a loop pretty much. Phase 1 -> Phase 2 -> Phase 1 -> Phase 2 till death or enrage
            {
                if (TargetGUID)
                    RevertThreatOnTarget(TargetGUID);
                TargetGUID = 0;
                Phase1 = true;
                BloodboilTimer = 10000;
                BloodboilCount = 0;
                ArcingSmashTimer += 2000;
                FelBreathTimer += 2000;
                EjectTimer += 2000;
                PhaseChangeTimer = 65000;
                me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false);
                me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false);
            }
        }
        else PhaseChangeTimer -= diff;

        DoMeleeAttackIfReady();
    }
Example #9
0
void
ReactorAI::EnterEvadeMode()
{
    if (!m_creature->IsAlive())
    {
        DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "Creature stopped attacking, he is dead [guid=%u]", m_creature->GetGUIDLow());
        m_creature->GetMotionMaster()->MovementExpired();
        m_creature->GetMotionMaster()->MoveIdle();
        i_victimGuid.Clear();
        m_creature->CombatStop(true);
        m_creature->DeleteThreatList();
        return;
    }

    Unit* victim = m_creature->GetMap()->GetUnit(i_victimGuid);

    if (!victim)
    {
        DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "Creature stopped attacking, no victim [guid=%u]", m_creature->GetGUIDLow());
    }
    else if (victim->HasStealthAura())
    {
        DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "Creature stopped attacking, victim is in stealth [guid=%u]", m_creature->GetGUIDLow());
    }
    else if (victim->IsTaxiFlying())
    {
        DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "Creature stopped attacking, victim is in flight [guid=%u]", m_creature->GetGUIDLow());
    }
    else
    {
        DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "Creature stopped attacking, victim %s [guid=%u]", victim->IsAlive() ? "out run him" : "is dead", m_creature->GetGUIDLow());
    }

    m_creature->RemoveAllAurasOnEvade();
    m_creature->DeleteThreatList();
    i_victimGuid.Clear();
    m_creature->CombatStop(true);
    m_creature->SetLootRecipient(NULL);

    // Remove ChaseMovementGenerator from MotionMaster stack list, and add HomeMovementGenerator instead
    if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
        m_creature->GetMotionMaster()->MoveTargetedHome();
}
            void UpdateAI(uint32 diff) override
            {
                if (!UpdateVictim() || _targetDied)
                    return;

                if (Unit* target = ObjectAccessor::GetPlayer(*me, _targetGUID))
                {
                    if (!target->IsAlive())
                    {
                        Unit* gormok = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(NPC_GORMOK));
                        if (gormok && gormok->IsAlive())
                        {
                            SetCombatMovement(false);
                            _targetDied = true;

                            // looping through Gormoks seats
                            for (uint8 i = 0; i < MAX_SNOBOLDS; i++)
                            {
                                if (!gormok->GetVehicleKit()->GetPassenger(i))
                                {
                                    me->EnterVehicle(gormok, i);
                                    DoAction(ACTION_ENABLE_FIRE_BOMB);
                                    break;
                                }
                            }
                        }
                        else if (Unit* target2 = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
                        {
                            _targetGUID = target2->GetGUID();
                            me->GetMotionMaster()->MoveJump(*target2, 15.0f, 15.0f);
                        }
                    }
                }

                _events.Update(diff);

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

                while (uint32 eventId = _events.ExecuteEvent())
                {
                    switch (eventId)
                    {
                        case EVENT_FIRE_BOMB:
                            if (me->GetVehicleBase())
                                if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, -me->GetVehicleBase()->GetCombatReach(), true))
                                    me->CastSpell(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), SPELL_FIRE_BOMB, true);
                            _events.ScheduleEvent(EVENT_FIRE_BOMB, 20*IN_MILLISECONDS);
                            return;
                        case EVENT_HEAD_CRACK:
                            // commented out while SPELL_SNOBOLLED gets fixed
                            //if (Unit* target = ObjectAccessor::GetPlayer(*me, m_uiTargetGUID))
                            DoCastVictim(SPELL_HEAD_CRACK);
                            _events.ScheduleEvent(EVENT_HEAD_CRACK, 30*IN_MILLISECONDS);
                            return;
                        case EVENT_BATTER:
                            // commented out while SPELL_SNOBOLLED gets fixed
                            //if (Unit* target = ObjectAccessor::GetPlayer(*me, m_uiTargetGUID))
                            DoCastVictim(SPELL_BATTER);
                            _events.ScheduleEvent(EVENT_BATTER, 10*IN_MILLISECONDS);
                            return;
                        default:
                            return;
                    }
                }

                // do melee attack only when not on Gormoks back
                if (!me->GetVehicleBase())
                    DoMeleeAttackIfReady();
            }
	void UpdateAI(const uint32 diff)
	{
		if (!UpdateVictim())
			return;

		if (SummonKilrekTimer <= diff && SummonedKilrek == false)
		{
			Creature* Kilrek = me->SummonCreature(CREATURE_KILREK, -11237.955078, -1693.597412, 179.237823, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 15000);
			if (Kilrek)
			{
				Kilrek->SetReactState(REACT_AGGRESSIVE);
				Kilrek->AddThreat(me->GetVictim(), 1.0f);
				Kilrek->AI()->AttackStart(SelectUnit(SELECT_TARGET_RANDOM, 1));
				SummonedKilrek = true;
			}			
		}
		else SummonKilrekTimer -= diff;

		if (ReSummonKilrek_Timer <= diff && SummonedKilrek == true && ReSummonedKilrek == false)
		{
			if (me->HasAura(SPELL_BROKEN_PACT, 0))
				me->RemoveAurasDueToSpell(SPELL_BROKEN_PACT);

			Creature* Kilrek = me->SummonCreature(CREATURE_KILREK, -11237.955078, -1693.597412, 179.237823, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 15000);
			if (Kilrek)				
			{
				Kilrek->SetReactState(REACT_AGGRESSIVE);
				Kilrek->AddThreat(me->GetVictim(), 1.0f);
				Kilrek->AI()->AttackStart(SelectUnit(SELECT_TARGET_RANDOM, 1));
				ReSummonedKilrek = true;
			}
		}
		else ReSummonKilrek_Timer -= diff;


		if (SacrificeTimer <= diff)
		{
			Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);  // target tank as well patch pre 2.1.0
			if (pTarget && pTarget->IsAlive())
			{
				DoCast(pTarget, SPELL_SACRIFICE, true);
				me->SummonCreature(17248, -11233.81f, -1698.38f, 179.236f, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30500);

				if (Creature* Chains = me->FindNearestCreature(CREATURE_DEMONCHAINS, 5000))
				{
					CAST_AI(mob_demon_chainAI, Chains->AI())->SacrificeGUID = pTarget->GetGUID();
					Chains->CastSpell(Chains, SPELL_DEMON_CHAINS, true);
					DoScriptText(RAND(SAY_SACRIFICE1, SAY_SACRIFICE2), me);
					SacrificeTimer = 30000;
				}
			}
		}
		else SacrificeTimer -= diff;

		if (ShadowboltTimer <= diff)
		{
			DoCast(SelectUnit(SELECT_TARGET_TOPAGGRO, 0), SPELL_SHADOW_BOLT);
			ShadowboltTimer = 10000;
		}
		else ShadowboltTimer -= diff;

		if (SummonTimer <= diff)
		{
			if (!SummonedPortals)
			{
				for (uint8 i = 0; i < 2; ++i)
				{
					Creature* Portal = me->SummonCreature(CREATURE_PORTAL, PortalLocations[i][0], PortalLocations[i][1], PORTAL_Z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
					if (Portal)
						PortalGUID[i] = Portal->GetGUID();
				}

				SummonedPortals = true;
			}

			uint32 random = rand() % 2;
			Creature* Imp = me->SummonCreature(CREATURE_FIENDISHIMP, PortalLocations[random][0], PortalLocations[random][1], PORTAL_Z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 15000);
			if (Imp)
			{
				Imp->AddThreat(me->GetVictim(), 1.0f);
				Imp->AI()->AttackStart(SelectUnit(SELECT_TARGET_RANDOM, 0));
			}
			SummonTimer = urand(1500, 5000);
		}
		else SummonTimer -= diff;

		if (!Berserk)
		{
			if (BerserkTimer <= diff)
			{
				DoCast(me, SPELL_BERSERK);
				Berserk = true;
			}
			else BerserkTimer -= diff;
		}

		DoMeleeAttackIfReady();
	}
Example #12
0
void WorldSession::HandlePetAction(WorldPacket& recv_data)
{
    ObjectGuid petGuid;
    uint32 data;
    ObjectGuid targetGuid;
    recv_data >> petGuid;
    recv_data >> data;
    recv_data >> targetGuid;

    uint32 spellid = UNIT_ACTION_BUTTON_ACTION(data);
    uint8 flag = UNIT_ACTION_BUTTON_TYPE(data);             // delete = 0x07 CastSpell = C1

    DETAIL_LOG("HandlePetAction: %s flag is %u, spellid is %u, target %s.", petGuid.GetString().c_str(), uint32(flag), spellid, targetGuid.GetString().c_str());

    // used also for charmed creature/player
    Unit* pet = _player->GetMap()->GetUnit(petGuid);
    if (!pet)
    {
        sLog.outError("HandlePetAction: %s not exist.", petGuid.GetString().c_str());
        return;
    }

    if (GetPlayer()->GetObjectGuid() != pet->GetCharmerOrOwnerGuid())
    {
        sLog.outError("HandlePetAction: %s isn't controlled by %s.", petGuid.GetString().c_str(), GetPlayer()->GetGuidStr().c_str());
        return;
    }

    if (!pet->IsAlive())
        { return; }

    if (pet->GetTypeId() == TYPEID_PLAYER)
    {
        // controller player can only do melee attack
        if (!(flag == ACT_COMMAND && spellid == COMMAND_ATTACK))
            { return; }
    }
    else if (((Creature*)pet)->IsPet())
    {
        // pet can have action bar disabled
        if (((Pet*)pet)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS)
            { return; }
    }

    CharmInfo* charmInfo = pet->GetCharmInfo();
    if (!charmInfo)
    {
        sLog.outError("WorldSession::HandlePetAction: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId());
        return;
    }

    switch (flag)
    {
        case ACT_COMMAND:                                   // 0x07
            switch (spellid)
            {
                case COMMAND_STAY:                          // flat=1792  // STAY
                    pet->clearUnitState(UNIT_STAT_MOVING);
                    pet->StopMoving();
                    pet->GetMotionMaster()->Clear(false);
                    pet->GetMotionMaster()->MoveIdle();
                    charmInfo->SetCommandState(COMMAND_STAY);
                    break;
                case COMMAND_FOLLOW:                        // spellid=1792  // FOLLOW
                    pet->AttackStop();
                    pet->GetMotionMaster()->MoveFollow(_player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
                    charmInfo->SetCommandState(COMMAND_FOLLOW);
                    break;
                case COMMAND_ATTACK:                        // spellid=1792  // ATTACK
                {
                    Unit* TargetUnit = _player->GetMap()->GetUnit(targetGuid);
                    if (!TargetUnit)
                        { return; }

                    // not let attack friendly units.
                    if (GetPlayer()->IsFriendlyTo(TargetUnit))
                        { return; }
                    // Not let attack through obstructions
                    if (!pet->IsWithinLOSInMap(TargetUnit))
                        { return; }

                    // This is true if pet has no target or has target but targets differs.
                    if (pet->getVictim() != TargetUnit)
                    {
                        if (pet->getVictim())
                            { pet->AttackStop(); }

                        if (pet->hasUnitState(UNIT_STAT_CONTROLLED))
                        {
                            pet->Attack(TargetUnit, true);
                            pet->SendPetAIReaction();
                        }
                        else
                        {
                            pet->GetMotionMaster()->Clear();

                            if (((Creature*)pet)->AI())
                                { ((Creature*)pet)->AI()->AttackStart(TargetUnit); }

                            // 10% chance to play special pet attack talk, else growl
                            if (((Creature*)pet)->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && roll_chance_i(10))
                                { pet->SendPetTalk((uint32)PET_TALK_ATTACK); }
                            else
                            {
                                // 90% chance for pet and 100% chance for charmed creature
                                pet->SendPetAIReaction();
                            }
                        }
                    }
                    break;
                }
                case COMMAND_ABANDON:                       // abandon (hunter pet) or dismiss (summoned pet)
                    if (((Creature*)pet)->IsPet())
                    {
                        Pet* p = (Pet*)pet;
                        if (p->getPetType() == HUNTER_PET)
                            { p->Unsummon(PET_SAVE_AS_DELETED, _player); }
                        else
                            // dismissing a summoned pet is like killing them (this prevents returning a soulshard...)
                            { p->SetDeathState(CORPSE); }
                    }
                    else                                    // charmed
                        { _player->Uncharm(); }
                    break;
                default:
                    sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.", uint32(flag), spellid);
            }
            break;
        case ACT_REACTION:                                  // 0x6
            switch (spellid)
            {
                case REACT_PASSIVE:                         // passive
                case REACT_DEFENSIVE:                       // recovery
                case REACT_AGGRESSIVE:                      // activete
                    charmInfo->SetReactState(ReactStates(spellid));
                    break;
            }
            break;
        case ACT_DISABLED:                                  // 0x81    spell (disabled), ignore
        case ACT_PASSIVE:                                   // 0x01
        case ACT_ENABLED:                                   // 0xC1    spell
        {
            Unit* unit_target = NULL;
            if (targetGuid)
                { unit_target = _player->GetMap()->GetUnit(targetGuid); }

            // do not cast unknown spells
            SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellid);
            if (!spellInfo)
            {
                sLog.outError("WORLD: unknown PET spell id %i", spellid);
                return;
            }

            if (pet->GetCharmInfo() && pet->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo))
                { return; }

            for (int i = 0; i < MAX_EFFECT_INDEX; ++i)
            {
                if (spellInfo->EffectImplicitTargetA[i] == TARGET_ALL_ENEMY_IN_AREA || spellInfo->EffectImplicitTargetA[i] == TARGET_ALL_ENEMY_IN_AREA_INSTANT || spellInfo->EffectImplicitTargetA[i] == TARGET_ALL_ENEMY_IN_AREA_CHANNELED)
                    { return; }
            }

            // do not cast not learned spells
            if (!pet->HasSpell(spellid) || IsPassiveSpell(spellInfo))
                { return; }

            pet->clearUnitState(UNIT_STAT_MOVING);

            Spell* spell = new Spell(pet, spellInfo, false);

            SpellCastResult result = spell->CheckPetCast(unit_target);

            // auto turn to target unless possessed
            if (result == SPELL_FAILED_UNIT_NOT_INFRONT && !pet->HasAuraType(SPELL_AURA_MOD_POSSESS))
            {
                if (unit_target)
                {
                    pet->SetInFront(unit_target);
                    if (unit_target->GetTypeId() == TYPEID_PLAYER)
                        { pet->SendCreateUpdateToPlayer((Player*)unit_target); }
                }
                else if (Unit* unit_target2 = spell->m_targets.getUnitTarget())
                {
                    pet->SetInFront(unit_target2);
                    if (unit_target2->GetTypeId() == TYPEID_PLAYER)
                        { pet->SendCreateUpdateToPlayer((Player*)unit_target2); }
                }
                if (Unit* powner = pet->GetCharmerOrOwner())
                    if (powner->GetTypeId() == TYPEID_PLAYER)
                        { pet->SendCreateUpdateToPlayer((Player*)powner); }
                result = SPELL_CAST_OK;
            }

            if (result == SPELL_CAST_OK)
            {
                ((Creature*)pet)->AddCreatureSpellCooldown(spellid);
                if (((Creature*)pet)->IsPet())
                    { ((Pet*)pet)->CheckLearning(spellid); }

                unit_target = spell->m_targets.getUnitTarget();

                // 10% chance to play special pet attack talk, else growl
                // actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell
                if (((Creature*)pet)->IsPet() && (((Pet*)pet)->getPetType() == SUMMON_PET) && (pet != unit_target) && (urand(0, 100) < 10))
                    { pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); }
                else
                {
                    pet->SendPetAIReaction();
                }

                if (unit_target && !GetPlayer()->IsFriendlyTo(unit_target) && !pet->HasAuraType(SPELL_AURA_MOD_POSSESS))
                {
                    // This is true if pet has no target or has target but targets differs.
                    if (pet->getVictim() != unit_target)
                    {
                        if (pet->getVictim())
                            { pet->AttackStop(); }
                        pet->GetMotionMaster()->Clear();
                        if (((Creature*)pet)->AI())
                            { ((Creature*)pet)->AI()->AttackStart(unit_target); }
                    }
                }

                spell->prepare(&(spell->m_targets));
            }
            else
            {
                if (pet->HasAuraType(SPELL_AURA_MOD_POSSESS))
                    { Spell::SendCastResult(GetPlayer(), spellInfo, result); }
                else
                    { pet->SendPetCastFail(spellid, result); }

                if (!((Creature*)pet)->HasSpellCooldown(spellid))
                    { GetPlayer()->SendClearCooldown(spellid, pet); }

                spell->finish(false);
                delete spell;
            }
            break;
        }
        default:
            sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.", uint32(flag), spellid);
    }
}
Example #13
0
            void UpdateAI(uint32 diff) override
            {
                if (!UpdateVictim())
                    return;
                // Pounding
                if (Pounding_Timer <= diff)
                {
                    DoCastVictim(SPELL_POUNDING);
                    Talk(SAY_POUNDING);
                    Pounding_Timer = 15000; //cast time(3000) + cooldown time(12000)
                }
                else
                    Pounding_Timer -= diff;
                // Arcane Orb
                if (ArcaneOrb_Timer <= diff)
                {
                    Unit* target = NULL;
                    std::list<HostileReference*> t_list = me->getThreatManager().getThreatList();
                    std::vector<Unit*> target_list;
                    for (std::list<HostileReference*>::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr)
                    {
                        target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid());
                        if (!target)
                            continue;
                        // exclude pets & totems, 18 yard radius minimum
                        if (target->GetTypeId() == TYPEID_PLAYER && target->IsAlive() && !target->IsWithinDist(me, 18, false))
                            target_list.push_back(target);
                        target = NULL;
                    }

                    if (!target_list.empty())
                        target = *(target_list.begin() + rand32() % target_list.size());
                    else
                        target = me->GetVictim();

                    if (target)
                        me->CastSpell(target, SPELL_ARCANE_ORB, false, NULL, NULL);
                    ArcaneOrb_Timer = 3000;
                }
                else
                    ArcaneOrb_Timer -= diff;
                // Single Target knock back, reduces aggro
                if (KnockAway_Timer <= diff)
                {
                    DoCastVictim(SPELL_KNOCK_AWAY);
                    //Drop 25% aggro
                    if (DoGetThreat(me->GetVictim()))
                        DoModifyThreatPercent(me->GetVictim(), -25);
                    KnockAway_Timer = 30000;
                }
                else
                    KnockAway_Timer -= diff;
                //Berserk
                if (Berserk_Timer < diff && !Enraged)
                {
                    DoCast(me, SPELL_BERSERK);
                    Enraged = true;
                }
                else
                    Berserk_Timer -= diff;

                DoMeleeAttackIfReady();
            }