Core/Auras: Implement basic absorb scaling with spellpower (#31405)

This commit is contained in:
Cristian Vintila
2025-11-27 23:50:33 +01:00
committed by GitHub
parent 6160d75889
commit fe5cf65923
3 changed files with 130 additions and 0 deletions
+118
View File
@@ -7584,6 +7584,124 @@ int32 Unit::SpellBaseHealingBonusDone(SpellSchoolMask schoolMask) const
return advertisedBenefit;
}
int32 Unit::SpellBaseAbsorbBonusDone(SpellSchoolMask schoolMask) const
{
return SpellBaseHealingBonusDone(schoolMask);
}
int32 Unit::SpellAbsorbBonusDone(Unit* victim, SpellInfo const* spellProto, int32 absorbamount, SpellEffectInfo const& spellEffectInfo, uint32 stack /*= 1*/, AuraEffect const* aurEff /*= nullptr*/) const
{
if (GetTypeId() == TYPEID_UNIT && IsTotem())
if (Unit* owner = GetOwner())
return owner->SpellAbsorbBonusDone(victim, spellProto, absorbamount, spellEffectInfo, stack, aurEff);
if (spellProto->HasAttribute(SPELL_ATTR3_IGNORE_CASTER_MODIFIERS)
|| spellProto->HasAttribute(SPELL_ATTR6_IGNORE_HEALING_MODIFIERS)
|| spellProto->HasAttribute(SPELL_ATTR9_IGNORE_CASTER_HEALING_MODIFIERS))
return absorbamount;
int32 doneTotal = 0;
float doneTotalMod = 1.f;
int32 doneAdvertisedBenefit = SpellBaseAbsorbBonusDone(spellProto->GetSchoolMask());
doneAdvertisedBenefit += victim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_HEALING, spellProto->GetSchoolMask());
if (HasUnitTypeMask(UNIT_MASK_GUARDIAN))
doneAdvertisedBenefit += static_cast<Guardian const*>(this)->GetBonusDamage();
if (doneAdvertisedBenefit)
{
float coeff = spellEffectInfo.BonusCoefficient;
if (Player* modOwner = GetSpellModOwner())
{
coeff *= 100.f;
modOwner->ApplySpellMod(spellProto, SpellModOp::BonusCoefficient, coeff);
coeff /= 100.f;
}
doneTotal += int32(doneAdvertisedBenefit * coeff * stack);
}
doneTotalMod = SpellAbsorbPctDone(victim, spellProto);
float absorbAmount = float(absorbamount + doneTotal) * doneTotalMod;
return static_cast<int32>(std::round(absorbAmount));
}
float Unit::SpellAbsorbPctDone(Unit* victim, SpellInfo const* spellProto) const
{
if (GetTypeId() == TYPEID_UNIT && IsTotem())
if (Unit* owner = GetOwner())
return owner->SpellAbsorbPctDone(victim, spellProto);
float doneTotalMod = 1.f;
if (Player* modOwner = GetSpellModOwner())
AddPct(doneTotalMod, modOwner->GetRatingBonusValue(CR_VERSATILITY_DAMAGE_DONE) + modOwner->GetTotalAuraModifier(SPELL_AURA_MOD_VERSATILITY));
if (Player const* thisPlayer = ToPlayer())
{
float maxModHealingPercentSchool = 0.f;
for (uint32 i = 0; i < MAX_SPELL_SCHOOL; ++i)
if (spellProto->GetSchoolMask() & (1 << i))
maxModHealingPercentSchool = std::max(maxModHealingPercentSchool, thisPlayer->m_activePlayerData->ModHealingDonePercent[i]);
doneTotalMod *= maxModHealingPercentSchool;
}
else
doneTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_HEALING_DONE_PERCENT);
return doneTotalMod;
}
int32 Unit::SpellAbsorbBonusTaken(Unit* caster, SpellInfo const* spellProto, int32 absorbamount) const
{
bool allowPositive = !spellProto->HasAttribute(SPELL_ATTR6_IGNORE_HEALING_MODIFIERS);
bool allowNegative = !spellProto->HasAttribute(SPELL_ATTR6_IGNORE_HEALING_MODIFIERS) || spellProto->HasAttribute(SPELL_ATTR13_ALWAYS_ALLOW_NEGATIVE_HEALING_PERCENT_MODIFIERS);
if (!allowPositive && !allowNegative)
return absorbamount;
float takenTotalMod = 1.f;
if (allowNegative)
{
float minval = float(GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HEALING_PCT));
if (minval)
AddPct(takenTotalMod, minval);
}
if (allowPositive)
{
float maxval = float(GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HEALING_PCT));
if (maxval)
AddPct(takenTotalMod, maxval);
}
if (caster)
{
takenTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_HEALING_RECEIVED, [caster, spellProto, allowPositive, allowNegative](AuraEffect const* aurEff)
{
if (caster->GetGUID() != aurEff->GetCasterGUID() || !aurEff->IsAffectingSpell(spellProto))
return false;
if (aurEff->GetAmount() > 0)
{
if (!allowPositive)
return false;
}
else if (!allowNegative)
return false;
return true;
});
}
float absorb = absorbamount * takenTotalMod;
return static_cast<int32>(std::round(absorb));
}
bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* caster, bool requireImmunityPurgesEffectAttribute /*= false*/) const
{
if (!spellInfo)
+5
View File
@@ -1661,6 +1661,11 @@ class TC_GAME_API Unit : public WorldObject
float SpellHealingPctDone(Unit* victim, SpellInfo const* spellProto) const;
int32 SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, int32 healamount, DamageEffectType damagetype) const;
int32 SpellBaseAbsorbBonusDone(SpellSchoolMask schoolMask) const;
int32 SpellAbsorbBonusDone(Unit* victim, SpellInfo const* spellProto, int32 absorbamount, SpellEffectInfo const& spellEffectInfo, uint32 stack = 1, AuraEffect const* aurEff = nullptr) const;
float SpellAbsorbPctDone(Unit* victim, SpellInfo const* spellProto) const;
int32 SpellAbsorbBonusTaken(Unit* caster, SpellInfo const* spellProto, int32 absorbamount) const;
int32 MeleeDamageBonusDone(Unit* pVictim, int32 damage, WeaponAttackType attType, DamageEffectType damagetype, SpellInfo const* spellProto = nullptr, SpellEffectInfo const* spellEffectInfo = nullptr, Mechanics mechanic = MECHANIC_NONE, SpellSchoolMask damageSchoolMask = SPELL_SCHOOL_MASK_NORMAL, Spell* spell = nullptr, AuraEffect const* aurEff = nullptr);
int32 MeleeDamageBonusTaken(Unit* attacker, int32 pdamage, WeaponAttackType attType, DamageEffectType damagetype, SpellInfo const* spellProto = nullptr, SpellSchoolMask damageSchoolMask = SPELL_SCHOOL_MASK_NORMAL);
@@ -781,6 +781,13 @@ int32 AuraEffect::CalculateAmount(Unit* caster)
amount = int32(unitOwner->CountPctFromMaxHealth(10));
break;
case SPELL_AURA_SCHOOL_ABSORB:
m_canBeRecalculated = false;
if (!caster || !unitOwner)
break;
amount = caster->SpellAbsorbBonusDone(unitOwner, m_spellInfo, amount, m_effectInfo, 1, this);
amount = unitOwner->SpellAbsorbBonusTaken(caster, m_spellInfo, amount);
break;
case SPELL_AURA_MANA_SHIELD:
m_canBeRecalculated = false;
break;