Код:
void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage *damageInfo, int32 damage, SpellEntry const *spellInfo, WeaponAttackType attackType, bool crit)
{
if (damage < 0)
return;
Unit *pVictim = damageInfo->target;
if (!pVictim || !pVictim->isAlive())
return;
SpellSchoolMask damageSchoolMask = SpellSchoolMask(damageInfo->schoolMask);
uint32 crTypeMask = pVictim->GetCreatureTypeMask();
// Check spell crit chance
//bool crit = isSpellCrit(pVictim, spellInfo, damageSchoolMask, attackType);
bool blocked = false;
// Per-school calc
switch (spellInfo->DmgClass)
{
// Melee and Ranged Spells
case SPELL_DAMAGE_CLASS_RANGED:
case SPELL_DAMAGE_CLASS_MELEE:
{
// Physical Damage
if (damageSchoolMask & SPELL_SCHOOL_MASK_NORMAL)
{
// Get blocked status
blocked = isSpellBlocked(pVictim, 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
int32 critPctDamageMod = 0;
if (attackType == RANGED_ATTACK)
critPctDamageMod += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE);
else
{
critPctDamageMod += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE);
critPctDamageMod += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE);
}
// Increase crit damage from SPELL_AURA_MOD_CRIT_PERCENT_VERSUS
critPctDamageMod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, crTypeMask);
if (critPctDamageMod != 0)
damage = int32(damage * float((100.0f + critPctDamageMod)/100.0f));
// Resilience - reduce crit damage
if (pVictim->GetTypeId() == TYPEID_PLAYER)
damage -= pVictim->ToPlayer()->GetMeleeCritDamageReduction(damage);
}
// Spell weapon based damage CAN BE crit & blocked at same time
if (blocked)
{
damageInfo->blocked = uint32(pVictim->GetShieldBlockValue());
if (damage < damageInfo->blocked)
damageInfo->blocked = damage;
damage -= damageInfo->blocked;
}
}
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 = SpellCriticalBonus(spellInfo, damage, pVictim);
// Resilience - reduce crit damage
if (pVictim->GetTypeId() == TYPEID_PLAYER)
damage -= pVictim->ToPlayer()->GetSpellCritDamageReduction(damage);
}
}
break;
}
// damage before absorb/resist calculation
damageInfo->cleanDamage = damage;
if (damageSchoolMask & SPELL_SCHOOL_MASK_NORMAL && (spellmgr.GetSpellCustomAttr(spellInfo->Id) & SPELL_ATTR_CU_IGNORE_ARMOR) == 0)
damage = CalcArmorReducedDamage(pVictim, damage);
// Calculate absorb resist
if (damage > 0)
{
CalcAbsorbResist(pVictim, damageSchoolMask, SPELL_DIRECT_DAMAGE, damage, &damageInfo->absorb, &damageInfo->resist);
damage-= damageInfo->absorb + damageInfo->resist;
}
else
damage = 0;
damageInfo->damage = damage;
}