refactor UnitAI::SelectTarget to allow having a predicate function (1st step).
--HG-- branch : trunk
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user