Beispiel #1
0
Unit* PetAI::SelectNextTarget(bool allowAutoSelect) const
{
    // Provides next target selection after current target death.
    // This function should only be called internally by the AI
    // Targets are not evaluated here for being valid targets, that is done in _CanAttack()
    // The parameter: allowAutoSelect lets us disable aggressive pet auto targeting for certain situations

    // Passive pets don't do next target selection
    if (me->HasReactState(REACT_PASSIVE))
        return NULL;

    // Check pet attackers first so we don't drag a bunch of targets to the owner
    if (Unit* myAttacker = me->getAttackerForHelper())
        if (!myAttacker->HasBreakableByDamageCrowdControlAura() && me->_CanDetectFeignDeathOf(myAttacker) && me->CanCreatureAttack(myAttacker) && !me->isTargetNotAcceptableByMMaps(myAttacker->GetGUID(), sWorld->GetGameTime(), myAttacker))
            return myAttacker;

    // Check pet's attackers first to prevent dragging mobs back to owner
    if (me->HasAuraType(SPELL_AURA_MOD_TAUNT))
    {
        const Unit::AuraEffectList& tauntAuras = me->GetAuraEffectsByType(SPELL_AURA_MOD_TAUNT);
        if (!tauntAuras.empty())
            for (Unit::AuraEffectList::const_reverse_iterator itr = tauntAuras.rbegin(); itr != tauntAuras.rend(); ++itr)
                if (Unit* caster = (*itr)->GetCaster())
                    if (me->_CanDetectFeignDeathOf(caster) && me->CanCreatureAttack(caster) && !caster->HasAuraTypeWithCaster(SPELL_AURA_IGNORED, me->GetGUID()))
                        return caster;
    }

    // Not sure why we wouldn't have an owner but just in case...
    Unit* owner = me->GetCharmerOrOwner();
    if (!owner)
        return NULL;

    // Check owner attackers
    if (Unit* ownerAttacker = owner->getAttackerForHelper())
        if (!ownerAttacker->HasBreakableByDamageCrowdControlAura() && me->_CanDetectFeignDeathOf(ownerAttacker) && me->CanCreatureAttack(ownerAttacker) && !me->isTargetNotAcceptableByMMaps(ownerAttacker->GetGUID(), sWorld->GetGameTime(), ownerAttacker))
            return ownerAttacker;

    // Check owner victim
    // 3.0.2 - Pets now start attacking their owners victim in defensive mode as soon as the hunter does
    if (Unit* ownerVictim = owner->GetVictim())
        if (me->_CanDetectFeignDeathOf(ownerVictim) && me->CanCreatureAttack(ownerVictim) && !me->isTargetNotAcceptableByMMaps(ownerVictim->GetGUID(), sWorld->GetGameTime(), ownerVictim))
            return ownerVictim;

    // Neither pet or owner had a target and aggressive pets can pick any target
    // To prevent aggressive pets from chain selecting targets and running off, we
    // only select a random target if certain conditions are met.
    if (allowAutoSelect)
        if (!me->GetCharmInfo()->IsReturning() || me->GetCharmInfo()->IsFollowing() || me->GetCharmInfo()->IsAtStay())
            if (Unit* nearTarget = me->ToCreature()->SelectNearestTargetInAttackDistance(MAX_AGGRO_RADIUS))
                return nearTarget;

    // Default - no valid targets
    return NULL;
}
        void EnterCombat(Unit* who)
        {
            if (!ghost && instance)
            {
                Talk(YELL_SKARVALD_AGGRO);

                Unit* dalronn = Unit::GetUnit(*me, instance->GetData64(DATA_DALRONN));
                if (dalronn && dalronn->IsAlive() && !dalronn->GetVictim())
                    dalronn->getThreatManager().addThreat(who, 0.0f);

                instance->SetData(DATA_SKARVALD_DALRONN_EVENT, IN_PROGRESS);
            }
        }
        void EnterCombat(Unit* who)
        {
            if (!ghost && instance)
            {
                Unit* skarvald = Unit::GetUnit(*me, instance->GetData64(DATA_SKARVALD));
                if (skarvald && skarvald->IsAlive() && !skarvald->GetVictim())
                    skarvald->getThreatManager().addThreat(who, 0.0f);

                AggroYell_Timer = 5000;

                if (instance)
                    instance->SetData(DATA_SKARVALD_DALRONN_EVENT, IN_PROGRESS);
            }
        }
