aboutsummaryrefslogtreecommitdiff
path: root/src/game/UnitAI.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/game/UnitAI.cpp')
-rw-r--r--src/game/UnitAI.cpp116
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;
}
}