refactor UnitAI::SelectTarget to allow having a predicate function (1st step).

--HG--
branch : trunk
This commit is contained in:
Trazom62
2010-02-27 16:29:58 +01:00
parent e010310c6d
commit d9056adc8a
7 changed files with 113 additions and 96 deletions
-13
View File
@@ -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();
+15
View File
@@ -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
+38 -78
View File
@@ -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;
if(dist && (!me || !target || !me->IsWithinCombatRange(target, dist)))
return false;
// 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) {}
if(aura)
{
if(aura > 0)
bool operator() (const Unit *pTarget) {
if (m_playerOnly && (!pTarget || pTarget->GetTypeId() != TYPEID_PLAYER))
return false;
if (m_dist && (!me || !pTarget || !me->IsWithinCombatRange(pTarget, m_dist)))
return false;
if (m_aura)
{
if(!target->HasAura(aura))
return false;
if (m_aura > 0)
{
if (!pTarget->HasAura(m_aura))
return false;
}
else
{
if (pTarget->HasAura(m_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));
return true;
}
};
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:
{
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;
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;
}
}
+57 -2
View File
@@ -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);
@@ -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));
@@ -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
@@ -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;