diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/game/Spell.cpp | 13 | ||||
-rw-r--r-- | src/game/Unit.h | 15 | ||||
-rw-r--r-- | src/game/UnitAI.cpp | 116 | ||||
-rw-r--r-- | src/game/UnitAI.h | 59 | ||||
-rw-r--r-- | src/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp | 2 | ||||
-rw-r--r-- | src/scripts/northrend/naxxramas/boss_four_horsemen.cpp | 2 | ||||
-rw-r--r-- | src/scripts/northrend/naxxramas/boss_razuvious.cpp | 2 |
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; |