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

View File

@@ -2652,7 +2652,7 @@ void Spell::EffectDispel(SpellEffIndex effIndex)
// put in combat
if (unitTarget->IsFriendlyTo(m_caster))
unitTarget->getHostileRefMgr().threatAssist(m_caster, 0.0f, m_spellInfo);
unitTarget->GetThreatMgr().ForwardThreatForAssistingMe(m_caster, 0.0f, m_spellInfo);
if (success_list.empty())
return;
@@ -3299,33 +3299,25 @@ void Spell::EffectTaunt(SpellEffIndex /*effIndex*/)
if (!unitTarget)
return;
// xinef: Hand of Reckoning, cast before checing canhavethreatlist. fixes damage against pets
// xinef: Hand of Reckoning, cast before checking canhavethreatlist. fixes damage against pets
if (m_spellInfo->Id == 62124 && unitTarget->GetVictim() != m_caster)
{
m_caster->CastSpell(unitTarget, 67485, true);
unitTarget->CombatStart(m_caster);
}
// this effect use before aura Taunt apply for prevent taunt already attacking target
// for spell as marked "non effective at already attacking target"
if (!unitTarget->CanHaveThreatList() || (unitTarget->GetVictim() == m_caster && !m_spellInfo->HasAura(SPELL_AURA_MOD_TAUNT)))
if (!unitTarget->CanHaveThreatList())
{
SendCastResult(SPELL_FAILED_DONT_REPORT);
return;
}
if (!unitTarget->GetThreatMgr().GetOnlineContainer().empty())
ThreatManager& mgr = unitTarget->GetThreatMgr();
if (mgr.GetCurrentVictim() == m_caster)
{
// Also use this effect to set the taunter's threat to the taunted creature's highest value
float myThreat = unitTarget->GetThreatMgr().GetThreat(m_caster);
float topThreat = unitTarget->GetThreatMgr().GetOnlineContainer().getMostHated()->GetThreat();
if (topThreat > myThreat)
unitTarget->GetThreatMgr().DoAddThreat(m_caster, topThreat - myThreat);
//Set aggro victim to caster
if (HostileReference* forcedVictim = unitTarget->GetThreatMgr().GetOnlineContainer().getReferenceByTarget(m_caster))
unitTarget->GetThreatMgr().setCurrentVictim(forcedVictim);
SendCastResult(SPELL_FAILED_DONT_REPORT);
return;
}
if (!mgr.IsThreatListEmpty())
mgr.MatchUnitThreatToHighestThreat(m_caster);
}
void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
@@ -3677,7 +3669,8 @@ void Spell::EffectThreat(SpellEffIndex /*effIndex*/)
if (!unitTarget->CanHaveThreatList() || m_caster->IsFriendlyTo(unitTarget))
return;
unitTarget->AddThreat(m_caster, float(damage));
// SPELL_EFFECT_THREAT adds flat threat that should not be modified by threat reduction
unitTarget->GetThreatMgr().AddThreat(m_caster, float(damage), m_spellInfo, true);
}
void Spell::EffectHealMaxHealth(SpellEffIndex /*effIndex*/)
@@ -4002,24 +3995,18 @@ void Spell::EffectSanctuary(SpellEffIndex /*effIndex*/)
if (!unitTarget)
return;
if (unitTarget->GetInstanceScript() && unitTarget->GetInstanceScript()->IsEncounterInProgress())
unitTarget->GetThreatMgr().EvaluateSuppressed();
if (unitTarget->IsPlayer() && !unitTarget->GetMap()->IsDungeon())
{
unitTarget->getHostileRefMgr().UpdateVisibility(true);
// Xinef: replaced with CombatStop(false)
unitTarget->AttackStop();
unitTarget->RemoveAllAttackers();
// Night Elf: Shadowmeld only resets threat temporarily
if (m_spellInfo->Id != 59646)
unitTarget->getHostileRefMgr().addThreatPercent(-100);
if (unitTarget->IsPlayer())
unitTarget->ToPlayer()->SendAttackSwingCancelAttack(); // melee and ranged forced attack cancel
// stop all pve combat for players outside dungeons, suppress pvp combat
unitTarget->CombatStop(false, false);
}
else
{
unitTarget->getHostileRefMgr().UpdateVisibility(m_spellInfo->Id == 59646); // Night Elf: Shadowmeld
unitTarget->CombatStop(true);
// in dungeons (or for nonplayers), reset this unit on all enemies' threat lists
for (auto const& pair : unitTarget->GetThreatMgr().GetThreatenedByMeList())
pair.second->ScaleThreat(0.0f);
}
UnitList targets;
@@ -5185,7 +5172,7 @@ void Spell::EffectDispelMechanic(SpellEffIndex effIndex)
// put in combat
if (unitTarget->IsFriendlyTo(m_caster))
unitTarget->getHostileRefMgr().threatAssist(m_caster, 0.0f, m_spellInfo);
unitTarget->GetThreatMgr().ForwardThreatForAssistingMe(m_caster, 0.0f, m_spellInfo);
}
void Spell::EffectResurrectPet(SpellEffIndex /*effIndex*/)
@@ -5903,7 +5890,7 @@ void Spell::EffectRedirectThreat(SpellEffIndex /*effIndex*/)
return;
if (unitTarget)
m_caster->SetRedirectThreat(unitTarget->GetGUID(), uint32(damage));
m_caster->GetThreatMgr().RegisterRedirectThreat(m_spellInfo->Id, unitTarget->GetGUID(), uint32(damage));
}
void Spell::EffectGameObjectDamage(SpellEffIndex /*effIndex*/)