aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTrazom62 <none@none>2010-02-27 16:29:58 +0100
committerTrazom62 <none@none>2010-02-27 16:29:58 +0100
commitd9056adc8acd4915100f24af66f803bca897a80b (patch)
tree17ebaed269fc94ce70d7d2a0c8929dd416b9fb70 /src
parente010310c6dff74e04d218cb7279e295897285673 (diff)
refactor UnitAI::SelectTarget to allow having a predicate function (1st step).
--HG-- branch : trunk
Diffstat (limited to 'src')
-rw-r--r--src/game/Spell.cpp13
-rw-r--r--src/game/Unit.h15
-rw-r--r--src/game/UnitAI.cpp116
-rw-r--r--src/game/UnitAI.h59
-rw-r--r--src/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp2
-rw-r--r--src/scripts/northrend/naxxramas/boss_four_horsemen.cpp2
-rw-r--r--src/scripts/northrend/naxxramas/boss_razuvious.cpp2
7 files changed, 113 insertions, 96 deletions
diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp
index a302079faa3..f4380197f5d 100644
--- a/src/game/Spell.cpp
+++ b/src/game/Spell.cpp
@@ -1588,19 +1588,6 @@ struct ChainHealingOrder : public std::binary_function<const Unit*, const Unit*,
}
};
-// Helper for targets nearest to the spell target
-// The spell target is always first unless there is a target at _completely_ the same position (unbelievable case)
-struct TargetDistanceOrder : public std::binary_function<const Unit, const Unit, bool>
-{
- const Unit* MainTarget;
- TargetDistanceOrder(const Unit* Target) : MainTarget(Target) {};
- // functor for operator ">"
- bool operator()(const Unit* _Left, const Unit* _Right) const
- {
- return MainTarget->GetDistanceOrder(_Left,_Right);
- }
-};
-
void Spell::SearchChainTarget(std::list<Unit*> &TagUnitMap, float max_range, uint32 num, SpellTargets TargetType)
{
Unit *cur = m_targets.getUnitTarget();
diff --git a/src/game/Unit.h b/src/game/Unit.h
index d30f694e88d..05c0c493abe 100644
--- a/src/game/Unit.h
+++ b/src/game/Unit.h
@@ -2085,4 +2085,19 @@ namespace Trinity
}
}
+// binary function to sort unit based on the distance to a reference unit
+struct TargetDistanceOrder : public std::binary_function<const Unit *, const Unit *, bool>
+{
+ const Unit *me;
+
+ // pUnit: the reference unit from which the distance is computed.
+ TargetDistanceOrder(const Unit* pUnit) : me(pUnit) {};
+
+ // functor for operator "<"
+ bool operator()(const Unit* left, const Unit* right) const
+ {
+ return (me->GetExactDistSq(left) < me->GetExactDistSq(right));
+ }
+};
+
#endif
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;
}
}
diff --git a/src/game/UnitAI.h b/src/game/UnitAI.h
index 6e4f80c0b35..48d8aab385e 100644
--- a/src/game/UnitAI.h
+++ b/src/game/UnitAI.h
@@ -65,8 +65,63 @@ class UnitAI
virtual void SetGUID(const uint64 &guid, int32 id = 0) {}
virtual uint64 GetGUID(int32 id = 0) { return 0; }
- Unit* SelectTarget(SelectAggroTarget target, uint32 position = 0, float dist = 0, bool playerOnly = false, int32 aura = 0);
- void SelectTargetList(std::list<Unit*> &targetList, uint32 num, SelectAggroTarget target, float dist = 0, bool playerOnly = false, int32 aura = 0);
+ Unit* SelectTarget(SelectAggroTarget targetType, uint32 position = 0, float dist = 0.0f, bool playerOnly = false, int32 aura = 0);
+ void SelectTargetList(std::list<Unit*> &targetList, uint32 num, SelectAggroTarget targetType, float dist = 0.0f, bool playerOnly = false, int32 aura = 0);
+
+ // Select the targets satifying the predicate.
+ // predicate shall extend std::unary_function<Unit *, bool>
+ template<class PREDICATE> Unit* SelectTarget(SelectAggroTarget targetType, uint32 position, PREDICATE predicate)
+ {
+ 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)
+ {
+ HostilReference* ref = (*itr);
+ if (predicate(ref->getTarget()))
+ targetList.push_back(ref->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:
+ {
+ std::list<Unit*>::iterator itr = targetList.begin();
+ advance(itr, position);
+ return *itr;
+ }
+ break;
+
+ case SELECT_TARGET_FARTHEST:
+ case SELECT_TARGET_BOTTOMAGGRO:
+ {
+ std::list<Unit*>::reverse_iterator ritr = targetList.rbegin();
+ advance(ritr, position);
+ return *ritr;
+ }
+ break;
+
+ case SELECT_TARGET_RANDOM:
+ {
+ std::list<Unit*>::iterator itr = targetList.begin();
+ advance(itr, urand(position, targetList.size()-1));
+ return *itr;
+ }
+ break;
+ }
+
+ return NULL;
+ }
void AttackStartCaster(Unit *victim, float dist);
diff --git a/src/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp b/src/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp
index 6fc53263ed1..ee594a17f8b 100644
--- a/src/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp
+++ b/src/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp
@@ -794,7 +794,7 @@ struct boss_hunter_toc5AI : public ScriptedAI
if (uiShootTimer <= uiDiff)
{
- if (Unit* pTarget = SelectTarget(SELECT_TARGET_FARTHEST,0,30))
+ if (Unit* pTarget = SelectTarget(SELECT_TARGET_FARTHEST,0,30.0f))
{
uiTargetGUID = pTarget->GetGUID();
DoCast(pTarget, DUNGEON_MODE(SPELL_SHOOT,SPELL_SHOOT_H));
diff --git a/src/scripts/northrend/naxxramas/boss_four_horsemen.cpp b/src/scripts/northrend/naxxramas/boss_four_horsemen.cpp
index 78277186571..43ca22e7a21 100644
--- a/src/scripts/northrend/naxxramas/boss_four_horsemen.cpp
+++ b/src/scripts/northrend/naxxramas/boss_four_horsemen.cpp
@@ -327,7 +327,7 @@ struct boss_four_horsemenAI : public BossAI
if (caster)
{
- if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 45))
+ if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f))
DoCast(pTarget, SPELL_PRIMARY(id));
}
else
diff --git a/src/scripts/northrend/naxxramas/boss_razuvious.cpp b/src/scripts/northrend/naxxramas/boss_razuvious.cpp
index a58bb5636db..4f49aa426fe 100644
--- a/src/scripts/northrend/naxxramas/boss_razuvious.cpp
+++ b/src/scripts/northrend/naxxramas/boss_razuvious.cpp
@@ -109,7 +109,7 @@ struct boss_razuviousAI : public BossAI
events.ScheduleEvent(EVENT_SHOUT, 25000);
return;
case EVENT_KNIFE:
- if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 45))
+ if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f))
DoCast(pTarget, SPELL_JAGGED_KNIFE);
events.ScheduleEvent(EVENT_KNIFE, 10000);
return;