void AIUpdate()
	{
		if((GetHealthPercent() <= 85  && mSummon == 0) || 
			( GetHealthPercent() <= 70 && mSummon == 1 ) ||
			( GetHealthPercent() <= 55 && mSummon == 2 ) ||
			( GetHealthPercent() <= 40 && mSummon == 3 ) || 
		( GetHealthPercent() <= 25 && mSummon == 4 ))
		{
			CastSpell(mPureEnergy);
			++mSummon;
			//SpawnCreature(CN_PURE_ENERGY, 231, -207, 6, 0, true);
		}

		if( GetHealthPercent() <= 10 && GetPhase() == 1 )
			SetPhase(2);
	
		
		ParentClass::AIUpdate();
	} 
bool PlayerbotPaladinAI::ChangeAura(uint32 aura)
{
    Player *m_bot = GetPlayerBot();
    if(!aura) return false;

    if(!CanCast(aura,m_bot)) return false;

    if(m_bot->HasAura(aura))
    {
        if (aura == DEVOTION_AURA)
        {
            if (ChangeAura(FIRE_AURA)) return true;
            if (ChangeAura(FROST_AURA)) return true;
            if (ChangeAura(SHADOW_AURA)) return true;
            return true;
        }
        else return ChangeAura(DEVOTION_AURA);
    }
    return CastSpell(aura,m_bot,false);
}
CombatManeuverReturns PlayerbotDruidAI::_DoNextPVECombatManeuverHeal()
{
    if (!m_ai)  return RETURN_NO_ACTION_ERROR;
    if (!m_bot) return RETURN_NO_ACTION_ERROR;

    // (un)Shapeshifting is considered one step closer so will return true (and have the bot wait a bit for the GCD)
    if (TREE_OF_LIFE > 0 && !m_bot->HasAura(TREE_OF_LIFE, EFFECT_INDEX_0))
        if (CastSpell(TREE_OF_LIFE, m_bot))
            return RETURN_CONTINUE;

    if (m_bot->HasAura(CAT_FORM, EFFECT_INDEX_0))
    {
        m_bot->RemoveAurasDueToSpell(CAT_FORM_1);
        //m_ai->TellMaster("FormClearCat");
        return RETURN_CONTINUE;
    }
    if (m_bot->HasAura(BEAR_FORM, EFFECT_INDEX_0))
    {
        m_bot->RemoveAurasDueToSpell(BEAR_FORM_1);
        //m_ai->TellMaster("FormClearBear");
        return RETURN_CONTINUE;
    }
    if (m_bot->HasAura(DIRE_BEAR_FORM, EFFECT_INDEX_0))
    {
        m_bot->RemoveAurasDueToSpell(DIRE_BEAR_FORM_1);
        //m_ai->TellMaster("FormClearDireBear");
        return RETURN_CONTINUE;
    }
    // spellcasting form, but disables healing spells so it's got to go
    if (m_bot->HasAura(MOONKIN_FORM, EFFECT_INDEX_0))
    {
        m_bot->RemoveAurasDueToSpell(MOONKIN_FORM_1);
        //m_ai->TellMaster("FormClearMoonkin");
        return RETURN_CONTINUE;
    }

    if (HealPlayer(GetHealTarget()) & (RETURN_NO_ACTION_OK | RETURN_CONTINUE))
        return RETURN_CONTINUE;

    return RETURN_NO_ACTION_UNKNOWN;
}
bool PlayerbotShamanAI::HealTarget(Unit *target, uint8 hp)
{
    if(!target || target->isDead()) return false;
    Player *m_bot = GetPlayerBot();

    if(hp < 30 && m_bot->isInCombat() && CastSpell(NATURES_SWIFTNESS, m_bot)) {} // NO gcd
    if(hp < 60 && CanCast(HEAL,target,true) && m_bot->HasAura(NATURES_SWIFTNESS) && CastSpell(HEAL, target, false)) { return true; }
    if(hp < 30 && CastSpell(LESSER_HEAL,target,true,true)) { return true; }
    if(hp < 40 && m_bot->getRace() == (uint8) RACE_DRAENEI && CastSpell(R_GIFT_OF_NAARU,target)) {} // no GCD
    if(hp < 65 && CanCast(EARTH_SHIELD,target) && !m_bot->HasAura(EARTH_SHIELD,m_bot->GetGUID()) && CastSpell(EARTH_SHIELD,target,false)) { return true; }
    if(hp < 65 && CastSpell(HEAL,target,true,true)) { return true; }
    if(hp < 85 && CastSpell(LESSER_HEAL,target,true,true)) { return true; }

    return false;
} //end HealTarget
Example #5
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 PlayerbotDruidAI::_DoNextPVECombatManeuverBear(Unit* pTarget)
{
    if (!m_ai)  return RETURN_NO_ACTION_ERROR;
    if (!m_bot) return RETURN_NO_ACTION_ERROR;

    if (!m_bot->HasAura( (DIRE_BEAR_FORM > 0 ? DIRE_BEAR_FORM : BEAR_FORM) )) return RETURN_NO_ACTION_ERROR;

    // 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);
    Unit* pVictim = pTarget->getVictim();

    // Face enemy, make sure you're attacking
    if (!m_bot->HasInArc(M_PI_F, pTarget))
    {
        m_bot->SetFacingTo(m_bot->GetAngle(pTarget));
        if (pVictim)
            pVictim->Attack(pTarget, true);
    }

    if (PlayerbotAI::ORDERS_TANK & m_ai->GetCombatOrder() && !newTarget && GROWL > 0 && !m_bot->HasSpellCooldown(GROWL))
        if (CastSpell(GROWL, pTarget))
            return RETURN_CONTINUE;

    if (FAERIE_FIRE_FERAL > 0 && m_ai->In_Reach(pTarget,FAERIE_FIRE_FERAL) && !pTarget->HasAura(FAERIE_FIRE_FERAL, EFFECT_INDEX_0))
        if (CastSpell(FAERIE_FIRE_FERAL, pTarget))
            return RETURN_CONTINUE;

    if (SWIPE > 0 && m_ai->In_Reach(pTarget,SWIPE) && m_ai->GetAttackerCount() >= 2 && CastSpell(SWIPE, pTarget))
        return RETURN_CONTINUE;

    if (ENRAGE > 0 && !m_bot->HasSpellCooldown(ENRAGE) && CastSpell(ENRAGE, m_bot))
        return RETURN_CONTINUE;

    if (DEMORALIZING_ROAR > 0 && !pTarget->HasAura(DEMORALIZING_ROAR, EFFECT_INDEX_0) && CastSpell(DEMORALIZING_ROAR, pTarget))
        return RETURN_CONTINUE;

    if (MANGLE_BEAR > 0 && !pTarget->HasAura(MANGLE_BEAR) && CastSpell(MANGLE_BEAR, pTarget))
        return RETURN_CONTINUE;

    if (LACERATE > 0 && !pTarget->HasAura(LACERATE, EFFECT_INDEX_0) && CastSpell(LACERATE, pTarget))
        return RETURN_CONTINUE;

    if (MAUL > 0 && CastSpell(MAUL, pTarget))
        return RETURN_CONTINUE;

    return RETURN_NO_ACTION_UNKNOWN;
}
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
Example #8
0
void Totem::InitStats(uint32 duration)
{
    // client requires SMSG_TOTEM_CREATED to be sent before adding to world and before removing old totem
    if (m_owner->GetTypeId() == TYPEID_PLAYER
        && m_Properties->Slot >= SUMMON_SLOT_TOTEM
        && m_Properties->Slot < MAX_TOTEM_SLOT)
    {
        WorldPacket data(SMSG_TOTEM_CREATED, 1 + 8 + 4 + 4);
        data << uint8(m_Properties->Slot - 1);
        data << uint64(GetGUID());
        data << uint32(duration);
        data << uint32(GetUInt32Value(UNIT_CREATED_BY_SPELL));
        m_owner->ToPlayer()->SendDirectMessage(&data);

        // set display id depending on caster's race
        SetDisplayId(m_owner->GetModelForTotem(PlayerTotemType(m_Properties->Id)));
    }

    if (m_owner->GetDummyAuraEffect(SPELLFAMILY_GENERIC, 2019, EFFECT_0))
        if (m_Properties->Slot == SUMMON_SLOT_TOTEM)
            CastSpell(this, 77747, true);

    Minion::InitStats(duration);

    // Get spell cast by totem
    if (SpellInfo const* totemSpell = sSpellMgr->GetSpellInfo(GetSpell()))
        if (totemSpell->CalcCastTime())   // If spell has cast time -> its an active totem
            m_type = TOTEM_ACTIVE;

    if (GetEntry() == SENTRY_TOTEM_ENTRY)
        SetReactState(REACT_AGGRESSIVE);

    m_duration = duration;

    SetLevel(m_owner->getLevel());
}
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->In_Reach(target,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
    }

    // Remove negative magic on group members if orders allow bot to do so
    if (Player* pCursedTarget = GetDispelTarget(DISPEL_MAGIC))
    {
        if (PRIEST_DISPEL_MAGIC > 0 && (m_ai->GetCombatOrder() & PlayerbotAI::ORDERS_NODISPEL) == 0 && CastSpell(PRIEST_DISPEL_MAGIC, pCursedTarget))
            return RETURN_CONTINUE;
    }

    // Remove disease on group members if orders allow bot to do so
    if (Player* pDiseasedTarget = GetDispelTarget(DISPEL_DISEASE))
    {
        uint32 cure = ABOLISH_DISEASE > 0 ? ABOLISH_DISEASE : CURE_DISEASE;
        // uint32 poison = ABOLISH_POISON ? ABOLISH_POISON : CURE_POISON;
        if (cure > 0 && (m_ai->GetCombatOrder() & PlayerbotAI::ORDERS_NODISPEL) == 0 && CastSpell(cure, pDiseasedTarget))
            return RETURN_CONTINUE;
    }

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

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

    if (hp >= 90)
        return RETURN_NO_ACTION_OK;

    // 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_HEAL))
    {
        m_bot->GetMotionMaster()->MoveFollow(target, 39.0f, m_bot->GetOrientation());
        return RETURN_CONTINUE;
    }

    // Get a free and more efficient heal if needed: low mana for bot or average health for target
    if (m_ai->IsInCombat() && (hp < 50 || m_ai->GetManaPercent() < 40))
        if (INNER_FOCUS > 0 && m_bot->IsSpellReady(INNER_FOCUS) && !m_bot->HasAura(INNER_FOCUS, EFFECT_INDEX_0) && CastSpell(INNER_FOCUS, m_bot))
            return RETURN_CONTINUE;

    if (hp < 25 && POWER_WORD_SHIELD > 0 && m_ai->In_Reach(target,POWER_WORD_SHIELD) && !m_bot->HasAura(POWER_WORD_SHIELD, EFFECT_INDEX_0) && !target->HasAura(WEAKNED_SOUL,EFFECT_INDEX_0) && m_ai->CastSpell(POWER_WORD_SHIELD, *target))
        return RETURN_CONTINUE;
    if (hp < 35 && FLASH_HEAL > 0 && m_ai->In_Reach(target,FLASH_HEAL) && m_ai->CastSpell(FLASH_HEAL, *target))
        return RETURN_CONTINUE;
    if (hp < 50 && GREATER_HEAL > 0 && m_ai->In_Reach(target,GREATER_HEAL) && 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->In_Reach(target,BINDING_HEAL) && m_ai->CastSpell(BINDING_HEAL, *target))
        return RETURN_CONTINUE;
    if (hp < 60 && PRAYER_OF_MENDING > 0 && m_ai->In_Reach(target,PRAYER_OF_MENDING) && !target->HasAura(PRAYER_OF_MENDING, EFFECT_INDEX_0) && CastSpell(PRAYER_OF_MENDING, target))
        return RETURN_FINISHED_FIRST_MOVES;
    if (hp < 70 && HEAL > 0 && m_ai->In_Reach(target,HEAL) && m_ai->CastSpell(HEAL, *target))
        return RETURN_CONTINUE;
    if (hp < 90 && RENEW > 0 && m_ai->In_Reach(target,RENEW) && !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
Example #10
0
CombatManeuverReturns PlayerbotPriestAI::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 spec = m_bot->GetSpec();

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

    if (m_ai->GetCombatStyle() != PlayerbotAI::COMBAT_RANGED && !meleeReach)
        m_ai->SetCombatStyle(PlayerbotAI::COMBAT_RANGED);
    // switch to melee if in melee range AND can't shoot OR have no ranged (wand) equipped AND is not healer
    else if(m_ai->GetCombatStyle() != PlayerbotAI::COMBAT_MELEE
            && meleeReach
            && (SHOOT == 0 || !m_bot->GetWeaponForAttack(RANGED_ATTACK, true, true))
            && !m_ai->IsHealer())
        m_ai->SetCombatStyle(PlayerbotAI::COMBAT_MELEE);

    // Priests will try to buff with Fear Ward
    if (FEAR_WARD > 0 && m_bot->IsSpellReady(FEAR_WARD))
    {
        // Buff tank first
        if (pMainTank)
        {
            if (m_ai->In_Reach(pMainTank, FEAR_WARD) && !pMainTank->HasAura(FEAR_WARD, EFFECT_INDEX_0) && CastSpell(FEAR_WARD, pMainTank))
                return RETURN_CONTINUE;
        }
        // Else try to buff master
        else if (GetMaster())
        {
            if (m_ai->In_Reach(GetMaster(), FEAR_WARD) && !GetMaster()->HasAura(FEAR_WARD, EFFECT_INDEX_0) && CastSpell(FEAR_WARD, GetMaster()))
                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->IsNeutralized(newTarget)) // TODO: && party has a tank
    {
        if (FADE > 0 && !m_bot->HasAura(FADE, EFFECT_INDEX_0) && m_bot->IsSpellReady(FADE))
        {
            if (CastSpell(FADE, m_bot))
            {
                m_ai->TellMaster("I'm casting fade.");
                return RETURN_CONTINUE;
            }
            else
                m_ai->TellMaster("I have AGGRO.");
        }

        // Heal myself
        // TODO: move to HealTarget code
        if (m_ai->GetHealthPercent() < 35 && POWER_WORD_SHIELD > 0 && !m_bot->HasAura(POWER_WORD_SHIELD, EFFECT_INDEX_0) && !m_bot->HasAura(WEAKNED_SOUL, EFFECT_INDEX_0))
        {
            if (CastSpell(POWER_WORD_SHIELD) & RETURN_CONTINUE)
            {
                m_ai->TellMaster("I'm casting PW:S on myself.");
                return RETURN_CONTINUE;
            }
            else if (m_ai->IsHealer()) // Even if any other RETURN_ANY_OK - aside from RETURN_CONTINUE
                m_ai->TellMaster("Your healer's about TO DIE. HELP ME.");
        }
        if (m_ai->GetHealthPercent() < 35 && DESPERATE_PRAYER > 0 && m_ai->In_Reach(m_bot,DESPERATE_PRAYER) && CastSpell(DESPERATE_PRAYER, m_bot) & RETURN_CONTINUE)
        {
            m_ai->TellMaster("I'm casting desperate prayer.");
            return RETURN_CONTINUE;
        }
        // Night Elves priest bot can also cast Elune's Grace to improve his/her dodge rating
        if (ELUNES_GRACE && !m_bot->HasAura(ELUNES_GRACE, EFFECT_INDEX_0) && m_bot->IsSpellReady(ELUNES_GRACE) && CastSpell(ELUNES_GRACE, m_bot))
            return RETURN_CONTINUE;

        // If enemy comes in melee reach
        if (meleeReach)
        {
            // Already healed self or tank. If healer, do nothing else to anger mob
            if (m_ai->IsHealer())
                return RETURN_NO_ACTION_OK; // In a sense, mission accomplished.

            // Have threat, can't quickly lower it. 3 options remain: Stop attacking, lowlevel damage (wand), keep on keeping on.
            if (newTarget->GetHealthPercent() > 25)
            {
                // If elite, do nothing and pray tank gets aggro off you
                if (m_ai->IsElite(newTarget))
                    return RETURN_NO_ACTION_OK;

                // Not an elite. You could insert PSYCHIC SCREAM here but in any PvE situation that's 90-95% likely
                // to worsen the situation for the group. ... So please don't.
                return CastSpell(SHOOT, pTarget);
            }
        }
    }

    // Damage tweaking for healers
    if (m_ai->IsHealer())
    {
        // Heal other players/bots first
        if (HealPlayer(GetHealTarget()) & RETURN_CONTINUE)
            return RETURN_CONTINUE;

        // No one needs to be healed: do small damage instead
        // If target is elite and not handled by MT: do nothing
        if (m_ai->IsElite(pTarget) && pMainTank && pMainTank->getVictim() != pTarget)
            return RETURN_NO_ACTION_OK;

        // Cast Shadow Word:Pain on current target and keep its up (if mana >= 40% or target HP < 15%)
        if (SHADOW_WORD_PAIN > 0 && m_ai->In_Reach(pTarget,SHADOW_WORD_PAIN) && !pTarget->HasAura(SHADOW_WORD_PAIN, EFFECT_INDEX_0) &&
        (pTarget->GetHealthPercent() < 15 || m_ai->GetManaPercent() >= 40) && CastSpell(SHADOW_WORD_PAIN, pTarget))
            return RETURN_CONTINUE;
        else // else shoot at it
            return CastSpell(SHOOT, pTarget);
    }

    // Damage Spells
    switch (spec)
    {
        case PRIEST_SPEC_HOLY:
            if (HOLY_FIRE > 0 && m_ai->In_Reach(pTarget,HOLY_FIRE) && !pTarget->HasAura(HOLY_FIRE, EFFECT_INDEX_0) && CastSpell(HOLY_FIRE, pTarget))
                return RETURN_CONTINUE;
            if (SMITE > 0 && m_ai->In_Reach(pTarget,SMITE) && CastSpell(SMITE, pTarget))
                return RETURN_CONTINUE;
            //if (HOLY_NOVA > 0 && m_ai->In_Reach(pTarget,HOLY_NOVA) && meleeReach && m_ai->CastSpell(HOLY_NOVA))
            //    return RETURN_CONTINUE;
            break;

        case PRIEST_SPEC_SHADOW:
            if (DEVOURING_PLAGUE > 0 && m_ai->In_Reach(pTarget,DEVOURING_PLAGUE) && !pTarget->HasAura(DEVOURING_PLAGUE, EFFECT_INDEX_0) && CastSpell(DEVOURING_PLAGUE, pTarget))
                return RETURN_CONTINUE;
            if (VAMPIRIC_TOUCH > 0 && m_ai->In_Reach(pTarget,VAMPIRIC_TOUCH) && !pTarget->HasAura(VAMPIRIC_TOUCH, EFFECT_INDEX_0) && CastSpell(VAMPIRIC_TOUCH, pTarget))
                return RETURN_CONTINUE;
            if (SHADOW_WORD_PAIN > 0 && m_ai->In_Reach(pTarget,SHADOW_WORD_PAIN) && !pTarget->HasAura(SHADOW_WORD_PAIN, EFFECT_INDEX_0) && CastSpell(SHADOW_WORD_PAIN, pTarget))
                return RETURN_CONTINUE;
            if (MIND_BLAST > 0 && m_ai->In_Reach(pTarget,MIND_BLAST) && (m_bot->IsSpellReady(MIND_BLAST)) && CastSpell(MIND_BLAST, pTarget))
                return RETURN_CONTINUE;
            if (MIND_FLAY > 0 && m_ai->In_Reach(pTarget,MIND_FLAY) && CastSpell(MIND_FLAY, pTarget))
            {
                m_ai->SetIgnoreUpdateTime(3);
                return RETURN_CONTINUE;
            }
            if (SHADOWFIEND > 0 && m_ai->In_Reach(pTarget,SHADOWFIEND) && !m_bot->GetPet() && CastSpell(SHADOWFIEND))
                return RETURN_CONTINUE;
            if (SHADOWFORM == 0 && MIND_FLAY == 0 && SMITE > 0 && m_ai->In_Reach(pTarget,SMITE) && CastSpell(SMITE, pTarget)) // low levels
                return RETURN_CONTINUE;
            break;

        case PRIEST_SPEC_DISCIPLINE:
            if (POWER_INFUSION > 0 && m_ai->In_Reach(GetMaster(),POWER_INFUSION) && CastSpell(POWER_INFUSION, GetMaster())) // TODO: just master?
                return RETURN_CONTINUE;
            if (INNER_FOCUS > 0 && m_ai->In_Reach(m_bot,INNER_FOCUS) && !m_bot->HasAura(INNER_FOCUS, EFFECT_INDEX_0) && CastSpell(INNER_FOCUS, m_bot))
                return RETURN_CONTINUE;
            if (SMITE > 0 && m_ai->In_Reach(pTarget,SMITE) && CastSpell(SMITE, pTarget))
                return RETURN_CONTINUE;
            break;
    }

    // No spec due to low level OR no spell found yet
    if (MIND_BLAST > 0 && m_ai->In_Reach(pTarget,MIND_BLAST) && (m_bot->IsSpellReady(MIND_BLAST)) && CastSpell(MIND_BLAST, pTarget))
        return RETURN_CONTINUE;
    if (SHADOW_WORD_PAIN > 0 && m_ai->In_Reach(pTarget,SHADOW_WORD_PAIN) && !pTarget->HasAura(SHADOW_WORD_PAIN, EFFECT_INDEX_0) && CastSpell(SHADOW_WORD_PAIN, pTarget))
        return RETURN_CONTINUE;
    if (MIND_FLAY > 0 && m_ai->In_Reach(pTarget,MIND_FLAY) && CastSpell(MIND_FLAY, pTarget))
    {
        m_ai->SetIgnoreUpdateTime(3);
        return RETURN_CONTINUE;
    }
    if (SHADOWFORM == 0 && SMITE > 0 && m_ai->In_Reach(pTarget,SMITE) && CastSpell(SMITE, pTarget))
        return RETURN_CONTINUE;

    // Default: shoot with wand
    return CastSpell(SHOOT, pTarget);

    return RETURN_NO_ACTION_OK;
} // end DoNextCombatManeuver
Example #11
0
CombatManeuverReturns PlayerbotPriestAI::DoFirstCombatManeuverPVE(Unit* /*pTarget*/)
{
    if (!m_ai)  return RETURN_NO_ACTION_ERROR;
    if (!m_bot) return RETURN_NO_ACTION_ERROR;

    if (m_ai->IsHealer())
    {
        // TODO: This must be done with toggles: FullHealth allowed
        Unit* healTarget = GetHealTarget(JOB_TANK);
        // This is cast on a target, which activates (and switches to another target within the group) upon receiving+healing damage
        // Mana efficient even at one use
        if (healTarget && PRAYER_OF_MENDING > 0 && m_ai->In_Reach(healTarget,PRAYER_OF_MENDING) && !healTarget->HasAura(PRAYER_OF_MENDING, EFFECT_INDEX_0) && CastSpell(PRAYER_OF_MENDING, healTarget) & RETURN_CONTINUE)
            return RETURN_FINISHED_FIRST_MOVES;

            // Cast renew on tank
        if (CastHoTOnTank())
            return RETURN_FINISHED_FIRST_MOVES;
    }
    return RETURN_NO_ACTION_OK;
}
Example #12
0
bool Client::UseDiscipline(uint32 spell_id, uint32 target) {
    // Dont let client waste a reuse timer if they can't use the disc
    if (IsStunned() || IsFeared() || IsMezzed() || IsAmnesiad() || IsPet())
    {
        return(false);
    }

    //make sure we have the spell...
    int r;
    for(r = 0; r < MAX_PP_DISCIPLINES; r++) {
        if(m_pp.disciplines.values[r] == spell_id)
            break;
    }
    if(r == MAX_PP_DISCIPLINES)
        return(false);	//not found.

    //Check the disc timer
    pTimerType DiscTimer = pTimerDisciplineReuseStart + spells[spell_id].EndurTimerIndex;
    if(!p_timers.Expired(&database, DiscTimer)) {
        /*char val1[20]={0};*/	//unused
        /*char val2[20]={0};*/	//unused
        uint32 remain = p_timers.GetRemainingTime(DiscTimer);
        //Message_StringID(0, DISCIPLINE_CANUSEIN, ConvertArray((remain)/60,val1), ConvertArray(remain%60,val2));
        Message(0, "You can use this discipline in %d minutes %d seconds.", ((remain)/60), (remain%60));
        return(false);
    }

    //make sure we can use it..
    if(!IsValidSpell(spell_id)) {
        Message(13, "This tome contains invalid knowledge.");
        return(false);
    }

    //can we use the spell?
    const SPDat_Spell_Struct &spell = spells[spell_id];
    uint8 level_to_use = spell.classes[GetClass() - 1];
    if(level_to_use == 255) {
        Message(13, "Your class cannot learn from this tome.");
        //should summon them a new one...
        return(false);
    }

    if(level_to_use > GetLevel()) {
        Message_StringID(13, DISC_LEVEL_USE_ERROR);
        //should summon them a new one...
        return(false);
    }

    if(GetEndurance() > spell.EndurCost) {
        SetEndurance(GetEndurance() - spell.EndurCost);
    } else {
        Message(11, "You are too fatigued to use this skill right now.");
        return(false);
    }

    if(spell.recast_time > 0)
    {
        uint32 reduced_recast = spell.recast_time / 1000;
        reduced_recast -= CastToClient()->GetFocusEffect(focusReduceRecastTime, spell_id);
        if(reduced_recast < 0)
            reduced_recast = 0;

        CastSpell(spell_id, target, DISCIPLINE_SPELL_SLOT, -1, -1, 0, -1, (uint32)DiscTimer, reduced_recast);
        if(spells[spell_id].EndurTimerIndex < MAX_DISCIPLINE_TIMERS)
        {
            EQApplicationPacket *outapp = new EQApplicationPacket(OP_DisciplineTimer, sizeof(DisciplineTimer_Struct));
            DisciplineTimer_Struct *dts = (DisciplineTimer_Struct *)outapp->pBuffer;
            dts->TimerID = spells[spell_id].EndurTimerIndex;
            dts->Duration = reduced_recast;
            QueuePacket(outapp);
            safe_delete(outapp);
        }
    }
    else
    {
        CastSpell(spell_id, target, DISCIPLINE_SPELL_SLOT);
    }
    return(true);
}
Example #13
0
CombatManeuverReturns PlayerbotMageAI::DoNextCombatManeuverPVE(Unit *pTarget)
{
    if (!m_ai)  return RETURN_NO_ACTION_ERROR;
    if (!m_bot) return RETURN_NO_ACTION_ERROR;

    Unit* pVictim = pTarget->getVictim();
    bool meleeReach = m_bot->CanReachWithMeleeAttack(pTarget);

    uint32 spec = m_bot->GetSpec();

    if (m_ai->GetCombatStyle() != PlayerbotAI::COMBAT_RANGED && !meleeReach)
        m_ai->SetCombatStyle(PlayerbotAI::COMBAT_RANGED);
    // switch to melee if in melee range AND can't shoot OR have no ranged (wand) equipped
    else if(m_ai->GetCombatStyle() != PlayerbotAI::COMBAT_MELEE
            && meleeReach
            && (SHOOT == 0 || !m_bot->GetWeaponForAttack(RANGED_ATTACK, true, true)))
        m_ai->SetCombatStyle(PlayerbotAI::COMBAT_MELEE);

    //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);

    // Remove curse on group members
    if (Player* pCursedTarget = GetDispelTarget(DISPEL_CURSE))
    {
        if (MAGE_REMOVE_CURSE > 0 && CastSpell(MAGE_REMOVE_CURSE, pCursedTarget))
            return RETURN_CONTINUE;
    }

    if (newTarget && !m_ai->IsNeutralized(newTarget)) // Bot has aggro and the mob is not already crowd controled
    {
        if (newTarget->GetHealthPercent() > 25)
        {
            // If elite
            if (m_ai->IsElite(newTarget))
            {
                // If the attacker is a beast or humanoid, let's the bot give it a form more suited to the low intellect of something fool enough to attack a mage
                Creature * pCreature = (Creature*) newTarget;
                if (pCreature && (pCreature->GetCreatureInfo()->CreatureType == CREATURE_TYPE_HUMANOID || pCreature->GetCreatureInfo()->CreatureType == CREATURE_TYPE_BEAST))
                {
                    if (POLYMORPH > 0 && CastSpell(POLYMORPH, newTarget))
                        return RETURN_CONTINUE;
                }

                // Things are getting dire: cast Ice block
                if (ICE_BLOCK > 0 && !m_bot->HasSpellCooldown(ICE_BLOCK) && m_ai->GetHealthPercent() < 30 && !m_bot->HasAura(ICE_BLOCK, EFFECT_INDEX_0) && m_ai->CastSpell(ICE_BLOCK))
                    return RETURN_CONTINUE;

                // Cast Ice Barrier if health starts to goes low
                if (ICE_BARRIER > 0 && !m_bot->HasSpellCooldown(ICE_BARRIER) && m_ai->GetHealthPercent() < 50 && !m_bot->HasAura(ICE_BARRIER) && m_ai->SelfBuff(ICE_BARRIER))
                    return RETURN_CONTINUE;

                // Have threat, can't quickly lower it. 3 options remain: Stop attacking, lowlevel damage (wand), keep on keeping on.
                return CastSpell(SHOOT, pTarget);
            }
            else // not elite
            {
                // Cast mana shield if no shield is already up
                if (MANA_SHIELD > 0 && m_ai->GetHealthPercent() < 70 && !m_bot->HasAura(MANA_SHIELD) && !m_bot->HasAura(ICE_BARRIER) && m_ai->SelfBuff(MANA_SHIELD))
                    return RETURN_CONTINUE;
            }
        }
    }

    // Mana check and replenishment
    if (EVOCATION && m_ai->GetManaPercent() <= 10 && !m_bot->HasSpellCooldown(EVOCATION) && !newTarget && m_ai->SelfBuff(EVOCATION))
        return RETURN_CONTINUE;
    if (m_ai->GetManaPercent() <= 20)
    {
        Item* gem = FindManaGem();
        if (gem)
            m_ai->UseItem(gem);
    }

    // If bot has frost/fire resist order use Frost/Fire Ward when available
    if (m_ai->GetCombatOrder() & PlayerbotAI::ORDERS_RESIST_FROST && FROST_WARD && !m_bot->HasSpellCooldown(FROST_WARD) && m_ai->SelfBuff(FROST_WARD))
        return RETURN_CONTINUE;
    if (m_ai->GetCombatOrder() & PlayerbotAI::ORDERS_RESIST_FIRE && FIRE_WARD && !m_bot->HasSpellCooldown(FIRE_WARD) && m_ai->SelfBuff(FIRE_WARD))
        return RETURN_CONTINUE;

    if (COUNTERSPELL > 0 && !m_bot->HasSpellCooldown(COUNTERSPELL) && pTarget->IsNonMeleeSpellCasted(true) && CastSpell(COUNTERSPELL, pTarget))
        return RETURN_CONTINUE;

    // If Clearcasting is active, cast arcane missiles
    // Bot could also cast flamestrike or blizzard for free, but the AoE could break some crowd control
    // or add threat on mobs ignoring the bot currently, so only focus on the bot's current target
    if (m_bot->HasAura(CLEARCASTING_1) && ARCANE_MISSILES > 0 && CastSpell(ARCANE_MISSILES, pTarget))
    {
        m_ai->SetIgnoreUpdateTime(3);
        return RETURN_CONTINUE;
    }

    switch (spec)
    {
    case MAGE_SPEC_FROST:
        if (COLD_SNAP && !m_bot->HasSpellCooldown(COLD_SNAP) && CheckFrostCooldowns() > 2 && m_ai->SelfBuff(COLD_SNAP))  // Clear frost spell cooldowns if bot has more than 2 active
            return RETURN_CONTINUE;
        if (CONE_OF_COLD > 0 && !m_bot->HasSpellCooldown(CONE_OF_COLD) && meleeReach)
        {
            // Cone of Cold does not require a target, so ensure that the bot faces the current one before casting
            m_ai->FaceTarget(pTarget);
            if (m_ai->CastSpell(CONE_OF_COLD))
                return RETURN_CONTINUE;
        }
        if (FROSTBOLT > 0 && m_ai->In_Reach(pTarget,FROSTBOLT) && !pTarget->HasAura(FROSTBOLT, EFFECT_INDEX_0) && CastSpell(FROSTBOLT, pTarget))
            return RETURN_CONTINUE;
        if (FROST_NOVA > 0 && !m_bot->HasSpellCooldown(FROST_NOVA) && meleeReach && !pTarget->HasAura(FROST_NOVA, EFFECT_INDEX_0) && CastSpell(FROST_NOVA, pTarget))
            return RETURN_CONTINUE;
        // Default frost spec action
        if (FROSTBOLT > 0 && m_ai->In_Reach(pTarget,FROSTBOLT))
            return CastSpell(FROSTBOLT, pTarget);
        /*
        if (BLIZZARD > 0 && m_ai->In_Reach(pTarget,BLIZZARD) && m_ai->GetAttackerCount() >= 5 && CastSpell(BLIZZARD, pTarget))
        {
            m_ai->SetIgnoreUpdateTime(8);
            return RETURN_CONTINUE;
        }
        */
        break;

    case MAGE_SPEC_FIRE:
        if (COMBUSTION > 0 && m_ai->SelfBuff(COMBUSTION))
            return RETURN_CONTINUE;
        if (BLAST_WAVE > 0 && m_ai->GetAttackerCount() >= 3 && meleeReach && CastSpell(BLAST_WAVE, pTarget))
            return RETURN_CONTINUE;
        // Try to have 3 scorch stacks to let tank build aggro while getting a nice crit% bonus
        if (IMPROVED_SCORCH > 0 && SCORCH > 0)
        {
            if (!pTarget->HasAura(FIRE_VULNERABILITY, EFFECT_INDEX_0) && CastSpell(SCORCH, pTarget))   // no stacks: cast it
                return RETURN_CONTINUE;
            else
            {
                SpellAuraHolder* holder = pTarget->GetSpellAuraHolder(FIRE_VULNERABILITY);
                if (holder && (holder->GetStackAmount() < 3) && CastSpell(SCORCH, pTarget))
                    return RETURN_CONTINUE;
            }
        }
        // At least 3 stacks of Scorch: cast an opening fireball
        if (FIREBALL > 0 && !pTarget->HasAura(FIREBALL, EFFECT_INDEX_1) && CastSpell(FIREBALL, pTarget))
            return RETURN_CONTINUE;
        // 3 stacks of Scorch and fireball DoT: use fire blast if available
        if (FIRE_BLAST > 0 && !m_bot->HasSpellCooldown(FIRE_BLAST) && CastSpell(FIRE_BLAST, pTarget))
            return RETURN_CONTINUE;
        // All DoTs, cooldowns used, try to maximise scorch stacks (5) to get a even nicer crit% bonus
        if (IMPROVED_SCORCH > 0 && SCORCH > 0)
        {
            SpellAuraHolder* holder = pTarget->GetSpellAuraHolder(FIRE_VULNERABILITY);
            if (holder && (holder->GetStackAmount() < 5) && CastSpell(SCORCH, pTarget))
                return RETURN_CONTINUE;
        }
        // Default fire spec action
        if (FIREBALL > 0 && m_ai->In_Reach(pTarget,FIREBALL))
            return CastSpell(FIREBALL, pTarget);
        /*
        if (FLAMESTRIKE > 0 && m_ai->In_Reach(pTarget,FLAMESTRIKE) && CastSpell(FLAMESTRIKE, pTarget))
            return RETURN_CONTINUE;
        */
        break;

    case MAGE_SPEC_ARCANE:
        if (ARCANE_POWER > 0 && !m_bot->HasSpellCooldown(ARCANE_POWER) && m_ai->IsElite(pTarget) && m_ai->CastSpell(ARCANE_POWER))    // Do not waste Arcane Power on normal NPCs as the bot is likely in a group
            return RETURN_CONTINUE;
        if (PRESENCE_OF_MIND > 0 && !m_bot->HasAura(PRESENCE_OF_MIND) && !m_bot->HasSpellCooldown(PRESENCE_OF_MIND) && m_ai->IsElite(pTarget) && m_ai->SelfBuff(PRESENCE_OF_MIND))
            return RETURN_CONTINUE;
        // If bot has presence of mind active, cast long casting time spells
        if (PRESENCE_OF_MIND && m_bot->HasAura(PRESENCE_OF_MIND))
        {
            // Instant Pyroblast, yeah! Tanks will probably hate this, but what do they know about power? Nothing...
            if (PYROBLAST > 0 && CastSpell(PYROBLAST, pTarget))
                return RETURN_CONTINUE;
            if (FIREBALL > 0 && CastSpell(FIREBALL, pTarget))
                return RETURN_CONTINUE;
        }
        if (ARCANE_EXPLOSION > 0 && m_ai->GetAttackerCount() >= 3 && meleeReach && CastSpell(ARCANE_EXPLOSION, pTarget))
            return RETURN_CONTINUE;
        // Default arcane spec actions (yes, two fire spells)
        if (FIRE_BLAST > 0 && !m_bot->HasSpellCooldown(FIRE_BLAST) && CastSpell(FIRE_BLAST, pTarget))
            return RETURN_CONTINUE;
        if (FIREBALL > 0 && m_ai->In_Reach(pTarget,FIREBALL))
            return CastSpell(FIREBALL, pTarget);
        // If no fireball, arcane missiles
        if (ARCANE_MISSILES > 0 && CastSpell(ARCANE_MISSILES, pTarget))
        {
            m_ai->SetIgnoreUpdateTime(3);
            return RETURN_CONTINUE;
        }
        break;
    }

    // No spec due to low level OR no spell found yet
    if (FROSTBOLT > 0 && m_ai->In_Reach(pTarget,FROSTBOLT) && !pTarget->HasAura(FROSTBOLT, EFFECT_INDEX_0) && CastSpell(FROSTBOLT, pTarget))
        return RETURN_CONTINUE;
    if (FIREBALL > 0 && m_ai->In_Reach(pTarget,FIREBALL) && CastSpell(FIREBALL, pTarget)) // Very low levels
        return RETURN_CONTINUE;

    // Default: shoot with wand
    return CastSpell(SHOOT, pTarget);

    return RETURN_NO_ACTION_ERROR; // What? Not even Fireball or wand are available?
} // end DoNextCombatManeuver
	void AIUpdate()
	{
		float OggCast = (float)RandomFloat(100.0f);
		CastSpell(OggCast);
	}
bool PlayerbotShamanAI::ChangeTotems(uint32 mode)
{
    uint32 earth=0, fire=0, water=0, air=0;

    PlayerbotAI *ai = GetAI();
    if(!ai) return false;
    Player *m_bot = GetPlayerBot();
    if(!m_bot || m_bot->isDead()) return false;

    Unit *pTarget = m_bot->GetSelectedUnit();
    Unit *pVictim = NULL;
    if (m_bot->GetSelectedUnit()->IsFriendlyTo(m_bot)) pTarget = NULL;
    if (pTarget) pVictim = pTarget->getVictim();

    //Defaults
    if (!HasAuraName(m_bot,"Horn of Winter") )earth = STRENGTH_OF_EARTH_TOTEM;
    if (!earth) earth = STONESKIN_TOTEM;
    if (!earth) earth = EARTHBIND_TOTEM;
    fire = TOTEM_OF_WRATH;
    if (!fire) fire = FLAMETONGUE_TOTEM;
    if (!fire) fire = SEARING_TOTEM;
    water = MANA_SPRING_TOTEM;
    if (!water) water = HEALING_STREAM_TOTEM;
    if (TALENT_ELEMENTAL || TALENT_RESTO) air = WRATH_OF_AIR_TOTEM;
    else air = WINDFURY_TOTEM;

    //Target reactive stuff
    if (pTarget)
    {
        if (GROUNDING_TOTEM && pTarget->IsNonMeleeSpellCasted(true)) air = GROUNDING_TOTEM;
    }

    if (STONESKIN_TOTEM && isUnderAttack()) earth = STONESKIN_TOTEM;

    uint32 totz[4] = {earth, fire, water, air};

    for (int i = 0; i < 4; i++)
    {
        if (!totz[i]) continue;
        SpellEntry const *tSpell = GetSpellStore()->LookupEntry(totz[i]);
        if (!tSpell) continue;
        uint32 tEntry = (uint32) tSpell->EffectMiscValue[0];
        if (!tEntry) continue;
        CreatureTemplate const *totemEntry = sObjectMgr->GetCreatureTemplate(tEntry);
        if (!tEntry) continue;

        if (CanCast(totz[i], m_bot) && !m_bot->FindNearestCreature(tEntry,30)) { return CastSpell(totz[i],m_bot,false); }
    }
    return false;
}
// Decision tree for putting a curse on the current target
bool PlayerbotWarlockAI::CheckCurse(Unit* pTarget)
{
    Creature * pCreature = (Creature*) pTarget;
    uint32 CurseToCast = 0;

    // Prevent low health humanoid from fleeing or fleeing too fast
    // Curse of Exhaustion first to avoid increasing damage output on tank
    if (pCreature && pCreature->GetCreatureInfo()->CreatureType == CREATURE_TYPE_HUMANOID && pTarget->GetHealthPercent() < 20 && !pCreature->IsWorldBoss())
    {
        if (CURSE_OF_EXHAUSTION && m_ai->In_Reach(pTarget,CURSE_OF_EXHAUSTION) && !pTarget->HasAura(CURSE_OF_EXHAUSTION))
        {
            if (AMPLIFY_CURSE && m_bot->IsSpellReady(AMPLIFY_CURSE))
                CastSpell(AMPLIFY_CURSE, m_bot);

            if (CastSpell(CURSE_OF_EXHAUSTION, pTarget))
            {
                m_CurrentCurse = CURSE_OF_EXHAUSTION;
                return true;
            }
        }
        else if (CURSE_OF_RECKLESSNESS && m_ai->In_Reach(pTarget,CURSE_OF_RECKLESSNESS) && !pTarget->HasAura(CURSE_OF_RECKLESSNESS) && !pTarget->HasAura(CURSE_OF_EXHAUSTION) && CastSpell(CURSE_OF_RECKLESSNESS, pTarget))
        {
            m_CurrentCurse = CURSE_OF_RECKLESSNESS;
            return true;
        }
    }

    // If bot already put a curse and curse is still active on target: no need to go further
    if (m_CurrentCurse > 0 && pTarget->HasAura(m_CurrentCurse))
        return false;

    // No curse or effect worn off: choose again which curse to use

    // Target is a boss
    if (pCreature && pCreature->IsWorldBoss())
    {
        if (m_bot->GetGroup())
        {
            uint8 mages = 0;
            uint8 warlocks = 1;
            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;
                switch (groupMember->getClass())
                {
                    case CLASS_WARLOCK:
                        warlocks++;
                        continue;
                    case CLASS_MAGE:
                        mages++;
                        continue;
                }
            }
            if (warlocks > 1 && warlocks > mages)
                CurseToCast = CURSE_OF_SHADOW;
            else if (mages > warlocks)
                CurseToCast = CURSE_OF_THE_ELEMENTS;
            else
                CurseToCast = CURSE_OF_AGONY;
        }
    // If target is not elite, no need to put a curse useful
    // in the long run: go for direct damage
    } else if (!m_ai->IsElite(pTarget))
        CurseToCast = CURSE_OF_AGONY;
    // Enemy elite mages have low health but can cast dangerous spells: group safety before bot DPS
    else if (pCreature && pCreature->GetCreatureInfo()->UnitClass == 8)
        CurseToCast = CURSE_OF_TONGUES;
    // Default case: Curse of Agony
    else
        CurseToCast = CURSE_OF_AGONY;

    // Try to curse the target with the selected curse
    if (CurseToCast && m_ai->In_Reach(pTarget,CurseToCast) && !pTarget->HasAura(CurseToCast))
    {
        if (CurseToCast == CURSE_OF_AGONY)
            if (AMPLIFY_CURSE && m_bot->IsSpellReady(AMPLIFY_CURSE))
                CastSpell(AMPLIFY_CURSE, m_bot);

        if (CastSpell(CurseToCast, pTarget))
        {
            m_CurrentCurse = CurseToCast;
            return true;
        }
    }
    // else: go for Curse of Agony
    else if (CURSE_OF_AGONY && m_ai->In_Reach(pTarget,CURSE_OF_AGONY) && !pTarget->HasAura(CURSE_OF_AGONY))
    {
        if (AMPLIFY_CURSE && m_bot->IsSpellReady(AMPLIFY_CURSE))
            CastSpell(AMPLIFY_CURSE, m_bot);

        if (CastSpell(CURSE_OF_AGONY, pTarget))
        {
            m_CurrentCurse = CURSE_OF_AGONY;
            return true;
        }
    }
    // else: go for Curse of Weakness
    else if (CURSE_OF_WEAKNESS && !pTarget->HasAura(CURSE_OF_WEAKNESS) && !pTarget->HasAura(CURSE_OF_AGONY))
    {
        if (AMPLIFY_CURSE && m_bot->IsSpellReady(AMPLIFY_CURSE))
            CastSpell(AMPLIFY_CURSE, m_bot);

        if (CastSpell(CURSE_OF_WEAKNESS, pTarget))
        {
            m_CurrentCurse = CURSE_OF_WEAKNESS;
            return true;
        }
    }
    return false;
}
CombatManeuverReturns PlayerbotWarlockAI::DoNextCombatManeuverPVE(Unit *pTarget)
{
    if (!m_ai)  return RETURN_NO_ACTION_ERROR;
    if (!m_bot) return RETURN_NO_ACTION_ERROR;

    //Unit* pVictim = pTarget->getVictim();
    bool meleeReach = m_bot->CanReachWithMeleeAttack(pTarget);
    Pet *pet = m_bot->GetPet();
    uint32 spec = m_bot->GetSpec();
    uint8 shardCount = m_bot->GetItemCount(SOUL_SHARD, false, nullptr);

    // Voidwalker is near death - sacrifice it for a shield
    if (pet && pet->GetEntry() == DEMON_VOIDWALKER && SACRIFICE && !m_bot->HasAura(SACRIFICE) && pet->GetHealthPercent() < 10)
        m_ai->CastPetSpell(SACRIFICE);

    // Use healthstone
    if (m_ai->GetHealthPercent() < 30)
    {
        Item* healthStone = m_ai->FindConsumable(HEALTHSTONE_DISPLAYID);
        if (healthStone)
            m_ai->UseItem(healthStone);
    }

    // Voidwalker sacrifice gives shield - but you lose the pet (and it's DPS/tank) - use only as last resort for your own health!
    if (m_ai->GetHealthPercent() < 20 && pet && pet->GetEntry() == DEMON_VOIDWALKER && SACRIFICE && !m_bot->HasAura(SACRIFICE))
        m_ai->CastPetSpell(SACRIFICE);

    if (m_ai->GetCombatStyle() != PlayerbotAI::COMBAT_RANGED && !meleeReach)
        m_ai->SetCombatStyle(PlayerbotAI::COMBAT_RANGED);
    // switch to melee if in melee range AND can't shoot OR have no ranged (wand) equipped
    else if(m_ai->GetCombatStyle() != PlayerbotAI::COMBAT_MELEE
            && meleeReach
            && (SHOOT == 0 || !m_bot->GetWeaponForAttack(RANGED_ATTACK, true, true)))
        m_ai->SetCombatStyle(PlayerbotAI::COMBAT_MELEE);

    //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->IsNeutralized(newTarget)) // TODO: && party has a tank
    {
        // Have threat, can't quickly lower it. 3 options remain: Stop attacking, lowlevel damage (wand), keep on keeping on.
        if (newTarget->GetHealthPercent() > 25)
        {
            // If elite
            if (m_ai->IsElite(newTarget))
            {
                // let warlock pet handle it to win some time
                Creature * pCreature = (Creature*) newTarget;
                if (pet)
                {
                    switch (pet->GetEntry())
                    {
                        // taunt the elite and tank it
                        case DEMON_VOIDWALKER:
                            if (TORMENT && m_ai->CastPetSpell(TORMENT, newTarget))
                                return RETURN_NO_ACTION_OK;
                        // maybe give it some love?
                        case DEMON_SUCCUBUS:
                            if (pCreature && pCreature->GetCreatureInfo()->CreatureType == CREATURE_TYPE_HUMANOID)
                                if (SEDUCTION && !newTarget->HasAura(SEDUCTION) && m_ai->CastPetSpell(SEDUCTION, newTarget))
                                    return RETURN_NO_ACTION_OK;
                    }

                }
                // if aggroed mob is a demon or an elemental: banish it
                if (pCreature && (pCreature->GetCreatureInfo()->CreatureType == CREATURE_TYPE_DEMON || pCreature->GetCreatureInfo()->CreatureType == CREATURE_TYPE_ELEMENTAL))
                {
                    if (BANISH && !newTarget->HasAura(BANISH) && CastSpell(BANISH, newTarget))
                        return RETURN_CONTINUE;
                }

                return RETURN_NO_ACTION_OK; // do nothing and pray tank gets aggro off you
            }

            // Not an elite. You could insert FEAR here but in any PvE situation that's 90-95% likely
            // to worsen the situation for the group. ... So please don't.
            return CastSpell(SHOOT, pTarget);
        }
    }

    // Create soul shard (only on non-worldboss)
    uint8 freeSpace = m_ai->GetFreeBagSpace();
    uint8 HPThreshold = (m_ai->IsElite(pTarget) ? 10 : 25);
    if (!m_ai->IsElite(pTarget, true) && pTarget->GetHealthPercent() < HPThreshold && (shardCount < MAX_SHARD_COUNT && freeSpace > 0))
    {
        if (SHADOWBURN && m_ai->In_Reach(pTarget, SHADOWBURN) && !pTarget->HasAura(SHADOWBURN) && m_bot->IsSpellReady(SHADOWBURN) && CastSpell(SHADOWBURN, pTarget))
            return RETURN_CONTINUE;

        // Do not cast Drain Soul if Shadowburn is active on target
        if (DRAIN_SOUL && m_ai->In_Reach(pTarget, DRAIN_SOUL) && !pTarget->HasAura(DRAIN_SOUL) && !pTarget->HasAura(SHADOWBURN) && CastSpell(DRAIN_SOUL, pTarget))
        {
            m_ai->SetIgnoreUpdateTime(15);
            return RETURN_CONTINUE;
        }
    }

    if (pet && DARK_PACT && (100 * pet->GetPower(POWER_MANA) / pet->GetMaxPower(POWER_MANA)) > 10 && m_ai->GetManaPercent() <= 20)
        if (m_ai->CastSpell(DARK_PACT, *m_bot))
            return RETURN_CONTINUE;

    // Mana check and replenishment
    if (LIFE_TAP && m_ai->GetManaPercent() <= 20 && m_ai->GetHealthPercent() > 50)
        if (m_ai->CastSpell(LIFE_TAP, *m_bot))
            return RETURN_CONTINUE;

    // HP, mana and aggro checks done
    // Curse the target
    if (CheckCurse(pTarget))
        return RETURN_CONTINUE;

    // Damage Spells
    if (spec)
    {
        switch (spec)
        {
            case WARLOCK_SPEC_AFFLICTION:
                if (CORRUPTION && m_ai->In_Reach(pTarget,CORRUPTION) && !pTarget->HasAura(CORRUPTION) && CastSpell(CORRUPTION, pTarget))
                    return RETURN_CONTINUE;
                if (IMMOLATE && m_ai->In_Reach(pTarget,IMMOLATE) && !pTarget->HasAura(IMMOLATE) && CastSpell(IMMOLATE, pTarget))
                    return RETURN_CONTINUE;
                if (SIPHON_LIFE > 0 && m_ai->In_Reach(pTarget,SIPHON_LIFE) && !pTarget->HasAura(SIPHON_LIFE) && CastSpell(SIPHON_LIFE, pTarget))
                    return RETURN_CONTINUE;
                break;

            case WARLOCK_SPEC_DEMONOLOGY:
                if (CORRUPTION && m_ai->In_Reach(pTarget,CORRUPTION) && !pTarget->HasAura(CORRUPTION) && CastSpell(CORRUPTION, pTarget))
                    return RETURN_CONTINUE;
                if (IMMOLATE && m_ai->In_Reach(pTarget,IMMOLATE) && !pTarget->HasAura(IMMOLATE) && CastSpell(IMMOLATE, pTarget))
                    return RETURN_CONTINUE;
                break;

            case WARLOCK_SPEC_DESTRUCTION:
                if (SHADOWBURN && pTarget->GetHealthPercent() < (HPThreshold / 2.0) && m_ai->In_Reach(pTarget, SHADOWBURN) && !pTarget->HasAura(SHADOWBURN) && CastSpell(SHADOWBURN, pTarget))
                    return RETURN_CONTINUE;
                if (CORRUPTION && m_ai->In_Reach(pTarget,CORRUPTION) && !pTarget->HasAura(CORRUPTION) && CastSpell(CORRUPTION, pTarget))
                    return RETURN_CONTINUE;
                if (IMMOLATE && m_ai->In_Reach(pTarget,IMMOLATE) && !pTarget->HasAura(IMMOLATE) && CastSpell(IMMOLATE, pTarget))
                    return RETURN_CONTINUE;
                if (CONFLAGRATE && m_ai->In_Reach(pTarget,CONFLAGRATE) && pTarget->HasAura(IMMOLATE) && m_bot->IsSpellReady(CONFLAGRATE) && CastSpell(CONFLAGRATE, pTarget))
                    return RETURN_CONTINUE;
                break;
        }

        // Shadow bolt is common to all specs
        if (SHADOW_BOLT && m_ai->In_Reach(pTarget,SHADOW_BOLT) && CastSpell(SHADOW_BOLT, pTarget))
            return RETURN_CONTINUE;

        // Default: shoot with wand
        return CastSpell(SHOOT, pTarget);

        return RETURN_NO_ACTION_OK;

                //if (DRAIN_LIFE && LastSpellAffliction < 4 && !pTarget->HasAura(DRAIN_SOUL) && !pTarget->HasAura(DRAIN_LIFE) && !pTarget->HasAura(DRAIN_MANA) && m_ai->GetHealthPercent() <= 70)
                //    m_ai->CastSpell(DRAIN_LIFE, *pTarget);
                //    //m_ai->SetIgnoreUpdateTime(5);
                //else if (HOWL_OF_TERROR && !pTarget->HasAura(HOWL_OF_TERROR) && m_ai->GetAttackerCount() > 3 && LastSpellAffliction < 8)
                //    m_ai->CastSpell(HOWL_OF_TERROR, *pTarget);
                //    m_ai->TellMaster("casting howl of terror!");
                //else if (FEAR && !pTarget->HasAura(FEAR) && pVictim == m_bot && m_ai->GetAttackerCount() >= 2 && LastSpellAffliction < 9)
                //    m_ai->CastSpell(FEAR, *pTarget);
                //    //m_ai->TellMaster("casting fear!");
                //    //m_ai->SetIgnoreUpdateTime(1.5);
                //else if (RAIN_OF_FIRE && LastSpellDestruction < 3 && m_ai->GetAttackerCount() >= 3)
                //    m_ai->CastSpell(RAIN_OF_FIRE, *pTarget);
                //    //m_ai->TellMaster("casting rain of fire!");
                //    //m_ai->SetIgnoreUpdateTime(8);
                //else if (SEARING_PAIN && LastSpellDestruction < 8)
                //    m_ai->CastSpell(SEARING_PAIN, *pTarget);
                //else if (SOUL_FIRE && LastSpellDestruction < 9)
                //    m_ai->CastSpell(SOUL_FIRE, *pTarget);
                //    //m_ai->SetIgnoreUpdateTime(6);
                //else if (HELLFIRE && LastSpellDestruction < 12 && !m_bot->HasAura(HELLFIRE) && m_ai->GetAttackerCount() >= 5 && m_ai->GetHealthPercent() >= 50)
                //    m_ai->CastSpell(HELLFIRE);
                //    m_ai->TellMaster("casting hellfire!");
                //    //m_ai->SetIgnoreUpdateTime(15);
    }

    // No spec due to low level OR no spell found yet
    if (CORRUPTION && m_ai->In_Reach(pTarget,CORRUPTION) && !pTarget->HasAura(CORRUPTION) && CastSpell(CORRUPTION, pTarget))
        return RETURN_CONTINUE;
    if (IMMOLATE && m_ai->In_Reach(pTarget,IMMOLATE) && !pTarget->HasAura(IMMOLATE) && CastSpell(IMMOLATE, pTarget))
        return RETURN_CONTINUE;
    if (SHADOW_BOLT && m_ai->In_Reach(pTarget,SHADOW_BOLT))
        return CastSpell(SHADOW_BOLT, pTarget);

    // Default: shoot with wand
    return CastSpell(SHOOT, pTarget);

    return RETURN_NO_ACTION_OK;
} // end DoNextCombatManeuver
Example #18
0
void GameObject::Update(uint32 diff)
{
    if (IS_MO_TRANSPORT(GetGUID()))
    {
        //((Transport*)this)->Update(p_time);
        return;
    }

    switch (m_lootState)
    {
        case GO_NOT_READY:
        {
            switch(GetGoType())
            {
                case GAMEOBJECT_TYPE_TRAP:
                {
                    // Arming Time for GAMEOBJECT_TYPE_TRAP (6)
                    Unit* owner = GetOwner();
                    if (owner && ((Player*)owner)->isInCombat())
                        m_cooldownTime = time(NULL) + GetGOInfo()->trap.startDelay;
                    m_lootState = GO_READY;
                    break;
                }
                case GAMEOBJECT_TYPE_FISHINGNODE:
                {
                    // fishing code (bobber ready)
                    if( time(NULL) > m_respawnTime - FISHING_BOBBER_READY_TIME )
                    {
                        // splash bobber (bobber ready now)
                        Unit* caster = GetOwner();
                        if(caster && caster->GetTypeId()==TYPEID_PLAYER)
                        {
                            SetGoState(0);
                            SetUInt32Value(GAMEOBJECT_FLAGS, GO_FLAG_NODESPAWN);

                            UpdateData udata;
                            WorldPacket packet;
                            BuildValuesUpdateBlockForPlayer(&udata,((Player*)caster));
                            udata.BuildPacket(&packet);
                            ((Player*)caster)->GetSession()->SendPacket(&packet);

                            WorldPacket data(SMSG_GAMEOBJECT_CUSTOM_ANIM,8+4);
                            data << GetGUID();
                            data << (uint32)(0);
                            ((Player*)caster)->SendMessageToSet(&data,true);
                        }

                        m_lootState = GO_READY;                 // can be successfully open with some chance
                    }
                    return;
                }
                default:
                    m_lootState = GO_READY;                         // for other GOis same switched without delay to GO_READY
                    break;
            }
            // NO BREAK for switch (m_lootState)
        }
        case GO_READY:
        {
            if (m_respawnTime > 0)                          // timer on
            {
                if (m_respawnTime <= time(NULL))            // timer expired
                {
                    m_respawnTime = 0;
                    m_SkillupList.clear();
                    m_usetimes = 0;

                    switch (GetGoType())
                    {
                        case GAMEOBJECT_TYPE_FISHINGNODE:   //  can't fish now
                        {
                            Unit* caster = GetOwner();
                            if(caster && caster->GetTypeId()==TYPEID_PLAYER)
                            {
                                if(caster->m_currentSpells[CURRENT_CHANNELED_SPELL])
                                {
                                    caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->SendChannelUpdate(0);
                                    caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->finish(false);
                                }

                                WorldPacket data(SMSG_FISH_NOT_HOOKED,0);
                                ((Player*)caster)->GetSession()->SendPacket(&data);
                            }
                            // can be delete
                            m_lootState = GO_JUST_DEACTIVATED;
                            return;
                        }
                        case GAMEOBJECT_TYPE_DOOR:
                        case GAMEOBJECT_TYPE_BUTTON:
                            //we need to open doors if they are closed (add there another condition if this code breaks some usage, but it need to be here for battlegrounds)
                            if( !GetGoState() )
                                SwitchDoorOrButton(false);
                            //flags in AB are type_button and we need to add them here so no break!
                        default:
                            if(!m_spawnedByDefault)         // despawn timer
                            {
                                                            // can be despawned or destroyed
                                SetLootState(GO_JUST_DEACTIVATED);
                                return;
                            }
                                                            // respawn timer
                            MapManager::Instance().GetMap(GetMapId(), this)->Add(this);
                            break;
                    }
                }
            }

            // traps can have time and can not have
            GameObjectInfo const* goInfo = GetGOInfo();
            if(goInfo->type == GAMEOBJECT_TYPE_TRAP)
            {
                // traps
                Unit* owner = GetOwner();
                Unit* ok = NULL;                            // pointer to appropriate target if found any

                if(m_cooldownTime >= time(NULL))
                    return;

                bool IsBattleGroundTrap = false;
                //FIXME: this is activation radius (in different casting radius that must be selected from spell data)
                //TODO: move activated state code (cast itself) to GO_ACTIVATED, in this place only check activating and set state
                float radius = goInfo->trap.radius;

                if(!radius)
                {
                    if(goInfo->trap.cooldown != 3)            // cast in other case (at some triggering/linked go/etc explicit call)
                    {
                        // try to read radius from trap spell
                        if(const SpellEntry *spellEntry = sSpellStore.LookupEntry(goInfo->trap.spellId))
                            radius = GetSpellRadius(spellEntry,0,false);
                        //    radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(spellEntry->EffectRadiusIndex[0]));

                        if(!radius)
                            break;
                    }
                    else
                    {
                        if(m_respawnTime > 0)
                            break;

                        radius = goInfo->trap.cooldown;       // battlegrounds gameobjects has data2 == 0 && data5 == 3
                        IsBattleGroundTrap = true;
                    }
                }

                bool NeedDespawn = (goInfo->trap.charges != 0);

                CellPair p(Trinity::ComputeCellPair(GetPositionX(),GetPositionY()));
                Cell cell(p);
                cell.data.Part.reserved = ALL_DISTRICT;

                // Note: this hack with search required until GO casting not implemented
                // search unfriendly creature
                if(owner && NeedDespawn)                    // hunter trap
                {
                    Trinity::AnyUnfriendlyNoTotemUnitInObjectRangeCheck u_check(this, owner, radius);
                    Trinity::UnitSearcher<Trinity::AnyUnfriendlyNoTotemUnitInObjectRangeCheck> checker(ok, u_check);

                    CellLock<GridReadGuard> cell_lock(cell, p);

                    TypeContainerVisitor<Trinity::UnitSearcher<Trinity::AnyUnfriendlyNoTotemUnitInObjectRangeCheck>, GridTypeMapContainer > grid_object_checker(checker);
                    cell_lock->Visit(cell_lock, grid_object_checker, *MapManager::Instance().GetMap(GetMapId(), this));

                    // or unfriendly player/pet
                    if(!ok)
                    {
                        TypeContainerVisitor<Trinity::UnitSearcher<Trinity::AnyUnfriendlyNoTotemUnitInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker);
                        cell_lock->Visit(cell_lock, world_object_checker, *MapManager::Instance().GetMap(GetMapId(), this));
                    }
                }
                else                                        // environmental trap
                {
                    // environmental damage spells already have around enemies targeting but this not help in case not existed GO casting support

                    // affect only players
                    Player* p_ok = NULL;
                    Trinity::AnyPlayerInObjectRangeCheck p_check(this, radius);
                    Trinity::PlayerSearcher<Trinity::AnyPlayerInObjectRangeCheck>  checker(p_ok, p_check);

                    CellLock<GridReadGuard> cell_lock(cell, p);

                    TypeContainerVisitor<Trinity::PlayerSearcher<Trinity::AnyPlayerInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker);
                    cell_lock->Visit(cell_lock, world_object_checker, *MapManager::Instance().GetMap(GetMapId(), this));
                    ok = p_ok;
                }

                if (ok)
                {
                    //Unit *caster =  owner ? owner : ok;

                    //caster->CastSpell(ok, goInfo->trap.spellId, true);
                    CastSpell(ok, goInfo->trap.spellId);
                    m_cooldownTime = time(NULL) + 4;        // 4 seconds

                    if(NeedDespawn)
                        SetLootState(GO_JUST_DEACTIVATED);  // can be despawned or destroyed

                    if(IsBattleGroundTrap && ok->GetTypeId() == TYPEID_PLAYER)
                    {
                        //BattleGround gameobjects case
                        if(((Player*)ok)->InBattleGround())
                            if(BattleGround *bg = ((Player*)ok)->GetBattleGround())
                                bg->HandleTriggerBuff(GetGUID());
                    }
                }
            }

            if (m_charges && m_usetimes >= m_charges)
                SetLootState(GO_JUST_DEACTIVATED);          // can be despawned or destroyed

            break;
        }
        case GO_ACTIVATED:
        {
            switch(GetGoType())
            {
                case GAMEOBJECT_TYPE_DOOR:
                case GAMEOBJECT_TYPE_BUTTON:
                    if(GetAutoCloseTime() && (m_cooldownTime < time(NULL)))
                    {
                        SwitchDoorOrButton(false);
                        SetLootState(GO_JUST_DEACTIVATED);
                    }
                    break;
                case GAMEOBJECT_TYPE_CHEST:
                    if(m_groupLootTimer && lootingGroupLeaderGUID)
                    {
                        if(diff <= m_groupLootTimer)
                        {
                            m_groupLootTimer -= diff;
                        }
                        else
                        {
                            Group* group = objmgr.GetGroupByLeader(lootingGroupLeaderGUID);
                            if (group)
                                group->EndRoll();
                            m_groupLootTimer = 0;
                            lootingGroupLeaderGUID = 0;
                        }
                    }
                    break;
            }
            break;
        }
        case GO_JUST_DEACTIVATED:
        {
            //if Gameobject should cast spell, then this, but some GOs (type = 10) should be destroyed
            if (GetGoType() == GAMEOBJECT_TYPE_GOOBER)
            {
                uint32 spellId = GetGOInfo()->goober.spellId;

                if(spellId)
                {
                    std::set<uint32>::iterator it = m_unique_users.begin();
                    std::set<uint32>::iterator end = m_unique_users.end();
                    for (; it != end; it++)
                    {
                        Unit* owner = Unit::GetUnit(*this, uint64(*it));
                        if (owner) owner->CastSpell(owner, spellId, false);
                    }

                    m_unique_users.clear();
                    m_usetimes = 0;
                }
                //any return here in case battleground traps
            }

            if(GetOwnerGUID())
            {
                m_respawnTime = 0;
                Delete();
                return;
            }

            //burning flags in some battlegrounds, if you find better condition, just add it
            if (GetGoAnimProgress() > 0)
            {
                SendObjectDeSpawnAnim(this->GetGUID());
                //reset flags
                SetUInt32Value(GAMEOBJECT_FLAGS, GetGOInfo()->flags);
            }

            loot.clear();
            SetLootState(GO_READY);

            if(!m_respawnDelayTime)
                return;

            if(!m_spawnedByDefault)
            {
                m_respawnTime = 0;
                return;
            }

            m_respawnTime = time(NULL) + m_respawnDelayTime;

            // if option not set then object will be saved at grid unload
            if(sWorld.getConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY))
                SaveRespawnTime();

            ObjectAccessor::UpdateObjectVisibility(this);

            break;
        }
    }
}
Example #19
0
void PlayerbotMageAI::DoNonCombatActions()
{
    Player* master = GetMaster();

    if (!m_bot || !master)
        return;

    // Remove curse on group members if orders allow bot to do so
    if (Player* pCursedTarget = GetDispelTarget(DISPEL_CURSE))
    {
        if (MAGE_REMOVE_CURSE > 0 && (m_ai->GetCombatOrder() & PlayerbotAI::ORDERS_NODISPEL) == 0 && CastSpell(MAGE_REMOVE_CURSE, pCursedTarget))
            return;
    }

    // Buff armor
    if (MAGE_ARMOR)
    {
        if (m_ai->SelfBuff(MAGE_ARMOR))
            return;
    }
    else if (ICE_ARMOR)
    {
        if (m_ai->SelfBuff(ICE_ARMOR))
            return;
    }
    else if (FROST_ARMOR)
    {
        if (m_ai->SelfBuff(FROST_ARMOR))
            return;
    }

    if (COMBUSTION && !m_bot->HasSpellCooldown(COMBUSTION) && m_ai->SelfBuff(COMBUSTION))
        return;

    // buff group
    // the check for group targets is performed by NeedGroupBuff (if group is found for bots by the function)
    if (NeedGroupBuff(ARCANE_BRILLIANCE, ARCANE_INTELLECT) && m_ai->HasSpellReagents(ARCANE_BRILLIANCE))
    {
        if (Buff(&PlayerbotMageAI::BuffHelper, ARCANE_BRILLIANCE) & RETURN_CONTINUE)
            return;
    }
    else if (Buff(&PlayerbotMageAI::BuffHelper, ARCANE_INTELLECT, JOB_MANAONLY) & RETURN_CONTINUE)
        return;

    Item* gem = FindManaGem();
    if (!gem && CONJURE_MANA_GEM && m_ai->CastSpell(CONJURE_MANA_GEM, *m_bot))
    {
        m_ai->SetIgnoreUpdateTime(3);
        return;
    }

    // TODO: The beauty of a mage is not only its ability to supply itself with water, but to share its water
    // So, conjure at *least* 1.25 stacks, ready to trade a stack and still have some left for self
    if (m_ai->FindDrink() == nullptr && CONJURE_WATER && m_ai->CastSpell(CONJURE_WATER, *m_bot))
    {
        m_ai->TellMaster("I'm conjuring some water.");
        m_ai->SetIgnoreUpdateTime(3);
        return;
    }
    if (m_ai->FindFood() == nullptr && CONJURE_FOOD && m_ai->CastSpell(CONJURE_FOOD, *m_bot))
    {
        m_ai->TellMaster("I'm conjuring some food.");
        m_ai->SetIgnoreUpdateTime(3);
        return;
    }

    if (EatDrinkBandage())
        return;
} // end DoNonCombatActions
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
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 AIUpdate()
	{
		float BazCast = (float)RandomFloat(100.0f);
		CastSpell(BazCast);
	}
