Revert GetAITarget changes

This commit is contained in:
Rochet2
2017-09-29 00:43:13 +03:00
parent 2c5edff901
commit 06384d1f3a
2 changed files with 92 additions and 136 deletions

View File

@@ -647,17 +647,26 @@ namespace LuaCreature
return 0; return 0;
} }
enum SelectAggroTarget
{
SELECT_TARGET_RANDOM = 0, // Just selects a random target
SELECT_TARGET_TOPAGGRO, // Selects targes from top aggro to bottom
SELECT_TARGET_BOTTOMAGGRO, // Selects targets from bottom aggro to top
SELECT_TARGET_NEAREST,
SELECT_TARGET_FARTHEST
};
/** /**
* Returns a target from the [Creature]'s threat list based on the * Returns a target from the [Creature]'s threat list based on the
* supplied arguments. * supplied arguments.
* *
* enum SelectAggroTarget * enum SelectAggroTarget
* { * {
* SELECT_TARGET_RANDOM = 0, // just pick a random target * SELECT_TARGET_RANDOM = 0, //Just selects a random target
* SELECT_TARGET_MAXTHREAT, // prefer targets higher in the threat list * SELECT_TARGET_TOPAGGRO, //Selects targets from top aggro to bottom
* SELECT_TARGET_MINTHREAT, // prefer targets lower in the threat list * SELECT_TARGET_BOTTOMAGGRO, //Selects targets from bottom aggro to top
* SELECT_TARGET_MAXDISTANCE, // prefer targets further from us * SELECT_TARGET_NEAREST,
* SELECT_TARGET_MINDISTANCE // prefer targets closer to us * SELECT_TARGET_FARTHEST
* }; * };
* *
* For example, if you wanted to select the third-farthest [Player] * For example, if you wanted to select the third-farthest [Player]
@@ -671,133 +680,88 @@ namespace LuaCreature
* @param uint32 position = 0 : used as an offset into the threat list. If `targetType` is random, used as the number of players from top of aggro to choose from * @param uint32 position = 0 : used as an offset into the threat list. If `targetType` is random, used as the number of players from top of aggro to choose from
* @param float distance = 0.0 : if positive, the maximum distance for the target. If negative, the minimum distance * @param float distance = 0.0 : if positive, the maximum distance for the target. If negative, the minimum distance
* @param int32 aura = 0 : if positive, the target must have this [Aura]. If negative, the the target must not have this Aura * @param int32 aura = 0 : if positive, the target must have this [Aura]. If negative, the the target must not have this Aura
* @param [Unit] except = nil : An unit that is excluded from the search
* @return [Unit] target : the target, or `nil` * @return [Unit] target : the target, or `nil`
*/ */
int GetAITarget(lua_State* L, Creature* creature) int GetAITarget(lua_State* L, Creature* creature)
{ {
uint32 targetType = Eluna::CHECKVAL<uint32>(L, 2); uint32 targetType = Eluna::CHECKVAL<uint32>(L, 2);
bool m_playerOnly = Eluna::CHECKVAL<bool>(L, 3, false); bool playerOnly = Eluna::CHECKVAL<bool>(L, 3, false);
uint32 offset = Eluna::CHECKVAL<uint32>(L, 4, 0); uint32 position = Eluna::CHECKVAL<uint32>(L, 4, 0);
float m_dist = Eluna::CHECKVAL<float>(L, 5, 0.0f); float dist = Eluna::CHECKVAL<float>(L, 5, 0.0f);
int32 m_aura = Eluna::CHECKVAL<int32>(L, 6, 0); int32 aura = Eluna::CHECKVAL<int32>(L, 6, 0);
Unit* except = Eluna::CHECKOBJ<Unit>(L, 7, false);
ThreatManager& mgr = creature->GetThreatManager(); #ifdef CMANGOS
// shortcut: if we ignore the first <offset> elements, and there are at most <offset> elements, then we ignore ALL elements ThreatList const& threatlist = creature->getThreatManager().getThreatList();
if (mgr.GetThreatListSize() <= offset) #else
ThreatList const& threatlist = creature->GetThreatManager().getThreatList();
#endif
if (threatlist.empty())
return 1;
if (position >= threatlist.size())
return 1; return 1;
std::list<Unit*> targetList; std::list<Unit*> targetList;
if (targetType == SELECT_TARGET_MAXDISTANCE || targetType == SELECT_TARGET_MINDISTANCE) for (ThreatList::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr)
{ {
for (ThreatReference* ref : mgr.GetUnsortedThreatList()) Unit* target = (*itr)->getTarget();
{
if (ref->IsOffline())
continue;
targetList.push_back(ref->GetVictim());
}
}
else
{
Unit* currentVictim = mgr.GetCurrentVictim();
if (currentVictim)
targetList.push_back(currentVictim);
for (ThreatReference* ref : mgr.GetSortedThreatList())
{
if (ref->IsOffline())
continue;
Unit* thisTarget = ref->GetVictim();
if (thisTarget != currentVictim)
targetList.push_back(thisTarget);
}
}
// filter by predicate
auto predicate = [&, creature](Unit* target)
{
if (!creature)
return false;
if (!target) if (!target)
return false; continue;
if (playerOnly && target->GetTypeId() != TYPEID_PLAYER)
if (target == except) continue;
return false; if (aura > 0 && !target->HasAura(aura))
continue;
if (m_playerOnly && (target->GetTypeId() != TYPEID_PLAYER)) else if (aura < 0 && target->HasAura(-aura))
return false; continue;
if (dist > 0.0f && !creature->IsWithinDist(target, dist))
if (m_dist > 0.0f && !creature->IsWithinCombatRange(target, m_dist)) continue;
return false; else if (dist < 0.0f && creature->IsWithinDist(target, -dist))
continue;
if (m_dist < 0.0f && creature->IsWithinCombatRange(target, -m_dist)) targetList.push_back(target);
return false;
if (m_aura)
{
if (m_aura > 0)
{
if (!target->HasAura(m_aura))
return false;
}
else
{
if (target->HasAura(-m_aura))
return false;
}
} }
return true;
};
targetList.remove_if([&predicate](Unit* target) { return !predicate(target); });
// shortcut: the list certainly isn't gonna get any larger after this point
if (targetList.size() <= offset)
return 1;
// right now, list is unsorted for DISTANCE types - re-sort by MAXDISTANCE
if (targetType == SELECT_TARGET_MAXDISTANCE || targetType == SELECT_TARGET_MINDISTANCE)
targetList.sort([creature, targetType](WorldObject const* left, WorldObject const* right) { return creature->GetDistanceOrder(left, right) == (targetType == SELECT_TARGET_MINDISTANCE);
});
// then reverse the sorting for MIN sortings
if (targetType == SELECT_TARGET_MINTHREAT)
targetList.reverse();
// now pop the first <offset> elements
while (offset)
{
targetList.pop_front();
--offset;
}
// maybe nothing fulfills the predicate
if (targetList.empty()) if (targetList.empty())
return 1; return 1;
if (position >= targetList.size())
return 1;
if (targetType == SELECT_TARGET_NEAREST || targetType == SELECT_TARGET_FARTHEST)
targetList.sort(ElunaUtil::ObjectDistanceOrderPred(creature));
switch (targetType) switch (targetType)
{ {
case SELECT_TARGET_MAXTHREAT: case SELECT_TARGET_NEAREST:
case SELECT_TARGET_MINTHREAT: case SELECT_TARGET_TOPAGGRO:
case SELECT_TARGET_MAXDISTANCE: {
case SELECT_TARGET_MINDISTANCE: std::list<Unit*>::const_iterator itr = targetList.begin();
Eluna::Push(L, targetList.front()); if (position)
return 1; std::advance(itr, position);
Eluna::Push(L, *itr);
}
break;
case SELECT_TARGET_FARTHEST:
case SELECT_TARGET_BOTTOMAGGRO:
{
std::list<Unit*>::reverse_iterator ritr = targetList.rbegin();
if (position)
std::advance(ritr, position);
Eluna::Push(L, *ritr);
}
break;
case SELECT_TARGET_RANDOM: case SELECT_TARGET_RANDOM:
{ {
auto it = std::begin(targetList); std::list<Unit*>::const_iterator itr = targetList.begin();
std::advance(it, urand(0, uint32(targetList.size()) - 1)); if (position)
Eluna::Push(L, *it); std::advance(itr, urand(0, position));
return 1; else
std::advance(itr, urand(0, targetList.size() - 1));
Eluna::Push(L, *itr);
} }
break;
default: default:
luaL_argerror(L, 2, "SelectAggroTarget expected"); luaL_argerror(L, 2, "SelectAggroTarget expected");
return 1; break;
} }
return 1; return 1;
} }

View File

@@ -139,14 +139,6 @@ typedef ThreatContainer::StorageType ThreatList;
typedef TemporarySummon TempSummon; typedef TemporarySummon TempSummon;
typedef SpellEntry SpellInfo; typedef SpellEntry SpellInfo;
enum SelectAggroTarget
{
SELECT_TARGET_RANDOM = 0, // just pick a random target
SELECT_TARGET_MAXTHREAT, // prefer targets higher in the threat list
SELECT_TARGET_MINTHREAT, // prefer targets lower in the threat list
SELECT_TARGET_MAXDISTANCE, // prefer targets further from us
SELECT_TARGET_MINDISTANCE // prefer targets closer to us
};
#endif // TRINITY #endif // TRINITY
#endif // _ELUNA_INCLUDES_H #endif // _ELUNA_INCLUDES_H