示例#1
0
        void UpdateAI(const uint32 diff)
        {
            if (!UpdateVictim())
                return;

            events.Update(diff);

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

            while (uint32 eventId = events.ExecuteEvent())
            {
                switch (eventId)
                {
                    case EVENT_SHADOW_WORD_PAIN:
                        if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
                            DoCast(target, SPELL_SHADOW_WORD_PAIN);
                        events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 8000);
                        return;
                    case EVENT_CIRCLE_OF_DESTRUCTION:
                        if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
                            DoCast(target, SPELL_CIRCLE_OF_DESTRUCTION);
                        events.ScheduleEvent(EVENT_CIRCLE_OF_DESTRUCTION, 12000);
                        return;
                    case EVENT_COWER_IN_FEAR:
                        if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
                            DoCast(target, SPELL_COWER_IN_FEAR);
                        events.ScheduleEvent(EVENT_COWER_IN_FEAR, 10000);
                        return;
                    case EVENT_DARK_MENDING:
                        // find an ally with missing HP
                        if (Unit* target = DoSelectLowestHpFriendly(40, DUNGEON_MODE(30000, 50000)))
                        {
                            DoCast(target, SPELL_DARK_MENDING);
                            events.ScheduleEvent(EVENT_DARK_MENDING, 20000);
                        }
                        else
                        {
                            // no friendly unit with missing hp. re-check in just 5 sec.
                            events.ScheduleEvent(EVENT_DARK_MENDING, 5000);
                        }
                        return;
                }
            }

            DoMeleeAttackIfReady();
        }
示例#2
0
    void UpdateAI(const uint32 diff)
    {
        if (!UpdateVictim())
            return;

        if (uiShieldTimer <= diff)
        {
            me->AddAura(RAND(SPELL_MAGIC_REFLECTION, SPELL_DAMAGE_REFLECTION), me);
       //     DoCast(m_creature, RAND(SPELL_MAGIC_REFLECTION, SPELL_DAMAGE_REFLECTION));
            uiShieldTimer = urand(20000, 30000);
        } else uiShieldTimer -= diff;

        switch (me->GetEntry())
        {
        case NPC_FLAMEWAKER_ELITE:
            if (Blastwave_Timer <= diff)
            {
                DoCast(SPELL_BLAST_WAVE);
                Blastwave_Timer = 10000;
            } else Blastwave_Timer -= diff;

            if (uiFireBlastTimer <= diff)
            {
                DoCast(SPELL_FIRE_BLAST);
                uiFireBlastTimer = 15000;
            } else uiFireBlastTimer -= diff;

            break;
        case NPC_FLAMEWAKER_HEALER:
            if (uiShadowShockTimer <= diff)
            {
                if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
                    DoCast(pTarget, SPELL_SHADOW_SHOCK);
                uiShadowShockTimer = 2000;
            } else uiShadowShockTimer -= diff;

            if (uiHealTimer <= diff)
            {
                if (Unit* pTarget = DoSelectLowestHpFriendly(200))
                    DoCast(pTarget, SPELL_HEAL_BRETHREN);
                uiHealTimer = urand(15000, 20000);
            } else uiHealTimer -= diff;
            break;
        }
        DoMeleeAttackIfReady();
    }
        void UpdateAI(const uint32 diff)
        {
            if (!UpdateVictim())
                return;

            events.Update(diff);

            while (uint32 eventId = events.ExecuteEvent())
            {
                switch(eventId)
                {
                    case EVENT_ENRAGE:
                        DoScriptText(SAY_MOLGEIM_BERSERK, me);
                        DoCast(SPELL_BERSERK);
                        break;
                    case EVENT_RUNE_OF_POWER: // Improve target selection; random alive friendly
                    {
                        Unit *pTarget = DoSelectLowestHpFriendly(60);
                        if (!pTarget || !pTarget->isAlive())
                            pTarget = me;
                        DoCast(pTarget, SPELL_SUMMON_RUNE_OF_POWER);
                        events.ScheduleEvent(EVENT_RUNE_OF_POWER, 60000);
                        break;
                    }
                    case EVENT_SHIELD_OF_RUNES:
                        DoCast(me, RAID_MODE(SPELL_SHIELD_OF_RUNES, SPELL_SHIELD_OF_RUNES_H));
                        events.ScheduleEvent(EVENT_SHIELD_OF_RUNES, urand(27000,34000));
                        break;
                    case EVENT_RUNE_OF_DEATH:
                        DoScriptText(SAY_MOLGEIM_RUNE_DEATH, me);
                        if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM))
                            DoCast(pTarget, SPELL_RUNE_OF_DEATH);
                        events.ScheduleEvent(EVENT_RUNE_OF_DEATH, urand(30000,40000));
                        break;
                    case EVENT_RUNE_OF_SUMMONING:
                        DoScriptText(SAY_MOLGEIM_SUMMON, me);
                        if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM))
                            DoCast(pTarget, SPELL_RUNE_OF_SUMMONING);
                        events.ScheduleEvent(EVENT_RUNE_OF_SUMMONING, urand(20000,30000));
                        break;
                }
            }

            DoMeleeAttackIfReady();
        }
示例#4
0
            void UpdateAI(const uint32 uiDiff)
            {
                if (!UpdateVictim())
                    return;
					
                if (me->HasUnitState(UNIT_STAT_CASTING))
                    return;
				
                //Chain heal Timer
                if (m_uiHealTimer <= uiDiff)
                {
                    if (Unit *pAlly = DoSelectLowestHpFriendly(INTERACTION_DISTANCE*100))
                        DoCast(pAlly, SPELL_HEAL);

                    m_uiHealTimer = urand(15000, 20000);
                }
                else
                    m_uiHealTimer -= uiDiff;

                //Fel Fireball Timer
                if (m_uiFFireballTimer <= uiDiff)
                {
                    if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM))
                        DoCast(pTarget, SPELL_FEL_FIREBALL);

                    m_uiFFireballTimer = urand(10000, 15000);
                }
                else
                    m_uiFFireballTimer -= uiDiff;

                //Fire Nova timer
                if (m_uiFireNovaTimer <= uiDiff)
                {
                    DoCast(me, SPELL_FIRE_NOVA);

                    m_uiFireNovaTimer = urand(8000,  15000);
                }
                else
                    m_uiFireNovaTimer -= uiDiff;


                DoMeleeAttackIfReady();
            }
    void UpdateAI(const uint32 uiDiff) override
    {
        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        // Casting Heal to Sulfuron or other Guards.
        if (m_uiHealTimer < uiDiff)
        {
            if (Unit* pUnit = DoSelectLowestHpFriendly(60.0f, 1))
            {
                if (DoCastSpellIfCan(pUnit, SPELL_HEAL) == CAST_OK)
                    m_uiHealTimer = urand(15000, 20000);
            }
        }
        else
            m_uiHealTimer -= uiDiff;

        // ShadowWord Pain Timer
        if (m_uiShadowWordPainTimer < uiDiff)
        {
            if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
            {
                if (DoCastSpellIfCan(pTarget, SPELL_SHADOWWORD_PAIN) == CAST_OK)
                    m_uiShadowWordPainTimer = urand(18000, 26000);
            }
        }
        else
            m_uiShadowWordPainTimer -= uiDiff;

        // Immolate Timer
        if (m_uiImmolateTimer < uiDiff)
        {
            if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
            {
                if (DoCastSpellIfCan(pTarget, SPELL_IMMOLATE) == CAST_OK)
                    m_uiImmolateTimer = urand(15000, 25000);
            }
        }
        else
            m_uiImmolateTimer -= uiDiff;

        DoMeleeAttackIfReady();
    }
    bool UpdateChampionAI(const uint32 uiDiff)
    {
        if (m_uiLightningTimer < uiDiff)
        {
            if (DoCastSpellIfCan(m_creature, SPELL_CHAIN_LIGHTNING) == CAST_OK)
                m_uiLightningTimer = urand(1000, 3000);
        }
        else
            m_uiLightningTimer -= uiDiff;

        if (m_uiHealingWaveTimer < uiDiff)
        {
            if (Unit* pTarget = DoSelectLowestHpFriendly(40.0f))
            {
                if (DoCastSpellIfCan(pTarget, SPELL_HEALING_WAVE) == CAST_OK)
                    m_uiHealingWaveTimer = urand(8000, 13000);
            }
        }
        else
            m_uiHealingWaveTimer -= uiDiff;

        if (m_uiEarthShieldTimer < uiDiff)
        {
            if (DoCastSpellIfCan(m_creature, SPELL_EARTH_SHIELD, CAST_AURA_NOT_PRESENT) == CAST_OK)
                m_uiEarthShieldTimer = 30000;
            else
                m_uiEarthShieldTimer = 5000;
        }
        else
            m_uiEarthShieldTimer -= uiDiff;

        if (m_uiHexTimer < uiDiff)
        {
            if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_HEX_OF_MENDING) == CAST_OK)
                m_uiHexTimer = urand(17000, 25000);
        }
        else
            m_uiHexTimer -= uiDiff;

        return true;
    }
    void UpdateEscortAI(const uint32 uiDiff) override
    {
        DialogueUpdate(uiDiff);

        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        if (m_uiExorcismTimer < uiDiff)
        {
            if (DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_EXORCISM : SPELL_EXORCISM_H) == CAST_OK)
                m_uiExorcismTimer = urand(9000, 13000);
        }
        else
            m_uiExorcismTimer -= uiDiff;

        if (m_uiHolyLightTimer < uiDiff)
        {
            if (Unit* pTarget = DoSelectLowestHpFriendly(40.0f))
            {
                if (DoCastSpellIfCan(pTarget, SPELL_HOLY_LIGHT) == CAST_OK)
                    m_uiHolyLightTimer = urand(18000, 25000);
            }
        }
        else
            m_uiHolyLightTimer -= uiDiff;

        if (!m_bYell50Pct && m_creature->GetHealthPercent() < 50.0f)
        {
            DoScriptText(SAY_ARTHAS_HALF_HP, m_creature);
            m_bYell50Pct = true;
        }

        if (!m_bYell20Pct && m_creature->GetHealthPercent() < 20.0f)
        {
            DoScriptText(SAY_ARTHAS_LOW_HP, m_creature);
            m_bYell20Pct = true;
        }

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

        //Casting Heal to Sulfuron or other Guards.
        if (Heal_Timer <= diff)
        {
            Unit* pUnit = DoSelectLowestHpFriendly(60.0f, 1);
            if (!pUnit)
                return;

            DoCast(pUnit, SPELL_HEAL);

            Heal_Timer = 15000+rand()%5000;
        } else Heal_Timer -= diff;

        //ShadowWordPain_Timer
        if (ShadowWordPain_Timer <= diff)
        {
            Unit *pTarget = NULL;
            pTarget = SelectUnit(SELECT_TARGET_RANDOM,0);
            if (pTarget) DoCast(pTarget, SPELL_SHADOWWORDPAIN);

            ShadowWordPain_Timer = 18000+rand()%8000;
        } else ShadowWordPain_Timer -= diff;

        //Immolate_Timer
        if (Immolate_Timer <= diff)
        {
            Unit *pTarget = NULL;
            pTarget = SelectUnit(SELECT_TARGET_RANDOM,0);
            if (pTarget) DoCast(pTarget, SPELL_IMMOLATE);

            Immolate_Timer = 15000+rand()%10000;
        } else Immolate_Timer -= diff;

        DoMeleeAttackIfReady();
    }
void PlayerbotPaladinAI::DoNonCombatActions()
{
    PlayerbotAI *ai = GetAI();
    Player *m_bot = GetPlayerBot();
    if (!m_bot || !ai || m_bot->isDead()) { return; }

    //If Casting or Eating/Drinking return
    if (m_bot->HasUnitState(UNIT_STATE_CASTING)) { return; }
    if (m_bot->getStandState() == UNIT_STAND_STATE_SIT) { return; }

    //buff and heal raid
    if (DoSupportRaid(m_bot)) { return; }

    //heal pets and bots
    Unit *target = DoSelectLowestHpFriendly(40, 1000);
    if (target && target->isAlive() && HealTarget(target, target->GetHealth()*100 / target->GetMaxHealth())) { return; }

    //mana/hp check
    //Don't bother with eating, if low on hp, just let it heal themself
    if (m_bot->getRace() == (uint8) RACE_UNDEAD_PLAYER && ai->GetHealthPercent() < 75 && CastSpell(R_CANNIBALIZE,m_bot)) { return; }
    if (m_bot->GetHealth() < m_bot->GetMaxHealth() && CastSpell(FLASH_OF_LIGHT,m_bot)) { return; }
    if (ai->GetManaPercent() < 70) { ai->Feast(); }
} //end DoNonCombatActions
bool PlayerbotShamanAI::HealGroup (Unit *target, uint8 hp, uint8 &countNeedHeal)
{
    Player *m_bot = GetPlayerBot();
    if (countNeedHeal < 2) {
        return false;
    }
    Unit *rTarget = DoSelectLowestHpFriendly(30,500);
    if (!rTarget || rTarget->isDead() || rTarget->GetHealth() * 100 / rTarget->GetMaxHealth() > 80 ) {
        return false;
    }

    if (hp < 65 && RIPTIDE && rTarget->HasAura(RIPTIDE,m_bot->GetGUID()) && CastSpell(CHAIN_HEAL, rTarget)) {
        return true;
    }
    if (hp < 85 && CastSpell(RIPTIDE, rTarget)) {
        return true;
    }
    if (hp < 75 && CastSpell(CHAIN_HEAL, rTarget,true,true)) {
        return true;
    }

    return false;
}
示例#11
0
    void UpdateAI(const uint32 diff)
    {
        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return;

        //cast bubble at 20% hp
        if (m_creature->GetHealthPercent() < 20.0f)
             timedCast(SPELL_BUBBLE, diff);

            if (Unit *target = DoSelectLowestHpFriendly(40.0f))
                if (target->GetHealthPercent() < 15.0f)
                    timedCast(SPELL_HAND_OF_PROTECTION, diff);

            timedCast(SPELL_HOLY_SHOCK, diff);

            if (Unit *target = SelectRandomFriendlyMissingBuff(SPELL_HAND_OF_FREEDOM))
                timedCast(SPELL_HAND_OF_FREEDOM, diff, target);

            timedCast(SPELL_HAMMER_OF_JUSTICE, diff);

        if (timedQuery(SPELL_FLASH_OF_LIGHT, diff))
        {
            switch (urand(0,4))
            {
                case 0: case 1:
                        doCast(SPELL_FLASH_OF_LIGHT);
                    break;
                case 2: case 3:
                        doCast(SPELL_HOLY_LIGHT);
                    break;
                case 4:
                        doCast(SPELL_CLEANSE);
                    break;
            }
        }

        boss_faction_championsAI::UpdateAI(diff);
    }