Example #23
0
void Vehicle::AddPassenger(Unit *unit, int8 seatId, bool force)
{
    SeatMap::iterator seat;
    seat = m_Seats.find(seatId);

    // this should never happen
    if(seat == m_Seats.end())
        return;

    unit->SetVehicleGUID(GetGUID());

    seat->second.passenger = unit;
    if(unit->GetTypeId() == TYPEID_UNIT && ((Creature*)unit)->isVehicle())
    {
        if(((Vehicle*)unit)->GetEmptySeatsCount(true) == 0)
            seat->second.flags = SEAT_VEHICLE_FULL;
        else
            seat->second.flags = SEAT_VEHICLE_FREE;
    }
    else
    {
        seat->second.flags = SEAT_FULL;
    }

    if(unit->GetTypeId() == TYPEID_PLAYER)
    {
        WorldPacket data0(SMSG_FORCE_MOVE_ROOT, 10);
        data0 << unit->GetPackGUID();
        data0 << (uint32)((seat->second.vs_flags & SF_CAN_CAST) ? 2 : 0);
        unit->SendMessageToSet(&data0,true);
    }

    if(seat->second.vs_flags & SF_MAIN_RIDER)
    {
        if(!(GetVehicleFlags() & VF_MOVEMENT))
        {
            GetMotionMaster()->Clear(false);
            GetMotionMaster()->MoveIdle();
            SetCharmerGUID(unit->GetGUID());
            unit->SetUInt64Value(UNIT_FIELD_CHARM, GetGUID());
            if(unit->GetTypeId() == TYPEID_PLAYER)
            {
                ((Player*)unit)->SetMover(this);
                ((Player*)unit)->SetMoverInQueve(this);
                ((Player*)unit)->SetClientControl(this, 1);
            }
            if(canFly() || HasAuraType(SPELL_AURA_FLY) || HasAuraType(SPELL_AURA_MOD_FLIGHT_SPEED))
            {
                WorldPacket data3(SMSG_MOVE_SET_CAN_FLY, 12);
                data3 << GetPackGUID();
                data3 << (uint32)(0);
                SendMessageToSet(&data3,false);
            }
            //Make vehicle fly
            if(GetVehicleFlags() & VF_FLYING)
                CastSpell(this, 49303, false);
        }

        SpellClickInfoMapBounds clickPair = sObjectMgr.GetSpellClickInfoMapBounds(GetEntry());
        for(SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr)
        {
            if (unit->GetTypeId() == TYPEID_UNIT || itr->second.IsFitToRequirements((Player*)unit))
            {
                Unit *caster = (itr->second.castFlags & 0x1) ? unit : this;
                Unit *target = (itr->second.castFlags & 0x2) ? unit : this;

                caster->CastSpell(target, itr->second.spellId, true);
            }
        }
        if(unit->GetTypeId() == TYPEID_PLAYER)
        {
            // it should be added only on rider enter?
            if(((Player*)unit)->GetGroup())
                ((Player*)unit)->SetGroupUpdateFlag(GROUP_UPDATE_VEHICLE);

            ((Player*)unit)->SetFarSightGUID(GetGUID());

            BuildVehicleActionBar((Player*)unit);
        }

        if(!(GetVehicleFlags() & VF_FACTION))
            setFaction(unit->getFaction());

        if(GetVehicleFlags() & VF_CANT_MOVE)
        {
            WorldPacket data2(SMSG_FORCE_MOVE_ROOT, 10);
            data2 << GetPackGUID();
            data2 << (uint32)(2);
            SendMessageToSet(&data2,false);
        }

        if(GetVehicleFlags() & VF_CAST_AURA && m_VehicleData  && m_VehicleData->v_spells[0] != 0)
            CastSpell(unit, m_VehicleData->v_spells[0], true);

        if(GetVehicleFlags() & VF_NON_SELECTABLE)
            SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
    }
    if(seat->second.vs_flags & SF_UNATTACKABLE)
        unit->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);

    EmptySeatsCountChanged();
}
Example #24
0
void Totem::InitSummon()
{
    if (m_type == TOTEM_PASSIVE)
        for(uint32 spellId, i = 0; spellId = GetSpell(i); i++)
            CastSpell(this, spellId, false, NULL, NULL, GetOwnerGUID());  
}
	void AIUpdate()
	{
		float TarCast = (float)RandomFloat(100.0f);
		CastSpell(TarCast);
	}
    void UpdateAI(uint32 timeDelta) override
    {
        if (mJustStepped)
            return;

        if (mEventTimer > timeDelta)
        {
            mEventTimer -= timeDelta;
            return;
        }

        if (mEventStep == 0)
        {
            m_creature->GetMotionMaster()->MovePoint(0, -11817.48f, 1250.02f, 2.64f);
            mJustStepped = true;
        }
        else if (mEventStep == 1)
        {
            m_creature->GetMotionMaster()->MovePoint(0, -11829.73f, 1258.05f, 1.88f);
            mJustStepped = true;
        }
        else if (mEventStep == 2)
        {
            m_creature->GetMotionMaster()->MovePoint(0, -11837.02f, 1293.10f, 0.69f);
            mJustStepped = true;
        }
        else if (mEventStep == 3)
        {
            m_creature->GetMotionMaster()->MovePoint(0, -11825.56f, 1322.88f, 0.29f);
            mJustStepped = true;
            mEventTimer = 1000;
        }
        else if (mEventStep == 4)
        {
            m_creature->CastSpell(m_creature, SPELL_QUEST_TROLL_HERO_SUMMON_VISUAL, false);
            ++mEventStep;
            mEventTimer = 30000;
        }
        else if (mEventStep == 5)
        {
            for (int i = 0; i < 4; ++i)
            {
                auto cr = m_creature->SummonCreature(NPC_SERVANT, servant_positions[i][0], servant_positions[i][1], servant_positions[i][2], servant_positions[i][3],
                    TEMPSUMMON_MANUAL_DESPAWN, 0);
                if (!cr)
                {
                    m_creature->MonsterSay("Etwas lief falsch, bitte beim Team melden!", 0);
                    m_creature->Respawn();
                    Reset();
                    return;
                }

                cr->CastSpell(cr, SPELL_SPAWN_RED_LIGHTNING, true);
                servants.push_back(cr);
            }


            ++mEventStep;
            mEventTimer = 2000;
        }
        else if (mEventStep == 6)
        {
            if (Unit* pTarget = m_creature->GetMap()->GetUnit(targetDummy))
                m_creature->CastSpell(pTarget, SPELL_HEART_OF_HAKKAR_MOLTHOR_CHUCKS_THE_HEART, true);

            ++mEventStep;
            mEventTimer = 5000;
        }
        else if (mEventStep == 7)
        {
            if (Unit* pTarget = m_creature->GetMap()->GetUnit(targetDummy))
                pTarget->CastSpell(pTarget, SPELL_CREATE_HEART_OF_HAKKAR_RIFT, true);

            ++mEventStep;
            mEventTimer = 500;
        }
        else if (mEventStep == 8)
        {
            DoScriptText(-1200000, m_creature);
            for (int i = 0; i < 4; ++i)
            {
                servants[i]->CastSpell(servants[i], SPELL_HEART_OF_HAKKAR_SUMMON_CIRCLE, true);
                servants[i]->CastSpell(servants[i], SPELL_HEART_OF_HAKKAR_RITUAL_CAST, true);

            }
            m_creature->CastSpell(m_creature, SPELL_HEART_OF_HAKKAR_BANNING, true);
            ++mEventStep;
            mEventTimer = 30000;
        }
        else if (mEventStep == 9)
        {
            if (Unit* pTarget = m_creature->GetMap()->GetUnit(targetDummy))
            {
                m_creature->CastSpell(pTarget, SPELL_CREATE_HEART_OF_HAKKAR_EXPLOISON, true);
                m_creature->CastSpell(pTarget, SPELL_HELLFIRE_CAST_VISUAL, true);
            }
            ++mEventStep;
            mEventTimer = 4000;
        }
        else if (mEventStep == 10)
        {
            DoScriptText(-1200001, m_creature);
            ++mEventStep;
            mEventTimer = 1000;
        }
        else if (mEventStep == 11)
        {
            if (Unit* pTarget = m_creature->GetMap()->GetUnit(target))
                m_creature->CastSpell(pTarget, SPELL_SPIRIT_OF_ZANDALAR, false);
            ++mEventStep;
            mEventTimer = 4000;
        }
        else if (mEventStep == 12)
        {
            m_creature->GetMotionMaster()->MovePoint(0, -11837.02f, 1293.10f, 0.69f);
            mJustStepped = true;
        }
        else if (mEventStep == 13)
        {
            m_creature->GetMotionMaster()->MovePoint(0, -11829.73f, 1258.05f, 1.88f);
            mJustStepped = true;
        }
        else if (mEventStep == 14)
        {
            m_creature->GetMotionMaster()->MovePoint(0, -11817.48f, 1250.02f, 2.64f);
            mJustStepped = true;
        }
        else if (mEventStep == 15)
        {
            auto a = m_creature->GetMotionMaster()->top();

            float x, y, z;
            m_creature->GetRespawnCoord(x, y, z);
            m_creature->GetMotionMaster()->MovePoint(0, x, y, z);
            mJustStepped = true;
        }
        else if (mEventStep == 16)
        {
            m_creature->SetFacingTo(4.24f);
            if (Creature* pTarget = m_creature->GetMap()->GetCreature(targetDummy))
                pTarget->ForcedDespawn();
            for (int i = 0; i < 4; ++i)
                servants[i]->ForcedDespawn();
            if (GameObject* pObject = m_creature->GetMap()->GetGameObject(heart))
            {
                pObject->SetLootState(GO_JUST_DEACTIVATED);
                pObject->RemoveFromWorld();
            }
            Reset();
        }
    }
