mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/Unit: simplified and arranged spell bonus calculation
- Remove duplicated SPELLMOD_BONUS_MULTIPLIER handling (both on done and taken) - Handle properly bonus data, don't apply bonus by default, only player spells should take into account spell power - Moved Earthliving Weapon coefficient to DB - Refactored Avenging Wrath handling Closes #13287 Closes #21230
This commit is contained in:
8
sql/updates/world/3.3.5/2018_01_13_01_world_335.sql
Normal file
8
sql/updates/world/3.3.5/2018_01_13_01_world_335.sql
Normal file
@@ -0,0 +1,8 @@
|
||||
DELETE FROM `spell_bonus_data` WHERE `entry` IN (51945, 51990, 51997, 51998, 51999, 52000);
|
||||
INSERT INTO `spell_bonus_data` (`entry`, `direct_bonus`, `dot_bonus`, `ap_bonus`, `ap_dot_bonus`, `comments`) VALUES
|
||||
(51945, 0, 0.1692, 0, 0, 'Shaman - Earthliving Weapon (Rank 1)'),
|
||||
(51990, 0, 0.1692, 0, 0, 'Shaman - Earthliving Weapon (Rank 2)'),
|
||||
(51997, 0, 0.1692, 0, 0, 'Shaman - Earthliving Weapon (Rank 3)'),
|
||||
(51998, 0, 0.1692, 0, 0, 'Shaman - Earthliving Weapon (Rank 4)'),
|
||||
(51999, 0, 0.1692, 0, 0, 'Shaman - Earthliving Weapon (Rank 5)'),
|
||||
(52000, 0, 0.1692, 0, 0, 'Shaman - Earthliving Weapon (Rank 6)');
|
||||
@@ -6771,8 +6771,7 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
|
||||
|
||||
// Check for table values
|
||||
float coeff = 0.f;
|
||||
SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id);
|
||||
if (bonus)
|
||||
if (SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id))
|
||||
{
|
||||
WeaponAttackType const attType = (spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK;
|
||||
float APbonus = float(victim->GetTotalAuraModifier(attType == BASE_ATTACK ? SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS : SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS));
|
||||
@@ -6793,19 +6792,16 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
|
||||
}
|
||||
|
||||
// Default calculation
|
||||
if (DoneAdvertisedBenefit)
|
||||
if (coeff && DoneAdvertisedBenefit)
|
||||
{
|
||||
if (!bonus || coeff < 0)
|
||||
coeff = CalculateDefaultCoefficient(spellProto, damagetype) * int32(stack);
|
||||
|
||||
float factorMod = CalculateLevelPenalty(spellProto) * stack;
|
||||
|
||||
if (Player* modOwner = GetSpellModOwner())
|
||||
{
|
||||
coeff *= 100.0f;
|
||||
modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_BONUS_MULTIPLIER, coeff);
|
||||
coeff /= 100.0f;
|
||||
}
|
||||
|
||||
DoneTotal += int32(DoneAdvertisedBenefit * coeff * factorMod);
|
||||
}
|
||||
|
||||
@@ -7134,7 +7130,6 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui
|
||||
|
||||
int32 TakenTotal = 0;
|
||||
float TakenTotalMod = 1.0f;
|
||||
float TakenTotalCasterMod = 0.0f;
|
||||
|
||||
// Mod damage from spell mechanic
|
||||
if (uint32 mechanicMask = spellProto->GetAllEffectsMechanicMask())
|
||||
@@ -7166,67 +7161,64 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Spells with SPELL_ATTR4_FIXED_DAMAGE should only benefit from mechanic damage mod auras.
|
||||
|
||||
// Spells with SPELL_ATTR4_FIXED_DAMAGE should only benefit from mechanic damage mod auras.
|
||||
if (!spellProto->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE))
|
||||
{
|
||||
// get all auras from caster that allow the spell to ignore resistance (sanctified wrath)
|
||||
TakenTotalCasterMod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_IGNORE_TARGET_RESIST, spellProto->GetSchoolMask());
|
||||
|
||||
// from positive and negative SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN
|
||||
// multiplicative bonus, for example Dispersion + Shadowform (0.10*0.85=0.085)
|
||||
TakenTotalMod *= GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, spellProto->GetSchoolMask());
|
||||
|
||||
// From caster spells
|
||||
TakenTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_DAMAGE_FROM_CASTER, [caster, spellProto](AuraEffect const* aurEff) -> bool
|
||||
if (caster)
|
||||
{
|
||||
if (aurEff->GetCasterGUID() == caster->GetGUID() && aurEff->IsAffectedOnSpell(spellProto))
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
TakenTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_DAMAGE_FROM_CASTER, [caster, spellProto](AuraEffect const* aurEff) -> bool
|
||||
{
|
||||
if (aurEff->GetCasterGUID() == caster->GetGUID() && aurEff->IsAffectedOnSpell(spellProto))
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
int32 TakenAdvertisedBenefit = SpellBaseDamageBonusTaken(spellProto->GetSchoolMask());
|
||||
|
||||
// Check for table values
|
||||
float coeff = 0;
|
||||
SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id);
|
||||
if (bonus)
|
||||
float coeff = 0.f;
|
||||
if (SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id))
|
||||
coeff = (damagetype == DOT) ? bonus->dot_damage : bonus->direct_damage;
|
||||
|
||||
// Default calculation
|
||||
if (TakenAdvertisedBenefit)
|
||||
{
|
||||
if (!bonus || coeff < 0)
|
||||
coeff = CalculateDefaultCoefficient(spellProto, damagetype) * int32(stack);
|
||||
|
||||
float factorMod = CalculateLevelPenalty(spellProto) * stack;
|
||||
// level penalty still applied on Taken bonus - is it blizzlike?
|
||||
if (Player* modOwner = GetSpellModOwner())
|
||||
if (coeff < 0.f)
|
||||
{
|
||||
coeff *= 100.0f;
|
||||
modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_BONUS_MULTIPLIER, coeff);
|
||||
coeff /= 100.0f;
|
||||
Unit const* calc = caster ? caster : this;
|
||||
coeff = calc->CalculateDefaultCoefficient(spellProto, damagetype) * int32(stack);
|
||||
}
|
||||
|
||||
// level penalty still applied on Taken bonus - is it blizzlike?
|
||||
float factorMod = CalculateLevelPenalty(spellProto) * stack;
|
||||
TakenTotal += int32(TakenAdvertisedBenefit * coeff * factorMod);
|
||||
}
|
||||
}
|
||||
|
||||
float tmpDamage = 0.0f;
|
||||
|
||||
if (TakenTotalCasterMod)
|
||||
// Sanctified Wrath (bypass damage reduction)
|
||||
if (caster && TakenTotalMod < 1.0f)
|
||||
{
|
||||
if (TakenTotal < 0)
|
||||
float damageReduction = 1.0f - TakenTotalMod;
|
||||
Unit::AuraEffectList const& casterIgnoreResist = caster->GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST);
|
||||
for (AuraEffect const* aurEff : casterIgnoreResist)
|
||||
{
|
||||
if (TakenTotalMod < 1)
|
||||
tmpDamage = ((float(CalculatePct(pdamage, TakenTotalCasterMod) + TakenTotal) * TakenTotalMod) + CalculatePct(pdamage, TakenTotalCasterMod));
|
||||
else
|
||||
tmpDamage = ((float(CalculatePct(pdamage, TakenTotalCasterMod) + TakenTotal) + CalculatePct(pdamage, TakenTotalCasterMod)) * TakenTotalMod);
|
||||
}
|
||||
else if (TakenTotalMod < 1)
|
||||
tmpDamage = ((CalculatePct(float(pdamage) + TakenTotal, TakenTotalCasterMod) * TakenTotalMod) + CalculatePct(float(pdamage) + TakenTotal, TakenTotalCasterMod));
|
||||
}
|
||||
if (!tmpDamage)
|
||||
tmpDamage = (float(pdamage) + TakenTotal) * TakenTotalMod;
|
||||
if (!(aurEff->GetMiscValue() & spellProto->GetSchoolMask()))
|
||||
continue;
|
||||
|
||||
ApplyPct(damageReduction, aurEff->GetAmount());
|
||||
}
|
||||
|
||||
TakenTotalMod = 1.0f - damageReduction;
|
||||
}
|
||||
|
||||
float tmpDamage = float(pdamage + TakenTotal) * TakenTotalMod;
|
||||
return uint32(std::max(tmpDamage, 0.0f));
|
||||
}
|
||||
|
||||
@@ -7641,10 +7633,8 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
|
||||
int32 DoneAdvertisedBenefit = SpellBaseHealingBonusDone(spellProto->GetSchoolMask());
|
||||
|
||||
// Check for table values
|
||||
SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id);
|
||||
float coeff = 0;
|
||||
float factorMod = 1.0f;
|
||||
if (bonus)
|
||||
float coeff = 0.f;
|
||||
if (SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id))
|
||||
{
|
||||
if (damagetype == DOT)
|
||||
{
|
||||
@@ -7669,13 +7659,9 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
|
||||
}
|
||||
|
||||
// Default calculation
|
||||
if (DoneAdvertisedBenefit)
|
||||
if (coeff && DoneAdvertisedBenefit)
|
||||
{
|
||||
if (!bonus || coeff < 0)
|
||||
coeff = CalculateDefaultCoefficient(spellProto, damagetype) * int32(stack) * 1.88f; // As wowwiki says: C = (Cast Time / 3.5) * 1.88 (for healing spells)
|
||||
|
||||
factorMod *= CalculateLevelPenalty(spellProto) * stack;
|
||||
|
||||
float factorMod = CalculateLevelPenalty(spellProto) * stack;
|
||||
if (Player* modOwner = GetSpellModOwner())
|
||||
{
|
||||
coeff *= 100.0f;
|
||||
@@ -7683,10 +7669,6 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
|
||||
coeff /= 100.0f;
|
||||
}
|
||||
|
||||
// Earthliving - 0.45% of normal hot coeff
|
||||
if (spellProto->SpellFamilyName == SPELLFAMILY_SHAMAN && spellProto->SpellFamilyFlags[1] & 0x80000)
|
||||
factorMod *= 0.45f;
|
||||
|
||||
DoneTotal += int32(DoneAdvertisedBenefit * coeff * factorMod);
|
||||
}
|
||||
|
||||
@@ -7838,10 +7820,8 @@ uint32 Unit::SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, u
|
||||
}
|
||||
|
||||
// Check for table values
|
||||
SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id);
|
||||
float coeff = 0;
|
||||
float factorMod = 1.0f;
|
||||
if (bonus)
|
||||
if (SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id))
|
||||
coeff = (damagetype == DOT) ? bonus->dot_damage : bonus->direct_damage;
|
||||
else
|
||||
{
|
||||
@@ -7856,30 +7836,26 @@ uint32 Unit::SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, u
|
||||
// Default calculation
|
||||
if (TakenAdvertisedBenefit)
|
||||
{
|
||||
if (!bonus || coeff < 0)
|
||||
coeff = CalculateDefaultCoefficient(spellProto, damagetype) * int32(stack) * 1.88f; // As wowwiki says: C = (Cast Time / 3.5) * 1.88 (for healing spells)
|
||||
|
||||
factorMod *= CalculateLevelPenalty(spellProto) * int32(stack);
|
||||
if (Player* modOwner = GetSpellModOwner())
|
||||
if (coeff < 0.f)
|
||||
{
|
||||
coeff *= 100.0f;
|
||||
modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_BONUS_MULTIPLIER, coeff);
|
||||
coeff /= 100.0f;
|
||||
Unit const* calc = caster ? caster : this;
|
||||
coeff = calc->CalculateDefaultCoefficient(spellProto, damagetype) * int32(stack) * 1.88f; // As wowwiki says: C = (Cast Time / 3.5) * 1.88 (for healing spells)
|
||||
}
|
||||
|
||||
// Earthliving - 0.45% of normal hot coeff
|
||||
if (spellProto->SpellFamilyName == SPELLFAMILY_SHAMAN && spellProto->SpellFamilyFlags[1] & 0x80000)
|
||||
factorMod *= 0.45f;
|
||||
|
||||
// level penalty still applied on Taken bonus - is it blizzlike?
|
||||
float factorMod = CalculateLevelPenalty(spellProto) * int32(stack);
|
||||
TakenTotal += int32(TakenAdvertisedBenefit * coeff * factorMod);
|
||||
}
|
||||
|
||||
TakenTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_HEALING_RECEIVED, [caster, spellProto](AuraEffect const* aurEff) -> bool
|
||||
if (caster)
|
||||
{
|
||||
if (caster->GetGUID() == aurEff->GetCasterGUID() && aurEff->IsAffectedOnSpell(spellProto))
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
TakenTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_HEALING_RECEIVED, [caster, spellProto](AuraEffect const* aurEff) -> bool
|
||||
{
|
||||
if (caster->GetGUID() == aurEff->GetCasterGUID() && aurEff->IsAffectedOnSpell(spellProto))
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
|
||||
{
|
||||
@@ -8299,11 +8275,6 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackT
|
||||
return 0;
|
||||
|
||||
int32 TakenFlatBenefit = 0;
|
||||
float TakenTotalCasterMod = 0.0f;
|
||||
|
||||
// get all auras from caster that allow the spell to ignore resistance (sanctified wrath)
|
||||
SpellSchoolMask const attackSchoolMask = spellProto ? spellProto->GetSchoolMask() : SPELL_SCHOOL_MASK_NORMAL;
|
||||
TakenTotalCasterMod += attacker->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_IGNORE_TARGET_RESIST, attackSchoolMask);
|
||||
|
||||
// ..taken
|
||||
TakenFlatBenefit += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_DAMAGE_TAKEN, attacker->GetMeleeDamageSchoolMask());
|
||||
@@ -8382,24 +8353,25 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackT
|
||||
else
|
||||
TakenTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT);
|
||||
|
||||
float tmpDamage = 0.0f;
|
||||
|
||||
if (TakenTotalCasterMod)
|
||||
// Sanctified Wrath (bypass damage reduction)
|
||||
if (attacker && TakenTotalMod < 1.0f)
|
||||
{
|
||||
if (TakenFlatBenefit < 0)
|
||||
{
|
||||
if (TakenTotalMod < 1)
|
||||
tmpDamage = ((float(CalculatePct(pdamage, TakenTotalCasterMod) + TakenFlatBenefit) * TakenTotalMod) + CalculatePct(pdamage, TakenTotalCasterMod));
|
||||
else
|
||||
tmpDamage = ((float(CalculatePct(pdamage, TakenTotalCasterMod) + TakenFlatBenefit) + CalculatePct(pdamage, TakenTotalCasterMod)) * TakenTotalMod);
|
||||
}
|
||||
else if (TakenTotalMod < 1)
|
||||
tmpDamage = ((CalculatePct(float(pdamage) + TakenFlatBenefit, TakenTotalCasterMod) * TakenTotalMod) + CalculatePct(float(pdamage) + TakenFlatBenefit, TakenTotalCasterMod));
|
||||
}
|
||||
if (!tmpDamage)
|
||||
tmpDamage = (float(pdamage) + TakenFlatBenefit) * TakenTotalMod;
|
||||
SpellSchoolMask const attackSchoolMask = spellProto ? spellProto->GetSchoolMask() : SPELL_SCHOOL_MASK_NORMAL;
|
||||
|
||||
// bonus result can be negative
|
||||
float damageReduction = 1.0f - TakenTotalMod;
|
||||
Unit::AuraEffectList const& casterIgnoreResist = attacker->GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST);
|
||||
for (AuraEffect const* aurEff : casterIgnoreResist)
|
||||
{
|
||||
if (!(aurEff->GetMiscValue() & attackSchoolMask))
|
||||
continue;
|
||||
|
||||
ApplyPct(damageReduction, aurEff->GetAmount());
|
||||
}
|
||||
|
||||
TakenTotalMod = 1.0f - damageReduction;
|
||||
}
|
||||
|
||||
float tmpDamage = float(pdamage + TakenFlatBenefit) * TakenTotalMod;
|
||||
return uint32(std::max(tmpDamage, 0.0f));
|
||||
}
|
||||
|
||||
@@ -11505,7 +11477,6 @@ float Unit::CalculateDefaultCoefficient(SpellInfo const* spellInfo, DamageEffect
|
||||
float DotFactor = 1.0f;
|
||||
if (damagetype == DOT)
|
||||
{
|
||||
|
||||
int32 DotDuration = spellInfo->GetDuration();
|
||||
if (!spellInfo->IsChanneled() && DotDuration > 0)
|
||||
DotFactor = DotDuration / 15000.0f;
|
||||
|
||||
Reference in New Issue
Block a user