mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-23 21:56:22 +00:00
fix(Core/Threat): Creatures should target the closest unit when threat is tied between players (#24227)
This commit is contained in:
@@ -328,7 +328,7 @@ HostileReference* ThreatContainer::SelectNextVictim(Creature* attacker, HostileR
|
||||
Unit* cvUnit = currentVictim->getTarget();
|
||||
if (!attacker->CanCreatureAttack(cvUnit)) // pussywizard: if currentVictim is not valid => don't compare the threat with it, just take the highest threat valid target
|
||||
currentVictim = nullptr;
|
||||
else if (cvUnit->IsImmunedToDamageOrSchool(attacker->GetMeleeDamageSchoolMask()) || cvUnit->HasNegativeAuraWithInterruptFlag(AURA_INTERRUPT_FLAG_TAKE_DAMAGE) || cvUnit->HasUnitState(UNIT_STATE_CONFUSED)) // pussywizard: no 10%/30% if currentVictim is immune to damage or has auras breakable by damage
|
||||
else if (!IsPreferredTarget(attacker, cvUnit)) // pussywizard: no 10%/30% if currentVictim is immune to damage or has auras breakable by damage
|
||||
currentVictim = nullptr;
|
||||
}
|
||||
|
||||
@@ -345,7 +345,7 @@ HostileReference* ThreatContainer::SelectNextVictim(Creature* attacker, HostileR
|
||||
|
||||
// pussywizard: don't go to threat comparison if this ref is immune to damage or has aura breakable on damage (second choice target)
|
||||
// pussywizard: if this is the last entry on the threat list, then all targets are second choice, set bool to true and loop threat list again, ignoring this section
|
||||
if (!noPriorityTargetFound && (target->IsImmunedToDamageOrSchool(attacker->GetMeleeDamageSchoolMask()) || target->HasNegativeAuraWithInterruptFlag(AURA_INTERRUPT_FLAG_TAKE_DAMAGE) || target->HasUnitState(UNIT_STATE_CONFUSED) || target->HasAuraTypeWithCaster(SPELL_AURA_IGNORED, attacker->GetGUID())))
|
||||
if (!noPriorityTargetFound && !IsPreferredTarget(attacker, target))
|
||||
{
|
||||
if (iter != lastRef)
|
||||
{
|
||||
@@ -394,6 +394,8 @@ HostileReference* ThreatContainer::SelectNextVictim(Creature* attacker, HostileR
|
||||
}
|
||||
else // pussywizard: no currentVictim, first passing all checks is chosen (highest threat, list is sorted)
|
||||
{
|
||||
// tie-breaker if multiple targets have the same threat: select closest target
|
||||
currentRef = SelectNextVictimTieBreaker(attacker, iter, noPriorityTargetFound);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
@@ -406,6 +408,69 @@ HostileReference* ThreatContainer::SelectNextVictim(Creature* attacker, HostileR
|
||||
return currentRef;
|
||||
}
|
||||
|
||||
// Helper for Tie-breakers
|
||||
HostileReference* ThreatContainer::SelectNextVictimTieBreaker(Creature* attacker, ThreatContainer::StorageType::const_iterator currentIter, bool noPriorityTargetFound) const
|
||||
{
|
||||
HostileReference* bestRef = *currentIter;
|
||||
float bestThreat = bestRef->GetThreat();
|
||||
float shortestDistSq = attacker->GetExactDistSq(bestRef->getTarget());
|
||||
|
||||
auto tieIter = std::next(currentIter);
|
||||
|
||||
while (tieIter != iThreatList.end())
|
||||
{
|
||||
HostileReference* nextRef = *tieIter;
|
||||
|
||||
if (!nextRef)
|
||||
{
|
||||
++tieIter;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Threatlist is sorted, so we can stop as soon as we find a lower threat
|
||||
if (bestThreat - nextRef->GetThreat() > 0.01f)
|
||||
break;
|
||||
|
||||
Unit* target = nextRef->getTarget();
|
||||
|
||||
if (!target)
|
||||
{
|
||||
++tieIter;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (attacker->CanCreatureAttack(target) && (noPriorityTargetFound || IsPreferredTarget(attacker, target)))
|
||||
{
|
||||
float distSq = attacker->GetExactDistSq(target);
|
||||
if (distSq < shortestDistSq)
|
||||
{
|
||||
bestRef = nextRef;
|
||||
shortestDistSq = distSq;
|
||||
}
|
||||
}
|
||||
++tieIter;
|
||||
}
|
||||
return bestRef;
|
||||
}
|
||||
|
||||
// Helper for checking if a target is preferred (not immune, not confused, etc)
|
||||
bool ThreatContainer::IsPreferredTarget(Creature* attacker, Unit* target) const
|
||||
{
|
||||
if (target->IsImmunedToDamageOrSchool(attacker->GetMeleeDamageSchoolMask()))
|
||||
return false;
|
||||
|
||||
if (target->HasNegativeAuraWithInterruptFlag(AURA_INTERRUPT_FLAG_TAKE_DAMAGE))
|
||||
return false;
|
||||
|
||||
if (target->HasUnitState(UNIT_STATE_CONFUSED))
|
||||
return false;
|
||||
|
||||
if (target->HasAuraTypeWithCaster(SPELL_AURA_IGNORED, attacker->GetGUID()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//============================================================
|
||||
//=================== ThreatMgr ==========================
|
||||
//============================================================
|
||||
|
||||
@@ -156,6 +156,10 @@ public:
|
||||
|
||||
HostileReference* SelectNextVictim(Creature* attacker, HostileReference* currentVictim) const;
|
||||
|
||||
HostileReference* SelectNextVictimTieBreaker(Creature* attacker, ThreatContainer::StorageType::const_iterator currentIter, bool noPriorityTargetFound) const;
|
||||
|
||||
bool IsPreferredTarget(Creature* attacker, Unit* target) const;
|
||||
|
||||
void setDirty(bool isDirty) { iDirty = isDirty; }
|
||||
|
||||
[[nodiscard]] bool isDirty() const { return iDirty; }
|
||||
|
||||
Reference in New Issue
Block a user