Example #27
0
void CMobController::DoRoamTick(time_point tick)
{
    // If there's someone on our enmity list, go from roaming -> engaging
    if (PMob->PEnmityContainer->GetHighestEnmity() != nullptr && !(PMob->m_roamFlags & ROAMFLAG_IGNORE))
    {
        Engage(PMob->PEnmityContainer->GetHighestEnmity()->targid);
        return;
    }
    else if (PMob->m_OwnerID.id != 0 && !(PMob->m_roamFlags & ROAMFLAG_IGNORE))
    {
        // i'm claimed by someone and need hate towards this person
        PTarget = (CBattleEntity*)PMob->GetEntity(PMob->m_OwnerID.targid, TYPE_PC | TYPE_MOB | TYPE_PET);

        battleutils::ClaimMob(PMob, PTarget);

        Engage(PTarget->targid);
        return;
    }
    //#TODO
    else if (PMob->GetDespawnTime() > time_point::min() && PMob->GetDespawnTime() < m_Tick)
    {
        Despawn();
        return;
    }

    if (PMob->m_roamFlags & ROAMFLAG_IGNORE)
    {
        // don't claim me if I ignore
        PMob->m_OwnerID.clean();
    }

    //skip roaming if waiting
    if (m_Tick >= m_WaitTime)
    {
        // don't aggro a little bit after I just disengaged
        PMob->m_neutral = PMob->CanBeNeutral() && m_Tick <= m_NeutralTime + 10s;

        if (PMob->PAI->PathFind->IsFollowingPath())
        {
            FollowRoamPath();
        }
        else if (m_Tick >= m_LastActionTime + std::chrono::milliseconds(PMob->getBigMobMod(MOBMOD_ROAM_COOL)))
        {
            // lets buff up or move around

            if (PMob->CalledForHelp())
            {
                PMob->CallForHelp(false);
            }

            // can't rest with poison or disease
            if (PMob->CanRest())
            {
                // recover 10% health
                if (PMob->Rest(0.1f))
                {
                    // health updated
                    PMob->updatemask |= UPDATE_HP;
                }

                if (PMob->GetHPP() == 100)
                {
                    // at max health undirty exp
                    PMob->m_giveExp = true;
                }
            }

            // if I just disengaged check if I should despawn
            if (PMob->IsFarFromHome())
            {
                if (PMob->CanRoamHome() && PMob->PAI->PathFind->PathTo(PMob->m_SpawnPoint))
                {
                    // walk back to spawn if too far away

                    // limit total path to just 10 or
                    // else we'll move straight back to spawn
                    PMob->PAI->PathFind->LimitDistance(10.0f);

                    FollowRoamPath();

                    // move back every 5 seconds
                    m_LastActionTime = m_Tick - (std::chrono::milliseconds(PMob->getBigMobMod(MOBMOD_ROAM_COOL)) + 10s);
                }
                else if (!PMob->getMobMod(MOBMOD_NO_DESPAWN) != 0 &&
                    !map_config.mob_no_despawn)
                {
                    PMob->PAI->Despawn();
                    return;
                }
            }
            else
            {
                if (PMob->getMobMod(MOBMOD_SPECIAL_SKILL) != 0 &&
                    m_Tick >= m_LastSpecialTime + std::chrono::milliseconds(PMob->getBigMobMod(MOBMOD_SPECIAL_COOL)) &&
                    TrySpecialSkill())
                {
                    // I spawned a pet
                }
                else if (PMob->GetMJob() == JOB_SMN && CanCastSpells() && PMob->SpellContainer->HasBuffSpells() &&
                    m_Tick >= m_LastMagicTime + std::chrono::milliseconds(PMob->getBigMobMod(MOBMOD_MAGIC_COOL)))
                {
                    // summon pet
                    CastSpell(PMob->SpellContainer->GetBuffSpell());
                }
                else if (CanCastSpells() && dsprand::GetRandomNumber(10) < 3 && PMob->SpellContainer->HasBuffSpells())
                {
                    // cast buff
                    CastSpell(PMob->SpellContainer->GetBuffSpell());
                }
                else if ((PMob->m_roamFlags & ROAMFLAG_AMBUSH))
                {
                    //#TODO: #AIToScript move to scripts
                    // stay underground
                    PMob->HideName(true);
                    PMob->HideModel(true);
                    PMob->animationsub = 0;

                    PMob->updatemask |= UPDATE_HP;
                }
                else if ((PMob->m_roamFlags & ROAMFLAG_STEALTH))
                {
                    // hidden name
                    PMob->HideName(true);
                    PMob->Untargetable(true);

                    PMob->updatemask |= UPDATE_HP;
                }
                else if (PMob->m_roamFlags & ROAMFLAG_EVENT)
                {
                    // allow custom event action
                    luautils::OnMobRoamAction(PMob);
                    m_LastActionTime = m_Tick;
                }
                else if (PMob->CanRoam() && PMob->PAI->PathFind->RoamAround(PMob->m_SpawnPoint, PMob->GetRoamDistance(), PMob->getMobMod(MOBMOD_ROAM_TURNS), PMob->m_roamFlags))
                {
                    //#TODO: #AIToScript (event probably)
                    if (PMob->m_roamFlags & ROAMFLAG_WORM)
                    {
                        // move down
                        PMob->animationsub = 1;
                        PMob->HideName(true);

                        // don't move around until i'm fully in the ground
                        Wait(2s);
                    }
                    else
                    {
                        FollowRoamPath();
                    }
                }
                else
                {
                    m_LastActionTime = m_Tick;
                }
            }
        }
    }
    if (m_Tick >= m_LastRoamScript + 3s)
    {
        luautils::OnMobRoam(PMob);
        m_LastRoamScript = m_Tick;
    }
}
Example #28
0
CombatManeuverReturns PlayerbotPriestAI::DoNextCombatManeuverPVE(Unit *pTarget)
{
    if (!m_ai)  return RETURN_NO_ACTION_ERROR;
    if (!m_bot) return RETURN_NO_ACTION_ERROR;

    Unit* pVictim = pTarget->getVictim();
    float dist = m_bot->GetCombatDistance(pTarget);
    uint32 spec = m_bot->GetSpec();

    Group *m_group = m_bot->GetGroup();

    if (m_ai->GetCombatStyle() != PlayerbotAI::COMBAT_RANGED && dist > ATTACK_DISTANCE)
        m_ai->SetCombatStyle(PlayerbotAI::COMBAT_RANGED);
    // if in melee range OR can't shoot OR have no ranged (wand) equipped
    else if(m_ai->GetCombatStyle() != PlayerbotAI::COMBAT_MELEE 
            && (SHOOT == 0 || !m_bot->GetWeaponForAttack(RANGED_ATTACK, true, true))
            && !m_ai->IsHealer())
        m_ai->SetCombatStyle(PlayerbotAI::COMBAT_MELEE);

    //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 (newTarget && FADE > 0 && !m_bot->HasAura(FADE, EFFECT_INDEX_0))
        {
            if (CastSpell(FADE, m_bot))
            {
                //m_ai->TellMaster("I'm casting fade.");
                return RETURN_CONTINUE;
            }
            else
                m_ai->TellMaster("I have AGGRO.");
        }

        // Heal myself
        // TODO: move to HealTarget code
        // TODO: you forgot to check for the 'temporarily immune to PW:S because you only just got it cast on you' effect
        //       - which is different effect from the actual shield.
        if (m_ai->GetHealthPercent() < 25 && POWER_WORD_SHIELD > 0 && !m_bot->HasAura(POWER_WORD_SHIELD, EFFECT_INDEX_0))
        {
            if (CastSpell(POWER_WORD_SHIELD) & RETURN_CONTINUE)
            {
                //m_ai->TellMaster("I'm casting PW:S on myself.");
                return RETURN_CONTINUE;
            }
            else if (m_ai->IsHealer()) // Even if any other RETURN_ANY_OK - aside from RETURN_CONTINUE
                m_ai->TellMaster("Your healer's about TO DIE. HELP ME.");
        }
        if (m_ai->GetHealthPercent() < 35 && DESPERATE_PRAYER > 0 && CastSpell(DESPERATE_PRAYER, m_bot) & RETURN_CONTINUE)
        {
            //m_ai->TellMaster("I'm casting desperate prayer.");
            return RETURN_CONTINUE;
        }

        // Already healed self or tank. If healer, do nothing else to anger mob.
        if (m_ai->IsHealer())
            return RETURN_NO_ACTION_OK; // In a sense, mission accomplished.

        // Have threat, can't quickly lower it. 3 options remain: Stop attacking, lowlevel damage (wand), keep on keeping on.
        if (newTarget->GetHealthPercent() > 25)
        {
            // If elite, do nothing and pray tank gets aggro off you
            // TODO: Is there an IsElite function? If so, find it and insert.
            //if (newTarget->IsElite())
            //    return;

            // Not an elite. You could insert PSYCHIC SCREAM here but in any PvE situation that's 90-95% likely
            // to worsen the situation for the group. ... So please don't.
            return CastSpell(SHOOT, pTarget);
        }
    }

    // Heal
    if (m_ai->IsHealer())
    {
        if (HealPlayer(GetHealTarget()) & RETURN_CONTINUE)
            return RETURN_CONTINUE;
    }
    else
    {
        // Is this desirable? Debatable.
        // ... Certainly could be very detrimental to a shadow priest
        // TODO: In a group/raid with a healer you'd want this bot to focus on DPS (it's not specced/geared for healing either)
        if (HealPlayer(m_bot) & RETURN_CONTINUE)
            return RETURN_CONTINUE;
    }

    // Do damage tweaking for healers here
    if (m_ai->IsHealer())
    {
        // TODO: elite exception
        //if (Any target is an Elite)
        //    return;

        return CastSpell(SHOOT, pTarget);
    }

    // Damage Spells
    switch (spec)
    {
        case PRIEST_SPEC_HOLY:
            if (HOLY_FIRE > 0 && !pTarget->HasAura(HOLY_FIRE, EFFECT_INDEX_0) && CastSpell(HOLY_FIRE, pTarget))
                return RETURN_CONTINUE;
            if (SMITE > 0 && CastSpell(SMITE, pTarget))
                return RETURN_CONTINUE;
            //if (HOLY_NOVA > 0 && dist <= ATTACK_DISTANCE && m_ai->CastSpell(HOLY_NOVA))
            //    return RETURN_CONTINUE;
            break;

        case PRIEST_SPEC_SHADOW:
            if (DEVOURING_PLAGUE > 0 && !pTarget->HasAura(DEVOURING_PLAGUE, EFFECT_INDEX_0) && CastSpell(DEVOURING_PLAGUE, pTarget))
                return RETURN_CONTINUE;
            if (VAMPIRIC_TOUCH > 0 && !pTarget->HasAura(VAMPIRIC_TOUCH, EFFECT_INDEX_0) && CastSpell(VAMPIRIC_TOUCH, pTarget))
                return RETURN_CONTINUE;
            if (SHADOW_WORD_PAIN > 0 && !pTarget->HasAura(SHADOW_WORD_PAIN, EFFECT_INDEX_0) && CastSpell(SHADOW_WORD_PAIN, pTarget))
                return RETURN_CONTINUE;
            if (MIND_BLAST > 0 && (!m_bot->HasSpellCooldown(MIND_BLAST)) && CastSpell(MIND_BLAST, pTarget))
                return RETURN_CONTINUE;
            if (MIND_FLAY > 0 && CastSpell(MIND_FLAY, pTarget))
            {
                m_ai->SetIgnoreUpdateTime(3);
                return RETURN_CONTINUE;
            }
            if (SHADOWFIEND > 0 && !m_bot->GetPet() && CastSpell(SHADOWFIEND))
                return RETURN_CONTINUE;
            /*if (MIND_SEAR > 0 && m_ai->GetAttackerCount() >= 3 && CastSpell(MIND_SEAR, pTarget))
            {
                m_ai->SetIgnoreUpdateTime(5);
                return RETURN_CONTINUE;
            }*/
            if (SHADOWFORM == 0 && MIND_FLAY == 0 && SMITE > 0 && CastSpell(SMITE, pTarget)) // low levels
                return RETURN_CONTINUE;
            break;

        case PRIEST_SPEC_DISCIPLINE:
            if (POWER_INFUSION > 0 && CastSpell(POWER_INFUSION, GetMaster())) // TODO: just master?
                return RETURN_CONTINUE;
            if (INNER_FOCUS > 0 && !m_bot->HasAura(INNER_FOCUS, EFFECT_INDEX_0) && CastSpell(INNER_FOCUS, m_bot))
                return RETURN_CONTINUE;
            if (PENANCE > 0 && CastSpell(PENANCE))
                return RETURN_CONTINUE;
            if (SMITE > 0 && CastSpell(SMITE, pTarget))
                return RETURN_CONTINUE;
            break;
    }

    // No spec due to low level OR no spell found yet
    if (MIND_BLAST > 0 && (!m_bot->HasSpellCooldown(MIND_BLAST)) && CastSpell(MIND_BLAST, pTarget))
        return RETURN_CONTINUE;
    if (SHADOW_WORD_PAIN > 0 && !pTarget->HasAura(SHADOW_WORD_PAIN, EFFECT_INDEX_0) && CastSpell(SHADOW_WORD_PAIN, pTarget))
        return RETURN_CONTINUE;
    if (MIND_FLAY > 0 && CastSpell(MIND_FLAY, pTarget))
    {
        m_ai->SetIgnoreUpdateTime(3);
        return RETURN_CONTINUE;
    }
    if (SHADOWFORM == 0 && SMITE > 0 && CastSpell(SMITE, pTarget))
        return RETURN_CONTINUE;

    return RETURN_NO_ACTION_OK;
} // end DoNextCombatManeuver
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;
}
Example #30
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