//Gets the first found attacker of Unit if not nearestToAttacked > finds the one nearest to bot
Unit *PlayerbotClassAI::GetNearestAttackerOf(Unit *pAttacked, bool nearestToAttacked)
{
    if (!pAttacked) { pAttacked = m_bot; if (!pAttacked) return NULL;}

    Unit::AttackerSet fAttackerSet = pAttacked->getAttackers();
    if (fAttackerSet.size() <= 0) { return NULL; }

    Unit *nearestTo = m_bot;
    if (nearestToAttacked) { nearestTo = pAttacked; }

    Unit *curAtt = NULL;
    float minDist = 30;


    for (Unit::AttackerSet::const_iterator itr = fAttackerSet.begin(); itr != fAttackerSet.end(); ++itr)
    {
        Unit *tAtt = (*itr);
        if (!tAtt) break; // Something is wrong.. How can a non existing mob attack?
        if (tAtt->isDead()) break;
        if (m_bot->GetDistance(tAtt) >= minDist) continue; //Get the nearest one
        curAtt = tAtt;
        minDist = tAtt->GetDistance(nearestTo);
    }
    return curAtt;

}
Example #2
0
void
TotemAI::UpdateAI(const uint32 /*diff*/)
{
  if (me->ToTotem()->GetTotemType() != TOTEM_ACTIVE)
        return;

    if (!me->isAlive() || me->IsNonMeleeSpellCasted(false))
        return;

    // Search spell
    SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(me->ToTotem()->GetSpell());
    if (!spellInfo)
        return;

    // Get spell range
    float max_range = spellInfo->GetMaxRange(false);

    // SPELLMOD_RANGE not applied in this place just because not existence range mods for attacking totems

    // pointer to appropriate target if found any
    Unit* victim = i_victimGuid ? ObjectAccessor::GetUnit(*me, i_victimGuid) : NULL;
    Unit* tmpvictim = 0;

    // Search victim if no, not attackable, or out of range, or friendly (possible in case duel end)
    if (!victim || (!victim->isTargetableForAttack() || !me->IsWithinDistInMap(victim, max_range) ||
        me->IsFriendlyTo(victim) || !me->canSeeOrDetect(victim)))
        {
            Trinity::NearestAttackableUnitInObjectRangeCheck u_check(me, me, max_range);
            Trinity::UnitLastSearcher<Trinity::NearestAttackableUnitInObjectRangeCheck> checker(me, victim, u_check);
            me->VisitNearbyObject(max_range, checker);
            tmpvictim = victim;
        }
    else if(!(victim->HasAura(FLAME_SHOCK, me->GetOwnerGUID()) || victim->HasAura(STORMSTRIKE, me->GetOwnerGUID())))
        tmpvictim = victim;

    Unit* owner = me->GetOwner();
    // looking for attacker with specific auras, do only if new victim found in radius or current victim has no aura
    if (owner && tmpvictim)
    {
        if (Unit* ownervictim = owner->getVictim())
        {
            //Owner's target is priority
            if (me->IsWithinDistInMap(ownervictim, max_range) && (ownervictim->HasAura(FLAME_SHOCK, owner->GetGUID()) || ownervictim->HasAura(STORMSTRIKE, owner->GetGUID())))
                victim = ownervictim;
            else
            {
                Unit::AttackerSet attackers = owner->getAttackers();
                for (Unit::AttackerSet::iterator itr = attackers.begin(); itr != attackers.end(); ++itr)
                {
                    tmpvictim = *itr;
                    if (me->IsWithinDistInMap(tmpvictim, max_range) && 
                       (tmpvictim->HasAura(FLAME_SHOCK, owner->GetGUID()) || tmpvictim->HasAura(STORMSTRIKE, owner->GetGUID())))
                        victim = tmpvictim;
                }
            }
        }
    }

    // If have target
    if (victim)
    {
        // remember
        i_victimGuid = victim->GetGUID();

        // attack
        me->SetInFront(victim);                         // client change orientation by self
        me->CastSpell(victim, me->ToTotem()->GetSpell(), false, NULL, NULL, me->GetOwnerGUID());
    }
    else
        i_victimGuid = 0;
}