Beispiel #4
0
 void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
 {
     Unit* target = GetTarget();
     Unit* victim = target->GetVictim();
     if (victim && (target->GetHealthPct() > victim->GetHealthPct()))
     {
         if (!target->HasAura(SPELL_ROGUE_PREY_ON_THE_WEAK))
         {
             int32 bp = GetSpellInfo()->Effects[EFFECT_0].CalcValue();
             target->CastCustomSpell(target, SPELL_ROGUE_PREY_ON_THE_WEAK, &bp, nullptr, nullptr, true);
         }
     }
     else
         target->RemoveAurasDueToSpell(SPELL_ROGUE_PREY_ON_THE_WEAK);
 }
void AttackersValue::AddAttackersOf(Unit* unit, set<Unit*>& targets)
{
    HostileRefManager& refManager = unit->getHostileRefManager();
    HostileReference *ref = refManager.getFirst();
    if (!ref)
        return;

    while( ref )
    {
        ThreatManager *threatManager = ref->GetSource();
        Unit *attacker = threatManager->GetOwner();
        Unit *victim = attacker->GetVictim();
        if (victim == unit)
            targets.insert(attacker);
        ref = ref->next();
    }
}
void EffectMovementGenerator::Finalize(Unit& unit)
{
    if (unit.GetTypeId() != TYPEID_UNIT)
        return;

    // Need restore previous movement since we have no proper states system
    if (unit.IsAlive() && !unit.HasUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_FLEEING | UNIT_STATE_DISTRACTED))
    {
        if (Unit* victim = unit.GetVictim())
            unit.GetMotionMaster()->MoveChase(victim);
        else
            unit.GetMotionMaster()->Initialize();
    }
    else if (!unit.IsAlive())
    {
        unit.GetMotionMaster()->MoveIdle();
    }

    if (unit.ToCreature()->AI())
        unit.ToCreature()->AI()->MovementInform(EFFECT_MOTION_TYPE, m_Id);
}
Beispiel #7
0
        void UpdateAI(uint32 diff) override
        {
            if (TalkTimer)
            {
                if (!TalkSequence)
                {
                    me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE);
                    me->InterruptNonMeleeSpells(true);
                    me->RemoveAllAuras();
                    me->DeleteThreatList();
                    me->CombatStop();
                    ++TalkSequence;
                }
                if (TalkTimer <= diff)
                {
                    if (isFriendly)
                        GoodEnding();
                    else
                        BadEnding();
                    ++TalkSequence;
                } else TalkTimer -= diff;
            }
            else
            {
                if (bJustReset)
                {
                    if (ResetTimer <= diff)
                    {
                        me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
                        me->SetDisableGravity(false);
                        me->SetVisible(true);
                        me->SetStandState(UNIT_STAND_STATE_SLEEP);
                        ResetTimer = 10000;
                        bJustReset = false;
                    } else ResetTimer -= diff;
                    return;
                }

                if (!UpdateVictim())
                    return;

                if (CheckTimer <= diff)
                {
                    if (me->GetDistance(CENTER_X, CENTER_Y, DRAGON_REALM_Z) >= 75)
                    {
                        EnterEvadeMode();
                        return;
                    }
                    if (HealthBelowPct(10) && !isEnraged)
                    {
                        if (Creature* Sath = ObjectAccessor::GetCreature(*me, SathGUID))
                            Sath->AI()->DoAction(DO_ENRAGE);
                        DoAction(DO_ENRAGE);
                    }
                    if (!isBanished && HealthBelowPct(1))
                    {
                        if (Creature* Sath = ObjectAccessor::GetCreature(*me, SathGUID))
                        {
                            if (Sath->HasAura(SPELL_BANISH))
                            {
                                Sath->DealDamage(Sath, Sath->GetHealth());
                                return;
                            }
                            else
                                DoAction(DO_BANISH);
                        }
                        else
                        {
                            TC_LOG_ERROR("scripts", "Didn't find Shathrowar. Kalecgos event reseted.");
                            EnterEvadeMode();
                            return;
                        }
                    }
                    CheckTimer = 1000;
                } else CheckTimer -= diff;

                if (ArcaneBuffetTimer <= diff)
                {
                    DoCastAOE(SPELL_ARCANE_BUFFET);
                    ArcaneBuffetTimer = 8000;
                } else ArcaneBuffetTimer -= diff;

                if (FrostBreathTimer <= diff)
                {
                    DoCastAOE(SPELL_FROST_BREATH);
                    FrostBreathTimer = 15000;
                } else FrostBreathTimer -= diff;

                if (TailLashTimer <= diff)
                {
                    DoCastAOE(SPELL_TAIL_LASH);
                    TailLashTimer = 15000;
                } else TailLashTimer -= diff;

                if (WildMagicTimer <= diff)
                {
                    DoCastAOE(WildMagic[rand32() % 6]);
                    WildMagicTimer = 20000;
                } else WildMagicTimer -= diff;

                if (SpectralBlastTimer <= diff)
                {
                    ThreatContainer::StorageType const& m_threatlist = me->getThreatManager().getThreatList();
                    std::list<Unit*> targetList;
                    for (ThreatContainer::StorageType::const_iterator itr = m_threatlist.begin(); itr!= m_threatlist.end(); ++itr)
                    {
                        Unit* target = (*itr)->getTarget();
                        if (target
                                && target->GetTypeId() == TYPEID_PLAYER
                                && (!target->GetVictim() || target->GetGUID() != me->EnsureVictim()->GetGUID())
                                && target->GetPositionZ() > me->GetPositionZ() - 5
                                && !target->HasAura(AURA_SPECTRAL_EXHAUSTION))
                        {
                            targetList.push_back(target);
                        }
                    }
                    if (targetList.empty())
                    {
                        SpectralBlastTimer = 1000;
                        return;
                    }

                    std::list<Unit*>::const_iterator i = targetList.begin();
                    advance(i, rand32() % targetList.size());
                    if ((*i))
                    {
                        (*i)->CastSpell((*i), SPELL_SPECTRAL_BLAST, true);
                        SpectralBlastTimer = 20000 + rand32() % 5000;
                    } else SpectralBlastTimer = 1000;
                } else SpectralBlastTimer -= diff;

                DoMeleeAttackIfReady();
            }
        }
        void DoNormalAttack(uint32 diff)
        {
            opponent = me->GetVictim();
            if (opponent)
            {
                if (!IsCasting())
                    StartAttack(opponent);
            }
            else
                return;

            AttackerSet m_attackers = master->getAttackers();
            AttackerSet b_attackers = me->getAttackers();

            Unit* u = me->SelectNearestTarget(20);
            //ICE_BARRIER
            if (ICE_BARRIER && Ice_Barrier_cd <= diff && u && u->GetVictim() == me &&
                u->GetDistance(me) < 8 && !me->HasAura(ICE_BARRIER))
            {
                if (me->IsNonMeleeSpellCast(true))
                    me->InterruptNonMeleeSpells(true);
                if (doCast(me, ICE_BARRIER))
                {
                    Ice_Barrier_cd = 25000;
                    GC_Timer = 800;
                    return;
                }
            }
            if ((!ICE_BARRIER || Ice_Barrier_cd > diff) &&
                BLINK && Blink_cd < 3000 && u && u->GetVictim() == me &&
                u->GetDistance(me) < 6 && !me->HasAura(ICE_BARRIER))
            {
                if (me->IsNonMeleeSpellCast(true))
                    me->InterruptNonMeleeSpells(true);
                if (doCast(me, BLINK))
                {
                    Blink_cd = 13000;
                    GC_Timer = 800;
                    return;
                }
            }

            if (me->HasAura(ICEBLOCK))
                if (((GetManaPCT(me) > 45 && GetHealthPCT(me) > 80) || b_attackers.empty()) && Iceblock_cd <= 57000 && tank)
                    me->RemoveAurasDueToSpell(ICEBLOCK);
            //ICEBLOCK
            if (ICEBLOCK && Rand() < 50 && !b_attackers.empty() && tank && Iceblock_cd <= diff &&
                (GetManaPCT(me) < 15 || GetHealthPCT(me) < 45 || b_attackers.size() > 4) &&
                !me->HasAura(ICEBLOCK))
            {
                if (me->IsNonMeleeSpellCast(true))
                    me->InterruptNonMeleeSpells(true);
                if (doCast(me, ICEBLOCK))
                {
                    Iceblock_cd = 60000;
                    Nova_cd = 0; //Glyph of Iceblock
                    return;
                }
            }

            if (IsCasting()) return;

            float dist = me->GetExactDist(opponent);

            BOLT = (CCed(opponent, true) || !FROSTBOLT) ? FIREBALL : FROSTBOLT;
            NOVA = BOLT == FROSTBOLT && BLASTWAVE && dist > 5 ? BLASTWAVE : FROSTNOVA ? FROSTNOVA : 0;

            ////Combustion doesn't work properly on 434 (14.08.13)
            //if (COMBUSTION && Combustion_cd <= diff && Rand() < 15 && dist < 40)
            //{
            //    if (opponent->HasAuraTypeWithCaster(SPELL_AURA_PERIODIC_DAMAGE, me->GetGUID()))
            //    {
            //        temptimer = GC_Timer;
            //        if (doCast(me, COMBUSTION))
            //        {
            //            Combustion_cd = 60000;
            //            Nova_cd = 0; FireBlast_cd = 0; DragonBreath_cd = 0;
            //        }
            //        GC_Timer = temptimer;
            //    }
            //}
            //DAMAGE
            //PYROBLAST
            if (PYROBLAST && Pyroblast_cd <= diff && GC_Timer <= diff && Rand() < 95 &&
                (b_attackers.size() < 2 || (*b_attackers.begin()) == opponent) &&
                dist < 40 && opponent->IsPolymorphed() &&
                doCast(opponent, PYROBLAST))
            {
                Pyroblast_cd = 7500;
                //debug
                DragonBreath_cd = std::max<uint32>(DragonBreath_cd, 450);
                Nova_cd = std::max<uint32>(Nova_cd, 450);
                return;
            }
            //nova //TODO: SEPARATE
            u = me->SelectNearestTarget(6.3f);
            if (NOVA && Nova_cd <= diff && u && Rand() < 75 && !CCed(u, true) && IsInBotParty(u->GetVictim()))
            {
                if (doCast(me, NOVA))
                {
                    Nova_cd = 15000;
                    GetInPosition(true);
                    return;
                }
            }
            //living bomb
            if (LIVINGBOMB && Living_Bomb_cd <= diff && GC_Timer <= diff && Rand() < 45 && dist < 40 &&
                opponent->GetHealth() > me->GetHealth()/2 &&
                !opponent->HasAura(LIVINGBOMB, me->GetGUID()) &&
                doCast(opponent, LIVINGBOMB))
            {
                Living_Bomb_cd = 6000;
                GC_Timer = 500;
                return;
            }
            //cone of cold
            if (CONEOFCOLD && ConeofCold_cd <= diff && GC_Timer <= diff && Rand() < 50 && dist < 7 &&
                me->HasInArc(M_PI*0.75f, opponent) &&
                doCast(opponent, CONEOFCOLD))
            {
                ConeofCold_cd = 8000;
                GC_Timer = 500;
                GetInPosition(true);
                return;
            }
            //dragon's breath
            if (DRAGONBREATH && DragonBreath_cd <= diff && GC_Timer <= diff && !CCed(opponent, true) &&
                ((me->HasInArc(M_PI*0.75f, opponent) && dist < 7) ||
                (u && u != opponent && me->HasInArc(M_PI*0.75f, u) && IsInBotParty(u->GetVictim()))) &&
                doCast(/*opponent*/me, DRAGONBREATH))
            {
                DragonBreath_cd = 15000;
                GC_Timer = 800;
                return;
            }
            /*//blast wave //TODO Separate again
            u = me->SelectNearestTarget(8);
            if (BLASTWAVE != 0 && u && isTimerReady(BlastWave_cd) &&
                !HasAuraName(u, FROSTNOVA) && !HasAuraName(u, DRAGONBREATH) &&
                doCast(me, BLASTWAVE))
            {
                BlastWave_cd = BLASTWAVE_CD;
                GC_Timer = 800;
            }*/
            //fire blast
            if (FIREBLAST && FireBlast_cd <= diff && GC_Timer <= diff && dist < 40)
            {
                if (Rand() < 20 + 80*(!opponent->isFrozen() && !opponent->HasAuraType(SPELL_AURA_MOD_STUN) && me->HasAura(IMPACT_BUFF)))
                {
                    if (doCast(opponent, FIREBLAST))
                    {

                        FireBlast_cd = 6000;
                        GC_Timer = 500;
                        return;
                    }
                }
            }
            //flamestrike - use Improved Flamestrike for instant cast
            if (FLAMESTRIKE && GC_Timer <= diff && me->getLevel() >= 50 && Rand() < 25)
            {
                Unit* FStarget = FindAOETarget(40, true, false);
                if (FStarget && doCast(FStarget, FLAMESTRIKE, true))
                    return;
            }
            //blizzard
            if (BLIZZARD && Blizzard_cd <= diff && !me->isMoving() && Rand() < 40)
            {
                Unit* blizztarget = FindAOETarget(35, true);
                if (blizztarget && doCast(blizztarget, BLIZZARD))
                {
                    Blizzard_cd = 5000;
                    return;
                }
                Blizzard_cd = 1500; //fail
            }
            //Frost of Fire Bolt
            if (BOLT && Bolt_cd <= diff && Rand() < 75 && dist < 35 &&
                doCast(opponent, BOLT))
            {
                Bolt_cd = uint32(float(sSpellMgr->GetSpellInfo(BOLT)->CalcCastTime()/100) * me->GetFloatValue(UNIT_MOD_CAST_SPEED) + 200);
                //debug
                DragonBreath_cd = std::max<uint32>(DragonBreath_cd, 450);
                Nova_cd = std::max<uint32>(Nova_cd, 450);
                return;
            }
            ////Arcane Missiles
            //if (Rand() < 15 && GC_Timer <= diff && !me->isMoving() && dist < 40 &&
            //    doCast(opponent, ARCANEMISSILES))
            //    return;
        }
