Beispiel #1
0
void PlayerbotDruidAI::DoNextCombatManeuver(Unit *pTarget)
{
    PlayerbotAI* ai = GetAI();
    if (!ai)
        return;

    switch (ai->GetScenarioType())
    {
        case PlayerbotAI::SCENARIO_DUEL:
            ai->CastSpell(MOONFIRE);
            return;
        default:
            break;
    }

    uint32 masterHP = GetMaster()->GetHealth() * 100 / GetMaster()->GetMaxHealth();

    Player *m_bot = GetPlayerBot();
    Unit* pVictim = pTarget->getVictim();

    if (ai->GetCombatOrder() == PlayerbotAI::ORDERS_HEAL) // && ai->GetMovementOrder() == PlayerbotAI::MOVEMENT_STAY)
        SpellSequence = DruidHeal;
    else if (IsFeral() && ai->GetCombatOrder() == PlayerbotAI::ORDERS_ASSIST) // && ai->GetMovementOrder() == PlayerbotAI::MOVEMENT_STAY)
        SpellSequence = DruidCombat;
    else if (IsFeral() && ai->GetCombatOrder() == PlayerbotAI::ORDERS_TANK)
        SpellSequence = DruidTank;
    else
        SpellSequence = DruidSpell;

    switch (SpellSequence)
    {
        case DruidTank: // Its now a tank druid!
            //ai->TellMaster("DruidTank");
            _DoNextPVECombatManeuverBear(pTarget);
            break;

        case DruidSpell:
            //ai->TellMaster("DruidSpell");
            _DoNextPVECombatManeuverSpellDPS(pTarget);
            break;

        case DruidHeal:
            //ai->TellMaster("DruidHeal");
            _DoNextPVECombatManeuverHeal(pTarget);
            break;

        case DruidCombat:
            //ai->TellMaster("DruidCombat");
            _DoNextPVECombatManeuverMeleeDPS(pTarget);
            break;
    }
} // end DoNextCombatManeuver
void PlayerbotDruidAI::DoNextCombatManeuver(Unit *pTarget)
{
    PlayerbotAI* ai = GetAI();
    if (!ai)
        return;

    switch (ai->GetScenarioType())
    {
    case PlayerbotAI::SCENARIO_DUEL:
        ai->CastSpell(MOONFIRE);
        return;
    }

    uint32 masterHP = GetMaster()->GetHealth() * 100 / GetMaster()->GetMaxHealth();

    Player *m_bot = GetPlayerBot();
    Unit* pVictim = pTarget->getVictim();

    if (ai->GetCombatOrder() == PlayerbotAI::ORDERS_HEAL)
        SpellSequence = DruidHeal;
    else if (ai->GetCombatOrder() == PlayerbotAI::ORDERS_ASSIST && CAT_FORM > 0)
        SpellSequence = DruidCombat;
    // No check for Dire Bear here: you must have Bear form to learn Dire Bear form.
    else if (ai->GetCombatOrder() == PlayerbotAI::ORDERS_TANK && BEAR_FORM > 0)
        SpellSequence = DruidTank;
    else
        SpellSequence = DruidSpell;

    switch (SpellSequence)
    {
    case DruidTank: // Its now a tank druid!
        //ai->TellMaster("DruidTank");
        _DoNextPVECombatManeuverBear(pTarget);
        break;

    case DruidSpell:
        //ai->TellMaster("DruidSpell");
        _DoNextPVECombatManeuverSpellDPS(pTarget);
        break;

    case DruidHeal:
        //ai->TellMaster("DruidHeal");
        _DoNextPVECombatManeuverHeal(pTarget);
        break;

    case DruidCombat:
        //ai->TellMaster("DruidCombat");
        _DoNextPVECombatManeuverMeleeDPS(pTarget);
        break;
    }
} // end DoNextCombatManeuver
Beispiel #3
0
void PlayerbotDruidAI::_DoNextPVECombatManeuverMeleeDPS(Unit* pTarget)
{
    PlayerbotAI* ai = GetAI();
    if (!ai)
        return;

    // True, bear form is set up for tanking but even then it's better DPS for levels 10-19 than humanoid form
    if (CAT_FORM == 0 && BEAR_FORM > 0)
        // but only go there if you can get into bear form. else stay here.
        if (ai->CastSpell(BEAR_FORM))
            return _DoNextPVECombatManeuverBear(pTarget);

    //uint32 masterHP = GetMaster()->GetHealth() * 100 / GetMaster()->GetMaxHealth();

    Player *m_bot = GetPlayerBot();
    Unit* pVictim = pTarget->getVictim();

    if (!m_bot->HasInArc(M_PI_F, pTarget))
    {
        m_bot->SetFacingTo(m_bot->GetAngle(pTarget));
        if (pVictim)
            pVictim->Attack(pTarget, true);
    }

    if (CAT_FORM > 0 && !m_bot->HasAura(CAT_FORM, EFFECT_INDEX_0))
        if (!ai->CastSpell(CAT_FORM))
        {
            if (ai->GetManaPercent() < 30) // TODO: tweak this value. Pretty sure bear form mana Req is way less than 30% of base mana, let alone total mana
                return;  // conserve mana
            else
                _DoNextPVECombatManeuverSpellDPS(pTarget);
        }

    // Commented out: Above should take care of it
    //// Technically bear form is better than no form for melee druids levels 10-19.
    //if (m_bot->HasAura(BEAR_FORM, EFFECT_INDEX_0))
    //{
    //    m_bot->RemoveAurasDueToSpell(BEAR_FORM_1);
    //    //ai->TellMaster("FormClearBear");
    //    return;
    //}
    //if (m_bot->HasAura(DIRE_BEAR_FORM, EFFECT_INDEX_0))
    //{
    //    m_bot->RemoveAurasDueToSpell(DIRE_BEAR_FORM_1);
    //    //ai->TellMaster("FormClearDireBear");
    //    return;
    //}
    //if (m_bot->HasAura(MOONKIN_FORM, EFFECT_INDEX_0))
    //{
    //    m_bot->RemoveAurasDueToSpell(MOONKIN_FORM_1);
    //    //ai->TellMaster("FormClearMoonkin");
    //    return;
    //}

    //if (COWER > 0 && m_bot->GetComboPoints() == 1 && ai->GetEnergyAmount() >= 20) // && HasAnyAggroWhereSecondAggroIsNotHealer()
    //{
    //    ai->CastSpell(COWER);
    //    //ai->TellMaster("Cower");
    //}
    if (MAIM > 0 && m_bot->GetComboPoints() >= 1 && pTarget->IsNonMeleeSpellCasted(true))
    {
        ai->CastSpell(MAIM, *pTarget);
        //ai->TellMaster("SpellPreventing Maim");
        return;
    }

    if (RAKE > 0 && m_bot->GetComboPoints() < 1 && ai->GetEnergyAmount() >= 40) // should be replaced by a check for the bleed effect it causes (along with Combo != 5)
    {
        ai->CastSpell(RAKE, *pTarget);
        //ai->TellMaster("Rake");
        return;
    }
    if (MANGLE > 0 && m_bot->GetComboPoints() == 1 && ai->GetEnergyAmount() >= 45)
    {
        ai->CastSpell(MANGLE, *pTarget);
        //ai->TellMaster("Mangle");
        return;
    }
    if (CLAW > 0 && m_bot->GetComboPoints() < 5 && ai->GetEnergyAmount() >= 45)
    {
        ai->CastSpell(CLAW, *pTarget);
        //ai->TellMaster("Claw");
        return;
    }

    if (m_bot->GetComboPoints() == 5)
    {
        if (RIP > 0 && pTarget->getClass() == CLASS_ROGUE && ai->GetEnergyAmount() >= 30)
            ai->CastSpell(RIP, *pTarget);
        else if (FEROCIOUS_BITE > 0 && ai->GetEnergyAmount() >= 35 &&
                 (pTarget->getClass() == CLASS_HUNTER || pTarget->getClass() == CLASS_WARRIOR ||
                  pTarget->getClass() == CLASS_PALADIN || pTarget->getClass() == CLASS_DEATH_KNIGHT))
            ai->CastSpell(FEROCIOUS_BITE, *pTarget);
        else if (ai->GetEnergyAmount() >= 35)
        {
            //ai->TellMaster("Else Maim, Ferocious Bite or Rip.");
            // MAIM must be first check, best option against other classes
            if (MAIM > 0)
                ai->CastSpell(MAIM, *pTarget);
            else if (FEROCIOUS_BITE > 0)
                ai->CastSpell(FEROCIOUS_BITE, *pTarget);
            else if (RIP > 0) // Fair enough, only needs 30 energy... but that means 35 is plenty
                ai->CastSpell(RIP, *pTarget);
        }
        return;
    }
}
CombatManeuverReturns PlayerbotDruidAI::DoNextCombatManeuverPVE(Unit* pTarget)
{
    if (!m_ai)  return RETURN_NO_ACTION_ERROR;
    if (!m_bot) return RETURN_NO_ACTION_ERROR;

    //uint32 masterHP = GetMaster()->GetHealth() * 100 / GetMaster()->GetMaxHealth();

    uint32 spec = m_bot->GetSpec();
    if (spec == 0) // default to spellcasting or healing for healer
        spec = (PlayerbotAI::ORDERS_HEAL & m_ai->GetCombatOrder() ? DRUID_SPEC_RESTORATION : DRUID_SPEC_BALANCE);

    // Make sure healer stays put, don't even melee (aggro) if in range.
    if (m_ai->IsHealer() && m_ai->GetCombatStyle() != PlayerbotAI::COMBAT_RANGED)
        m_ai->SetCombatStyle(PlayerbotAI::COMBAT_RANGED);
    else if (!m_ai->IsHealer() && m_ai->GetCombatStyle() != PlayerbotAI::COMBAT_MELEE)
        m_ai->SetCombatStyle(PlayerbotAI::COMBAT_MELEE);

    //Unit* pVictim = pTarget->getVictim();
    uint32 BEAR = (DIRE_BEAR_FORM > 0 ? DIRE_BEAR_FORM : BEAR_FORM);

    // TODO: do something to allow emergency heals for non-healers?
    switch (CheckForms())
    {
        case RETURN_OK_SHIFTING:
            return RETURN_CONTINUE;

        case RETURN_FAIL:
        case RETURN_OK_CANNOTSHIFT:
            if (spec == DRUID_SPEC_FERAL)
                spec = DRUID_SPEC_BALANCE; // Can't shift, force spellcasting
            break; // rest functions without form

        //case RETURN_OK_NOCHANGE: // great!
        //case RETURN_FAIL_WAITINGONSELFBUFF: // This is war dammit! No time for silly buffs during combat...
        default:
            break;
    }

    //Used to determine if this bot is highest on threat
    Unit *newTarget = m_ai->FindAttacker((PlayerbotAI::ATTACKERINFOTYPE) (PlayerbotAI::AIT_VICTIMSELF | PlayerbotAI::AIT_HIGHESTTHREAT), m_bot);
    if (newTarget) // TODO: && party has a tank
    {
        if (HealPlayer(m_bot) == RETURN_CONTINUE)
            return RETURN_CONTINUE;

        // TODO: Heal tank

        // We have aggro, don't need to heal self or tank, wait for aggro to subside
        //if (m_ai->IsHealer()) // Commented out: not necessary because of below. Leave code here in case below ever changes.
        //    return RETURN_NO_ACTION_OK;

        // We have no shoot spell; Assume auto-attack is on
        return RETURN_NO_ACTION_OK;
    }

    if (m_ai->IsHealer())
       return _DoNextPVECombatManeuverHeal();

    switch (spec)
    {
        case DRUID_SPEC_FERAL:
            if (BEAR > 0 && m_bot->HasAura(BEAR))
                return _DoNextPVECombatManeuverBear(pTarget);
            if (CAT_FORM > 0 && m_bot->HasAura(CAT_FORM))
                return _DoNextPVECombatManeuverCat(pTarget);
            // NO break - failover to DRUID_SPEC_BALANCE

        case DRUID_SPEC_RESTORATION: // There is no Resto DAMAGE rotation. If you insist, go Balance...
        case DRUID_SPEC_BALANCE:
            if (m_bot->HasAura(BEAR) || m_bot->HasAura(CAT_FORM) || m_bot->HasAura(TREE_OF_LIFE))
                return RETURN_NO_ACTION_UNKNOWN; // Didn't shift out of inappropriate form

            return _DoNextPVECombatManeuverSpellDPS(pTarget);

        /*if (BASH > 0 && !pTarget->HasAura(BASH, EFFECT_INDEX_0) && DruidSpellCombat < 5 && CastSpell(BASH, pTarget))
            return RETURN_CONTINUE;
        if (CHALLENGING_ROAR > 0 && pVictim != m_bot && !pTarget->HasAura(CHALLENGING_ROAR, EFFECT_INDEX_0) && !pTarget->HasAura(GROWL, EFFECT_INDEX_0) && CastSpell(CHALLENGING_ROAR, pTarget))
            return RETURN_CONTINUE;
        if (ROOTS > 0 && !pTarget->HasAura(ROOTS, EFFECT_INDEX_0) && CastSpell(ROOTS, pTarget))
            return RETURN_CONTINUE;
        if (HURRICANE > 0 && ai->In_Reach(target,HURRICANE) && m_ai->GetAttackerCount() >= 5 && CastSpell(HURRICANE, pTarget))
        {
            m_ai->SetIgnoreUpdateTime(10);
            return RETURN_CONTINUE;
        }
        if (STARFALL > 0 && ai->In_Reach(target,STARFALL) && !m_bot->HasAura(STARFALL, EFFECT_INDEX_0) && m_ai->GetAttackerCount() >= 3 && CastSpell(STARFALL, pTarget))
            return RETURN_CONTINUE;
        if (BARKSKIN > 0 && pVictim == m_bot && m_ai->GetHealthPercent() < 75 && !m_bot->HasAura(BARKSKIN, EFFECT_INDEX_0) && CastSpell(BARKSKIN, m_bot))
            return RETURN_CONTINUE;
        if (INNERVATE > 0 && ai->In_Reach(m_bot,INNERVATE) && !m_bot->HasAura(INNERVATE, EFFECT_INDEX_0) && CastSpell(INNERVATE, m_bot))
            return RETURN_CONTINUE;
        */
    }

    return RETURN_NO_ACTION_UNKNOWN;
} // end DoNextCombatManeuver
CombatManeuverReturns PlayerbotDruidAI::DoNextCombatManeuverPVE(Unit* pTarget)
{
    if (!m_ai)  return RETURN_NO_ACTION_ERROR;
    if (!m_bot) return RETURN_NO_ACTION_ERROR;

    bool meleeReach = m_bot->CanReachWithMeleeAttack(pTarget);

    //uint32 masterHP = GetMaster()->GetHealth() * 100 / GetMaster()->GetMaxHealth();

    uint32 spec = m_bot->GetSpec();
    if (spec == 0) // default to spellcasting or healing for healer
        spec = (PlayerbotAI::ORDERS_HEAL & m_ai->GetCombatOrder() ? DRUID_SPEC_RESTORATION : DRUID_SPEC_BALANCE);

    // Make sure healer stays put, don't even melee (aggro) if in range: only melee if feral spec AND not healer
    if (!m_ai->IsHealer() && spec == DRUID_SPEC_FERAL && m_ai->GetCombatStyle() != PlayerbotAI::COMBAT_MELEE)
        m_ai->SetCombatStyle(PlayerbotAI::COMBAT_MELEE);
    else    // ranged combat in all other cases
        m_ai->SetCombatStyle(PlayerbotAI::COMBAT_RANGED);

    //Unit* pVictim = pTarget->getVictim();
    uint32 BEAR = (DIRE_BEAR_FORM > 0 ? DIRE_BEAR_FORM : BEAR_FORM);

    // TODO: do something to allow emergency heals for non-healers?
    switch (CheckForms())
    {
        case RETURN_OK_SHIFTING:
            return RETURN_CONTINUE;

        case RETURN_FAIL:
        case RETURN_OK_CANNOTSHIFT:
            if (spec == DRUID_SPEC_FERAL)
                spec = DRUID_SPEC_BALANCE; // Can't shift, force spellcasting
            break; // rest functions without form

        //case RETURN_OK_NOCHANGE: // great!
        //case RETURN_FAIL_WAITINGONSELFBUFF: // This is war dammit! No time for silly buffs during combat...
        default:
            break;
    }

    // Low mana and bot is a caster/healer: cast Innervate on self
    // TODO add group check to also cast on low mana healers or master
    if (m_ai->GetManaPercent() < 15 && ((m_ai->IsHealer() || spec == DRUID_SPEC_RESTORATION)))
        if (INNERVATE > 0 && !m_bot->HasAura(INNERVATE, EFFECT_INDEX_0) && CastSpell(INNERVATE, m_bot))
            return RETURN_CONTINUE;

    //Used to determine if this bot is highest on threat
    Unit* newTarget = m_ai->FindAttacker((PlayerbotAI::ATTACKERINFOTYPE)(PlayerbotAI::AIT_VICTIMSELF | PlayerbotAI::AIT_HIGHESTTHREAT), m_bot);
    if (newTarget && !(m_ai->GetCombatOrder() & PlayerbotAI::ORDERS_TANK) && !m_ai->IsNeutralized(newTarget)) // TODO: && party has a tank
    {
        if (HealPlayer(m_bot) == RETURN_CONTINUE)
            return RETURN_CONTINUE;

        // Aggroed by an elite that came in melee range
        if (m_ai->IsElite(newTarget) && meleeReach)
        {
            // protect the bot with barkskin: the increased casting time is meaningless
            // because bot will then avoid to cast to not angry mob further
            if (m_ai->IsHealer() || spec == DRUID_SPEC_RESTORATION || spec == DRUID_SPEC_BALANCE)
            {
                if (BARKSKIN > 0 && !m_bot->HasAura(BARKSKIN, EFFECT_INDEX_0) && CastSpell(BARKSKIN, m_bot))
                    return RETURN_CONTINUE;

                return RETURN_NO_ACTION_OK;
            }
            //no other cases: cats have cower in the damage rotation and bears can tank
        }
    }

    if (m_ai->IsHealer())
        if (_DoNextPVECombatManeuverHeal() & RETURN_CONTINUE)
            return RETURN_CONTINUE;

    switch (spec)
    {
        case DRUID_SPEC_FERAL:
            if (BEAR > 0 && m_bot->HasAura(BEAR))
                return _DoNextPVECombatManeuverBear(pTarget);
            if (CAT_FORM > 0 && m_bot->HasAura(CAT_FORM))
                return _DoNextPVECombatManeuverCat(pTarget);
        // NO break - failover to DRUID_SPEC_BALANCE

        case DRUID_SPEC_RESTORATION: // There is no Resto DAMAGE rotation. If you insist, go Balance...
        case DRUID_SPEC_BALANCE:
            if (m_bot->HasAura(BEAR) || m_bot->HasAura(CAT_FORM))
                return RETURN_NO_ACTION_UNKNOWN; // Didn't shift out of inappropriate form

            return _DoNextPVECombatManeuverSpellDPS(pTarget);

            /*if (BASH > 0 && !pTarget->HasAura(BASH, EFFECT_INDEX_0) && DruidSpellCombat < 5 && CastSpell(BASH, pTarget))
                return RETURN_CONTINUE;
            if (CHALLENGING_ROAR > 0 && pVictim != m_bot && !pTarget->HasAura(CHALLENGING_ROAR, EFFECT_INDEX_0) && !pTarget->HasAura(GROWL, EFFECT_INDEX_0) && CastSpell(CHALLENGING_ROAR, pTarget))
                return RETURN_CONTINUE;
            if (ROOTS > 0 && !pTarget->HasAura(ROOTS, EFFECT_INDEX_0) && CastSpell(ROOTS, pTarget))
                return RETURN_CONTINUE;
            */
    }

    return RETURN_NO_ACTION_UNKNOWN;
} // end DoNextCombatManeuver