示例#12
0
    void UpdateAI(const uint32 uiDiff) override
    {
        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        if (m_uiHealTimer <= uiDiff)
        {
            if (Unit* pTarget = DoSelectLowestHpFriendly(50.0f))
            {
                if (DoCastSpellIfCan(pTarget, SPELL_SOLARIUM_GREAT_HEAL) == CAST_OK)
                    m_uiHealTimer = 9000;
            }
        }
        else
            m_uiHealTimer -= uiDiff;

        if (m_uiHolySmiteTimer <= uiDiff)
        {
            if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, nullptr, SELECT_FLAG_PLAYER))
            {
                if (DoCastSpellIfCan(pTarget, SPELL_SOLARIUM_HOLY_SMITE) == CAST_OK)
                    m_uiHolySmiteTimer = 4000;
            }
        }
        else
            m_uiHolySmiteTimer -= uiDiff;

        if (m_uiAoESilenceTimer <= uiDiff)
        {
            if (DoCastSpellIfCan(m_creature, SPELL_SOLARIUM_ARCANE_TORRENT) == CAST_OK)
                m_uiAoESilenceTimer = 13000;
        }
        else
            m_uiAoESilenceTimer -= uiDiff;

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

                events.Update(diff);

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

                while (uint32 eventId = events.ExecuteEvent())
                {
                    switch (eventId)
                    {
                        case EVENT_HEAL:
                            if (Unit* target = DoSelectLowestHpFriendly(60.0f, 1))
                                DoCast(target, SPELL_HEAL);
                            events.ScheduleEvent(EVENT_HEAL, urand(15000, 20000));
                            break;
                        case EVENT_SHADOW_WORD_PAIN:
                            if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_SHADOWWORDPAIN))
                                DoCast(target, SPELL_SHADOWWORDPAIN);
                            events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(18000, 26000));
                            break;
                        case EVENT_IMMOLATE:
                            if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_IMMOLATE))
                                DoCast(target, SPELL_IMMOLATE);
                            events.ScheduleEvent(EVENT_IMMOLATE, urand(15000, 25000));
                            break;
                        default:
                            break;
                    }
                }

                DoMeleeAttackIfReady();
            }
