diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 118 | ||||
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 5 | ||||
| -rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 7 |
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; |