Beispiel #9
0
        void DoNormalAttack(uint32 diff)
        {
            opponent = me->GetVictim();
            if (opponent)
            {
                if (!IsCasting())
                    StartAttack(opponent);
            }
            else
                return;
            AttackerSet m_attackers = master->getAttackers();
            AttackerSet b_attackers = me->getAttackers();

            Unit* u = me->SelectNearestTarget(20);
            //ICE_BARRIER
            if (ICE_BARRIER && Ice_Barrier_cd <= diff && u && u->GetVictim() == me && 
                u->GetDistance(me) < 8 && !me->HasAura(ICE_BARRIER))
            {
                if (me->IsNonMeleeSpellCasted(true))
                    me->InterruptNonMeleeSpells(true);
                if (doCast(me, ICE_BARRIER))
                {
                    Ice_Barrier_cd = 41000 - me->getLevel()*200;//down to 25 sec on 80
                    GC_Timer = 800;
                    return;
                }
            }
            if ((!ICE_BARRIER || Ice_Barrier_cd > diff) && 
                BLINK && Blink_cd < 3000 && u && u->GetVictim() == me && 
                !me->HasAura(ICE_BARRIER) && u->GetDistance(me) < 6)
            {
                if (me->IsNonMeleeSpellCasted(true))
                    me->InterruptNonMeleeSpells(true);
                if (doCast(me, BLINK))
                {
                    Blink_cd = 15000 - me->getLevel()/4 * 100;
                    GC_Timer = 800;
                    return;
                }
            }

            if (me->HasAura(ICEBLOCK))
                if (((GetManaPCT(me) > 45 && GetHealthPCT(me) > 80) || b_attackers.empty()) && Iceblock_cd <= 57000 && tank)
                    me->RemoveAurasDueToSpell(ICEBLOCK);
            //ICEBLOCK
            if (ICEBLOCK && Rand() < 50 && !b_attackers.empty() && tank && Iceblock_cd <= diff && 
                (GetManaPCT(me) < 15 || GetHealthPCT(me) < 45 || b_attackers.size() > 4) && 
                !me->HasAura(ICEBLOCK))
            {
                if (me->IsNonMeleeSpellCasted(true))
                    me->InterruptNonMeleeSpells(true);
                if (doCast(me, ICEBLOCK))
                {
                    Iceblock_cd = 60000;
                    return;
                }
            }

            if (IsCasting()) return;

            BOLT = (CCed(opponent, true) || (opponent->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED) && me->HasAura(COMBUSTION))) ? FIREBALL : FROSTBOLT;
            NOVA = BOLT == FIREBALL && BLASTWAVE ? BLASTWAVE : FROSTNOVA ? FROSTNOVA : 0;

            float dist = me->GetExactDist(opponent);
            if (dist > 30)
                return;

            if (COMBUSTION && Rand() < 15 && 
                (opponent->GetMaxHealth() > master->GetMaxHealth()*10 || 
                m_attackers.size() > 1 || b_attackers.size() > 2))
            {
                if (!HasAuraName(me, "Combustion") && Combustion_cd <= diff)
                {
                    temptimer = GC_Timer;
                    if (doCast(me, COMBUSTION))
                    {
                        Combustion_cd = 60000;
                        //Reset timers for fun
                        Nova_cd = 0; FireBlast_cd = 0; DragonBreath_cd = 0;
                    }
                    GC_Timer = temptimer;
                }
            }
            //DAMAGE
            //PYROBLAST
            if (PYROBLAST && Rand() < 75 && Pyroblast_cd <= diff && GC_Timer <= diff && 
                b_attackers.size() < 2 && dist < 30 && opponent->IsPolymorphed() && 
                doCast(opponent, PYROBLAST))
                Pyroblast_cd = 50;
            //nova //TODO: SEPARATE
            u = me->SelectNearestTarget(7);
            if (u && NOVA && Nova_cd <= diff && !CCed(u, true) && IsInBotParty(u->GetVictim()))
            {
                Unit* tar = u->GetVictim();
                if (tar && IsInBotParty(tar) && doCast(me, NOVA))
                {
                    Nova_cd = 15000;
                    return;
                }
            }
            //living bomb
            if (LIVINGBOMB && Rand() < 25 && Living_Bomb_cd <= diff && GC_Timer <= diff && 
                dist < 30 && opponent->GetHealth() > me->GetHealth()/2 && 
                !opponent->HasAura(LIVINGBOMB, me->GetGUID()) && 
                doCast(opponent, LIVINGBOMB))
            {
                Living_Bomb_cd = 6000;
                GC_Timer = 500;
                return;
            }
            //cone of cold
            if (CONEOFCOLD && ConeofCold_cd <= diff && GC_Timer <= diff && dist < 7 && 
                me->HasInArc(M_PI, opponent) && 
                doCast(opponent, CONEOFCOLD))
            {
                ConeofCold_cd = 14000;
                GC_Timer = 500;
                return;
            }
            //dragon's breath
            u = me->SelectNearestTarget(7);
            if (DRAGONBREATH && u && DragonBreath_cd <= diff && GC_Timer <= diff && 
                me->HasInArc(M_PI, opponent) && !HasAuraName(u, FROSTNOVA) && 
                doCast(opponent, DRAGONBREATH))
            {
                DragonBreath_cd = 25000;
                GC_Timer = 800;
                return;
            }
            /*//blast wave //TODO Separate again
            u = me->SelectNearestTarget(8);
            if (BLASTWAVE != 0 && u && isTimerReady(BlastWave_cd) && 
                !HasAuraName(u, FROSTNOVA) && !HasAuraName(u, DRAGONBREATH) && 
                doCast(me, BLASTWAVE))
            {
                BlastWave_cd = BLASTWAVE_CD;
                GC_Timer = 800;
            }*/
            //fire blast
            if (FireBlast_cd <= diff && GC_Timer <= diff && dist < 20 && 
                Rand() < 20 + 80*(!opponent->HasAuraType(SPELL_AURA_MOD_STUN) && me->HasAura(IMPACT_BUFF)) && 
                doCast(opponent, FIREBLAST))
            {
                FireBlast_cd = 6000;
                GC_Timer = 500;
                return;
            }
            //flamestrike
            if (GC_Timer <= diff && Rand() < 60 && me->HasAura(FIRESTARTERBUFF))
            {
                Unit* FStarget = FindAOETarget(30, true, false);
                if (FStarget && doCast(FStarget, FLAMESTRIKE, true))
                {
                    me->RemoveAurasDueToSpell(FIRESTARTERBUFF);
                    GC_Timer = 0;
                    return;
                }
            }
            //blizzard
            if (BLIZZARD && Rand() < 80 && Blizzard_cd <= diff)
            {
                Unit* blizztarget = FindAOETarget(30, true);
                if (blizztarget && doCast(blizztarget, BLIZZARD))
                {
                    Blizzard_cd = 5000;
                    return;
                }
                Blizzard_cd = 2000;//fail
            }
            //Frost of Fire Bolt
            if (Rand() < 75 && Bolt_cd <= diff && dist < 30 && 
                doCast(opponent, BOLT))
            {
                Bolt_cd = uint32(float(sSpellMgr->GetSpellInfo(BOLT)->CalcCastTime()/100) * me->GetFloatValue(UNIT_MOD_CAST_SPEED) + 200);
                return;
            }
            //Arcane Missiles
            if (Rand() < 10 && GC_Timer <= diff && !me->isMoving() && dist < 20 && 
                doCast(opponent, ARCANEMISSILES))
                return;
        }