示例#14
0
void PlayerbotShamanAI::DoNextCombatManeuver(Unit *pTarget)
{
    if (!pTarget || pTarget->isDead()) return;
    PlayerbotAI *ai = GetAI();
    if (!ai) return;
    Player *m_bot = GetPlayerBot();
    if (!m_bot || m_bot->isDead()) return;
    Unit *pVictim = pTarget->getVictim();
    Unit *m_tank = FindMainTankInRaid(GetMaster());
    if (!m_tank && m_bot->GetGroup() && GetMaster()->GetGroup() != m_bot->GetGroup()) { FindMainTankInRaid(m_bot); }
    if (!m_tank) { m_tank = m_bot; }
    uint32 masterHP = GetMaster()->GetHealth()*100 / GetMaster()->GetMaxHealth();
    float pDist = m_bot->GetDistance(pTarget);
    uint8 pThreat = GetThreatPercent(pTarget);

    uint8 reqHeal = 0;
    uint8 OwnPartyHP = GetHealthPercentRaid(m_bot, reqHeal);

    switch(ai->GetScenarioType())
    {
        case SCENARIO_DUEL:
            ((ai->GetHealthPercent() < 80 && CastSpell(LESSER_HEAL)) ||
            CastSpell(LIGHTNING_BOLT, pTarget));
            return;
    }

    // Cast CC breakers if any match found (include any dispels first)  does not work yet
    //uint32 ccSpells[4] = { R_ESCAPE_ARTIST, R_EVERY_MAN_FOR_HIMSELF, R_WILL_OF_FORSAKEN, R_STONEFORM };
    //if (ai->GetManaPercent() < 35) { ccSpells[0] = 0; ccSpells[1] = 0; } //We dont have any mana to waste...
    //if (castSelfCCBreakers(ccSpells)) {  } // Most of them don't trigger gcd


    #pragma region Choose Actions
    // Choose actions accoring to talents
    if (m_tank->GetGUID() == m_bot->GetGUID()) { m_role=BOT_ROLE_TANK; } // Hey! I am Main Tank
    else if (TALENT_ENHANCEMENT) { m_role = BOT_ROLE_DPS_MELEE; }
    else if (TALENT_ELEMENTAL) { m_role = BOT_ROLE_DPS_RANGED; }
    else if (TALENT_RESTO) { m_role = BOT_ROLE_SUPPORT; }
    else { m_role = BOT_ROLE_DPS_MELEE; } //Unknown build or low level.. Mainly attack

    // if i am under attack and if i am not tank or offtank: change target if needed
    if (m_tank->GetGUID() != m_bot->GetGUID() && isUnderAttack()  )
    {
            if (pVictim && pVictim->GetGUID() == m_bot->GetGUID() && pDist <= 2) {  } // My target is almost up to me, no need to search
            else //Have to select nearest target
            {
                Unit *curAtt = GetNearestAttackerOf(m_bot);
                if (curAtt && curAtt->GetGUID() != pTarget->GetGUID())
                {
                    m_bot->SetSelection(curAtt->GetGUID());
                    //ai->AddLootGUID(curAtt->GetGUID());
                    DoNextCombatManeuver(curAtt); //Restart new update to get variables fixed..
                    return;
                }
            }
            //my target is attacking me
    }
    #pragma endregion

    // Choose Weapon Enchant
    if (ChangeWeaponEnchants()) return;

	if (TALENT_ELEMENTAL){ if (!m_bot->HasAura(WATER_SHIELD) && CastSpell(WATER_SHIELD,m_bot)) { return; }}
	if (TALENT_ENHANCEMENT){ if (!m_bot->HasAura(LIGHTNING_SHIELD) && CastSpell(LIGHTNING_SHIELD,m_bot)) { return; }}
	if (TALENT_RESTO){ if (!m_bot->HasAura(WATER_SHIELD) && CastSpell(WATER_SHIELD,m_bot)) { return; }}
    // Choose shield
	/*
    if (EARTH_SHIELD && ai->GetHealthPercent() < 80 && isUnderAttack()) { if (CastSpell(EARTH_SHIELD,m_bot)) { return; } }
    else if (WATER_SHIELD && ai->GetManaPercent() < 40) { if (CastSpell(WATER_SHIELD,m_bot)) { return; } }
    else if (LIGHTNING_SHIELD &&
        ( isUnderAttack() || m_tank->GetGUID() == m_bot->GetGUID() )  && !(m_bot->HasAura(WATER_SHIELD) && ai->GetManaPercent() < 80)
        ) { if (CastSpell(LIGHTNING_SHIELD,m_bot)) { return; } }
    else if (CastSpell(WATER_SHIELD,m_bot)) { return; }
	*/
    // If there's a cast stop
    if(m_bot->HasUnitState(UNIT_STAT_CASTING)) return;

    switch(m_role)
    {
        #pragma region BOT_ROLE_TANK / BOT_ROLE_OFFTANK
        case BOT_ROLE_TANK:
        case BOT_ROLE_OFFTANK:
             if (!TALENT_ELEMENTAL && !TALENT_RESTO) { TakePosition(pTarget); }
            else { TakePosition(pTarget,BOT_ROLE_DPS_RANGED); } // mob will come to you sooner or later no need to hurry

            // Do support stuff
            if (!m_bot->isMoving() && ChangeTotems(m_role)) { return; }
            if (ai->GetManaPercent() > 70 && DoSupportRaid(m_bot)) { return; }

            break;
        #pragma endregion

        #pragma region BOT_ROLE_DPS_MELEE
        case BOT_ROLE_DPS_MELEE:
            TakePosition(pTarget);
            // Do support stuff
            if (!m_bot->isMoving() && ChangeTotems(m_role)) { return; }
            if (ai->GetManaPercent() > 40 && DoSupportRaid(m_bot)) { return; }
            break;
        #pragma endregion

        #pragma region BOT_ROLE_DPS_RANGED
        case BOT_ROLE_DPS_RANGED:
            TakePosition(pTarget);
            // Do support stuff
            if (!m_bot->isMoving() && ChangeTotems(m_role)) { return; }
            if (ai->GetManaPercent() > 40 && DoSupportRaid(m_bot)) { return; }
            break;
        #pragma endregion

        #pragma region BOT_ROLE_SUPPORT
        case BOT_ROLE_SUPPORT:
            TakePosition(pTarget);
            // Do support stuff
            if (!m_bot->isMoving() && ChangeTotems(m_role)) { return; }
            if (DoSupportRaid(m_bot)) { return; }
            //heal pets and bots
            Unit *target = DoSelectLowestHpFriendly(40, 1000);
            if(target && target->isAlive() && HealTarget(target, target->GetHealth()*100 / target->GetMaxHealth()) ) { return; }

            break;
        #pragma endregion
    }
    #pragma region ShamanCommon


    //Defensive Stuff
    if (m_tank->GetGUID() != m_bot->GetGUID() && pVictim && pVictim->GetGUID() == m_bot->GetGUID() )
    {
        if (pDist > 5 && CastSpell(FROST_SHOCK, pTarget)) { return; }
        if ((pTarget->GetCreatureType() == (uint32) CREATURE_TYPE_BEAST || pTarget->GetCreatureType() == (uint32) CREATURE_TYPE_HUMANOID) && CastSpell(HEX, pTarget)) { return; } // no gcd
        if (CastSpell(WIND_SHEAR, pTarget)) { } // no gcd
    }
    if (m_bot->getRace() == (uint8) RACE_BLOODELF && pDist < 8 && pTarget->IsNonMeleeSpellCasted(true) && CastSpell(R_ARCANE_TORRENT, pTarget)) { } //no gcd
    if (pTarget->IsNonMeleeSpellCasted(true) && CastSpell(WIND_SHEAR, pTarget)) { } //no gcd
    if (m_bot->getRace() == (uint8) RACE_TAUREN && pVictim && pVictim->GetGUID() == m_bot->GetGUID() && pDist < 8 && CastSpell(R_WAR_STOMP, pTarget)) { return; }

    //Catch
    if (pTarget->HasUnitMovementFlag(UNIT_FLAG_FLEEING))
    {
        if (CastSpell(FROST_SHOCK,pTarget)) return;
    }


    //Buff and restores
    if ( ( (ai->GetHealthPercent() < 60 && isUnderAttack()) ||
        (ai->GetManaPercent() < 30) ) && CastSpell(SHAMANISTIC_RAGE, m_bot)) { return; }
    if (m_bot->getRace() == (uint8) RACE_TROLL && CastSpell(R_BERSERKING,m_bot)) {} // no GCD
    if (m_bot->getRace() == (uint8) RACE_ORC && CastSpell(R_BLOOD_FURY,m_bot)) {} // no GCD
    if (!m_bot->HasAura(HEROISM) && !m_bot->HasAura(EXHAUSTION) && !m_bot->HasAura(SATED) && CastSpell(HEROISM,m_bot)) { return; }
    if (m_role != BOT_ROLE_SUPPORT && CastSpell(NATURES_SWIFTNESS, m_bot)) { } //healers keep it for healing no gcd
    else if (CastSpell(ELEMENTAL_MASTERY, m_bot)) { } //no gcd

    // If at threat limit, use WIND_SHEAR to reduce threat
    if (pThreat > threatThreshold && m_tank->GetGUID() != m_bot->GetGUID() && !isUnderAttack())
    {
        if (m_tank->getVictim() && m_tank->getVictim()->GetGUID() != pTarget->GetGUID()) // I am attacking wrong target!!
        {
            m_bot->SetSelection(m_tank->getVictim()->GetGUID());
            return;
        }
        else
        {
            if (CastSpell(WIND_SHEAR,pTarget)) { return; } //Lets see if we can manage
            else { return; } //use no spells and wait threat to be reduced
        }
    }


	if (TALENT_ELEMENTAL)
	{
		if (CastSpell(ELEMENTAL_MASTERY, m_bot)) { } //no gcd
		if (!pTarget->HasAura(FLAME_SHOCK,m_bot->GetGUID()) && CastSpell(FLAME_SHOCK,pTarget)) { return; }
		if (CastSpell(LAVA_BURST,pTarget)) { return; }
		if (CastSpell(CHAIN_LIGHTNING,pTarget)) { return; }
		if (CastSpell(LIGHTNING_BOLT,pTarget)) { return; }
	}

    //dps
    if (MAELSTROM_WEAPON)
    {
        Aura *maelaura = m_bot->GetAura(MAELSTROM_WEAPON);
        if (maelaura && maelaura->GetStackAmount() == 5)
        {
            if ((isUnderAttack(m_tank,3) || m_tank->GetGUID() == m_bot->GetGUID()) && CastSpell(CHAIN_LIGHTNING,pTarget,true,true)) { return; }
            if (CastSpell(LIGHTNING_BOLT,pTarget,true,true)) { return; }
        }
    }
	if (CastSpell(FLAME_SHOCK,pTarget)) { return; }
    if (CastSpell(STORMSTRIKE,pTarget,true,true)) { return; }

    //if (!TALENT_ENHANCEMENT && CanCast(LAVA_BURST,pTarget,true) && pTarget->HasAura(FLAME_SHOCK,m_bot->GetGUID()) && CastSpell(LAVA_BURST,pTarget,false)) { return; }
	if (CastSpell(FERAL_SPIRIT,m_bot)) { return; }
    if (CanCast(EARTH_SHOCK,pTarget,true) && (pTarget->HasAura(STORMSTRIKE,m_bot->GetGUID()) || pTarget->HasAura(FLAME_SHOCK,m_bot->GetGUID()) ) && CastSpell(EARTH_SHOCK,pTarget)) { return; }
    //if (CanCast(FLAME_SHOCK,pTarget) && CastSpell(FLAME_SHOCK,pTarget)) { return; }
	if (CastSpell(LAVA_LASH,pTarget,true,true)) { return; }
	if (CastSpell(FIRE_NOVA,pTarget)) { return; }
    //if ((isUnderAttack(m_tank,4) || m_tank->GetGUID() == m_bot->GetGUID()) && CastSpell(FIRE_NOVA,pTarget)) { return; }
    if (ai->GetManaPercent() > 60 && castDispel(PURGE,pTarget)) { return; } //PURGE but dont overpurge

    #pragma endregion


    // drink potion if support / healer (Other builds simply overuse mana and waste mana pots)
    if(ai->GetManaPercent() < 5 && (m_role == BOT_ROLE_SUPPORT || m_role == BOT_ROLE_HEALER) )
    {
        Item *pItem = ai->FindPotion();
        if(pItem != NULL)
        {
            if (pItem->GetSpell() && m_bot->HasSpellCooldown(pItem->GetSpell()) ) { return; } //pot is in cooldown
            ai->UseItem(*pItem);
        }
    }


} //end DoNextCombatManeuver
示例#15
0
CanCastResult BSWScriptedAI::_BSWSpellSelector(uint8 m_uiSpellIdx, Unit* pTarget)
{

    BSWRecord* pSpell = &m_BSWRecords[m_uiSpellIdx];

    Unit* pSummon = NULL;

    CanCastResult result = CAST_FAIL_OTHER;

    debug_log("BSW: Casting spell number %u type %u",pSpell->m_uiSpellEntry[currentDifficulty], pSpell->m_CastTarget);

        if (pSpell->m_uiSpellTimerMax[currentDifficulty] >= HOUR*IN_MILLISECONDS)
            m_creature->InterruptNonMeleeSpells(true);

        switch (pSpell->m_CastTarget) {

            case DO_NOTHING:
                   result = CAST_OK;
                   break;

            case CAST_ON_SELF:
                   result = _BSWCastOnTarget(m_creature, m_uiSpellIdx);
                   break;

            case CAST_ON_SUMMONS:
                   result = _BSWCastOnTarget(pTarget, m_uiSpellIdx);
                   break;

            case CAST_ON_VICTIM:
                   pTarget = m_creature->getVictim();
                   result = _BSWCastOnTarget(pTarget, m_uiSpellIdx);
                   break;

            case CAST_ON_RANDOM:
                   pTarget = _doSelect(0, false, 60.0f);
                   result = _BSWCastOnTarget(pTarget, m_uiSpellIdx);
                   break;

            case CAST_ON_BOTTOMAGGRO:
                   pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_BOTTOMAGGRO,0);
                   result = _BSWCastOnTarget(pTarget, m_uiSpellIdx);
                   break;

            case CAST_ON_TARGET:
                   result = _BSWCastOnTarget(pTarget, m_uiSpellIdx);
                   break;

            case APPLY_AURA_SELF:
                       if (_doAura(m_uiSpellIdx, m_creature, EFFECT_INDEX_0))
                           result = CAST_OK;
                       else result = CAST_FAIL_OTHER;
                   break;

            case APPLY_AURA_TARGET:
                   if (!pTarget || !pTarget->IsInMap(m_creature))
                   {
                       result = CAST_FAIL_OTHER;
                       break;
                   }
                   if (_doAura(m_uiSpellIdx, pTarget, EFFECT_INDEX_0))
                       result = CAST_OK;
                   else result = CAST_FAIL_OTHER;
                   break;

            case SUMMON_NORMAL:
                   pSummon = _doSummon(m_uiSpellIdx, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000);
                   if(pSummon) result = CAST_OK;
                       else result = CAST_FAIL_OTHER;
                   break;

            case SUMMON_TEMP:
                   pSummon = _doSummon(m_uiSpellIdx, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,
                                        urand(pSpell->m_uiSpellTimerMin[currentDifficulty],pSpell->m_uiSpellTimerMax[currentDifficulty]));
                   if(pSummon) result = CAST_OK;
                       else result = CAST_FAIL_OTHER;
                   break;

            case SUMMON_INSTANT:
                   pSummon = _doSummon(m_uiSpellIdx, TEMPSUMMON_MANUAL_DESPAWN,0);
                   if(pSummon) result = CAST_OK;
                       else result = CAST_FAIL_OTHER;
                   break;

            case CAST_ON_ALLPLAYERS:
                   {
                       Map* pMap = m_creature->GetMap();
                       Map::PlayerList const& pPlayers = pMap->GetPlayers();
                       if (!pPlayers.isEmpty())
                       {
                           for (Map::PlayerList::const_iterator itr = pPlayers.begin(); itr != pPlayers.end(); ++itr)
                           {
                               pTarget = itr->getSource();
                               if (pTarget && pTarget->isAlive() && pTarget->IsWithinDistInMap(m_creature, pSpell->LocData.x))
                               {
                                   if (!pSpell->m_IsBugged)
                                   {
                                       m_creature->CastSpell(pTarget, pSpell->m_uiSpellEntry[currentDifficulty], false);
                                   }
                                   else
                                   {
                                       _BSWDoCast(m_uiSpellIdx, pTarget);
                                   };
                               result = CAST_OK;
                               };
                           }
                       } else result = CAST_FAIL_OTHER;
                   }
                   break;

            case CAST_ON_FRENDLY:
                   pTarget = DoSelectLowestHpFriendly(pSpell->LocData.x,0);
                   result = _BSWCastOnTarget(pTarget, m_uiSpellIdx);
                   break;

            case CAST_ON_FRENDLY_LOWHP:
                   pTarget = DoSelectLowestHpFriendly(pSpell->LocData.x,1);
                   result = _BSWCastOnTarget(pTarget, m_uiSpellIdx);
                   break;

            case CAST_ON_RANDOM_POINT:
                   if (!pTarget) pTarget = m_creature;
                   if (pSpell->LocData.z <= 1.0f)
                   {
                         float fPosX, fPosY, fPosZ;
                         if (!pTarget->IsPositionValid() || !pTarget->IsInMap(m_creature))
                         {
                             if (pTarget->GetTypeId() == TYPEID_PLAYER)
                                 error_log("BSW: CAST_ON_RANDOM_POINT FAILED: player has invalid position. SpellID is %u",pSpell->m_uiSpellEntry[currentDifficulty]);
                             else error_log("BSW: CAST_ON_RANDOM_POINT FAILED: creature has invalid position. SpellID is %u",pSpell->m_uiSpellEntry[currentDifficulty]);
                             result = CAST_FAIL_OTHER;
                             break;
                         }

                         pTarget->GetPosition(fPosX, fPosY, fPosZ);
                         pTarget->GetRandomPoint(fPosX, fPosY, fPosZ, urand((uint32)pSpell->LocData.x, (uint32)pSpell->LocData.y), fPosX, fPosY, fPosZ);
                         if ((int)fPosZ == 0)
                         {
                             error_log("BSW: CAST_ON_RANDOM_POINT FAILED: Positon Z is NULL. Strange bug");
                             result = CAST_FAIL_OTHER;
                             break;
                         }

                         if (SpellEntry const *spell = (SpellEntry *)GetSpellStore()->LookupEntry(pSpell->m_uiSpellEntry[currentDifficulty]))
                           if (SpellRangeEntry const *pSpellRange = GetSpellRangeStore()->LookupEntry(spell->rangeIndex))
                              if (m_creature->GetDistance(fPosX, fPosY, fPosZ) <= pSpellRange->maxRange)
                              {
                                   m_creature->CastSpell(fPosX, fPosY, fPosZ, pSpell->m_uiSpellEntry[currentDifficulty], false);
                                   result = CAST_OK;
                                   break;
                               };
                         result = CAST_FAIL_TOO_FAR;
                   } else  result = CAST_FAIL_OTHER;
                   break;

            case CAST_ON_RANDOM_PLAYER:
                   if ( pSpell->LocData.x < 1 ) pTarget = _doSelect(0, false, 60.0f);
                       else pTarget = _doSelect(0, false, (float)pSpell->LocData.x);
                   result = _BSWCastOnTarget(pTarget, m_uiSpellIdx);
                   break;

            case APPLY_AURA_ALLPLAYERS:
                   {
                       Map* pMap = m_creature->GetMap();
                       Map::PlayerList const& pPlayers = pMap->GetPlayers();
                       for (Map::PlayerList::const_iterator itr = pPlayers.begin(); itr != pPlayers.end(); ++itr)
                       {
                           pTarget = itr->getSource();
                           if (pTarget && pTarget->isAlive() && pTarget->IsWithinDistInMap(m_creature, pSpell->LocData.x))
                           {
                               _doAura(m_uiSpellIdx, pTarget, EFFECT_INDEX_0);
                               result = CAST_OK;
                           }
                       }
                   }
                   break;

            case FORCE_CAST:
                   result = _BSWDoForceCast(m_uiSpellIdx, pTarget);
                   break;

            case SPELLTABLEPARM_NUMBER:
            default:
                   error_log("BSW: FAILED casting spell number %u type %u - type not exists",pSpell->m_uiSpellEntry[currentDifficulty], pSpell->m_CastTarget);
                   result = CAST_FAIL_OTHER;
                   break;
            };

        if (pSpell->textEntry && result == CAST_OK)
        {
            if (pTarget)
                DoScriptText(pSpell->textEntry,m_creature,pTarget);
            else
                DoScriptText(pSpell->textEntry,m_creature);
        };

    debug_log("BSW: Casted spell number %u, result = %u",pSpell->m_uiSpellEntry[currentDifficulty], result);

    return result;
};
void PlayerbotPaladinAI::DoNextCombatManeuver(Unit *pTarget)
{
    if (!pTarget || pTarget->isDead()) return;
    PlayerbotAI *ai = GetAI();
    if (!ai) return;
    Player *m_bot = GetPlayerBot();
    if (!m_bot || m_bot->isDead()) return;
    Unit *pVictim = pTarget->getVictim();
    Unit *m_tank = FindMainTankInRaid(GetMaster());
    if (!m_tank && m_bot->GetGroup() && GetMaster()->GetGroup() != m_bot->GetGroup()) { FindMainTankInRaid(m_bot); }
    if (!m_tank) { m_tank = m_bot; }
    uint32 masterHP = GetMaster()->GetHealth()*100 / GetMaster()->GetMaxHealth();
    float pDist = m_bot->GetDistance(pTarget);
    uint8 pThreat = GetThreatPercent(pTarget);

    uint8 reqHeal = 0;
    uint8 OwnPartyHP = GetHealthPercentRaid(m_bot, reqHeal);


    // Fill mana if needed
    if (m_bot->getRace() == (uint8) RACE_BLOODELF && pDist < 8 && ai->GetManaPercent() < 20 && CastSpell(R_ARCANE_TORRENT, pTarget)) { } //no gcd
    if (ai->GetManaPercent() < 30 && CastSpell (DIVINE_PLEA, m_bot)) { return; }

    // If hp is too low divine shield
    if (ai->GetHealthPercent() < 20 && (!m_bot->HasAura(DIVINE_SHIELD) || !m_bot->HasAura(HOP) || !m_bot->HasAura(SACRED_SHIELD)))
    {
        if (!m_bot->HasAura(FORBEARANCE))
        {
            if (CastSpell(DIVINE_SHIELD,m_bot)) { return; }
            if (CastSpell(HOP,m_bot)) { return; }
        }
        else if (CastSpell(SACRED_SHIELD,m_bot)) { return; }
    }

    // if i am under attack and if i am not tank or offtank: change target if needed
    if (m_tank->GetGUID() != m_bot->GetGUID() && !TALENT_PROT && isUnderAttack() )
    {
        // Keep hitting but reduce threat
        if (CastSpell(HOS,m_bot,true,true)) { }
        //else if (m_bot->getRace() == (uint8) RACE_NIGHTELF && CastSpell(R_SHADOWMELD,m_bot)) { return; }
        else //I cannot reduce threat so
        {
            if (pVictim && pVictim->GetGUID() == m_bot->GetGUID() && pDist <= 2) {  } // My target is almost up to me, no need to search
            else //Have to select nearest target
            {
                Unit *curAtt = GetNearestAttackerOf(m_bot);
                if (curAtt && curAtt->GetGUID() != pTarget->GetGUID())
                {
                    m_bot->SetSelection(curAtt->GetGUID());
                    //ai->AddLootGUID(curAtt->GetGUID());
                    DoNextCombatManeuver(curAtt); //Restart new update to get variables fixed..
                    return;
                }
            }
            //my target is attacking me
        }
    }


    #pragma region Choose Actions
    // Choose actions accoring to talents
    if (m_tank->GetGUID() == m_bot->GetGUID()) // Hey! I am Main Tank
    {
        if (TALENT_PROT) { m_role=BOT_ROLE_TANK; } //Just Keep Tanking
        else
        {
            if (TALENT_RETRI) {
                if ((ai->GetHealthPercent() <= 40 || masterHP <40 ) && (ai->GetManaPercent() >= 40)) { m_role = BOT_ROLE_SUPPORT; }
                else if (OwnPartyHP < 40 && ai->GetManaPercent() >= 30) { m_role = BOT_ROLE_SUPPORT; }
                else { m_role = BOT_ROLE_TANK; } //have no shield but can tank if you think so
            }
            else if (TALENT_HOLY) //I am both healer and tank?? Hmm
            {
                if ((ai->GetHealthPercent() <= 70 || masterHP <70 ) && (ai->GetManaPercent() >= 50))m_role = BOT_ROLE_SUPPORT;
                else if (OwnPartyHP < 20 && ai->GetManaPercent() >= 30) { m_role = BOT_ROLE_SUPPORT; }
                else m_role = BOT_ROLE_TANK;
            }
            else { m_role = BOT_ROLE_TANK; } //Unknown build or low level
        }
    }
    else if (TALENT_RETRI) {
        if ((ai->GetHealthPercent() <= 40 || masterHP <40 ) && (ai->GetManaPercent() >= 40)) { m_role = BOT_ROLE_SUPPORT; }
        else if (OwnPartyHP < 40 && ai->GetManaPercent() >= 30) {m_role = BOT_ROLE_SUPPORT;}
        else { m_role = BOT_ROLE_DPS_MELEE; }
    }
    else if (TALENT_PROT) {
        if ((ai->GetHealthPercent() <= 30 || masterHP <40 ) && (ai->GetManaPercent() >= 20)) { m_role = BOT_ROLE_SUPPORT; }
        else if (OwnPartyHP < 40 && ai->GetManaPercent() >= 40) { m_role = BOT_ROLE_SUPPORT; }
        else { m_role = BOT_ROLE_OFFTANK; }
    }
    else if (TALENT_HOLY) { m_role = BOT_ROLE_SUPPORT; }
    else { m_role = BOT_ROLE_DPS_MELEE; } //Unknown build or low level.. Mainly attack

	//takepos
    if (m_role == BOT_ROLE_SUPPORT || m_role == BOT_ROLE_HEALER) TakePosition(pTarget,BOT_ROLE_DPS_MELEE,0.5f);
    else TakePosition(pTarget,m_role);

    // If there's a cast stop
    if(m_bot->HasUnitState(UNIT_STATE_CASTING)) return;

    Unit *target = DoSelectLowestHpFriendly(40, 1000);
    switch(m_role)
    {
        #pragma region BOT_ROLE_SUPPORT
        case BOT_ROLE_SUPPORT:

            ChangeAura(CONCENTRATION_AURA);
            if (!TALENT_PROT && m_tank->GetGUID() != m_bot->GetGUID()) m_bot->RemoveAurasDueToSpell(RIGHTEOUS_FURY);
            // Choose Seal
            if (SOW && ai->GetManaPercent() <= 30) {    if (CastSpell(SOW,m_bot)) { return; } }
            else if (m_bot->HasAura(SOW) && ai->GetManaPercent() < 85) { } // Paladin was striving for mana, keep until he got most of his mana back
            else if(SOL && ai->GetHealthPercent() < 40) { if(CastSpell(SOL,m_bot)) { return; } }
            else if(CastSpell(SOR, m_bot)) { return; }

            if (!m_bot->HasAura(FORBEARANCE) && CastSpell(AVENGING_WRATH,m_bot)) { } // no gcd

            if (DoSupportRaid(m_bot)) { return; }
            //heal pets and bots
            if(target && target->isAlive() && HealTarget(target, target->GetHealth()*100 / target->GetMaxHealth()) ) { return; }

            if (ai->GetManaPercent() <= 80 && CastSpell(JOW,pTarget,true,true)) { return; }

            // Use Spells only if mana is sufficient..
            if(ai->GetManaPercent() < offensiveSpellThreshold ) return;

        break;
        #pragma endregion

        #pragma region BOT_ROLE_TANK / BOT_ROLE_OFFTANK
        case BOT_ROLE_TANK:
        case BOT_ROLE_OFFTANK:

            ChangeAura(DEVOTION_AURA);
            if (CastSpell(RIGHTEOUS_FURY,m_bot)) { return; }
            // Choose Seal
            if (SOW && ai->GetManaPercent() <= 30) { if (CastSpell(SOW,m_bot)) { return; } }
            else if (m_bot->HasAura(SOW) && ai->GetManaPercent() < 85) { } // Paladin was striving for mana, keep until he got most of his mana back
            else if (SOL && ai->GetHealthPercent() < 40) { if (CastSpell(SOL,m_bot)) { return; } }
            else if (CastSpell(SOR,m_bot)) { return; }

            // We are tank/offtank threat is not an issiue;
            // Use taunts only if helping target is not main tank..
            // Taunt if needed (Only for master)
            if(GetMaster()->GetGUID() != m_tank->GetGUID())
            {
                // Taunt if needed (Only for master)
                Unit *curAtt = GetAttackerOf(GetMaster());
                if (curAtt)
                {
                    if (isUnderAttack(GetMaster(),2) && CastSpell(RIGHTEOUS_DEFENSE, GetMaster())) { return; }
                    if (CastSpell(HOR, curAtt,true,true))  { } //No GCD
                }
            }
            // My target is not attacking me, taunt..
            if ( m_tank->GetGUID() == m_bot->GetGUID() && pVictim && pVictim->GetGUID() != m_bot->GetGUID() && CastSpell(HOR, pTarget,true,true) )  { } //NO GCD

            // Tank specials
            if (TALENT_PROT && ai->GetManaPercent() < 90 && CastSpell (DIVINE_PLEA, m_bot)) { return; } //Prot paladin always uses this..
            if (pVictim && pVictim->GetGUID() == m_bot->GetGUID() && CastSpell(HOLY_SHIELD,m_bot)) { return; }
            if (CastSpell(AVENGERS_SHIELD,pTarget,true,true)) { return; }
            if (CastSpell(HOTR,pTarget,true,true)) { return; }
            if (CastSpell(HOLY_WRATH,pTarget,true,true)){ return; }
            if (CastSpell(CONSECRATION,pTarget)) { return; }
            if (m_bot->getRace() == (uint8) RACE_DWARF && CastSpell(R_STONEFORM,m_bot)) { return; }

            if (DoSupportRaid(m_bot)) { return; }
            //heal pets and bots
            if(target && target->isAlive() && HealTarget(target, target->GetHealth()*100 / target->GetMaxHealth()) ) { return; }


        break;
		#pragma endregion

		#pragma region BOT_ROLE_DPS_MELEE
		case BOT_ROLE_DPS_MELEE:

			ChangeAura(RETRIBUTION_AURA);
			if (!TALENT_PROT && m_tank->GetGUID() != m_bot->GetGUID()) m_bot->RemoveAurasDueToSpell(RIGHTEOUS_FURY);
			if (CastSpell(SOV,m_bot)) { return; }

			if (CastSpell (HAMMER_OF_JUSTICE, pTarget)) { return; }
			if (!m_bot->HasAura(FORBEARANCE) && CastSpell(AVENGING_WRATH,m_bot)) {} //no gcd
			if (CastSpell(JOW,pTarget)) { return; }
			if (CastSpell(DIVINE_STORM, pTarget)) { return; }
			if (CastSpell(CRUSADER_STRIKE, pTarget)) { return; }
			if (GetAI()->GetHealthPercent(*pTarget)<20 && CastSpell(HAMMER_OF_WRATH, pTarget)) { return; }
			if (CastSpell(CONSECRATION,pTarget)) { return; }
			if (m_bot->HasAura(AOW) && CastSpell(EXORCISM,pTarget)) { return; }
			if (CastSpell(HOLY_WRATH,pTarget)) { return; }

		break;
        #pragma endregion

    }
    #pragma region PaladinCommon
    // Shared dps spells
    if (pTarget->GetCreatureType() == (uint32) CREATURE_TYPE_HUMANOID && pTarget->IsNonMeleeSpellCasted(true) && CastSpell (REPENTANCE, pTarget)) { return; }
    if (m_bot->getRace() == (uint8) RACE_BLOODELF && pDist < 8 && pTarget->IsNonMeleeSpellCasted(true) && CastSpell(R_ARCANE_TORRENT, pTarget)) { } //no gcd
    if (m_bot->getRace() == (uint8) RACE_TROLL && CastSpell(R_BERSERKING,m_bot)) {} // no GCD
    if (m_bot->getRace() == (uint8) RACE_ORC && CastSpell(R_BLOOD_FURY,m_bot)) {} // no GCD

    // If at threat limit, stop
    if(pThreat > threatThreshold && !TALENT_PROT && m_tank->GetGUID() != m_bot->GetGUID() && !isUnderAttack())
    {
        if (m_tank->getVictim() && m_tank->getVictim()->GetGUID() != pTarget->GetGUID()) // I am attacking wrong target!!
        {
            m_bot->SetSelection(m_tank->getVictim()->GetGUID());
            return;
        }
        else
        {
            if (CastSpell(HOS,m_bot)) { return; } //Lets see if we can manage with HOS
            else { return; } //use no spells and wait threat to be reduced
        }
    }
    // Continue attacking if theres excess mana (for healers)
    if (m_role == BOT_ROLE_SUPPORT && ai->GetManaPercent() < offensiveSpellThreshold) { return; }

    if (GetAI()->GetHealthPercent(*pTarget)<20 && CastSpell(HAMMER_OF_WRATH, pTarget,true,true)) { return; } //no gcd but cast
    if (CastSpell (HAMMER_OF_JUSTICE, pTarget)) { return; }
    if (CanCast(JOW,pTarget,true) &&
        ( ( ai->GetManaPercent() <= 70 && ai->GetHealthPercent() > 90)
        || ( ai->GetManaPercent() <= 50 && ai->GetHealthPercent() > 75)
        || ( ai->GetManaPercent() <= 20 && ai->GetHealthPercent() > 20) )
        && CastSpell(JOW,pTarget,false)) { return; }
    else if (CastSpell(JOL,pTarget),true,true) { return; }
    if (CastSpell(SHIELD_OF_RIGHTEOUSNESS,pTarget,true,true)) { return; }
    if (CastSpell (DIVINE_STORM, pTarget,true,true)) { return; }
    if (CastSpell (CRUSADER_STRIKE, pTarget,true,true)) { return; }
    if (m_bot->getRace() == (uint8) RACE_TAUREN && pDist < 8 && CastSpell(R_WAR_STOMP, pTarget)) { return; } //no GCD but cast
    if (isUnderAttack(m_tank,4) && CastSpell(HOLY_WRATH,pTarget,true,true)) { return; }
    if (isUnderAttack(m_tank,4) && CastSpell(CONSECRATION,pTarget)) { return; }
    if (CastSpell(HOLY_SHOCK,pTarget,true,true)) { return; }
    if (m_role != BOT_ROLE_SUPPORT && ai->GetManaPercent() > 60 && OwnPartyHP < 65 && DoSupportRaid(m_bot)) { return; } //if there is spare time and mana, do healz and other stuff..
    else if (m_role != BOT_ROLE_SUPPORT && ai->GetManaPercent() > 30 && DoSupportRaid(m_bot,30,false,false,false,true,false)) { return; }
    if (CastSpell(EXORCISM,pTarget,true,true)) { return; }


    // drink potion if support / healer (Other builds simply overuse mana and waste mana pots)
    if(ai->GetManaPercent() < 5 && (m_role == BOT_ROLE_SUPPORT || m_role == BOT_ROLE_HEALER) )
    {
        Item *pItem = ai->FindPotion();
        if(pItem != NULL)
        {
            if (pItem->GetSpell() && m_bot->HasSpellCooldown(pItem->GetSpell()) ) { return; } //pot is in cooldown
            ai->UseItem(*pItem);
        }
    }
    #pragma endregion

} //end DoNextCombatManeuver
示例#17
0
    void UpdateAI(const uint32 uiDiff) override
    {
        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        if (m_uiBlessingTimer < uiDiff)
        {
            if (Unit* pTarget = DoSelectLowestHpFriendly(80.0f))
            {
                if (DoCastSpellIfCan(pTarget, urand(0, 1) ? SPELL_BLESS_SPELLWARD : SPELL_BLESS_PROTECTION) == CAST_OK)
                    m_uiBlessingTimer = 60000;
            }
        }
        else
            m_uiBlessingTimer -= uiDiff;

        if (m_uiConsecrationTimer < uiDiff)
        {
            if (DoCastSpellIfCan(m_creature, SPELL_CONSECRATION) == CAST_OK)
                m_uiConsecrationTimer = urand(10000, 15000);
        }
        else
            m_uiConsecrationTimer -= uiDiff;

        if (m_uiHammerOfJusticeTimer < uiDiff)
        {
            if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, SPELL_HAMMER_OF_JUSTICE, SELECT_FLAG_PLAYER | SELECT_FLAG_NOT_IN_MELEE_RANGE))
            {
                if (DoCastSpellIfCan(pTarget, SPELL_HAMMER_OF_JUSTICE) == CAST_OK)
                    m_uiHammerOfJusticeTimer = 20000;
            }
        }
        else
            m_uiHammerOfJusticeTimer -= uiDiff;

        if (m_uiSealTimer < uiDiff)
        {
            if (DoCastSpellIfCan(m_creature, urand(0, 1) ? SPELL_SEAL_OF_COMMAND : SPELL_SEAL_OF_BLOOD) == CAST_OK)
            {
                m_uiSealTimer = 40000;

                if (urand(0, 1))
                    m_uiJudgmentTimer = urand(4000, 7000);
            }
        }
        else
            m_uiSealTimer -= uiDiff;

        if (m_uiAuraTimer < uiDiff)
        {
            if (DoCastSpellIfCan(m_creature, urand(0, 1) ? SPELL_DEVOTION_AURA : SPELL_CHROMATIC_AURA) == CAST_OK)
                m_uiAuraTimer = 90000;
        }
        else
            m_uiAuraTimer -= uiDiff;

        if (m_uiJudgmentTimer)
        {
            if (m_uiJudgmentTimer <= uiDiff)
            {
                if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_JUDGMENT) == CAST_OK)
                    m_uiJudgmentTimer = 0;
            }
            else
                m_uiJudgmentTimer -= uiDiff;
        }

        DoMeleeAttackIfReady();
    }
