/**
 * GetDispelTarget()
 * return Unit* Returns unit to be dispelled. First checks 'critical' Healer(s), next Tank(s), next Master (if different from:), next DPS.
 *
 * return NULL If NULL is returned, no healing is required. At all.
 *
 * Will need extensive re-write for co-operation amongst multiple healers. As it stands, multiple healers would all pick the same 'ideal'
 * healing target.
 */
Player* PlayerbotClassAI::GetDispelTarget(DispelType dispelType, JOB_TYPE type, bool bMustBeOOC)
{
    if (!m_ai)  return nullptr;
    if (!m_bot) return nullptr;
    if (!m_bot->isAlive() || m_bot->IsInDuel()) return nullptr;
    if (bMustBeOOC && m_bot->isInCombat()) return nullptr;

    // First, fill the list of targets
    if (m_bot->GetGroup())
    {
        // define seperately for sorting purposes - DO NOT CHANGE ORDER!
        std::vector<heal_priority> targets;

        Group::MemberSlotList const& groupSlot = m_bot->GetGroup()->GetMemberSlots();
        for (Group::member_citerator itr = groupSlot.begin(); itr != groupSlot.end(); itr++)
        {
            Player *groupMember = sObjectMgr.GetPlayer(itr->guid);
            if (!groupMember || !groupMember->isAlive())
                continue;
            JOB_TYPE job = GetTargetJob(groupMember);
            if (job & type)
            {
                uint32 dispelMask  = GetDispellMask(dispelType);
                Unit::SpellAuraHolderMap const& auras = groupMember->GetSpellAuraHolderMap();
                for (Unit::SpellAuraHolderMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
                {
                    SpellAuraHolder *holder = itr->second;
                    // Only return group members with negative magic effect
                    if (dispelType == DISPEL_MAGIC && holder->IsPositive())
                        continue;
                    // poison, disease and curse are always negative: return everyone
                    if ((1 << holder->GetSpellProto()->Dispel) & dispelMask)
                        targets.push_back( heal_priority(groupMember, 0, job) );
                }
            }
        }

        // Sorts according to type: Healers first, tanks next, then master followed by DPS, thanks to the order of the TYPE enum
        std::sort(targets.begin(), targets.end());

        if (targets.size())
            return targets.at(0).p;
    }

    return nullptr;
}
示例#2
0
bool PlayerbotPriestAI::HealTarget(Unit* target)
{
    PlayerbotAI* ai = GetAI();
    uint8 hp = target->GetHealth() * 100 / target->GetMaxHealth();

    if (CURE_DISEASE > 0 && ai->GetCombatOrder() != PlayerbotAI::ORDERS_NODISPEL)
    {
        uint32 dispelMask  = GetDispellMask(DISPEL_DISEASE);
        Unit::SpellAuraHolderMap const& auras = target->GetSpellAuraHolderMap();
        for(Unit::SpellAuraHolderMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
        {
            SpellAuraHolder *holder = itr->second;
            if ((1<<holder->GetSpellProto()->Dispel) & dispelMask)
            {
                if(holder->GetSpellProto()->Dispel == DISPEL_DISEASE)
                    ai->CastSpell(CURE_DISEASE, *target);
                return false;
            }
        }
    }

    if (hp >= 80)
        return false;

    if (hp < 25 && FLASH_HEAL && ai->CastSpell(FLASH_HEAL, *target))
        return true;
    else if (hp < 30 && GREATER_HEAL > 0 && ai->CastSpell(GREATER_HEAL, *target))
        return true;
    else if (hp < 33 && BINDING_HEAL > 0 && ai->CastSpell(BINDING_HEAL, *target))
        return true;
    else if (hp < 40 && PRAYER_OF_HEALING > 0 && ai->CastSpell(PRAYER_OF_HEALING, *target))
        return true;
    else if (hp < 50 && CIRCLE_OF_HEALING > 0 && ai->CastSpell(CIRCLE_OF_HEALING, *target))
        return true;
    else if (hp < 60 && HEAL > 0 && ai->CastSpell(HEAL, *target))
        return true;
    else if (hp < 80 && RENEW > 0 && !target->HasAura(RENEW) &&  ai->CastSpell(RENEW, *target))
        return true;
    else
        return false;
} // end HealTarget
示例#3
0
bool PlayerbotClassAI::castDispel (uint32 dispelSpell, Unit *dTarget, bool checkFirst, bool castExistingAura, bool skipFriendlyCheck, bool skipEquipStanceCheck)
{
    if (dispelSpell == 0 || !dTarget ) return false;
    //if (!canCast(dispelSpell, dTarget, true)) return false; //Needless cpu cycles wasted, usually a playerbot can cast a dispell
    const SpellEntry *dSpell = GetSpellStore()->LookupEntry(dispelSpell);
    if (!dSpell) return false;

    for (uint8 i = 0 ; i < MAX_SPELL_EFFECTS ; ++i)
    {
        if (dSpell->Effect[i] != (uint32)SPELL_EFFECT_DISPEL) continue;
        uint32 dispel_type = dSpell->EffectMiscValue[i];
        uint32 dispelMask  = GetDispellMask(DispelType(dispel_type));
        Unit::AuraMap const& auras = dTarget->GetOwnedAuras();
        for (Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); itr++)
        {
            Aura * aura = itr->second;
            AuraApplication * aurApp = aura->GetApplicationOfTarget(dTarget->GetGUID());
            if (!aurApp)
                continue;

            if ((1<<aura->GetSpellProto()->Dispel) & dispelMask)
            {
                if(aura->GetSpellProto()->Dispel == DISPEL_MAGIC)
                {
                    bool positive = aurApp->IsPositive() ? (!(aura->GetSpellProto()->AttributesEx & SPELL_ATTR0_UNK7)) : false;

                    // do not remove positive auras if friendly target
                    //               negative auras if non-friendly target
                    if(positive == dTarget->IsFriendlyTo(GetPlayerBot()))
                        continue;
                }
                // If there is a successfull match return, else continue searching.
                if (CastSpell(dSpell, dTarget, checkFirst, castExistingAura, skipFriendlyCheck, skipEquipStanceCheck)) {
                    return true;
                }
            }
        }
    }
    return false;
}
CombatManeuverReturns PlayerbotPaladinAI::HealPlayer(Player* target)
{
    CombatManeuverReturns r = PlayerbotClassAI::HealPlayer(target);
    if (r != RETURN_NO_ACTION_OK)
        return r;

    if (!target->isAlive())
    {
        if (REDEMPTION && m_ai->CastSpell(REDEMPTION, *target))
        {
            std::string msg = "Resurrecting ";
            msg += target->GetName();
            m_bot->Say(msg, LANG_UNIVERSAL);
            return RETURN_CONTINUE;
        }
        return RETURN_NO_ACTION_ERROR; // not error per se - possibly just OOM
    }

    if (PURIFY > 0 && (m_ai->GetCombatOrder() & PlayerbotAI::ORDERS_NODISPEL) == 0)
    {
        uint32 DISPEL = CLEANSE > 0 ? CLEANSE : PURIFY;
        uint32 dispelMask  = GetDispellMask(DISPEL_DISEASE);
        uint32 dispelMask2 = GetDispellMask(DISPEL_POISON);
        uint32 dispelMask3 = GetDispellMask(DISPEL_MAGIC);
        Unit::SpellAuraHolderMap const& auras = target->GetSpellAuraHolderMap();
        for (Unit::SpellAuraHolderMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
        {
            SpellAuraHolder* holder = itr->second;
            if ((1 << holder->GetSpellProto()->Dispel) & dispelMask)
            {
                if (holder->GetSpellProto()->Dispel == DISPEL_DISEASE)
                {
                    if (m_ai->CastSpell(DISPEL, *target))
                        return RETURN_CONTINUE;
                    return RETURN_NO_ACTION_ERROR;
                }
            }
            else if ((1 << holder->GetSpellProto()->Dispel) & dispelMask2)
            {
                if (holder->GetSpellProto()->Dispel == DISPEL_POISON)
                {
                    if (m_ai->CastSpell(DISPEL, *target))
                        return RETURN_CONTINUE;
                    return RETURN_NO_ACTION_ERROR;
                }
            }
            else if ((1 << holder->GetSpellProto()->Dispel) & dispelMask3 & (DISPEL == CLEANSE))
            {
                if (holder->GetSpellProto()->Dispel == DISPEL_MAGIC)
                {
                    if (m_ai->CastSpell(DISPEL, *target))
                        return RETURN_CONTINUE;
                    return RETURN_NO_ACTION_ERROR;
                }
            }
        }
    }

    uint8 hp = target->GetHealthPercent();

    // Everyone is healthy enough, return OK. MUST correlate to highest value below (should be last HP check)
    if (hp >= 90)
        return RETURN_NO_ACTION_OK;

    if (hp < 25 && m_ai->CastSpell(LAY_ON_HANDS, *target))
        return RETURN_CONTINUE;

    // You probably want to save this for tank/healer trouble
    if (hp < 30 && HAND_OF_PROTECTION > 0 && !target->HasAura(FORBEARANCE, EFFECT_INDEX_0)
            && !target->HasAura(HAND_OF_PROTECTION, EFFECT_INDEX_0) && !target->HasAura(DIVINE_PROTECTION, EFFECT_INDEX_0)
            && !target->HasAura(DIVINE_SHIELD, EFFECT_INDEX_0) && (GetTargetJob(target) & (JOB_HEAL | JOB_TANK))
            && m_ai->CastSpell(HAND_OF_PROTECTION, *target))
        return RETURN_CONTINUE;

    // Isn't this more of a group heal spell?
    if (hp < 40 && m_ai->CastSpell(FLASH_OF_LIGHT, *target))
        return RETURN_CONTINUE;

    if (hp < 60 && m_ai->CastSpell(HOLY_SHOCK, *target))
        return RETURN_CONTINUE;

    if (hp < 90 && m_ai->CastSpell(HOLY_LIGHT, *target))
        return RETURN_CONTINUE;

    return RETURN_NO_ACTION_UNKNOWN;
} // end HealTarget
bool PlayerbotClassAI::castSelfCCBreakers (uint32 castList[])
{
    uint32 dispelSpell = 0;
    Player *dTarget = GetPlayerBot();


            /* dispelSpell = (uint32) R_ESCAPE_ARTIST; // this is script effect,
            Unit::AuraMap const& auras = dTarget->GetOwnedAuras();
            for (Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); itr++)
            {
                Aura * aura = itr->second;
                AuraApplication * aurApp = aura->GetApplicationOfTarget(dTarget->GetGUID());
                if (!aurApp)
                    continue;

                if ( ( aura->GetSpellProto()->Mechanic == MECHANIC_SNARE ) || ( aura->GetSpellProto()->Mechanic == MECHANIC_ROOT ) )
                {
                    if(aura->GetSpellProto()->Dispel == DISPEL_MAGIC)
                    {
                        bool positive = aurApp->IsPositive() ? (!(aura->GetSpellProto()->AttributesEx & SPELL_ATTR0_UNK7)) : false;

                        // do not remove positive auras if friendly target
                        //               negative auras if non-friendly target
                        if(positive == dTarget->IsFriendlyTo(caster))
                            continue;
                    }
                    return castSpell(dispelSpell, dTarget);
                }
            }
            return false;  */

        // racial abilities
    /*  if( GetPlayerBot()->getRace() == RACE_BLOODELF && !pTarget->HasAura( ARCANE_TORRENT,0 ) && castSpell( ARCANE_TORRENT,pTarget ) ) {
         //GetPlayerBot()->Say("Arcane Torrent!", LANG_UNIVERSAL);
    } else if( GetPlayerBot()->getRace() == RACE_HUMAN && (GetPlayerBot()->HasUnitState( UNIT_STAT_STUNNED ) || GetPlayerBot()->HasAuraType( SPELL_AURA_MOD_FEAR ) || GetPlayerBot()->HasAuraType( SPELL_AURA_MOD_DECREASE_SPEED ) || GetPlayerBot()->HasAuraType( SPELL_AURA_MOD_CHARM )) && castSpell( EVERY_MAN_FOR_HIMSELF, GetPlayerBot() ) ) {
        //GetPlayerBot()->Say("EVERY MAN FOR HIMSELF!", LANG_UNIVERSAL);
    } else if( GetPlayerBot()->getRace() == RACE_UNDEAD_PLAYER && (GetPlayerBot()->HasAuraType( SPELL_AURA_MOD_FEAR ) || GetPlayerBot()->HasAuraType( SPELL_AURA_MOD_CHARM )) && castSpell( WILL_OF_THE_FORSAKEN, GetPlayerBot() ) ) {
       // GetPlayerBot()->Say("WILL OF THE FORSAKEN!", LANG_UNIVERSAL);
    } else if( GetPlayerBot()->getRace() == RACE_DWARF && GetPlayerBot()->HasAuraState( AURA_STATE_DEADLY_POISON ) && castSpell( STONEFORM, GetPlayerBot() ) ) {
        //GetPlayerBot()->Say("STONEFORM!", LANG_UNIVERSAL);
    } else if( GetPlayerBot()->getRace() == RACE_GNOME && (GetPlayerBot()->HasUnitState( UNIT_STAT_STUNNED ) || GetPlayerBot()->HasAuraType( SPELL_AURA_MOD_DECREASE_SPEED )) && castSpell( ESCAPE_ARTIST, GetPlayerBot() ) ) {
       // GetPlayerBot()->Say("ESCAPE ARTIST!", LANG_UNIVERSAL);
    } */

    for (uint8 j = 0; j <  sizeof (castList); j++)
    {
        dispelSpell = castList[j];
        if (dispelSpell == 0 || !dTarget->HasSpell(dispelSpell) || !CanCast(dispelSpell, dTarget, true)) continue;
        SpellEntry const *dSpell = GetSpellStore()->LookupEntry(dispelSpell);
        if (!dSpell) continue;

        for (uint8 i = 0 ; i < MAX_SPELL_EFFECTS ; ++i)
        {
            if (dSpell->Effect[i] != (uint32)SPELL_EFFECT_DISPEL && dSpell->Effect[i] != (uint32)SPELL_EFFECT_APPLY_AURA) continue;
            if (dSpell->Effect[i] == (uint32)SPELL_EFFECT_APPLY_AURA && (
                (dSpell->EffectApplyAuraName[i] != (uint32) SPELL_AURA_MECHANIC_IMMUNITY) ||
                (dSpell->EffectApplyAuraName[i] != (uint32) SPELL_AURA_DISPEL_IMMUNITY)
                )) continue;

            Unit::AuraMap const& auras = dTarget->GetOwnedAuras();
            for (Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); itr++)
            {
                Aura * aura = itr->second;
                AuraApplication * aurApp = aura->GetApplicationOfTarget(dTarget->GetGUID());
                if (!aurApp) continue;

                if (aura->GetSpellProto() && (
                    (dSpell->Effect[i] == (uint32)SPELL_EFFECT_DISPEL  && ((1<<aura->GetSpellProto()->Dispel) & GetDispellMask(DispelType(dSpell->EffectMiscValue[i]))) )
                    || (dSpell->EffectApplyAuraName[i] == (uint32) SPELL_AURA_MECHANIC_IMMUNITY && ( GetAllSpellMechanicMask(aura->GetSpellProto()) & ( 1 << dSpell->EffectMiscValue[i]) ) )
                    || (dSpell->EffectApplyAuraName[i] == (uint32) SPELL_AURA_DISPEL_IMMUNITY && ( (1<<aura->GetSpellProto()->Dispel) & GetDispellMask(DispelType(dSpell->EffectMiscValue[i])) ) )
                    ) )
                {
                    if(aura->GetSpellProto()->Dispel == DISPEL_MAGIC)
                    {
                        bool positive = aurApp->IsPositive() ? (!(aura->GetSpellProto()->AttributesEx & SPELL_ATTR0_UNK7)) : false;
                        if(positive)continue;
                    }
                    return CastSpell(dispelSpell, dTarget, false);
                }
            }
        }
    }
    return false;
}
示例#6
0
bool PlayerbotDruidAI::HealTarget(Unit *target)
{
    PlayerbotAI* ai = GetAI();
    uint8 hp = target->GetHealth() * 100 / target->GetMaxHealth();

    //If spell exists and orders say we should be dispelling
    if ((REMOVE_CURSE > 0 || ABOLISH_POISON > 0) && ai->GetCombatOrder() != PlayerbotAI::ORDERS_NODISPEL)
    {
        //This does something important(lol)
        uint32 dispelMask  = GetDispellMask(DISPEL_CURSE);
        uint32 dispelMask2  = GetDispellMask(DISPEL_POISON);
        //Get a list of all the targets auras(spells affecting target)
        Unit::SpellAuraHolderMap const& auras = target->GetSpellAuraHolderMap();
        //Iterate through the auras
        for (Unit::SpellAuraHolderMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
        {
            SpellAuraHolderPtr holder = itr->second;
            //I dont know what this does but it doesn't work without it
            if ((1 << holder->GetSpellProto()->Dispel) & dispelMask)
            {
                //If the spell is dispellable and we can dispel it, do so
                if ((holder->GetSpellProto()->Dispel == DISPEL_CURSE) & (REMOVE_CURSE > 0))
                    ai->CastSpell(REMOVE_CURSE, *target);
                return false;
            }
            else if ((1 << holder->GetSpellProto()->Dispel) & dispelMask2)
            {
                if ((holder->GetSpellProto()->Dispel == DISPEL_POISON) & (ABOLISH_POISON > 0))
                    ai->CastSpell(ABOLISH_POISON, *target);
                return false;
            }
        }
    }

    if (hp >= 70)
        return false;

    // Reset form if needed
    GoBuffForm(GetPlayerBot());

    if (hp < 70 && REJUVENATION > 0 && !target->HasAura(REJUVENATION) && ai->CastSpell(REJUVENATION, *target))
        return true;

    if (hp < 60 && LIFEBLOOM > 0 && !target->HasAura(LIFEBLOOM) && ai->CastSpell(LIFEBLOOM, *target))
        return true;

    if (hp < 55 && REGROWTH > 0 && !target->HasAura(REGROWTH) && ai->CastSpell(REGROWTH, *target))
        return true;

    if (hp < 50 && SWIFTMEND > 0 && (target->HasAura(REJUVENATION) || target->HasAura(REGROWTH)) && ai->CastSpell(SWIFTMEND, *target))
        return true;

    if (hp < 45 && WILD_GROWTH > 0 && !target->HasAura(WILD_GROWTH) && ai->CastSpell(WILD_GROWTH, *target))
        return true;

    if (hp < 30 && NOURISH > 0 && ai->CastSpell(NOURISH, *target))
        return true;

    if (hp < 25 && HEALING_TOUCH > 0 && ai->CastSpell(HEALING_TOUCH, *target))
        return true;

    return false;
} // end HealTarget
CombatManeuverReturns PlayerbotShamanAI::HealPlayer(Player* target)
{
    CombatManeuverReturns r = PlayerbotClassAI::HealPlayer(target);
    if (r != RETURN_NO_ACTION_OK)
        return r;

    if (!target->isAlive())
    {
        if (ANCESTRAL_SPIRIT && m_ai->CastSpell(ANCESTRAL_SPIRIT, *target))
        {
            std::string msg = "Resurrecting ";
            msg += target->GetName();
            m_bot->Say(msg, LANG_UNIVERSAL);
            return RETURN_CONTINUE;
        }
        return RETURN_NO_ACTION_ERROR; // not error per se - possibly just OOM
    }

    // Dispel if necessary
    if ((CURE_DISEASE_SHAMAN > 0 || CURE_POISON_SHAMAN > 0) && (m_ai->GetCombatOrder() & PlayerbotAI::ORDERS_NODISPEL) == 0)
    {
        uint32 dispelMask  = GetDispellMask(DISPEL_POISON);
        uint32 dispelMask2  = GetDispellMask(DISPEL_DISEASE);
        Unit::SpellAuraHolderMap const& auras = target->GetSpellAuraHolderMap();
        for (Unit::SpellAuraHolderMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
        {
            SpellAuraHolder *holder = itr->second;
            if ((1 << holder->GetSpellProto()->Dispel) & dispelMask)
            {
                if (holder->GetSpellProto()->Dispel == DISPEL_POISON)
                {
                    if (m_ai->CastSpell(CURE_POISON_SHAMAN, *target))
                        return RETURN_CONTINUE;
                    return RETURN_NO_ACTION_ERROR;
                }
            }
            else if ((1 << holder->GetSpellProto()->Dispel) & dispelMask2)
            {
                if (holder->GetSpellProto()->Dispel == DISPEL_DISEASE)
                {
                    if (m_ai->CastSpell(CURE_DISEASE_SHAMAN, *target))
                        return RETURN_CONTINUE;
                    return RETURN_NO_ACTION_ERROR;
                }
            }
        }
    }

    // Everyone is healthy enough, return OK. MUST correlate to highest value below (should be last HP check)
    if (target->GetHealthPercent() >= 80)
        return RETURN_NO_ACTION_OK;

    // Technically the best rotation is CHAIN + LHW + LHW subbing in HW for trouble (bad mana efficiency)
    if (target->GetHealthPercent() < 30 && HEALING_WAVE > 0 && m_ai->CastSpell(HEALING_WAVE, *target))
        return RETURN_CONTINUE;
    if (target->GetHealthPercent() < 50 && LESSER_HEALING_WAVE > 0 && m_ai->CastSpell(LESSER_HEALING_WAVE, *target))
        return RETURN_CONTINUE;
    if (target->GetHealthPercent() < 80 && CHAIN_HEAL > 0 && m_ai->CastSpell(CHAIN_HEAL, *target))
        return RETURN_CONTINUE;

    return RETURN_NO_ACTION_UNKNOWN;
} // end HealTarget
示例#8
0
CombatManeuverReturns PlayerbotPriestAI::HealPlayer(Player* target)
{
    CombatManeuverReturns r = PlayerbotClassAI::HealPlayer(target);
    if (r != RETURN_NO_ACTION_OK)
        return r;

    if (!target->isAlive())
    {
        if (RESURRECTION && m_ai->CastSpell(RESURRECTION, *target))
        {
            std::string msg = "Resurrecting ";
            msg += target->GetName();
            m_bot->Say(msg, LANG_UNIVERSAL);
            return RETURN_CONTINUE;
        }
        return RETURN_NO_ACTION_ERROR; // not error per se - possibly just OOM
    }

    if (CURE_DISEASE > 0 && (m_ai->GetCombatOrder() & PlayerbotAI::ORDERS_NODISPEL) == 0)
    {
        uint32 dispelMask  = GetDispellMask(DISPEL_DISEASE);
        Unit::SpellAuraHolderMap const& auras = target->GetSpellAuraHolderMap();
        for (Unit::SpellAuraHolderMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
        {
            SpellAuraHolder *holder = itr->second;
            if ((1 << holder->GetSpellProto()->Dispel) & dispelMask)
            {
                if (holder->GetSpellProto()->Dispel == DISPEL_DISEASE)
                {
                    m_ai->CastSpell(CURE_DISEASE, *target);
                    return RETURN_CONTINUE;
                }
            }
        }
    }

    uint8 hp = target->GetHealthPercent();
    uint8 hpSelf = m_ai->GetHealthPercent();

    if (hp >= 90)
        return RETURN_NO_ACTION_OK;

    // TODO: Integrate shield here
    if (hp < 35 && FLASH_HEAL > 0 && m_ai->CastSpell(FLASH_HEAL, *target))
        return RETURN_CONTINUE;
    if (hp < 45 && GREATER_HEAL > 0 && m_ai->CastSpell(GREATER_HEAL, *target))
        return RETURN_CONTINUE;
    // Heals target AND self for equal amount
    if (hp < 60 && hpSelf < 80 && BINDING_HEAL > 0 && m_ai->CastSpell(BINDING_HEAL, *target))
        return RETURN_CONTINUE;
    if (hp < 60 && PRAYER_OF_MENDING > 0 && !target->HasAura(PRAYER_OF_MENDING, EFFECT_INDEX_0) && CastSpell(PRAYER_OF_MENDING, target))
        return RETURN_FINISHED_FIRST_MOVES;
    if (hp < 60 && HEAL > 0 && m_ai->CastSpell(HEAL, *target))
        return RETURN_CONTINUE;
    if (hp < 90 && RENEW > 0 && !target->HasAura(RENEW) && m_ai->CastSpell(RENEW, *target))
        return RETURN_CONTINUE;

    // Group heal. Not really useful until a group check is available?
    //if (hp < 40 && PRAYER_OF_HEALING > 0 && m_ai->CastSpell(PRAYER_OF_HEALING, *target) & RETURN_CONTINUE)
    //    return RETURN_CONTINUE;
    // Group heal. Not really useful until a group check is available?
    //if (hp < 50 && CIRCLE_OF_HEALING > 0 && m_ai->CastSpell(CIRCLE_OF_HEALING, *target) & RETURN_CONTINUE)
    //    return RETURN_CONTINUE;

    return RETURN_NO_ACTION_OK;
} // end HealTarget
CombatManeuverReturns PlayerbotPaladinAI::HealPlayer(Player* target)
{
    CombatManeuverReturns r = PlayerbotClassAI::HealPlayer(target);
    if (r != RETURN_NO_ACTION_OK)
        return r;

    if (!target->isAlive())
    {
        if (REDEMPTION && m_ai->CastSpell(REDEMPTION, *target))
        {
            std::string msg = "Resurrecting ";
            msg += target->GetName();
            m_bot->Say(msg, LANG_UNIVERSAL);
            return RETURN_CONTINUE;
        }
        return RETURN_NO_ACTION_ERROR; // not error per se - possibly just OOM
    }

    if (PURIFY > 0 && (m_ai->GetCombatOrder() & PlayerbotAI::ORDERS_NODISPEL) == 0)
    {
        uint32 DISPEL = CLEANSE > 0 ? CLEANSE : PURIFY;
        uint32 dispelMask  = GetDispellMask(DISPEL_DISEASE);
        uint32 dispelMask2 = GetDispellMask(DISPEL_POISON);
        uint32 dispelMask3 = GetDispellMask(DISPEL_MAGIC);
        Unit::SpellAuraHolderMap const& auras = target->GetSpellAuraHolderMap();
        for(Unit::SpellAuraHolderMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
        {
            SpellAuraHolder *holder = itr->second;
            if ((1 << holder->GetSpellProto()->Dispel) & dispelMask)
            {
                if (holder->GetSpellProto()->Dispel == DISPEL_DISEASE)
                {
                    if (m_ai->CastSpell(DISPEL, *target))
                        return RETURN_CONTINUE;
                    return RETURN_NO_ACTION_ERROR;
                }
            }
            else if ((1 << holder->GetSpellProto()->Dispel) & dispelMask2)
            {
                if (holder->GetSpellProto()->Dispel == DISPEL_POISON)
                {
                    if (m_ai->CastSpell(DISPEL, *target))
                        return RETURN_CONTINUE;
                    return RETURN_NO_ACTION_ERROR;
                }
            }
            else if ((1 << holder->GetSpellProto()->Dispel) & dispelMask3 & (DISPEL == CLEANSE))
            {
                if (holder->GetSpellProto()->Dispel == DISPEL_MAGIC)
                {
                    if (m_ai->CastSpell(DISPEL, *target))
                        return RETURN_CONTINUE;
                    return RETURN_NO_ACTION_ERROR;
                }
            }
        }
    }

    // Define a tank bot will look at
    Unit* pMainTank = GetHealTarget(JOB_TANK);

    // If target is out of range (40 yards) and is a tank: move towards it
    // Other classes have to adjust their position to the healers
    // TODO: This code should be common to all healers and will probably
    // move to a more suitable place
    if (pMainTank && !m_ai->In_Reach(pMainTank, FLASH_OF_LIGHT))
    {
        m_bot->GetMotionMaster()->MoveFollow(target, 39.0f, m_bot->GetOrientation());
        return RETURN_CONTINUE;
    }

    uint8 hp = target->GetHealthPercent();

    // Everyone is healthy enough, return OK. MUST correlate to highest value below (should be last HP check)
    if (hp >= 90)
        return RETURN_NO_ACTION_OK;

    if (hp < 10 && LAY_ON_HANDS && !m_bot->HasSpellCooldown(LAY_ON_HANDS) && m_ai->In_Reach(target,LAY_ON_HANDS) && m_ai->CastSpell(LAY_ON_HANDS, *target))
        return RETURN_CONTINUE;

    // Target is a moderately wounded healer or a badly wounded not tank? Blessing of Protection!
    if (BLESSING_OF_PROTECTION > 0
        && ((hp < 25 && (GetTargetJob(target) & JOB_HEAL)) || (hp < 15 && !(GetTargetJob(target) & JOB_TANK)))
        && !m_bot->HasSpellCooldown(BLESSING_OF_PROTECTION) && m_ai->In_Reach(target,BLESSING_OF_PROTECTION)
        && !target->HasAura(FORBEARANCE, EFFECT_INDEX_0)
        && !target->HasAura(BLESSING_OF_PROTECTION, EFFECT_INDEX_0) && !target->HasAura(DIVINE_PROTECTION, EFFECT_INDEX_0)
        && !target->HasAura(DIVINE_SHIELD, EFFECT_INDEX_0)
        && m_ai->CastSpell(BLESSING_OF_PROTECTION, *target))
        return RETURN_CONTINUE;

    // Low HP : activate Divine Favor to make next heal a critical heal
    if (hp < 25 && DIVINE_FAVOR > 0 && !m_bot->HasAura(DIVINE_FAVOR, EFFECT_INDEX_0) && !m_bot->HasSpellCooldown(DIVINE_FAVOR) && m_ai->CastSpell (DIVINE_FAVOR, *m_bot))
        return RETURN_CONTINUE;

    if (hp < 40 && FLASH_OF_LIGHT && m_ai->In_Reach(target,FLASH_OF_LIGHT) && m_ai->CastSpell(FLASH_OF_LIGHT, *target))
        return RETURN_CONTINUE;

    if (hp < 60 && HOLY_SHOCK && m_ai->In_Reach(target,HOLY_SHOCK) && m_ai->CastSpell(HOLY_SHOCK, *target))
        return RETURN_CONTINUE;

    if (hp < 90 && HOLY_LIGHT && m_ai->In_Reach(target,HOLY_LIGHT) && m_ai->CastSpell(HOLY_LIGHT, *target))
        return RETURN_CONTINUE;

    return RETURN_NO_ACTION_UNKNOWN;
} // end HealTarget
示例#10
0
CombatManeuverReturns PlayerbotDruidAI::HealPlayer(Player* target)
{
    CombatManeuverReturns r = PlayerbotClassAI::HealPlayer(target);
    if (r != RETURN_NO_ACTION_OK)
        return r;

    if (!target->isAlive())
    {
        if (m_bot->isInCombat())
        {
            // TODO: Add check for cooldown
            if (REBIRTH && m_ai->In_Reach(target,REBIRTH) && m_ai->CastSpell(REBIRTH, *target))
            {
                std::string msg = "Resurrecting ";
                msg += target->GetName();
                m_bot->Say(msg, LANG_UNIVERSAL);
                return RETURN_CONTINUE;
            }
        }
        else
        {
            if (REVIVE && m_ai->In_Reach(target,REVIVE) && m_ai->CastSpell(REVIVE, *target))
            {
                std::string msg = "Resurrecting ";
                msg += target->GetName();
                m_bot->Say(msg, LANG_UNIVERSAL);
                return RETURN_CONTINUE;
            }
        }
        return RETURN_NO_ACTION_ERROR; // not error per se - possibly just OOM
    }

    //If spell exists and orders say we should be dispelling
    if ((REMOVE_CURSE > 0 || ABOLISH_POISON > 0) && (m_ai->GetCombatOrder() & PlayerbotAI::ORDERS_NODISPEL) == 0)
    {
        //This does something important(lol)
        uint32 dispelMask  = GetDispellMask(DISPEL_CURSE);
        uint32 dispelMask2  = GetDispellMask(DISPEL_POISON);
        //Get a list of all the targets auras(spells affecting target)
        Unit::SpellAuraHolderMap const& auras = target->GetSpellAuraHolderMap();
        //Iterate through the auras
        for (Unit::SpellAuraHolderMap::const_iterator itr = auras.begin(); itr != auras.end(); itr++)
        {
            SpellAuraHolder *holder = itr->second;
            //I dont know what this does but it doesn't work without it
            if ((1 << holder->GetSpellProto()->Dispel) & dispelMask)
            {
                //If the spell is dispellable and we can dispel it, do so
                if ((holder->GetSpellProto()->Dispel == DISPEL_CURSE) & (REMOVE_CURSE > 0))
                {
                    if (CastSpell(REMOVE_CURSE, target))
                        return RETURN_CONTINUE;
                    return RETURN_NO_ACTION_ERROR;
                }
            }
            else if ((1 << holder->GetSpellProto()->Dispel) & dispelMask2)
            {
                if ((holder->GetSpellProto()->Dispel == DISPEL_POISON) & (ABOLISH_POISON > 0))
                {
                    if (CastSpell(ABOLISH_POISON, target))
                        return RETURN_CONTINUE;
                    return RETURN_NO_ACTION_ERROR;
                }
            }
        }
    }

    uint8 hp = target->GetHealthPercent();

    // Everyone is healthy enough, return OK. MUST correlate to highest value below (should be last HP check)
    if (hp >= 90)
        return RETURN_NO_ACTION_OK;

    // Reset form if needed
    if (!m_bot->HasAura(TREE_OF_LIFE) || TREE_OF_LIFE == 0)
        GoBuffForm(GetPlayerBot());

    // Start heals. Do lowest HP checks at the top
    if (hp < 30)
    {
        // TODO: Use in conjunction with Nature's Swiftness
        if (HEALING_TOUCH > 0 && m_ai->In_Reach(target,HEALING_TOUCH) && (NOURISH == 0 /*|| CastSpell(NATURES_SWIFTNESS)*/ ) && CastSpell(HEALING_TOUCH, target))
            return RETURN_CONTINUE;

        if (NOURISH > 0 && m_ai->In_Reach(target,NOURISH) && CastSpell(NOURISH, target))
            return RETURN_CONTINUE;
    }

    if (hp < 45 && WILD_GROWTH > 0 && m_ai->In_Reach(target,WILD_GROWTH) && !target->HasAura(WILD_GROWTH) && CastSpell(WILD_GROWTH, target))
        return RETURN_CONTINUE;

    if (hp < 50 && SWIFTMEND > 0 && m_ai->In_Reach(target,SWIFTMEND) && (target->HasAura(REJUVENATION) || target->HasAura(REGROWTH)) && CastSpell(SWIFTMEND, target))
        return RETURN_CONTINUE;

    if (hp < 60 && REGROWTH > 0 && m_ai->In_Reach(target,REGROWTH) && !target->HasAura(REGROWTH) && CastSpell(REGROWTH, target))
        return RETURN_CONTINUE;

    if (hp < 65 && LIFEBLOOM > 0 && m_ai->In_Reach(target,LIFEBLOOM) && !target->HasAura(LIFEBLOOM) && CastSpell(LIFEBLOOM, target))
        return RETURN_CONTINUE;

    if (hp < 90 && REJUVENATION > 0 && m_ai->In_Reach(target,REJUVENATION) && !target->HasAura(REJUVENATION) && CastSpell(REJUVENATION, target))
        return RETURN_CONTINUE;

    return RETURN_NO_ACTION_UNKNOWN;
} // end HealTarget