refactor(Core/Combat): Port TrinityCore heap-based threat system (#24715)

Co-authored-by: blinkysc <blinkysc@users.noreply.github.com>
Co-authored-by: Treeston <treeston.mmoc@gmail.com>
Co-authored-by: killerwife <killerwife@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
blinkysc
2026-03-18 13:36:59 -05:00
committed by GitHub
parent c80a0f1fad
commit 984baa92dd
101 changed files with 7045 additions and 2659 deletions
@@ -672,11 +672,12 @@ struct boss_nefarian : public BossAI
case EVENT_CLASSCALL:
if (classesPresent.empty())
{
for (auto& ref : me->GetThreatMgr().GetThreatList())
for (ThreatReference const* ref : me->GetThreatMgr().GetUnsortedThreatList())
{
if (ref->getTarget() && ref->getTarget()->IsPlayer())
if (Unit* victim = ref->GetVictim())
{
classesPresent.insert(ref->getTarget()->getClass());
if (victim->IsPlayer())
classesPresent.insert(victim->getClass());
}
}
}
@@ -172,7 +172,9 @@ public:
if (Unit* charmer = ObjectAccessor::GetUnit(*me, _charmerGUID))
{
charmer->RemoveAurasDueToSpell(SPELL_MINDCONTROL_VISUAL);
me->TauntApply(charmer);
me->EngageWithTarget(charmer);
me->AddThreat(charmer, 100.0f);
me->AI()->AttackStart(charmer);
}
}
}
@@ -237,7 +237,7 @@ public:
void EnterEvadeMode(EvadeReason why) override
{
if (!me->GetThreatMgr().GetThreatList().empty())
if (!me->GetThreatMgr().IsThreatListEmpty())
{
if (!_processingMagmaBurst)
{
@@ -389,18 +389,13 @@ class spell_midnight_fixate : public AuraScript
{
Unit* target = GetTarget();
if (Unit* caster = GetCaster())
{
caster->TauntApply(target);
}
caster->GetThreatMgr().FixateTarget(target);
}
void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
Unit* target = GetTarget();
if (Unit* caster = GetCaster())
{
caster->TauntFadeOut(target);
}
caster->GetThreatMgr().ClearFixate();
}
void Register() override
@@ -239,16 +239,14 @@ struct boss_priestess_lackey_commonAI : public ScriptedAI
void RecalculateThreat()
{
ThreatContainer::StorageType const& tList = me->GetThreatMgr().GetThreatList();
for (auto const& ref : tList)
for (ThreatReference const* ref : me->GetThreatMgr().GetUnsortedThreatList())
{
Unit* pUnit = ObjectAccessor::GetUnit(*me, ref->getUnitGuid());
Unit* pUnit = ref->GetVictim();
if (pUnit && pUnit->IsPlayer() && me->GetThreatMgr().GetThreat(pUnit))
{
float threatMod = GetThreatMod(me->GetDistance2d(pUnit), (float)pUnit->GetArmor(), pUnit->GetHealth(), pUnit->GetMaxHealth(), pUnit);
me->GetThreatMgr().ModifyThreatByPercent(pUnit, -100);
if (HostileReference* ref = me->GetThreatMgr().GetOnlineContainer().getReferenceByTarget(pUnit))
ref->AddThreat(10000000.0f * threatMod);
me->GetThreatMgr().ResetThreat(pUnit);
me->GetThreatMgr().AddThreat(pUnit, 10000000.0f * threatMod, nullptr, true, true);
}
}
}
@@ -254,14 +254,13 @@ class spell_scholomance_fixate_aura : public AuraScript
{
Unit* target = GetTarget();
if (Unit* caster = GetCaster())
caster->TauntApply(target);
caster->GetThreatMgr().FixateTarget(target);
}
void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
Unit* target = GetTarget();
if (Unit* caster = GetCaster())
caster->TauntFadeOut(target);
caster->GetThreatMgr().ClearFixate();
}
void Register() override
@@ -339,10 +338,9 @@ public:
Unit* SelectUnitCasting()
{
ThreatContainer::StorageType threatlist = me->GetThreatMgr().GetThreatList();
for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr)
for (ThreatReference const* ref : me->GetThreatMgr().GetUnsortedThreatList())
{
if (Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()))
if (Unit* unit = ref->GetVictim())
{
if (unit->HasUnitState(UNIT_STATE_CASTING))
{
@@ -83,14 +83,14 @@ struct boss_hazzarah : public BossAI
{
if (me->GetThreatMgr().GetThreatListSize() > 1)
{
ThreatContainer::StorageType::const_iterator lastRef = me->GetThreatMgr().GetOnlineContainer().GetThreatList().end();
--lastRef;
if (Unit* lastTarget = (*lastRef)->getTarget())
// Check if target is the lowest threat (last in sorted list)
ThreatReference const* lowestRef = nullptr;
for (ThreatReference const* ref : me->GetThreatMgr().GetSortedThreatList())
lowestRef = ref; // Last iteration will have the lowest threat target
if (lowestRef && lowestRef->GetVictim() != target)
{
if (lastTarget != target)
{
return !target->HasAura(SPELL_SLEEP);
}
return !target->HasAura(SPELL_SLEEP);
}
}
@@ -470,10 +470,10 @@ public:
case EVENT_CLEAVE:
{
std::list<Unit*> meleeRangeTargets;
auto i = me->GetThreatMgr().GetThreatList().begin();
for (; i != me->GetThreatMgr().GetThreatList().end(); ++i)
auto i = me->GetThreatMgr().GetUnsortedThreatList().begin();
for (; i != me->GetThreatMgr().GetUnsortedThreatList().end(); ++i)
{
Unit* target = (*i)->getTarget();
Unit* target = (*i)->GetVictim();
if (me->IsWithinMeleeRange(target))
{
meleeRangeTargets.push_back(target);
@@ -80,14 +80,14 @@ public:
{
if (me->GetThreatMgr().GetThreatListSize() > 1)
{
ThreatContainer::StorageType::const_iterator lastRef = me->GetThreatMgr().GetOnlineContainer().GetThreatList().end();
--lastRef;
if (Unit* lastTarget = (*lastRef)->getTarget())
// Check if target is the lowest threat (last in sorted list)
ThreatReference const* lowestRef = nullptr;
for (ThreatReference const* ref : me->GetThreatMgr().GetSortedThreatList())
lowestRef = ref; // Last iteration will have the lowest threat target
if (lowestRef && lowestRef->GetVictim() != target)
{
if (lastTarget != target)
{
return !target->HasAura(SPELL_GOUGE);
}
return !target->HasAura(SPELL_GOUGE);
}
}
@@ -161,10 +161,9 @@ public:
if (_thousandBladesTargets.empty())
{
std::vector<Unit*> targetList;
ThreatContainer::StorageType const& threatlist = me->GetThreatMgr().GetThreatList();
for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr)
for (ThreatReference const* ref : me->GetThreatMgr().GetUnsortedThreatList())
{
if (Unit* target = (*itr)->getTarget())
if (Unit* target = ref->GetVictim())
{
if (target->IsAlive() && target->IsWithinDist2d(me, 100.f))
{