aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp118
-rw-r--r--src/server/game/Entities/Unit/Unit.h5
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp7
3 files changed, 130 insertions, 0 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 287fc1753e7..837d8fa0947 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -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)
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index de5b2692cf0..9f6ac598a04 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -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);
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index c50ee012ca8..86b4ab48672 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -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;