mirror of
https://github.com/liyunfan1223/azerothcore-wotlk.git
synced 2026-08-07 15:28:02 +00:00
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:
@@ -2751,8 +2751,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
|
||||
float threat = float(gain) * 0.5f;
|
||||
if (caster->IsClass(CLASS_PALADIN))
|
||||
threat *= 0.5f;
|
||||
|
||||
unitTarget->getHostileRefMgr().threatAssist(caster, threat, m_spellInfo);
|
||||
unitTarget->GetThreatMgr().ForwardThreatForAssistingMe(caster, threat, m_spellInfo);
|
||||
m_healing = gain;
|
||||
|
||||
// Xinef: if heal actually healed something, add no overheal flag
|
||||
@@ -2877,8 +2876,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
|
||||
if (missInfo == SPELL_MISS_RESIST && m_spellInfo->HasAttribute(SPELL_ATTR0_CU_PICKPOCKET) && unitTarget->IsCreature() && m_caster)
|
||||
{
|
||||
m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TALK);
|
||||
if (unitTarget->ToCreature()->IsAIEnabled)
|
||||
unitTarget->ToCreature()->AI()->AttackStart(m_caster);
|
||||
unitTarget->ToCreature()->EngageWithTarget(m_caster);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2887,19 +2885,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
|
||||
if (missInfo != SPELL_MISS_EVADE && !m_caster->IsFriendlyTo(effectUnit) && (!m_spellInfo->IsPositive() || m_spellInfo->HasEffect(SPELL_EFFECT_DISPEL)))
|
||||
{
|
||||
if (!m_triggeredByAuraSpell.spellInfo || m_damage || (!(m_triggeredByAuraSpell.spellInfo->Effects[m_triggeredByAuraSpell.effectIndex].TriggerSpell == m_spellInfo->Id) && !(m_triggeredByAuraSpell.spellInfo->IsAuraEffectEqual(m_spellInfo))))
|
||||
m_caster->CombatStart(effectUnit, !(m_spellInfo->AttributesEx3 & SPELL_ATTR3_SUPPRESS_TARGET_PROCS));
|
||||
|
||||
// Patch 3.0.8: All player spells which cause a creature to become aggressive to you will now also immediately cause the creature to be tapped.
|
||||
if (effectUnit->IsInCombatWith(m_caster))
|
||||
{
|
||||
if (Creature* creature = effectUnit->ToCreature())
|
||||
{
|
||||
if (!creature->hasLootRecipient() && m_caster->IsPlayer())
|
||||
{
|
||||
creature->SetLootRecipient(m_caster);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_caster->AtTargetAttacked(effectUnit, !(m_spellInfo->HasAttribute(SPELL_ATTR1_NO_THREAT) || m_spellInfo->HasAttribute(SPELL_ATTR3_SUPPRESS_TARGET_PROCS)));
|
||||
|
||||
// Unsure if there are more spells that are not supposed to stop enemy from
|
||||
// regenerating HP from food, so for now it stays as an ID.
|
||||
@@ -3036,10 +3022,11 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA
|
||||
}
|
||||
|
||||
// xinef: triggered spells should not prolong combat
|
||||
if (unit->IsInCombat() && !m_spellInfo->HasAttribute(SPELL_ATTR3_SUPPRESS_TARGET_PROCS) && !m_triggeredByAuraSpell)
|
||||
if (m_originalCaster && unit->IsInCombat() && !m_spellInfo->HasAttribute(SPELL_ATTR3_SUPPRESS_TARGET_PROCS) && !m_triggeredByAuraSpell)
|
||||
{
|
||||
m_caster->SetInCombatState(unit->GetCombatTimer() > 0, unit);
|
||||
unit->getHostileRefMgr().threatAssist(m_caster, 0.0f);
|
||||
if (m_originalCaster->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
|
||||
m_originalCaster->GetCombatManager().InheritCombatStatesFrom(unit);
|
||||
unit->GetThreatMgr().ForwardThreatForAssistingMe(m_originalCaster, 0.0f, nullptr, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4048,12 +4035,6 @@ void Spell::_cast(bool skipCheck)
|
||||
if (target->IsCreature())
|
||||
m_caster->CastSpell(target, 32747, true);
|
||||
|
||||
// xinef: start combat at cast for delayed spells, only for explicit target
|
||||
if (Unit* target = m_targets.GetUnitTarget())
|
||||
if (m_caster->IsPlayer() || (m_caster->IsPet() && m_caster->IsControlledByPlayer()))
|
||||
if (GetDelayMoment() > 0 && !m_caster->IsFriendlyTo(target) && !m_spellInfo->HasAura(SPELL_AURA_BIND_SIGHT) && (!m_spellInfo->IsPositive() || m_spellInfo->HasEffect(SPELL_EFFECT_DISPEL)))
|
||||
m_caster->CombatStartOnCast(target, !m_spellInfo->HasAttribute(SPELL_ATTR3_SUPPRESS_TARGET_PROCS), GetDelayMoment() + 500); // xinef: increase this time so we dont leave and enter combat in a moment
|
||||
|
||||
if (m_caster->IsPlayer())
|
||||
if (m_caster->ToPlayer()->GetCommandStatus(CHEAT_COOLDOWN))
|
||||
m_caster->ToPlayer()->RemoveSpellCooldown(m_spellInfo->Id, true);
|
||||
@@ -5558,11 +5539,13 @@ void Spell::HandleThreatSpells()
|
||||
if (m_spellInfo->HasAttribute(SPELL_ATTR1_NO_THREAT) || m_spellInfo->HasAttribute(SPELL_ATTR3_SUPPRESS_TARGET_PROCS))
|
||||
return;
|
||||
|
||||
Unit* unitCaster = m_originalCaster ? m_originalCaster : m_caster;
|
||||
|
||||
float threat = 0.0f;
|
||||
if (SpellThreatEntry const* threatEntry = sSpellMgr->GetSpellThreatEntry(m_spellInfo->Id))
|
||||
{
|
||||
if (threatEntry->apPctMod != 0.0f)
|
||||
threat += threatEntry->apPctMod * m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
|
||||
threat += threatEntry->apPctMod * unitCaster->GetTotalAttackPowerValue(BASE_ATTACK);
|
||||
|
||||
threat += threatEntry->flatMod;
|
||||
}
|
||||
@@ -5576,23 +5559,27 @@ void Spell::HandleThreatSpells()
|
||||
// since 2.0.1 threat from positive effects also is distributed among all targets, so the overall caused threat is at most the defined bonus
|
||||
threat /= m_UniqueTargetInfo.size();
|
||||
|
||||
for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
|
||||
for (auto& ihit : m_UniqueTargetInfo)
|
||||
{
|
||||
float threatToAdd = threat;
|
||||
if (ihit->missCondition != SPELL_MISS_NONE)
|
||||
if (ihit.missCondition != SPELL_MISS_NONE)
|
||||
threatToAdd = 0.0f;
|
||||
|
||||
Unit* target = ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID);
|
||||
Unit* target = ObjectAccessor::GetUnit(*unitCaster, ihit.targetGUID);
|
||||
if (!target)
|
||||
continue;
|
||||
|
||||
bool IsFriendly = m_caster->IsFriendlyTo(target);
|
||||
// positive spells distribute threat among all units that are in combat with target, like healing
|
||||
if (m_spellInfo->_IsPositiveSpell() && IsFriendly)
|
||||
target->getHostileRefMgr().threatAssist(m_caster, threatToAdd, m_spellInfo);
|
||||
if (m_spellInfo->_IsPositiveSpell())
|
||||
target->GetThreatMgr().ForwardThreatForAssistingMe(unitCaster, threatToAdd, m_spellInfo);
|
||||
// for negative spells threat gets distributed among affected targets
|
||||
else if (!m_spellInfo->_IsPositiveSpell() && !IsFriendly && target->CanHaveThreatList())
|
||||
target->AddThreat(m_caster, threatToAdd, m_spellInfo->GetSchoolMask(), m_spellInfo);
|
||||
// ignoreModifiers=true because flat SpellThreatEntry threat should not have modifiers applied twice
|
||||
else
|
||||
{
|
||||
if (!target->CanHaveThreatList())
|
||||
continue;
|
||||
target->GetThreatMgr().AddThreat(unitCaster, threatToAdd, m_spellInfo, true);
|
||||
}
|
||||
}
|
||||
LOG_DEBUG("spells.aura", "Spell {}, added an additional {} threat for {} {} target(s)", m_spellInfo->Id, threat, m_spellInfo->_IsPositiveSpell() ? "assisting" : "harming", uint32(m_UniqueTargetInfo.size()));
|
||||
}
|
||||
@@ -5772,8 +5759,7 @@ SpellCastResult Spell::CheckCast(bool strict)
|
||||
if (Unit* victim = member->GetVictim())
|
||||
if (victim->IsInCombat() && m_caster->GetDistance(victim) < m_caster->GetVisibilityRange())
|
||||
{
|
||||
m_caster->CombatStart(victim);
|
||||
victim->AddThreat(m_caster, 1.0f);
|
||||
m_caster->EngageWithTarget(victim);
|
||||
break;
|
||||
}
|
||||
return SPELL_FAILED_TARGET_CANNOT_BE_RESURRECTED;
|
||||
|
||||
Reference in New Issue
Block a user