mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-02-07 21:01:37 +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();
|
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
|
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;
|
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;
|
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: 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
|
// 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)
|
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)
|
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;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -406,6 +408,69 @@ HostileReference* ThreatContainer::SelectNextVictim(Creature* attacker, HostileR
|
|||||||
return currentRef;
|
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 ==========================
|
//=================== ThreatMgr ==========================
|
||||||
//============================================================
|
//============================================================
|
||||||
|
|||||||
@@ -156,6 +156,10 @@ public:
|
|||||||
|
|
||||||
HostileReference* SelectNextVictim(Creature* attacker, HostileReference* currentVictim) const;
|
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; }
|
void setDirty(bool isDirty) { iDirty = isDirty; }
|
||||||
|
|
||||||
[[nodiscard]] bool isDirty() const { return iDirty; }
|
[[nodiscard]] bool isDirty() const { return iDirty; }
|
||||||
|
|||||||
Reference in New Issue
Block a user