diff options
Diffstat (limited to 'src/game/UnitAI.cpp')
-rw-r--r-- | src/game/UnitAI.cpp | 116 |
1 files changed, 38 insertions, 78 deletions
diff --git a/src/game/UnitAI.cpp b/src/game/UnitAI.cpp index dc81dcb0e0e..7d80209d3ab 100644 --- a/src/game/UnitAI.cpp +++ b/src/game/UnitAI.cpp @@ -82,90 +82,47 @@ bool UnitAI::DoSpellAttackIfReady(uint32 spell) return true; } -inline bool SelectTargetHelper(const Unit * me, const Unit * target, const bool &playerOnly, const float &dist, const int32 &aura) -{ - if(playerOnly && (!target || target->GetTypeId() != TYPEID_PLAYER)) - return false; +// default predicate function to select target based on distance, player and/or aura criteria +struct DefaultTargetSelector : public std::unary_function<Unit *, bool> { + const Unit *me; + float m_dist; + bool m_playerOnly; + int32 m_aura; + + // pUnit: the reference unit + // dist: if 0: ignored, if not 0: maximum distance to the reference unit + // playerOnly: self explaining + // aura: if 0: ignored, if > 0: the target shall have the aura, if < 0, the target shall NOT have the aura + DefaultTargetSelector(const Unit *pUnit, float dist, bool playerOnly, int32 aura) : me(pUnit), m_dist(dist), m_playerOnly(playerOnly), m_aura(aura) {} + + bool operator() (const Unit *pTarget) { + if (m_playerOnly && (!pTarget || pTarget->GetTypeId() != TYPEID_PLAYER)) + return false; - if(dist && (!me || !target || !me->IsWithinCombatRange(target, dist))) - return false; + if (m_dist && (!me || !pTarget || !me->IsWithinCombatRange(pTarget, m_dist))) + return false; - if(aura) - { - if(aura > 0) + if (m_aura) { - if(!target->HasAura(aura)) - return false; - } - else - { - if(target->HasAura(aura)) - return false; - } - } - - return true; -} - -struct TargetDistanceOrder : public std::binary_function<const Unit *, const Unit *, bool> -{ - const Unit * me; - TargetDistanceOrder(const Unit* Target) : me(Target) {}; - // functor for operator ">" - bool operator()(const Unit * _Left, const Unit * _Right) const - { - return (me->GetExactDistSq(_Left) < me->GetExactDistSq(_Right)); - } -}; - -Unit* UnitAI::SelectTarget(SelectAggroTarget targetType, uint32 position, float dist, bool playerOnly, int32 aura) -{ - const std::list<HostilReference *> &threatlist = me->getThreatManager().getThreatList(); - std::list<Unit*> targetList; - - if (position >= threatlist.size()) - return NULL; - - for (std::list<HostilReference*>::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) - if (SelectTargetHelper(me, (*itr)->getTarget(), playerOnly, dist, aura)) - targetList.push_back((*itr)->getTarget()); - - if (position >= targetList.size()) - return NULL; - - if (targetType == SELECT_TARGET_NEAREST || targetType == SELECT_TARGET_FARTHEST) - targetList.sort(TargetDistanceOrder(me)); - - switch(targetType) - { - case SELECT_TARGET_NEAREST: - case SELECT_TARGET_TOPAGGRO: + if (m_aura > 0) { - std::list<Unit*>::iterator itr = targetList.begin(); - advance(itr, position); - return *itr; + if (!pTarget->HasAura(m_aura)) + return false; } - break; - - case SELECT_TARGET_FARTHEST: - case SELECT_TARGET_BOTTOMAGGRO: + else { - std::list<Unit*>::reverse_iterator ritr = targetList.rbegin(); - advance(ritr, position); - return *ritr; + if (pTarget->HasAura(m_aura)) + return false; } - break; + } - case SELECT_TARGET_RANDOM: - { - std::list<Unit*>::iterator itr = targetList.begin(); - advance(itr, urand(position, targetList.size()-1)); - return *itr; - } - break; + return true; } +}; - return NULL; +Unit* UnitAI::SelectTarget(SelectAggroTarget targetType, uint32 position, float dist, bool playerOnly, int32 aura) +{ + return SelectTarget(targetType, position, DefaultTargetSelector(me, dist, playerOnly, aura)); } void UnitAI::SelectTargetList(std::list<Unit*> &targetList, uint32 num, SelectAggroTarget targetType, float dist, bool playerOnly, int32 aura) @@ -175,8 +132,9 @@ void UnitAI::SelectTargetList(std::list<Unit*> &targetList, uint32 num, SelectAg if (threatlist.empty()) return; + DefaultTargetSelector targetSelector(me, dist,playerOnly, aura); for (std::list<HostilReference*>::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) - if (SelectTargetHelper(me, (*itr)->getTarget(), playerOnly, dist, aura)) + if (targetSelector((*itr)->getTarget())) targetList.push_back((*itr)->getTarget()); if (targetType == SELECT_TARGET_NEAREST || targetType == SELECT_TARGET_FARTHEST) @@ -259,12 +217,14 @@ void UnitAI::DoCast(uint32 spellId) const SpellEntry * spellInfo = GetSpellStore()->LookupEntry(spellId); bool playerOnly = spellInfo->AttributesEx3 & SPELL_ATTR_EX3_PLAYERS_ONLY; float range = GetSpellMaxRange(spellInfo, false); - if(!(spellInfo->Attributes & SPELL_ATTR_BREAKABLE_BY_DAMAGE) + + DefaultTargetSelector targetSelector(me, range, playerOnly, -(int32)spellId); + if (!(spellInfo->Attributes & SPELL_ATTR_BREAKABLE_BY_DAMAGE) && !(spellInfo->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_VICTIM) - && SelectTargetHelper(me, me->getVictim(), playerOnly, range, -(int32)spellId)) + && targetSelector(me->getVictim())) target = me->getVictim(); else - target = SelectTarget(SELECT_TARGET_RANDOM, 0, range, playerOnly, -(int32)spellId); + target = SelectTarget(SELECT_TARGET_RANDOM, 0, targetSelector); break; } } |