示例#18
0
    void UpdateAI(const uint32 uiDiff) override
    {
        // spawn Romulo on timer after fake death
        if (m_uiSummonRomuloTimer)
        {
            if (m_uiSummonRomuloTimer <= uiDiff)
            {
                m_creature->SummonCreature(NPC_ROMULO, afRomuloSpawnLoc[0], afRomuloSpawnLoc[1], afRomuloSpawnLoc[2], afRomuloSpawnLoc[3], TEMPSUMMON_DEAD_DESPAWN, 0);
                m_uiSummonRomuloTimer = 0;
            }
            else
                m_uiSummonRomuloTimer -= uiDiff;
        }

        if (m_uiResurrectSelfTimer)
        {
            if (m_uiResurrectSelfTimer <= uiDiff)
            {
                if (m_pInstance)
                {
                    if (Creature* pRomulo = m_pInstance->GetSingleCreatureFromStorage(NPC_ROMULO))
                    {
                        // if Romulos is dead, then self kill
                        if (pRomulo->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
                        {
                            m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false);
                            pRomulo->DealDamage(pRomulo, pRomulo->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false);
                        }
                        else
                        {
                            DoRemoveFakeDeath();
                            DoCastSpellIfCan(m_creature, SPELL_FULL_HEALTH, CAST_TRIGGERED);
                        }
                    }
                }
                m_uiResurrectSelfTimer = 0;
            }
            else
                m_uiResurrectSelfTimer -= uiDiff;
        }

        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        // don't use spells during transition
        if (m_bIsFakingDeath)
            return;

        if (m_uiBlindingPassionTimer < uiDiff)
        {
            if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
            {
                if (DoCastSpellIfCan(pTarget, SPELL_BLINDING_PASSION) == CAST_OK)
                    m_uiBlindingPassionTimer = urand(30000, 45000);
            }
        }
        else
            m_uiBlindingPassionTimer -= uiDiff;

        if (m_uiDevotionTimer < uiDiff)
        {
            if (DoCastSpellIfCan(m_creature, SPELL_DEVOTION) == CAST_OK)
                m_uiDevotionTimer = urand(15000, 45000);
        }
        else
            m_uiDevotionTimer -= uiDiff;

        if (m_uiPowerfulAttractionTimer < uiDiff)
        {
            if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
            {
                if (DoCastSpellIfCan(pTarget, SPELL_POWERFUL_ATTRACTION) == CAST_OK)
                    m_uiPowerfulAttractionTimer = urand(5000, 30000);
            }
        }
        else
            m_uiPowerfulAttractionTimer -= uiDiff;

        if (m_uiEternalAffectionTimer < uiDiff)
        {
            if (Unit* pTarget = DoSelectLowestHpFriendly(30.0f))
            {
                if (DoCastSpellIfCan(pTarget, SPELL_ETERNAL_AFFECTION) == CAST_OK)
                    m_uiEternalAffectionTimer = urand(45000, 60000);
            }
        }
        else
            m_uiEternalAffectionTimer -= uiDiff;

        DoMeleeAttackIfReady();
    }
        void UpdateAI(const uint32 diff)
        {
            if (isInMountedGauntlet())
            {
                npc_mounted_championAI::UpdateAI(diff);
                return;
            }

            if (!UpdateVictim())
                return;

            if(defeated)
                return;

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

            if (chainLightningTimer <= diff)
            {
                if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
                    DoCast(target, SPELL_CHAIN_LIGHTNING);

                chainLightningTimer = 8000;
            } else chainLightningTimer -= diff;

            if (healingWaveTimer <= diff)
            {
                bool chance = urand(0, 1);

                if(!chance)
                {
                    if (Unit* friendUnit = DoSelectLowestHpFriendly(40))
                    {
                        DoCast(friendUnit, SPELL_HEALING_WAVE);
                        healingWaveTimer = 5000;
                    }
                }else
                {
                    DoCast(me, SPELL_HEALING_WAVE);
                    healingWaveTimer = 8000;
                }
            } else healingWaveTimer -= diff;

            if (eartShieldTimer <= diff)
            {
                Unit* friendUnit = DoSelectLowestHpFriendly(40);

                if (friendUnit && friendUnit->HealthBelowPct(60) && !friendUnit->HasAura(SPELL_EARTH_SHIELD))
                {
                    DoCast(friendUnit, SPELL_EARTH_SHIELD);
                    eartShieldTimer = urand(30000, 35000);
                }else if(!me->HasAura(SPELL_EARTH_SHIELD))
                {
                    DoCast(me, SPELL_EARTH_SHIELD);
                    eartShieldTimer = urand(30000, 35000);
                } else eartShieldTimer = urand(1500, 3500);
            } else eartShieldTimer -= diff;

            if (hexMendingTimer <= diff)
            {
                DoCastVictim(SPELL_HEX_OF_MENDING, true);

                hexMendingTimer = urand(12000, 15000);
            } else hexMendingTimer -= diff;

            DoMeleeAttackIfReady();
        }
