mirror of
https://github.com/araxiaonline/TrinityCore.git
synced 2026-06-18 06:00:10 -04:00
Core/Unit: corrected calculation for SPELL_AURA_MOD_DAMAGE_TAKEN/SPELL_AURA_MOD_HEALING auras
- Spell bonus calculation and penalty was done twice, but it's simply flat +SP, which should be taken into account before other bonuses - Fixed missing code from SpellDamageBonusDone/SpellHealingBonusDone and killed multiplication by stack amount twice for default coefficient spells (already multiplied on level penalty)
This commit is contained in:
@@ -6883,6 +6883,9 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
|
||||
|
||||
// Done fixed damage bonus auras
|
||||
int32 DoneAdvertisedBenefit = SpellBaseDamageBonusDone(spellProto->GetSchoolMask());
|
||||
// modify spell power by victim's SPELL_AURA_MOD_DAMAGE_TAKEN auras (eg Amplify/Dampen Magic)
|
||||
DoneAdvertisedBenefit += victim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_DAMAGE_TAKEN, spellProto->GetSchoolMask());
|
||||
|
||||
// Pets just add their bonus damage to their spell damage
|
||||
// note that their spell damage is just gain of their own auras
|
||||
if (HasUnitTypeMask(UNIT_MASK_GUARDIAN))
|
||||
@@ -6909,10 +6912,19 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
|
||||
DoneTotal += int32(bonus->ap_bonus * stack * ApCoeffMod * APbonus);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No bonus damage for SPELL_DAMAGE_CLASS_NONE class spells by default
|
||||
if (spellProto->DmgClass == SPELL_DAMAGE_CLASS_NONE)
|
||||
return uint32(std::max(pdamage * DoneTotalMod, 0.0f));
|
||||
}
|
||||
|
||||
// Default calculation
|
||||
if (coeff && DoneAdvertisedBenefit)
|
||||
if (DoneAdvertisedBenefit)
|
||||
{
|
||||
if (coeff < 0.f)
|
||||
coeff = CalculateDefaultCoefficient(spellProto, damagetype); // As wowwiki says: C = (Cast Time / 3.5)
|
||||
|
||||
float factorMod = CalculateSpellpowerCoefficientLevelPenalty(spellProto) * stack;
|
||||
if (Player* modOwner = GetSpellModOwner())
|
||||
{
|
||||
@@ -7247,7 +7259,6 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui
|
||||
if (!spellProto || damagetype == DIRECT_DAMAGE)
|
||||
return pdamage;
|
||||
|
||||
int32 TakenTotal = 0;
|
||||
float TakenTotalMod = 1.0f;
|
||||
|
||||
// Mod damage from spell mechanic
|
||||
@@ -7298,27 +7309,6 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
int32 TakenAdvertisedBenefit = SpellBaseDamageBonusTaken(spellProto->GetSchoolMask());
|
||||
|
||||
// Check for table values
|
||||
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 (coeff < 0.f)
|
||||
{
|
||||
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 = CalculateSpellpowerCoefficientLevelPenalty(spellProto) * stack;
|
||||
TakenTotal += int32(TakenAdvertisedBenefit * coeff * factorMod);
|
||||
}
|
||||
}
|
||||
|
||||
// Sanctified Wrath (bypass damage reduction)
|
||||
@@ -7337,7 +7327,7 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui
|
||||
TakenTotalMod = 1.0f - damageReduction;
|
||||
}
|
||||
|
||||
float tmpDamage = float(pdamage + TakenTotal) * TakenTotalMod;
|
||||
float tmpDamage = pdamage * TakenTotalMod;
|
||||
return uint32(std::max(tmpDamage, 0.0f));
|
||||
}
|
||||
|
||||
@@ -7369,11 +7359,6 @@ int32 Unit::SpellBaseDamageBonusDone(SpellSchoolMask schoolMask) const
|
||||
return DoneAdvertisedBenefit;
|
||||
}
|
||||
|
||||
int32 Unit::SpellBaseDamageBonusTaken(SpellSchoolMask schoolMask) const
|
||||
{
|
||||
return GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_DAMAGE_TAKEN, schoolMask);
|
||||
}
|
||||
|
||||
float Unit::SpellCritChanceDone(SpellInfo const* spellInfo, SpellSchoolMask schoolMask, WeaponAttackType attackType /*= BASE_ATTACK*/, bool isPeriodic /*= false*/) const
|
||||
{
|
||||
//! Mobs can't crit with spells. (Except player controlled)
|
||||
@@ -7750,36 +7735,48 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
|
||||
|
||||
// Done fixed damage bonus auras
|
||||
int32 DoneAdvertisedBenefit = SpellBaseHealingBonusDone(spellProto->GetSchoolMask());
|
||||
// modify spell power by victim's SPELL_AURA_MOD_HEALING auras (eg Amplify/Dampen Magic)
|
||||
DoneAdvertisedBenefit += victim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_HEALING, spellProto->GetSchoolMask());
|
||||
|
||||
// Pets just add their bonus damage to their spell damage
|
||||
// note that their spell damage is just gain of their own auras
|
||||
if (HasUnitTypeMask(UNIT_MASK_GUARDIAN))
|
||||
DoneAdvertisedBenefit += static_cast<Guardian const*>(this)->GetBonusDamage();
|
||||
|
||||
// Check for table values
|
||||
float coeff = 0.f;
|
||||
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));
|
||||
APbonus += GetTotalAttackPowerValue(attType);
|
||||
|
||||
if (damagetype == DOT)
|
||||
{
|
||||
coeff = bonus->dot_damage;
|
||||
if (bonus->ap_dot_bonus > 0)
|
||||
DoneTotal += int32(bonus->ap_dot_bonus * ApCoeffMod * stack * GetTotalAttackPowerValue(
|
||||
(spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK));
|
||||
DoneTotal += int32(bonus->ap_dot_bonus * stack * ApCoeffMod * APbonus);
|
||||
}
|
||||
else
|
||||
{
|
||||
coeff = bonus->direct_damage;
|
||||
if (bonus->ap_bonus > 0)
|
||||
DoneTotal += int32(bonus->ap_bonus * ApCoeffMod * stack * GetTotalAttackPowerValue(
|
||||
(spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK));
|
||||
DoneTotal += int32(bonus->ap_bonus * stack * ApCoeffMod * APbonus);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No bonus healing for SPELL_DAMAGE_CLASS_NONE class spells by default
|
||||
if (spellProto->DmgClass == SPELL_DAMAGE_CLASS_NONE)
|
||||
return healamount;
|
||||
return uint32(std::max(healamount * DoneTotalMod, 0.0f));
|
||||
}
|
||||
|
||||
// Default calculation
|
||||
if (coeff && DoneAdvertisedBenefit)
|
||||
if (DoneAdvertisedBenefit)
|
||||
{
|
||||
if (coeff < 0.f)
|
||||
coeff = CalculateDefaultCoefficient(spellProto, damagetype) * 1.88f; // As wowwiki says: C = (Cast Time / 3.5) * 1.88 (for healing spells)
|
||||
|
||||
float factorMod = CalculateSpellpowerCoefficientLevelPenalty(spellProto) * stack;
|
||||
if (Player* modOwner = GetSpellModOwner())
|
||||
{
|
||||
@@ -7911,12 +7908,6 @@ uint32 Unit::SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, u
|
||||
if (AuraEffect const* Tenacity = GetAuraEffect(58549, 0))
|
||||
AddPct(TakenTotalMod, Tenacity->GetAmount());
|
||||
|
||||
// Healing Done
|
||||
int32 TakenTotal = 0;
|
||||
|
||||
// Taken fixed damage bonus auras
|
||||
int32 TakenAdvertisedBenefit = SpellBaseHealingBonusTaken(spellProto->GetSchoolMask());
|
||||
|
||||
// Nourish cast
|
||||
if (spellProto->SpellFamilyName == SPELLFAMILY_DRUID && spellProto->SpellFamilyFlags[1] & 0x2000000)
|
||||
{
|
||||
@@ -7938,34 +7929,6 @@ uint32 Unit::SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, u
|
||||
AddPct(TakenTotalMod, maxval_hot);
|
||||
}
|
||||
|
||||
// Check for table values
|
||||
float coeff = 0;
|
||||
if (SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id))
|
||||
coeff = (damagetype == DOT) ? bonus->dot_damage : bonus->direct_damage;
|
||||
else
|
||||
{
|
||||
// No bonus healing for SPELL_DAMAGE_CLASS_NONE class spells by default
|
||||
if (spellProto->DmgClass == SPELL_DAMAGE_CLASS_NONE)
|
||||
{
|
||||
healamount = uint32(std::max((float(healamount) * TakenTotalMod), 0.0f));
|
||||
return healamount;
|
||||
}
|
||||
}
|
||||
|
||||
// Default calculation
|
||||
if (TakenAdvertisedBenefit)
|
||||
{
|
||||
if (coeff < 0.f)
|
||||
{
|
||||
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)
|
||||
}
|
||||
|
||||
// level penalty still applied on Taken bonus - is it blizzlike?
|
||||
float factorMod = CalculateSpellpowerCoefficientLevelPenalty(spellProto) * int32(stack);
|
||||
TakenTotal += int32(TakenAdvertisedBenefit * coeff * factorMod);
|
||||
}
|
||||
|
||||
if (caster)
|
||||
{
|
||||
TakenTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_HEALING_RECEIVED, [caster, spellProto](AuraEffect const* aurEff) -> bool
|
||||
@@ -7976,22 +7939,7 @@ uint32 Unit::SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, u
|
||||
});
|
||||
}
|
||||
|
||||
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
|
||||
{
|
||||
switch (spellProto->Effects[i].ApplyAuraName)
|
||||
{
|
||||
// Bonus healing does not apply to these spells
|
||||
case SPELL_AURA_PERIODIC_LEECH:
|
||||
case SPELL_AURA_PERIODIC_HEALTH_FUNNEL:
|
||||
TakenTotal = 0;
|
||||
break;
|
||||
}
|
||||
if (spellProto->Effects[i].Effect == SPELL_EFFECT_HEALTH_LEECH)
|
||||
TakenTotal = 0;
|
||||
}
|
||||
|
||||
float heal = float(int32(healamount) + TakenTotal) * TakenTotalMod;
|
||||
|
||||
float heal = healamount * TakenTotalMod;
|
||||
return uint32(std::max(heal, 0.0f));
|
||||
}
|
||||
|
||||
@@ -8028,11 +7976,6 @@ int32 Unit::SpellBaseHealingBonusDone(SpellSchoolMask schoolMask) const
|
||||
return advertisedBenefit;
|
||||
}
|
||||
|
||||
int32 Unit::SpellBaseHealingBonusTaken(SpellSchoolMask schoolMask) const
|
||||
{
|
||||
return GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_HEALING, schoolMask);
|
||||
}
|
||||
|
||||
bool Unit::IsImmunedToDamage(SpellSchoolMask schoolMask) const
|
||||
{
|
||||
if (schoolMask == SPELL_SCHOOL_MASK_NONE)
|
||||
|
||||
@@ -1514,12 +1514,10 @@ class TC_GAME_API Unit : public WorldObject
|
||||
Unit* GetMeleeHitRedirectTarget(Unit* victim, SpellInfo const* spellInfo = nullptr);
|
||||
|
||||
int32 SpellBaseDamageBonusDone(SpellSchoolMask schoolMask) const;
|
||||
int32 SpellBaseDamageBonusTaken(SpellSchoolMask schoolMask) const;
|
||||
uint32 SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, Optional<float> const& donePctTotal, uint32 stack = 1) const;
|
||||
float SpellDamagePctDone(Unit* victim, SpellInfo const* spellProto, DamageEffectType damagetype) const;
|
||||
uint32 SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack = 1) const;
|
||||
int32 SpellBaseHealingBonusDone(SpellSchoolMask schoolMask) const;
|
||||
int32 SpellBaseHealingBonusTaken(SpellSchoolMask schoolMask) const;
|
||||
uint32 SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, Optional<float> const& donePctTotal, uint32 stack = 1) const;
|
||||
float SpellHealingPctDone(Unit* victim, SpellInfo const* spellProto) const;
|
||||
uint32 SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack = 1) const;
|
||||
|
||||
@@ -2022,13 +2022,21 @@ class spell_pal_seal_of_righteousness : public SpellScriptLoader
|
||||
{
|
||||
PreventDefaultAction();
|
||||
|
||||
Unit* victim = eventInfo.GetProcTarget();
|
||||
|
||||
float ap = GetTarget()->GetTotalAttackPowerValue(BASE_ATTACK);
|
||||
int32 holy = GetTarget()->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_HOLY);
|
||||
holy += eventInfo.GetProcTarget()->SpellBaseDamageBonusTaken(SPELL_SCHOOL_MASK_HOLY);
|
||||
int32 bp = int32((ap * 0.022f + 0.044f * holy) * GetTarget()->GetAttackTime(BASE_ATTACK) / 1000);
|
||||
ap += victim->GetTotalAuraModifier(SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS);
|
||||
|
||||
int32 sph = GetTarget()->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_HOLY);
|
||||
sph += victim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_DAMAGE_TAKEN, SPELL_SCHOOL_MASK_HOLY);
|
||||
|
||||
float mws = GetTarget()->GetAttackTime(BASE_ATTACK);
|
||||
mws /= 1000.0f;
|
||||
|
||||
int32 bp = int32(mws * (0.022f * ap + 0.044f * sph));
|
||||
CastSpellExtraArgs args(aurEff);
|
||||
args.AddSpellBP0(bp);
|
||||
GetTarget()->CastSpell(eventInfo.GetProcTarget(), SPELL_PALADIN_SEAL_OF_RIGHTEOUSNESS, args);
|
||||
GetTarget()->CastSpell(victim, SPELL_PALADIN_SEAL_OF_RIGHTEOUSNESS, args);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
|
||||
@@ -715,7 +715,7 @@ class spell_sha_flametongue_weapon : public SpellScriptLoader
|
||||
if (!item || !item->IsEquipped())
|
||||
return false;
|
||||
|
||||
WeaponAttackType attType = static_cast<WeaponAttackType>(player->GetAttackBySlot(item->GetSlot()));
|
||||
WeaponAttackType attType = Player::GetAttackBySlot(item->GetSlot());
|
||||
if (attType != BASE_ATTACK && attType != OFF_ATTACK)
|
||||
return false;
|
||||
|
||||
@@ -738,26 +738,32 @@ class spell_sha_flametongue_weapon : public SpellScriptLoader
|
||||
|
||||
Item* item = ASSERT_NOTNULL(player->GetWeaponForAttack(attType));
|
||||
|
||||
float const basePoints = GetSpellInfo()->Effects[aurEff->GetEffIndex()].CalcValue();
|
||||
float basePoints = GetSpellInfo()->Effects[aurEff->GetEffIndex()].CalcValue();
|
||||
|
||||
// Flametongue max damage is normalized based on a 4.0 speed weapon
|
||||
// Tooltip says max damage = BasePoints / 25, so BasePoints / 25 / 4 to get base damage per 1.0s AS
|
||||
float attackSpeed = player->GetAttackTime(attType) / 1000.f;
|
||||
float fireDamage = basePoints / 100.0f;
|
||||
float const attackSpeed = player->GetAttackTime(attType) / 1000.f;
|
||||
fireDamage *= attackSpeed;
|
||||
|
||||
// clip value between (BasePoints / 77) and (BasePoints / 25) as the tooltip indicates
|
||||
RoundToInterval(fireDamage, basePoints / 77.0f, basePoints / 25.0f);
|
||||
|
||||
// Calculate Spell Power scaling
|
||||
float spellPowerBonus = player->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_FIRE) + target->SpellBaseDamageBonusTaken(SPELL_SCHOOL_MASK_FIRE);
|
||||
float spellPowerBonus = player->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_FIRE);
|
||||
spellPowerBonus += target->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_DAMAGE_TAKEN, SPELL_SCHOOL_MASK_FIRE);
|
||||
|
||||
// calculate penalty from passive aura as is the one with level
|
||||
float const factorMod = player->CalculateSpellpowerCoefficientLevelPenalty(GetSpellInfo());
|
||||
|
||||
float const spCoeff = 0.03811f;
|
||||
spellPowerBonus *= spCoeff * attackSpeed;
|
||||
spellPowerBonus *= spCoeff * attackSpeed * factorMod;
|
||||
|
||||
// All done, now proc damage
|
||||
CastSpellExtraArgs args(aurEff);
|
||||
args.CastItem = item;
|
||||
args.AddSpellBP0(fireDamage + spellPowerBonus);
|
||||
args
|
||||
.SetCastItem(item)
|
||||
.AddSpellBP0(fireDamage + spellPowerBonus);
|
||||
player->CastSpell(target, SPELL_SHAMAN_FLAMETONGUE_ATTACK, args);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user