|
|
|
@@ -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;
|
|
|
|
|
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;
|
|
|
|
|
// 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);
|
|
|
|
|
// 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_PERCENT_VERSUS
|
|
|
|
|
critPctDamageMod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, crTypeMask);
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (attackType != RANGED_ATTACK)
|
|
|
|
|
ApplyResilience(victim, NULL, &damage, crit, CR_CRIT_TAKEN_MELEE);
|
|
|
|
|
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_PERCENT_VERSUS
|
|
|
|
|
critPctDamageMod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, crTypeMask);
|
|
|
|
|
|
|
|
|
|
if (critPctDamageMod != 0)
|
|
|
|
|
AddPct(damage, critPctDamageMod);
|
|
|
|
|
ApplyResilience(victim, NULL, &damage, crit, CR_CRIT_TAKEN_RANGED);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Spell weapon based damage CAN BE crit & blocked at same time
|
|
|
|
|
if (blocked)
|
|
|
|
|
// Magical Attacks
|
|
|
|
|
case SPELL_DAMAGE_CLASS_NONE:
|
|
|
|
|
case SPELL_DAMAGE_CLASS_MAGIC:
|
|
|
|
|
{
|
|
|
|
|
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 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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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());
|
|
|
|
|
|
|
|
|
|
// Mod damage from spell mechanic
|
|
|
|
|
if (uint32 mechanicMask = spellProto->GetAllEffectsMechanicMask())
|
|
|
|
|
// Spells with SPELL_ATTR4_FIXED_DAMAGE should only benefit from mechanic damage mod auras.
|
|
|
|
|
if (!(spellProto->AttributesEx4 & SPELL_ATTR4_FIXED_DAMAGE))
|
|
|
|
|
{
|
|
|
|
|
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());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
// 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())
|
|
|
|
|
// 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)
|
|
|
|
|
{
|
|
|
|
|
coeff *= 100.0f;
|
|
|
|
|
modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_BONUS_MULTIPLIER, coeff);
|
|
|
|
|
coeff /= 100.0f;
|
|
|
|
|
if ((*i)->GetMiscValue() & spellProto->GetSchoolMask())
|
|
|
|
|
TakenTotalCasterMod += (float((*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());
|
|
|
|
|
|
|
|
|
|
// 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());
|
|
|
|
|
|
|
|
|
|
// 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())
|
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|