示例#20
0
        void UpdateAI(const uint32 uiDiff)
        {
            if (!bDone && GrandChampionsOutVehicle(me))
            {
                bDone = true;

                if (instance && me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_1))
                    me->SetHomePosition(739.678f, 662.541f, 412.393f, 4.49f);
                else if (instance && me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_2))
                    me->SetHomePosition(746.71f, 661.02f, 411.69f, 4.6f);
                else if (instance && me->GetGUID() == instance->GetData64(DATA_GRAND_CHAMPION_3))
                    me->SetHomePosition(754.34f, 660.70f, 412.39f, 4.79f);

                if (instance)
                    instance->SetData(BOSS_GRAND_CHAMPIONS, IN_PROGRESS);

                EnterEvadeMode();
                bHome = true;
            }

            if (uiPhaseTimer <= uiDiff)
            {
                if (uiPhase == 1)
                {
                    AggroAllPlayers(me);
                    uiPhase = 0;
                }
            }else uiPhaseTimer -= uiDiff;

            if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT))
                return;

            if (uiChainLightningTimer <= uiDiff)
            {
                if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
                    DoCast(target, SPELL_CHAIN_LIGHTNING);

                uiChainLightningTimer = 16000;
            } else uiChainLightningTimer -= uiDiff;

            if (uiHealingWaveTimer <= uiDiff)
            {
                bool bChance = urand(0, 1);

                if (!bChance)
                {
                    if (Unit* pFriend = DoSelectLowestHpFriendly(40))
                        DoCast(pFriend, SPELL_HEALING_WAVE);
                } else
                    DoCast(me, SPELL_HEALING_WAVE);

                uiHealingWaveTimer = 12000;
            } else uiHealingWaveTimer -= uiDiff;

            if (uiEartShieldTimer <= uiDiff)
            {
                DoCast(me, SPELL_EARTH_SHIELD);

                uiEartShieldTimer = urand(30000, 35000);
            } else uiEartShieldTimer -= uiDiff;

            if (uiHexMendingTimer <= uiDiff)
            {
                DoCastVictim(SPELL_HEX_OF_MENDING, true);

                uiHexMendingTimer = urand(20000, 25000);
            } else uiHexMendingTimer -= uiDiff;

            DoMeleeAttackIfReady();
        }
示例#21
0
    void UpdateEscortAI(const uint32 uiDiff) override
    {
        DialogueUpdate(uiDiff);

        if (m_uiOutroTimer)
        {
            if (m_uiOutroTimer <= uiDiff)
            {
                switch (m_uiOutroPhase)
                {
                    case 0:
                        DoScriptText(SAY_REMULOS_OUTRO_1, m_creature);
                        m_uiOutroTimer = 3000;
                        break;
                    case 1:
                        // Despawn Remulos after the outro is finished - he will respawn automatically at his home position after a few min
                        DoScriptText(SAY_REMULOS_OUTRO_2, m_creature);
                        m_creature->SetRespawnDelay(1 * MINUTE);
                        m_creature->ForcedDespawn(3000);
                        m_uiOutroTimer = 0;
                        break;
                }
                ++m_uiOutroPhase;
            }
            else
                m_uiOutroTimer -= uiDiff;
        }

        // during the battle
        if (m_uiShadesummonTimer)
        {
            if (m_uiShadesummonTimer <= uiDiff)
            {
                // do this yell only first time
                if (m_bIsFirstWave)
                {
                    // summon 3 shades inside the house
                    for (uint8 i = 0; i < MAX_SHADOWS; ++i)
                        m_creature->SummonCreature(NPC_NIGHTMARE_PHANTASM, aShadowsLocations[i].m_fX, aShadowsLocations[i].m_fY, aShadowsLocations[i].m_fZ, 0, TEMPSPAWN_DEAD_DESPAWN, 0);

                    if (Creature* pEranikus = m_creature->GetMap()->GetCreature(m_eranikusGuid))
                        DoScriptText(SAY_ERANIKUS_ATTACK_1, pEranikus);

                    ++m_uiSummonCount;
                    SetEscortPaused(false);
                    m_bIsFirstWave = false;
                }

                // Summon 3 shades per turn until the maximum summon turns are reached
                float fX, fY, fZ;
                // Randomize the summon point
                uint8 uiSummonPoint = roll_chance_i(70) ? uint32(MAX_SHADOWS) : urand(MAX_SHADOWS + 1, MAX_SHADOWS + 2);

                if (m_uiSummonCount < MAX_SUMMON_TURNS)
                {
                    for (uint8 i = 0; i < MAX_SHADOWS; ++i)
                    {
                        m_creature->GetRandomPoint(aShadowsLocations[uiSummonPoint].m_fX, aShadowsLocations[uiSummonPoint].m_fY, aShadowsLocations[uiSummonPoint].m_fZ, 10.0f, fX, fY, fZ);
                        m_creature->SummonCreature(NPC_NIGHTMARE_PHANTASM, fX, fY, fZ, 0.0f, TEMPSPAWN_DEAD_DESPAWN, 0);
                    }

                    ++m_uiSummonCount;
                }

                // If all the shades were summoned then set Eranikus in combat
                // We don't count the dead shades, because the boss is usually set in combat before all shades are dead
                if (m_uiSummonCount == MAX_SUMMON_TURNS)
                {
                    m_uiShadesummonTimer = 0;

                    if (Creature* pEranikus = m_creature->GetMap()->GetCreature(m_eranikusGuid))
                    {
                        pEranikus->SetByteFlag(UNIT_FIELD_BYTES_1, 3, 0);
                        pEranikus->SetLevitate(false);
                        pEranikus->GetMotionMaster()->MovePoint(POINT_ID_ERANIKUS_COMBAT, aEranikusLocations[2].m_fX, aEranikusLocations[2].m_fY, aEranikusLocations[2].m_fZ);
                    }
                }
                else
                    m_uiShadesummonTimer = urand(20000, 30000);
            }
            else
                m_uiShadesummonTimer -= uiDiff;
        }

        // Combat spells
        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        if (m_uiHealTimer < uiDiff)
        {
            if (Unit* pTarget = DoSelectLowestHpFriendly(DEFAULT_VISIBILITY_DISTANCE))
            {
                switch (urand(0, 2))
                {
                    case 0: DoCastSpellIfCan(pTarget, SPELL_HEALING_TOUCH); break;
                    case 1: DoCastSpellIfCan(pTarget, SPELL_REJUVENATION);  break;
                    case 2: DoCastSpellIfCan(pTarget, SPELL_REGROWTH);      break;
                }
            }
            m_uiHealTimer = 10000;
        }
        else
            m_uiHealTimer -= uiDiff;

        if (m_uiStarfireTimer < uiDiff)
        {
            if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
            {
                if (DoCastSpellIfCan(pTarget, SPELL_STARFIRE) == CAST_OK)
                    m_uiStarfireTimer = 20000;
            }
        }
        else
            m_uiStarfireTimer -= uiDiff;

        DoMeleeAttackIfReady();
    }
示例#22
0
    void UpdateEscortAI(const uint32 uiDiff) override
    {
        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        // start event epilog
        if (!m_bTirionSpawned && m_creature->GetHealthPercent() < 20.0f)
        {
            if (Creature* pTaelan = m_creature->GetMap()->GetCreature(m_taelanGuid))
                SendAIEvent(AI_EVENT_CUSTOM_B, m_creature, pTaelan);
            m_bTirionSpawned = true;
        }

        // combat spells
        if (m_uiMindBlastTimer < uiDiff)
        {
            if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_MIND_BLAST) == CAST_OK)
                m_uiMindBlastTimer = urand(3000, 5000);
        }
        else
            m_uiMindBlastTimer -= uiDiff;

        if (m_uiMindFlayTimer < uiDiff)
        {
            if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_MIND_FLAY) == CAST_OK)
                m_uiMindFlayTimer = urand(9000, 15000);
        }
        else
            m_uiMindFlayTimer -= uiDiff;

        if (m_uiManaBurnTimer < uiDiff)
        {
            if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_MANA_BURN) == CAST_OK)
                m_uiManaBurnTimer = urand(8000, 12000);
        }
        else
            m_uiManaBurnTimer -= uiDiff;

        if (m_uiDominateTimer < uiDiff)
        {
            if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1, SPELL_DOMINATE_MIND, SELECT_FLAG_PLAYER))
            {
                if (DoCastSpellIfCan(pTarget, SPELL_DOMINATE_MIND) == CAST_OK)
                    m_uiDominateTimer = urand(25000, 30000);
            }
        }
        else
            m_uiDominateTimer -= uiDiff;

        if (m_uFlashHealTimer < uiDiff)
        {
            if (Unit* pTarget = DoSelectLowestHpFriendly(50.0f))
            {
                if (DoCastSpellIfCan(pTarget, SPELL_FLASH_HEAL) == CAST_OK)
                    m_uFlashHealTimer = urand(10000, 15000);
            }
        }
        else
            m_uFlashHealTimer -= uiDiff;

        if (m_creature->GetHealthPercent() < 50.0f)
        {
            if (m_uiGreaterHealTimer < uiDiff)
            {
                if (DoCastSpellIfCan(m_creature, SPELL_GREATER_HEAL) == CAST_OK)
                    m_uiGreaterHealTimer = urand(15000, 20000);
            }
            else
                m_uiGreaterHealTimer -= uiDiff;
        }

        DoMeleeAttackIfReady();
    }
