diff options
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 232 | ||||
-rw-r--r-- | src/server/game/Miscellaneous/SharedDefines.h | 2 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 6 | ||||
-rw-r--r-- | src/server/game/Spells/SpellMgr.cpp | 3 |
4 files changed, 125 insertions, 118 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 8b09df988cf..4efa1374ec7 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -978,86 +978,90 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama SpellSchoolMask damageSchoolMask = SpellSchoolMask(damageInfo->schoolMask); uint32 crTypeMask = victim->GetCreatureTypeMask(); - if (IsDamageReducedByArmor(damageSchoolMask, spellInfo)) - damage = CalcArmorReducedDamage(victim, damage, spellInfo, attackType); - - bool blocked = false; - // Per-school calc - switch (spellInfo->DmgClass) + // Spells with SPELL_ATTR4_FIXED_DAMAGE ignore resilience because their damage is based off another spell's damage. + if (!(spellInfo->AttributesEx4 & SPELL_ATTR4_FIXED_DAMAGE)) { - // Melee and Ranged Spells - case SPELL_DAMAGE_CLASS_RANGED: - case SPELL_DAMAGE_CLASS_MELEE: + if (IsDamageReducedByArmor(damageSchoolMask, spellInfo)) + damage = CalcArmorReducedDamage(victim, damage, spellInfo, attackType); + + bool blocked = false; + // Per-school calc + switch (spellInfo->DmgClass) { - // Physical Damage - if (damageSchoolMask & SPELL_SCHOOL_MASK_NORMAL) + // Melee and Ranged Spells + case SPELL_DAMAGE_CLASS_RANGED: + case SPELL_DAMAGE_CLASS_MELEE: { - // Get blocked status - blocked = isSpellBlocked(victim, spellInfo, attackType); - } + // Physical Damage + if (damageSchoolMask & SPELL_SCHOOL_MASK_NORMAL) + { + // Get blocked status + blocked = isSpellBlocked(victim, spellInfo, attackType); + } - if (crit) - { - damageInfo->HitInfo |= SPELL_HIT_TYPE_CRIT; - - // Calculate crit bonus - uint32 crit_bonus = damage; - // Apply crit_damage bonus for melee spells - if (Player* modOwner = GetSpellModOwner()) - modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CRIT_DAMAGE_BONUS, crit_bonus); - damage += crit_bonus; - - // Apply SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE or SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE - float critPctDamageMod = 0.0f; - if (attackType == RANGED_ATTACK) - critPctDamageMod += victim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE); - else - critPctDamageMod += victim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE); + if (crit) + { + damageInfo->HitInfo |= SPELL_HIT_TYPE_CRIT; + + // Calculate crit bonus + uint32 crit_bonus = damage; + // Apply crit_damage bonus for melee spells + if (Player* modOwner = GetSpellModOwner()) + modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CRIT_DAMAGE_BONUS, crit_bonus); + damage += crit_bonus; + + // Apply SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE or SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE + float critPctDamageMod = 0.0f; + if (attackType == RANGED_ATTACK) + critPctDamageMod += victim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE); + else + critPctDamageMod += victim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE); - // Increase crit damage from SPELL_AURA_MOD_CRIT_DAMAGE_BONUS - critPctDamageMod += (GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS, spellInfo->GetSchoolMask()) - 1.0f) * 100; + // Increase crit damage from SPELL_AURA_MOD_CRIT_DAMAGE_BONUS + critPctDamageMod += (GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS, spellInfo->GetSchoolMask()) - 1.0f) * 100; - // Increase crit damage from SPELL_AURA_MOD_CRIT_PERCENT_VERSUS - critPctDamageMod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, crTypeMask); + // Increase crit damage from SPELL_AURA_MOD_CRIT_PERCENT_VERSUS + critPctDamageMod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, crTypeMask); - if (critPctDamageMod != 0) - AddPct(damage, critPctDamageMod); - } + if (critPctDamageMod != 0) + AddPct(damage, critPctDamageMod); + } - // Spell weapon based damage CAN BE crit & blocked at same time - if (blocked) - { - damageInfo->blocked = victim->GetShieldBlockValue(); - // double blocked amount if block is critical - if (victim->isBlockCritical()) - damageInfo->blocked += damageInfo->blocked; - if (damage < int32(damageInfo->blocked)) - damageInfo->blocked = uint32(damage); - damage -= damageInfo->blocked; - } + // Spell weapon based damage CAN BE crit & blocked at same time + if (blocked) + { + damageInfo->blocked = victim->GetShieldBlockValue(); + // double blocked amount if block is critical + if (victim->isBlockCritical()) + damageInfo->blocked += damageInfo->blocked; + if (damage < int32(damageInfo->blocked)) + damageInfo->blocked = uint32(damage); + damage -= damageInfo->blocked; + } - if (attackType != RANGED_ATTACK) - ApplyResilience(victim, NULL, &damage, crit, CR_CRIT_TAKEN_MELEE); - else - ApplyResilience(victim, NULL, &damage, crit, CR_CRIT_TAKEN_RANGED); - break; - } - // Magical Attacks - case SPELL_DAMAGE_CLASS_NONE: - case SPELL_DAMAGE_CLASS_MAGIC: - { - // If crit add critical bonus - if (crit) - { - damageInfo->HitInfo |= SPELL_HIT_TYPE_CRIT; - damage = SpellCriticalDamageBonus(spellInfo, damage, victim); + if (attackType != RANGED_ATTACK) + ApplyResilience(victim, NULL, &damage, crit, CR_CRIT_TAKEN_MELEE); + else + ApplyResilience(victim, NULL, &damage, crit, CR_CRIT_TAKEN_RANGED); + break; } + // Magical Attacks + case SPELL_DAMAGE_CLASS_NONE: + case SPELL_DAMAGE_CLASS_MAGIC: + { + // If crit add critical bonus + if (crit) + { + damageInfo->HitInfo |= SPELL_HIT_TYPE_CRIT; + damage = SpellCriticalDamageBonus(spellInfo, damage, victim); + } - ApplyResilience(victim, NULL, &damage, crit, CR_CRIT_TAKEN_SPELL); - break; + ApplyResilience(victim, NULL, &damage, crit, CR_CRIT_TAKEN_SPELL); + break; + } + default: + break; } - default: - break; } // Script Hook For CalculateSpellDamageTaken -- Allow scripts to change the Damage post class mitigation calculations @@ -9844,11 +9848,6 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin if (spellProto->AttributesEx3 & SPELL_ATTR3_NO_DONE_BONUS) return pdamage; - // small exception for Deep Wounds, can't find any general rule - // should ignore ALL damage mods, they already calculated in trigger spell - if (spellProto->Id == 12721) // Deep Wounds - return pdamage; - // For totems get damage bonus from owner if (GetTypeId() == TYPEID_UNIT && ToCreature()->IsTotem()) if (Unit* owner = GetOwner()) @@ -9864,7 +9863,7 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin DoneTotalMod *= ToCreature()->GetSpellDamageMod(ToCreature()->GetCreatureTemplate()->rank); // Some spells don't benefit from pct done mods - if (!(spellProto->AttributesEx6 & SPELL_ATTR6_NO_DONE_PCT_DAMAGE_MODS) && !spellProto->IsRankOf(sSpellMgr->GetSpellInfo(12162))) + if (!(spellProto->AttributesEx6 & SPELL_ATTR6_NO_DONE_PCT_DAMAGE_MODS)) { AuraEffectList const& mModDamagePercentDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); for (AuraEffectList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i) @@ -10261,19 +10260,16 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui int32 TakenTotal = 0; float TakenTotalMod = 1.0f; float TakenTotalCasterMod = 0.0f; - - // get all auras from caster that allow the spell to ignore resistance (sanctified wrath) - AuraEffectList const& IgnoreResistAuras = caster->GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST); - for (AuraEffectList::const_iterator i = IgnoreResistAuras.begin(); i != IgnoreResistAuras.end(); ++i) + + // Mod damage from spell mechanic + if (uint32 mechanicMask = spellProto->GetAllEffectsMechanicMask()) { - if ((*i)->GetMiscValue() & spellProto->GetSchoolMask()) - TakenTotalCasterMod += (float((*i)->GetAmount())); + AuraEffectList const& mDamageDoneMechanic = GetAuraEffectsByType(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT); + for (AuraEffectList::const_iterator i = mDamageDoneMechanic.begin(); i != mDamageDoneMechanic.end(); ++i) + if (mechanicMask & uint32(1 << ((*i)->GetMiscValue()))) + AddPct(TakenTotalMod, (*i)->GetAmount()); } - // 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()); - //.. taken pct: dummy auras AuraEffectList const& mDummyAuras = GetAuraEffectsByType(SPELL_AURA_DUMMY); for (AuraEffectList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i) @@ -10292,45 +10288,51 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui break; } } + // Spells with SPELL_ATTR4_FIXED_DAMAGE should only benefit from mechanic damage mod auras. + if (!(spellProto->AttributesEx4 & SPELL_ATTR4_FIXED_DAMAGE)) + { + // get all auras from caster that allow the spell to ignore resistance (sanctified wrath) + AuraEffectList const& IgnoreResistAuras = caster->GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST); + for (AuraEffectList::const_iterator i = IgnoreResistAuras.begin(); i != IgnoreResistAuras.end(); ++i) + { + if ((*i)->GetMiscValue() & spellProto->GetSchoolMask()) + TakenTotalCasterMod += (float((*i)->GetAmount())); + } - // From caster spells - AuraEffectList const& mOwnerTaken = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_FROM_CASTER); - for (AuraEffectList::const_iterator i = mOwnerTaken.begin(); i != mOwnerTaken.end(); ++i) - if ((*i)->GetCasterGUID() == caster->GetGUID() && (*i)->IsAffectedOnSpell(spellProto)) - AddPct(TakenTotalMod, (*i)->GetAmount()); + // 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()); - // Mod damage from spell mechanic - if (uint32 mechanicMask = spellProto->GetAllEffectsMechanicMask()) - { - AuraEffectList const& mDamageDoneMechanic = GetAuraEffectsByType(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT); - for (AuraEffectList::const_iterator i = mDamageDoneMechanic.begin(); i != mDamageDoneMechanic.end(); ++i) - if (mechanicMask & uint32(1<<((*i)->GetMiscValue()))) + // From caster spells + AuraEffectList const& mOwnerTaken = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_FROM_CASTER); + for (AuraEffectList::const_iterator i = mOwnerTaken.begin(); i != mOwnerTaken.end(); ++i) + if ((*i)->GetCasterGUID() == caster->GetGUID() && (*i)->IsAffectedOnSpell(spellProto)) AddPct(TakenTotalMod, (*i)->GetAmount()); - } - int32 TakenAdvertisedBenefit = SpellBaseDamageBonusTaken(spellProto->GetSchoolMask()); + int32 TakenAdvertisedBenefit = SpellBaseDamageBonusTaken(spellProto->GetSchoolMask()); - // Check for table values - float coeff = 0; - SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id); - if (bonus) - coeff = (damagetype == DOT) ? bonus->dot_damage : bonus->direct_damage; + // Check for table values + float coeff = 0; + SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id); + if (bonus) + 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()) + // Default calculation + if (TakenAdvertisedBenefit) { - coeff *= 100.0f; - modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_BONUS_MULTIPLIER, coeff); - coeff /= 100.0f; + 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()) + { + coeff *= 100.0f; + modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_BONUS_MULTIPLIER, coeff); + coeff /= 100.0f; + } + TakenTotal += int32(TakenAdvertisedBenefit * coeff * factorMod); } - TakenTotal+= int32(TakenAdvertisedBenefit * coeff * factorMod); } float tmpDamage = 0.0f; diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index fdf06a8f7e3..4ec1d5750a4 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -427,7 +427,7 @@ enum SpellAttr4 SPELL_ATTR4_UNK5 = 0x00000020, // 5 SPELL_ATTR4_NOT_STEALABLE = 0x00000040, // 6 although such auras might be dispellable, they cannot be stolen SPELL_ATTR4_TRIGGERED = 0x00000080, // 7 spells forced to be triggered - SPELL_ATTR4_FIXED_DAMAGE = 0x00000100, // 8 ignores taken percent damage mods? + SPELL_ATTR4_FIXED_DAMAGE = 0x00000100, // 8 Ignores resilience and any (except mechanic related) damage or % damage taken auras on target. SPELL_ATTR4_TRIGGER_ACTIVATE = 0x00000200, // 9 initially disabled / trigger activate from event (Execute, Riposte, Deep Freeze end other) SPELL_ATTR4_SPELL_VS_EXTEND_COST = 0x00000400, // 10 Rogue Shiv have this flag SPELL_ATTR4_UNK11 = 0x00000800, // 11 diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index b87524357d2..2096f21e5a1 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -5856,7 +5856,8 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const damage = caster->SpellCriticalDamageBonus(m_spellInfo, damage, target); int32 dmg = damage; - caster->ApplyResilience(target, NULL, &dmg, crit, CR_CRIT_TAKEN_SPELL); + if (!(GetSpellInfo()->AttributesEx4 & SPELL_ATTR4_FIXED_DAMAGE)) + caster->ApplyResilience(target, NULL, &dmg, crit, CR_CRIT_TAKEN_SPELL); damage = dmg; caster->CalcAbsorbResist(target, GetSpellInfo()->GetSchoolMask(), DOT, damage, &absorb, &resist, GetSpellInfo()); @@ -5923,7 +5924,8 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c } int32 dmg = damage; - caster->ApplyResilience(target, NULL, &dmg, crit, CR_CRIT_TAKEN_SPELL); + if (!(GetSpellInfo()->AttributesEx4 & SPELL_ATTR4_FIXED_DAMAGE)) + caster->ApplyResilience(target, NULL, &dmg, crit, CR_CRIT_TAKEN_SPELL); damage = dmg; caster->CalcAbsorbResist(target, GetSpellInfo()->GetSchoolMask(), DOT, damage, &absorb, &resist, m_spellInfo); diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 501cb1e77f2..4aced0c92dd 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3207,6 +3207,9 @@ void SpellMgr::LoadSpellInfoCorrections() case 63675: // Improved Devouring Plague spellInfo->AttributesEx3 |= SPELL_ATTR3_NO_DONE_BONUS; break; + case 12721: // Deep Wounds shouldnt ignore resillience or damage taken auras because its damage is not based off a spell. + spellInfo->AttributesEx4 = 0; + break; case 8145: // Tremor Totem (instant pulse) case 6474: // Earthbind Totem (instant pulse) spellInfo->AttributesEx5 |= SPELL_ATTR5_START_PERIODIC_AT_APPLY; |