fix(Core/Threat): Creatures should target the closest unit when threat is tied between players (#24227)

This commit is contained in:
Gultask
2026-01-22 00:52:18 -03:00
committed by GitHub
parent 6db120d78f
commit 2069445a97
2 changed files with 71 additions and 2 deletions

View File

@@ -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 ==========================
//============================================================

View File

@@ -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; }