示例#23
0
bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& holder, Unit* actionInvoker /*=NULL*/)
{
    if (!holder.Enabled || holder.Time)
        return false;

    //Check the inverse phase mask (event doesn't trigger if current phase bit is set in mask)
    if (holder.Event.event_inverse_phase_mask & (1 << m_Phase))
        return false;

    CreatureEventAI_Event const& event = holder.Event;

    //Check event conditions based on the event type, also reset events
    switch (event.event_type)
    {
    case EVENT_T_TIMER:
        if (!me->isInCombat())
            return false;

        //Repeat Timers
        holder.UpdateRepeatTimer(me, event.timer.repeatMin, event.timer.repeatMax);
        break;
    case EVENT_T_TIMER_OOC:
        if (me->isInCombat())
            return false;

        //Repeat Timers
        holder.UpdateRepeatTimer(me, event.timer.repeatMin, event.timer.repeatMax);
        break;
    case EVENT_T_HP:
    {
        if (!me->isInCombat() || !me->GetMaxHealth())
            return false;

        uint32 perc = uint32(me->GetHealthPct());

        if (perc > event.percent_range.percentMax || perc < event.percent_range.percentMin)
            return false;

        //Repeat Timers
        holder.UpdateRepeatTimer(me, event.percent_range.repeatMin, event.percent_range.repeatMax);
        break;
    }
    case EVENT_T_MANA:
    {
        if (!me->isInCombat() || !me->GetMaxPower(POWER_MANA))
            return false;

        uint32 perc = (me->GetPower(POWER_MANA)*100) / me->GetMaxPower(POWER_MANA);

        if (perc > event.percent_range.percentMax || perc < event.percent_range.percentMin)
            return false;

        //Repeat Timers
        holder.UpdateRepeatTimer(me, event.percent_range.repeatMin, event.percent_range.repeatMax);
        break;
    }
    case EVENT_T_AGGRO:
        break;
    case EVENT_T_KILL:
        //Repeat Timers
        holder.UpdateRepeatTimer(me, event.kill.repeatMin, event.kill.repeatMax);
        break;
    case EVENT_T_DEATH:
    case EVENT_T_EVADE:
        break;
    case EVENT_T_SPELLHIT:
        //Spell hit is special case, param1 and param2 handled within CreatureEventAI::SpellHit

        //Repeat Timers
        holder.UpdateRepeatTimer(me, event.spell_hit.repeatMin, event.spell_hit.repeatMax);
        break;
    case EVENT_T_RANGE:
        //Repeat Timers
        holder.UpdateRepeatTimer(me, event.range.repeatMin, event.range.repeatMax);
        break;
    case EVENT_T_OOC_LOS:
        //Repeat Timers
        holder.UpdateRepeatTimer(me, event.ooc_los.repeatMin, event.ooc_los.repeatMax);
        break;
    case EVENT_T_RESET:
    case EVENT_T_SPAWNED:
        break;
    case EVENT_T_TARGET_HP:
    {
        if (!me->isInCombat() || !me->getVictim() || !me->getVictim()->GetMaxHealth())
            return false;

        uint32 perc = uint32(me->getVictim()->GetHealthPct());

        if (perc > event.percent_range.percentMax || perc < event.percent_range.percentMin)
            return false;

        //Repeat Timers
        holder.UpdateRepeatTimer(me, event.percent_range.repeatMin, event.percent_range.repeatMax);
        break;
    }
    case EVENT_T_TARGET_CASTING:
        if (!me->isInCombat() || !me->getVictim() || !me->getVictim()->IsNonMeleeSpellCasted(false, false, true))
            return false;

        //Repeat Timers
        holder.UpdateRepeatTimer(me, event.target_casting.repeatMin, event.target_casting.repeatMax);
        break;
    case EVENT_T_FRIENDLY_HP:
    {
        if (!me->isInCombat())
            return false;

        Unit* unit = DoSelectLowestHpFriendly((float)event.friendly_hp.radius, event.friendly_hp.hpDeficit);
        if (!unit)
            return false;

        actionInvoker = unit;

        //Repeat Timers
        holder.UpdateRepeatTimer(me, event.friendly_hp.repeatMin, event.friendly_hp.repeatMax);
        break;
    }
    case EVENT_T_FRIENDLY_IS_CC:
    {
        if (!me->isInCombat())
            return false;

        std::list<Creature*> pList;
        DoFindFriendlyCC(pList, (float)event.friendly_is_cc.radius);

        //List is empty
        if (pList.empty())
            return false;

        //We don't really care about the whole list, just return first available
        actionInvoker = *(pList.begin());

        //Repeat Timers
        holder.UpdateRepeatTimer(me, event.friendly_is_cc.repeatMin, event.friendly_is_cc.repeatMax);
        break;
    }
    case EVENT_T_FRIENDLY_MISSING_BUFF:
    {
        std::list<Creature*> pList;
        DoFindFriendlyMissingBuff(pList, (float)event.friendly_buff.radius, event.friendly_buff.spellId);

        //List is empty
        if (pList.empty())
            return false;

        //We don't really care about the whole list, just return first available
        actionInvoker = *(pList.begin());

        //Repeat Timers
        holder.UpdateRepeatTimer(me, event.friendly_buff.repeatMin, event.friendly_buff.repeatMax);
        break;
    }
    case EVENT_T_SUMMONED_UNIT:
    {
        //Prevent event from occuring on no unit or non creatures
        if (!actionInvoker || actionInvoker->GetTypeId() != TYPEID_UNIT)
            return false;

        //Creature id doesn't match up
        if (actionInvoker->ToCreature()->GetEntry() != event.summon_unit.creatureId)
            return false;

        //Repeat Timers
        holder.UpdateRepeatTimer(me, event.summon_unit.repeatMin, event.summon_unit.repeatMax);
        break;
    }
    case EVENT_T_TARGET_MANA:
    {
        if (!me->isInCombat() || !me->getVictim() || !me->getVictim()->GetMaxPower(POWER_MANA))
            return false;

        uint32 perc = (me->getVictim()->GetPower(POWER_MANA)*100) / me->getVictim()->GetMaxPower(POWER_MANA);

        if (perc > event.percent_range.percentMax || perc < event.percent_range.percentMin)
            return false;

        //Repeat Timers
        holder.UpdateRepeatTimer(me, event.percent_range.repeatMin, event.percent_range.repeatMax);
        break;
    }
    case EVENT_T_REACHED_HOME:
    case EVENT_T_RECEIVE_EMOTE:
        break;
    case EVENT_T_BUFFED:
    {
        //Note: checked only aura for effect 0, if need check aura for effect 1/2 then
        // possible way: pack in event.buffed.amount 2 uint16 (ammount+effectIdx)
        Aura const* aura = me->GetAura(event.buffed.spellId);
        if (!aura || aura->GetStackAmount() < event.buffed.amount)
            return false;

        //Repeat Timers
        holder.UpdateRepeatTimer(me, event.buffed.repeatMin, event.buffed.repeatMax);
        break;
    }
    case EVENT_T_TARGET_BUFFED:
    {
        //Prevent event from occuring on no unit
        if (!actionInvoker)
            return false;

        //Note: checked only aura for effect 0, if need check aura for effect 1/2 then
        // possible way: pack in event.buffed.amount 2 uint16 (ammount+effectIdx)
        Aura const* aura = actionInvoker->GetAura(event.buffed.spellId);
        if (!aura || aura->GetStackAmount() < event.buffed.amount)
            return false;

        //Repeat Timers
        holder.UpdateRepeatTimer(me, event.buffed.repeatMin, event.buffed.repeatMax);
        break;
    }
    default:
        sLog->outErrorDb("CreatureEventAI: Creature %u using Event %u has invalid Event Type(%u), missing from ProcessEvent() Switch.", me->GetEntry(), holder.Event.event_id, holder.Event.event_type);
        break;
    }

    //Disable non-repeatable events
    if (!(holder.Event.event_flags & EFLAG_REPEATABLE))
        holder.Enabled = false;

    //Store random here so that all random actions match up
    uint32 rnd = rand();

    //Return if chance for event is not met
    if (holder.Event.event_chance <= rnd % 100)
        return false;

    //Process actions
    for (uint8 j = 0; j < MAX_ACTIONS; ++j)
        ProcessAction(holder.Event.action[j], rnd, holder.Event.event_id, actionInvoker);

    return true;
}
    void UpdateAI(const uint32 uiDiff) override
    {
        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        if (m_uiHealTimer < uiDiff)
        {
            if (Unit* pTarget = DoSelectLowestHpFriendly(50.0f))
            {
                if (DoCastSpellIfCan(pTarget, SPELL_FLASH_HEAL) == CAST_OK)
                    m_uiHealTimer = urand(15000, 20000);
            }
        }
        else
            m_uiHealTimer -= uiDiff;

        if (m_uiRenewTimer < uiDiff)
        {
            if (Unit* pTarget = DoSelectLowestHpFriendly(50.0f))
            {
                if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_RENEW : SPELL_RENEW_H) == CAST_OK)
                    m_uiRenewTimer = urand(5000, 10000);
            }
        }
        else
            m_uiRenewTimer -= uiDiff;

        if (m_uiShieldTimer < uiDiff)
        {
            if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_SHIELD : SPELL_SHIELD_H) == CAST_OK)
                m_uiShieldTimer = urand(30000, 35000);
        }
        else
            m_uiShieldTimer -= uiDiff;

        if (m_uiDispelTimer < uiDiff)
        {
            Unit* pTarget = nullptr;
            CreatureList lTempList = DoFindFriendlyCC(50.0f);

            if (!lTempList.empty())
                pTarget = *(lTempList.begin());
            else
                pTarget = DoSelectLowestHpFriendly(50.0f);

            if (pTarget)
            {
                if (DoCastSpellIfCan(pTarget, SPELL_DISPEL_MAGIC) == CAST_OK)
                    m_uiDispelTimer = urand(12000, 15000);
            }
        }
        else
            m_uiDispelTimer -= uiDiff;

        // Use the Medallion if CC - only on heroic. Not sure how many times they are allowed to use it.
        if (!m_bIsRegularMode && m_uiMedallionTimer)
        {
            if (m_creature->isFrozen() || m_creature->hasUnitState(UNIT_STAT_CAN_NOT_REACT))
            {
                if (m_uiMedallionTimer <= uiDiff)
                {
                    if (DoCastSpellIfCan(m_creature, SPELL_MEDALLION, CAST_TRIGGERED) == CAST_OK)
                        m_uiMedallionTimer = 0;
                }
                else
                    m_uiMedallionTimer -= uiDiff;
            }
        }

        if (m_uiSWPainTimer < uiDiff)
        {
            if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, nullptr, SELECT_FLAG_PLAYER))
            {
                if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_SHADOW_WORD_PAIN : SPELL_SHADOW_WORD_PAIN_H) == CAST_OK)
                    m_uiSWPainTimer = 10000;
            }
        }
        else
            m_uiSWPainTimer -= uiDiff;

        if (m_uiScreamTimer < uiDiff)
        {
            if (DoCastSpellIfCan(m_creature, SPELL_SCREAM) == CAST_OK)
                m_uiScreamTimer = urand(15000, 20000);
        }
        else
            m_uiScreamTimer -= uiDiff;

        DoMeleeAttackIfReady();
    }
    bool UpdateCompanionAI(const uint32 uiDiff)
    {
        if (m_uiGoblinDragonGunTimer < uiDiff)
        {
            if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_GOBLIN_DRAGON_GUN : SPELL_GOBLIN_DRAGON_GUN_H) == CAST_OK)
                m_uiGoblinDragonGunTimer = urand(10000, 20000);
        }
        else
            m_uiGoblinDragonGunTimer -= uiDiff;

        if (m_uiRocketLaunchTimer < uiDiff)
        {
            if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, nullptr, SELECT_FLAG_PLAYER))
            {
                if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_ROCKET_LAUNCH : SPELL_ROCKET_LAUNCH_H) == CAST_OK)
                    m_uiRocketLaunchTimer = 9000;
            }
        }
        else
            m_uiRocketLaunchTimer -= uiDiff;

        if (m_uiFelIronBombTimer < uiDiff)
        {
            if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, nullptr, SELECT_FLAG_PLAYER))
            {
                if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_FEL_IRON_BOMB : SPELL_FEL_IRON_BOMB_H) == CAST_OK)
                    m_uiFelIronBombTimer = 15000;
            }
        }
        else
            m_uiFelIronBombTimer -= uiDiff;

        if (m_uiRecombobulateTimer < uiDiff)
        {
            // Note: this should be casted only on Polyformed targets
            Unit* pTarget = nullptr;
            CreatureList lTempList = DoFindFriendlyCC(50.0f);

            if (!lTempList.empty())
                pTarget = *(lTempList.begin());
            else
                pTarget = DoSelectLowestHpFriendly(50.0f);

            if (pTarget)
            {
                if (DoCastSpellIfCan(pTarget, SPELL_RECOMBOBULATE) == CAST_OK)
                    m_uiRecombobulateTimer = 2000;
            }
        }
        else
            m_uiRecombobulateTimer -= uiDiff;

        if (m_uiHighExplosiveSheepTimer < uiDiff)
        {
            if (DoCastSpellIfCan(m_creature, SPELL_HIGH_EXPLOSIVE_SHEEP) == CAST_OK)
                m_uiHighExplosiveSheepTimer = 65000;
        }
        else
            m_uiHighExplosiveSheepTimer -= uiDiff;

        return true;
    }
示例#26
0
            void UpdateAI(const uint32 diff)
            {
                DoMeleeAttackIfReady();

                decrementTimers();

                if (IAmDead())
                    return;

                if (me->GetPower(POWER_MANA) < 400 && isTimerReady(uiPotion_Timer))
                {
                    doCast(me, SPELL_MANA_POTION);
                    uiPotion_Timer = 150;
                }

                if (me->GetPower(POWER_MANA)/me->GetMaxPower(POWER_MANA) < 10)
                {
                    if (uiOom_Timer == 0)
                        uiOom_Timer = 1;
                }

                BuffAndHealGroup(master);

                // Heal myself
                HealTarget (me, me->GetHealth() * 100 / me->GetMaxHealth());

                //the rest are combat so return if not fighting
                opponent = SelectTarget(SELECT_TARGET_TOPAGGRO, 0);

                if (!opponent && !me->getVictim())
                {
                    DoNonCombatActions();
                    ResetOrGetNextTarget();
                    return;
                }

                //Cast totems.
                if (me->isInCombat() && isTimerReady(uiEarthTotem_Timer) && !master->HasAura(SPELL_STONE_SKIN_AURA, 0))
                {
                    doCast(me, SPELL_STONE_SKIN_TOTEM);
                    GiveManaBack();
                    uiEarthTotem_Timer = 90;
                    return;
                }

                if (me->isInCombat() && isTimerReady(uiFireTotem_Timer))
                {
                    doCast(me, SPELL_SEARING_TOTEM);
                    GiveManaBack();
                    uiFireTotem_Timer = 180;
                    return;
                }

                if (me->isInCombat() && isTimerReady(uiWindTotem_Timer))
                {
                    doCast(me, SPELL_WINDFURY_TOTEM);
                    GiveManaBack();
                    uiWindTotem_Timer = 180;
                    return;
                }

                if (me->isInCombat())
                {
                    switch(master->getClass())
                    {
                        case CLASS_WARRIOR:
                        case CLASS_DEATH_KNIGHT:
                        case CLASS_ROGUE:
                            if (isTimerReady(uiWaterTotem_Timer) && !master->HasAura(SPELL_HEALING_STREAM_AURA))
                            {
                                doCast(me, SPELL_HEALING_STREAM_TOTEM);
                                uiWaterTotem_Timer = 90;
                                GiveManaBack();
                                return;
                            }
                            break;
                        default: //everyone else gets a mana totem
                            if (isTimerReady (uiWaterTotem_Timer) && !master->HasAura(SPELL_MANA_SPRING_AURA, 0))
                            {
                                doCast(me, SPELL_MANA_SPRING_TOTEM);
                                uiWaterTotem_Timer = 90;
                                GiveManaBack();
                                return;
                            }
                    }
                }

                if (isTimerReady(uiFlameShock_Timer))
                {
                    doCast(opponent, SPELL_FLAME_SHOCK);
                    uiFlameShock_Timer = 120;
                    return;
                }

                if (isTimerReady(uiLightningBolt_Timer))
                {
                    doCast(opponent, SPELL_LIGHTNING_BOLT);
                    uiLightningBolt_Timer = 180;
                    return;
                }

                if (isTimerReady(uiEarthShock_Timer))
                {
                    doCast(opponent, SPELL_EARTH_SHOCK);
                    uiEarthShock_Timer = 250;
                    return;
                }

                //now try to heal bots and pets.  DoSelectLowestHpFriendly will get
                //everyone in group including bots and pets.  Unfortunately it can
                //not be triggered for % of lost HP, so we just set it to -1000.
                //This means low level players wont be healed because they wont have
                //enough HP.
                Unit* target = DoSelectLowestHpFriendly(40, 1000);

                if (target)
                {
                    if (CanCast(target, GetSpellStore()->LookupEntry (SPELL_CHAIN_HEAL)))
                    {
                        doCast(target, SPELL_CHAIN_HEAL, false);
                        uiOthersHeal_Timer = 50;
                    }
                }
                else
                {
                    target = DoSelectLowestHpFriendly(40, 500); //now try someone with less HP lost

                    if (target)
                    {
                        if (CanCast(target, GetSpellStore()->LookupEntry (SPELL_CHAIN_HEAL)))
                        {
                            doCast(target, SPELL_CHAIN_HEAL, false);
                            uiOthersHeal_Timer = 100;
                        }
                    }
                }

                ScriptedAI::UpdateAI(diff);
            }
    void UpdateAI(const uint32 uiDiff) override
    {
        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        if (m_bCanResurrect)
        {
            // When casting resuruction make sure to delay so on rez when reinstate battle deepsleep runs out
            if (m_uiWait_Timer < uiDiff)
            {
                // spell has script target on Mograine
                DoCastSpellIfCan(m_creature, SPELL_SCARLETRESURRECTION);
                DoScriptText(SAY_WH_RESSURECT, m_creature);
                m_bCanResurrect = false;
            }
            else
                m_uiWait_Timer -= uiDiff;
        }

        // Cast Deep sleep when health is less than 50%
        if (!m_bCanResurrectCheck && m_creature->GetHealthPercent() <= 50.0f)
        {
            DoCastSpellIfCan(m_creature, SPELL_DEEPSLEEP, CAST_INTERRUPT_PREVIOUS);
            m_bCanResurrectCheck = true;
            m_bCanResurrect = true;
            return;
        }

        // while in "resurrect-mode", don't do anything
        if (m_bCanResurrect)
            return;

        // If we are <75% hp cast healing spells at self or Mograine
        if (m_uiHeal_Timer < uiDiff)
        {
            if (Unit* pTarget = DoSelectLowestHpFriendly(50.0f))
            {
                if (DoCastSpellIfCan(pTarget, SPELL_HEAL) == CAST_OK)
                    m_uiHeal_Timer = 13000;
            }
        }
        else
            m_uiHeal_Timer -= uiDiff;

        // m_uiPowerWordShield_Timer
        if (m_uiPowerWordShield_Timer < uiDiff)
        {
            if (DoCastSpellIfCan(m_creature, SPELL_POWERWORDSHIELD) == CAST_OK)
                m_uiPowerWordShield_Timer = urand(22000, 45000);
        }
        else
            m_uiPowerWordShield_Timer -= uiDiff;

        // m_uiHolySmite_Timer
        if (m_uiHolySmite_Timer < uiDiff)
        {
            if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_HOLYSMITE) == CAST_OK)
                m_uiHolySmite_Timer = urand(3500, 5000);
        }
        else
            m_uiHolySmite_Timer -= uiDiff;

        DoMeleeAttackIfReady();
    }
示例#28
0
文件: bot_ai.cpp 项目: Rhyuk/Dev
void bot_ai::ResetOrGetNextTarget()
{
    if (master->GetBotMustDie()) return;
    uint64 targetGUID = 0;

    // check if anyone has raid target
    //targetGUID = getTargetWithIcon();
    Group *group = master->GetGroup();
    targetGUID = group->GetTargetWithIconByGroup (m_creature->GetGUID());


    if (targetGUID && targetGUID!=master->GetGUID())
    {

        Unit * target = m_creature->GetCreature(*master, targetGUID);
        if (target && target->isAlive() && target->IsHostileTo(master) && target->isInCombat() /*&& m_creature->IsWithinDist(target, 30)*/)
        {
            BotAttackStart(target);
            return;
        }
    }

    AttackerSet m_attackers = master->getAttackers();

    //check if anyone is attacking master
    if(gettingAttacked(m_attackers)) return;

    //check if anyone is attacking me
    m_attackers = m_creature->getAttackers();
    if(gettingAttacked(m_attackers)) return;

    //check if master has a victim
    if(master->getVictim() && master->getVictim()->IsHostileTo(master))
    {
        if(m_creature->IsWithinDist(m_creature->getVictim(), 50))
        {
            BotAttackStart(master->getVictim());
            return;
        }
    }

    //lastly check a random victim, including bots, pets, etc
    Unit *target = DoSelectLowestHpFriendly(30);
    if(target != NULL && target->isAlive() && !target->IsHostileToPlayers())
    {
        m_attackers = target->getAttackers();
        if(gettingAttacked(m_attackers)) {
            return;
        }

    }

    //if there is no one to attack, make sure we are following master
    if(m_creature->getVictim() == NULL &&
        m_creature->GetCharmInfo()->GetCommandState() != COMMAND_STAY &&
        master->GetDistance(m_creature) > 20 &&
        !master->IsBeingTeleported())
    {
        if (!master->isAlive())
            master->SetBotCommandState(COMMAND_STAY);
        else if (master->GetBotCommandState()==COMMAND_ATTACK)
            master->SetBotCommandState(prevCommandState);


        return;
    }
}
示例#29
0
void PlayerbotDruidAI::DoNextCombatManeuver(Unit *pTarget)
{
    if (!pTarget || pTarget->isDead()) return;
    PlayerbotAI *ai = GetAI();
    if (!ai) return;
    Player *m_bot = GetPlayerBot();
    if (!m_bot || m_bot->isDead()) return;
    Unit *pVictim = pTarget->getVictim();
    Unit *m_tank = FindMainTankInRaid(GetMaster());
    if (!m_tank && m_bot->GetGroup() && GetMaster()->GetGroup() != m_bot->GetGroup()) { FindMainTankInRaid(m_bot); }
    if (!m_tank) { m_tank = m_bot; }
    uint32 masterHP = GetMaster()->GetHealth()*100 / GetMaster()->GetMaxHealth();
    float pDist = m_bot->GetDistance(pTarget);
    uint8 pThreat = GetThreatPercent(pTarget);

    uint8 reqHeal = 0;
    uint8 OwnPartyHP = GetHealthPercentRaid(m_bot, reqHeal);


    #pragma region Select behaviour
    if (m_tank->GetGUID() == m_bot->GetGUID()) // Hey! I am Main Tank
    {
        if (TALENT_FERAL && BEAR_FORM) { m_role = BOT_ROLE_TANK; } //Just Keep Tanking dont even change forms for healing
        else
        {
            if (TALENT_BALANCE) {
                if ((ai->GetHealthPercent() <= 40 || masterHP <30 ) && (ai->GetManaPercent() >= 40)) { m_role = BOT_ROLE_SUPPORT; }
                else if (OwnPartyHP < 20 && ai->GetManaPercent() >= 30) { m_role = BOT_ROLE_SUPPORT; }
                else if (ai->GetManaPercent() < 25 ) { m_role = BOT_ROLE_TANK; }
                else { m_role = BOT_ROLE_DPS_RANGED; }
            }
            else //I am both healer and tank?? Hmm
            {
                if ((ai->GetHealthPercent() <= 70 || masterHP <70 ) && (ai->GetManaPercent() >= 50)) { m_role = BOT_ROLE_SUPPORT; }
                else if (OwnPartyHP < 20 && ai->GetManaPercent() >= 30) { m_role = BOT_ROLE_SUPPORT; }
                else if (ai->GetManaPercent() < 15 ) { m_role = BOT_ROLE_TANK; }
                else { m_role = BOT_ROLE_DPS_RANGED; }
            }
        }
    }
    else if (isUnderAttack() && !( ai->GetForm() == FORM_MOONKIN || ai->GetForm() == FORM_TREE)  ) // if i am under attack
    {
        // Keep being in Cat Form if you can reduce threat
        if (ai->GetForm() == FORM_CAT && CastSpell(COWER,pTarget)) {return; }
        else if (TALENT_RESTO && ai->GetManaPercent() > 10 ) { m_role = BOT_ROLE_SUPPORT; }
        else { m_role = BOT_ROLE_OFFTANK; }
    }
    else if (TALENT_FERAL && CAT_FORM) { // If has any feral forms at all
        if ((ai->GetHealthPercent() <= 40 || masterHP <40 ) && (ai->GetManaPercent() >= 40)) { m_role = BOT_ROLE_SUPPORT; }
        else if (OwnPartyHP < 30 && ai->GetManaPercent() >= 30) { m_role = BOT_ROLE_SUPPORT; }
        else{ m_role = BOT_ROLE_DPS_MELEE; }
    }
    else if (TALENT_BALANCE) {
        if ((ai->GetHealthPercent() <= 50 || masterHP <40 ) && (ai->GetManaPercent() >= 10)) { m_role = BOT_ROLE_SUPPORT; }
        else if (OwnPartyHP < 40 && ai->GetManaPercent() >= 30) { m_role = BOT_ROLE_SUPPORT; }
        else { m_role = BOT_ROLE_DPS_RANGED; }
    }
    else if (TALENT_RESTO)    { m_role = BOT_ROLE_SUPPORT; }
    else
    {
        // Unknown build or low level : Do not change forms rapidly..
        if ( (ai->GetManaPercent() < 30 && BEAR_FORM) || ( (ai->GetForm() == FORM_CAT || ai->GetForm() == FORM_DIREBEAR || ai->GetForm() == FORM_BEAR) && ai->GetManaPercent() < 70 )  ) m_role = BOT_ROLE_DPS_MELEE;
        else { m_role = BOT_ROLE_DPS_RANGED; }
    }

    if (!isUnderAttack() && m_tank->GetGUID() != m_bot->GetGUID())
    {
        // Select Attacking target
        if (pVictim && pVictim->GetGUID() == m_bot->GetGUID() && pDist <= 2) {} //if my target is attacking me continue
        else
        {
            Unit *curAtt = GetNearestAttackerOf(m_bot);
            if (curAtt && curAtt->GetGUID() != pTarget->GetGUID())
            {
                m_bot->SetSelection(curAtt->GetGUID());
                //ai->AddLootGUID(curAtt->GetGUID());
                DoNextCombatManeuver(curAtt); //Restart new update to get variables fixed..
                return;
            }
        }
        //my target is attacking me
    }
    #pragma endregion

    // If there's a cast stop
    if (m_bot->HasUnitState(UNIT_STAT_CASTING)) return;
    // Return to normal form from non combat forms
    if (ai->GetForm() == FORM_NONE || ai->GetForm() == FORM_CAT || ai->GetForm() == FORM_TREE || ai->GetForm() == FORM_MOONKIN || ai->GetForm() == FORM_DIREBEAR || ai->GetForm() == FORM_BEAR )  { } //Those are valid incombat auras
    else if (ai->GetForm() != FORM_NONE && ChangeForm(1)) { } //return to caster form

    switch(m_role)
    {
        #pragma region BOT_ROLE_DPS_MELEE
        case BOT_ROLE_DPS_MELEE:
            //ai->TellMaster("DruidCombat");

            // Do caster form stuff
            if (ai->GetForm() == FORM_NONE)
            {
                //We have little mana probably cant change form
                if (ai->GetManaPercent() < 20 && CastSpell (INNERVATE, m_bot) ) { return; }
                else if(m_bot->getRace() == (uint8) RACE_TAUREN && pDist < 8 && CastSpell(R_WAR_STOMP, pTarget)) {  return;}
                else if(DoSupportRaid(GetMaster(),false,false,false)) return;
                else if(m_bot->GetGroup() && GetMaster()->GetGroup() != m_bot->GetGroup() && DoSupportRaid(m_bot,false,false,false)) { return; }
            }

            if (CAT_FORM) { if (ChangeForm(CAT_FORM)) { return; } }
            else if (BEAR_FORM) { if (ChangeForm(BEAR_FORM)) { return; } }
            else if (ai->GetForm() != FORM_NONE && ChangeForm(1)) {  } //Normal Form

            TakePosition(pTarget);
            break;
        #pragma endregion

        #pragma region BOT_ROLE_TANK / BOT_ROLE_OFFTANK
        case BOT_ROLE_OFFTANK:
        case BOT_ROLE_TANK: // It is a tank druid or a defending druid

            // Do what you must before getting attacked...
            if (ai->GetForm() == FORM_NONE)
            {
                // Non tank stuff to avoid
                if (m_tank->GetGUID() != m_bot->GetGUID())
                {
                    if (ROOTS && !pTarget->HasAura(CYCLONE) && !pTarget->HasAura(HIBERNATE) && CastSpell(ROOTS, pTarget)) { return; }
                    if (CYCLONE && pDist > 5 && !pTarget->HasAura(ROOTS) && !pTarget->HasAura(HIBERNATE) && CastSpell(CYCLONE, pTarget)) { return; }
                    if (HIBERNATE && pTarget->GetCreatureType() == (uint32) CREATURE_TYPE_BEAST && !pTarget->HasAura(ROOTS) && !pTarget->HasAura(CYCLONE) && CastSpell(HIBERNATE, pTarget)) { return; }
                    //if (m_bot->getRace() == (uint8) RACE_NIGHTELF && isUnderAttack() && CastSpell(R_SHADOWMELD, m_bot)) { return; }
                }
                // Things to do wheter Tank or not
                if (m_bot->getRace() == (uint8) RACE_TAUREN && pDist < 8 && CastSpell(R_WAR_STOMP, pTarget)) { return; } //no gcd
                if (ai->GetManaPercent() < 20 && CastSpell (INNERVATE, m_bot) ) { return; } //We have little mana probably cant change form
            }
            TakePosition(pTarget);

            if (ChangeForm(BEAR_FORM)) { return; }

            // if i am main tank, protect master by taunt
            if(m_tank->GetGUID() == m_bot->GetGUID())
            {
                // Taunt if needed (Only for master)
                Unit *curAtt = GetAttackerOf(GetMaster());
                if (curAtt)
                {
                    if (isUnderAttack(GetMaster(),2) && CastSpell(CHALLENGING_ROAR, curAtt)) { return; }
                    if (CastSpell(GROWL, curAtt))  { return; }
                }
                // My target is not attacking me, taunt..
                if (pVictim && pVictim->GetGUID() != m_bot->GetGUID() && CastSpell(GROWL, pTarget) )  { return; }
            }
            break;
        #pragma endregion

        #pragma region BOT_ROLE_DPS_RANGED
        case BOT_ROLE_DPS_RANGED:
            if ( ai->GetManaPercent() < 20 && CastSpell (INNERVATE, m_bot)) { return; }

            // Do caster form stuff
            if (ai->GetForm() == FORM_NONE)
            {
                if(DoSupportRaid(GetMaster())) return;
                else if(m_bot->GetGroup() && GetMaster()->GetGroup() != m_bot->GetGroup() && DoSupportRaid(m_bot)) { return; }
            }

            if (MOONKIN_FORM) { if (ChangeForm(MOONKIN_FORM)) { return; } }
            else if (ai->GetForm() != FORM_NONE && ChangeForm(1)) { } //Normal Form

            TakePosition(pTarget);

            // BUFF UP
            if(DoSupportRaid(GetMaster(),false,false,false)) return;
            else if(m_bot->GetGroup() && GetMaster()->GetGroup() != m_bot->GetGroup() && DoSupportRaid(m_bot,false,false,false)) { return; }

            break;
        #pragma endregion

        #pragma region BOT_ROLE_SUPPORT
        case BOT_ROLE_SUPPORT:
            if ( ai->GetManaPercent() < 20 && CastSpell (INNERVATE,m_bot)) { return; }
            //Get to tree form only if you will no longer cast attack spells
            if( TREE_OF_LIFE_FORM && (ai->GetManaPercent() < offensiveSpellThreshold || isUnderAttack()) )
            {
                 if (ChangeForm(TREE_OF_LIFE_FORM)) { return; }
            }
            else if (ai->GetForm() != FORM_NONE && ChangeForm(1)) { }  //Normal Form no gcd

            TakePosition(pTarget);

            //RezGroup(REBIRTH, GetMaster());
            if (DoSupportRaid(GetMaster())) { return; }
            if (m_bot->GetGroup() && GetMaster()->GetGroup() != m_bot->GetGroup() && DoSupportRaid(m_bot)) { return; }
            //heal pets and bots
            Unit *target = DoSelectLowestHpFriendly(30, 1000);
            if(target && target->isAlive() && HealTarget(target, target->GetHealth()*100 / target->GetMaxHealth()) ) { return; }

            break;
        #pragma endregion
    }

    #pragma region DruidCommon
    // Common Dps and protection routine
    if (ai->GetHealthPercent() <= 70 && CastSpell(BARKSKIN,m_bot)) { return; }
    if (isUnderAttack() && CastSpell(NATURES_GRASP,m_bot)) { return; }

    if (ai->GetForm() == FORM_CAT)
    {
        // If at threat limit, use Cower to reduce threat
        if (pThreat > threatThreshold && m_tank->GetGUID() != m_bot->GetGUID() && !isUnderAttack())
        {
            if (m_tank->getVictim() && m_tank->getVictim()->GetGUID() != pTarget->GetGUID()) // I am attacking wrong target!!
            {
                m_bot->SetSelection(m_tank->getVictim()->GetGUID());
                return;
            }
            else
            {
                if (CastSpell(COWER,pTarget)) { return; } //Lets see if we can manage
                else { return; } //use no spells and wait threat to be reduced
            }
        }
        if (CastSpell(FERAL_CHARGE_CAT,pTarget)) { return; }
        if (m_bot->GetComboPoints() >= 1 && pTarget->IsNonMeleeSpellCasted(true) && CastSpell(MAIM, pTarget)) { return; }

        if (CastSpell(BERSERK, m_bot)) { return; }
        if (ai->GetHealthPercent() <= 75 && CastSpell(SURVIVAL_INSTINCTS, m_bot)) { return; }
        if (isUnderAttack() && CastSpell(NATURES_GRASP, m_bot)) { return; }
        if (CastSpell(FAERIE_FIRE_FERAL, pTarget)) { return; }

        if (m_bot->GetComboPoints() < 5)
        {
            if (CastSpell(RAKE, pTarget)) { return; }
            if (CastSpell(MANGLE_CAT, pTarget)) { return; }
            if (!pTarget->HasInArc(M_PI,m_bot) && CastSpell(SHRED, pTarget)) { return; }
            if (ai->GetEnergyAmount() > 65 && CastSpell(MANGLE_CAT, pTarget)) { return; } //Spam mangle if cannot cast shred
            if (ai->GetEnergyAmount() > 65 && CastSpell(CLAW, pTarget) ) { return; } //Spam Claw if there is no mangle
            // if (CanCast(COWER, pTarget) && CastSpell(COWER, pTarget)) { return; } //if still nothing, use COWER to reduce threat
        }
        else
        {
            if (CastSpell(SAVAGE_ROAR)) { return; }
            if (CastSpell(RIP, pTarget)) { return; }
            if (ai->GetEnergyAmount() >= 65 && CastSpell(FEROCIOUS_BITE, pTarget)) { return; } //maxhit for feracious bite
        }
        if (CastSpell(TIGERS_FURY, m_bot)) { return; } //if nothing is ready yet, use tigers fury
    }
    else if (ai->GetForm() == FORM_DIREBEAR || ai->GetForm() == FORM_BEAR)
    {
        // If at threat limit, stop
        if (pThreat > threatThreshold && m_tank->GetGUID() != m_bot->GetGUID() && !isUnderAttack() )
        {
            //Change to tank's target
            if (m_tank->getVictim() && m_tank->getVictim()->GetGUID() != pTarget->GetGUID()) { m_bot->SetSelection(m_tank->getVictim()->GetGUID()); }
            return; //use no spells and wait threat to be reduced
        }
        if (CastSpell(FERAL_CHARGE_BEAR,pTarget)) { return; }
        if (CastSpell(BASH, pTarget,true,true)) { return; } //Need check for immunity
        if (CastSpell(BERSERK, m_bot)) { return; }
        if (CastSpell(DEMORALIZING_ROAR, pTarget)) { return; }
        if (ai->GetHealthPercent() > 90 && ai->GetRageAmount() < 50 && CastSpell(ENRAGE, m_bot)) { return; }
        if (ai->GetHealthPercent() <= 75 && CastSpell(SURVIVAL_INSTINCTS, m_bot)) { return; }
        if ( ( ai->GetHealthPercent() <= 30 || (ai->GetHealthPercent() < 85 && m_tank->GetGUID() != m_bot->GetGUID())  )
            && CastSpell(FRENZIED_REGENERATION)) { return; }
        if (CastSpell(FAERIE_FIRE_FERAL, pTarget)) { return; }
        if (CastSpell(MANGLE_BEAR, pTarget)) { return; }
        if ((ai->GetRageAmount() > 70 || m_tank->GetGUID() == m_bot->GetGUID()) && CastSpell(SWIPE_BEAR, pTarget)) { return; }
        if (ai->GetRageAmount() > 50 && CastSpell(MAUL, pTarget)) {} // Low Priority, Next Attack effect
        if (ai->GetRageAmount() > 60 && CastSpell(LACERATE, pTarget)) { return; } //Currently applies only 1
    }
    else
    {
        //Defensive stuff
        if (m_tank->GetGUID() != m_bot->GetGUID() && pVictim && pVictim->GetGUID() == m_bot->GetGUID() )
        {
            if (ROOTS && !pTarget->HasAura(CYCLONE) && !pTarget->HasAura(HIBERNATE) && CastSpell(ROOTS, pTarget)) { return; }
            if (CYCLONE && pDist > 5 && !pTarget->HasAura(ROOTS) && !pTarget->HasAura(HIBERNATE) && CastSpell(CYCLONE, pTarget)) { return; }
            if (HIBERNATE && pTarget->GetCreatureType() == (uint32) CREATURE_TYPE_BEAST && !pTarget->HasAura(ROOTS) && !pTarget->HasAura(CYCLONE) && CastSpell(HIBERNATE, pTarget)) { return; }
            //if (m_bot->getRace() == (uint8) RACE_NIGHTELF && isUnderAttack() && CastSpell(R_SHADOWMELD, m_bot)) { return; }
            if (m_bot->getRace() == (uint8) RACE_TAUREN && pDist < 8 && CastSpell(R_WAR_STOMP, pTarget)) { return; }
        }

        if (CastSpell(FAERIE_FIRE, pTarget)) { return; }

        // If at threat limit, stop
        if (pThreat > threatThreshold && m_tank->GetGUID() != m_bot->GetGUID() && !isUnderAttack() )
        {
            //Change to tank's target
            if (m_tank->getVictim() && m_tank->getVictim()->GetGUID() != pTarget->GetGUID()) { m_bot->SetSelection(m_tank->getVictim()->GetGUID()); }
            return; //use no spells and wait threat to be reduced
        }
        // Continue attacking if theres excess mana (for healers)
        if (m_role == BOT_ROLE_SUPPORT && ai->GetManaPercent() < offensiveSpellThreshold) { return; }
        if (m_role != BOT_ROLE_SUPPORT && CastSpell(NATURES_SWIFTNESS, m_bot)) { } //only balance no gcd

        if (m_bot->HasAura(NATURES_SWIFTNESS) && CastSpell(STARFIRE, pTarget)) { return; }
        if (CastSpell(INSECT_SWARM, pTarget)) { return; }
        if (CastSpell(TYPHOON, pTarget)) { return; }
        if (isUnderAttack(m_tank,4) && CastSpell(HURRICANE, pTarget)) { ai->SetIgnoreUpdateTime(8); return; }
        if (isUnderAttack(m_tank,5) && CastSpell(FORCE_OF_NATURE, m_bot)) { return; }
        if (isUnderAttack(m_tank,4) && CastSpell(STARFALL, pTarget)) { return; }
        if (CastSpell(MOONFIRE, pTarget)) { return; }
        if (CastSpell(WRATH, pTarget)) { return; }
        if (CastSpell(STARFIRE, pTarget)) { return; }
    }

    // If there is nothing else to do buff UP
    if (m_role == BOT_ROLE_DPS_MELEE) //Those already healed and buffed or should never buff in combat
    {
        if (DoSupportRaid(GetMaster(),false,false,false)) { return; }
        if (m_bot->GetGroup() && GetMaster()->GetGroup() != m_bot->GetGroup() && DoSupportRaid(m_bot,false,false,false)) { return; }
    }


    // drink potion if support / healer (Other builds simply overuse mana and waste mana pots)
    if(ai->GetManaPercent() < 5 && (m_role == BOT_ROLE_SUPPORT || m_role == BOT_ROLE_HEALER) )
    {
        Item *pItem = ai->FindPotion();
        if(pItem != NULL)
        {
            if (pItem->GetSpell() && m_bot->HasSpellCooldown(pItem->GetSpell()) ) { return; } //pot is in cooldown
            ai->UseItem(*pItem);
        }
    }
    #pragma endregion
} //end DoNextCombatManeuver
        void UpdateAI(uint32 diff)
        {
            npc_escortAI::UpdateAI(diff);

            if( !UpdateVictim() )
                return;

            events.Update(diff);

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

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

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

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

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

            DoMeleeAttackIfReady();
        }