feat(Core/Spells): add helper to get clean and unmitigated damage for pro… (#7244)

This commit is contained in:
UltraNix
2021-10-05 23:59:57 +02:00
committed by GitHub
parent 5af98783c9
commit 3223f90bcb
12 changed files with 283 additions and 169 deletions
+14 -5
View File
@@ -784,12 +784,21 @@ uint32 Player::EnvironmentalDamage(EnviromentalDamage type, uint32 damage)
// Absorb, resist some environmental damage type // Absorb, resist some environmental damage type
uint32 absorb = 0; uint32 absorb = 0;
uint32 resist = 0; uint32 resist = 0;
if (type == DAMAGE_LAVA)
Unit::CalcAbsorbResist(this, this, SPELL_SCHOOL_MASK_FIRE, DIRECT_DAMAGE, damage, &absorb, &resist);
else if (type == DAMAGE_SLIME)
Unit::CalcAbsorbResist(this, this, SPELL_SCHOOL_MASK_NATURE, DIRECT_DAMAGE, damage, &absorb, &resist);
damage -= absorb + resist; switch (type)
{
case DAMAGE_LAVA:
case DAMAGE_SLIME:
{
DamageInfo dmgInfo(this, this, damage, nullptr, type == DAMAGE_LAVA ? SPELL_SCHOOL_MASK_FIRE : SPELL_SCHOOL_MASK_NATURE, DIRECT_DAMAGE);
Unit::CalcAbsorbResist(dmgInfo);
absorb = dmgInfo.GetAbsorb();
resist = dmgInfo.GetResist();
damage = dmgInfo.GetDamage();
}
default:
break;
}
Unit::DealDamageMods(this, damage, &absorb); Unit::DealDamageMods(this, damage, &absorb);
+135 -86
View File
@@ -109,21 +109,28 @@ static bool isAlwaysTriggeredAura[TOTAL_AURAS];
// Prepare lists // Prepare lists
static bool procPrepared = InitTriggerAuraData(); static bool procPrepared = InitTriggerAuraData();
DamageInfo::DamageInfo(Unit* _attacker, Unit* _victim, uint32 _damage, SpellInfo const* _spellInfo, SpellSchoolMask _schoolMask, DamageEffectType _damageType) DamageInfo::DamageInfo(Unit* _attacker, Unit* _victim, uint32 _damage, SpellInfo const* _spellInfo, SpellSchoolMask _schoolMask, DamageEffectType _damageType, uint32 cleanDamage)
: m_attacker(_attacker), m_victim(_victim), m_damage(_damage), m_spellInfo(_spellInfo), m_schoolMask(_schoolMask), : m_attacker(_attacker), m_victim(_victim), m_damage(_damage), m_spellInfo(_spellInfo), m_schoolMask(_schoolMask),
m_damageType(_damageType), m_attackType(BASE_ATTACK) m_damageType(_damageType), m_attackType(BASE_ATTACK), m_cleanDamage(cleanDamage)
{ {
m_absorb = 0; m_absorb = 0;
m_resist = 0; m_resist = 0;
m_block = 0; m_block = 0;
} }
DamageInfo::DamageInfo(CalcDamageInfo& dmgInfo) DamageInfo::DamageInfo(CalcDamageInfo& dmgInfo)
: m_attacker(dmgInfo.attacker), m_victim(dmgInfo.target), m_damage(dmgInfo.damage), m_spellInfo(nullptr), m_schoolMask(SpellSchoolMask(dmgInfo.damageSchoolMask)), : m_attacker(dmgInfo.attacker), m_victim(dmgInfo.target), m_damage(dmgInfo.damage), m_spellInfo(nullptr), m_schoolMask(SpellSchoolMask(dmgInfo.damageSchoolMask)),
m_damageType(DIRECT_DAMAGE), m_attackType(dmgInfo.attackType) m_damageType(DIRECT_DAMAGE), m_attackType(dmgInfo.attackType), m_absorb(dmgInfo.absorb), m_resist(dmgInfo.resist), m_block(dmgInfo.blocked_amount),
m_cleanDamage(dmgInfo.cleanDamage)
{
}
DamageInfo::DamageInfo(SpellNonMeleeDamage const& spellNonMeleeDamage, DamageEffectType damageType)
: m_attacker(spellNonMeleeDamage.attacker), m_victim(spellNonMeleeDamage.target), m_damage(spellNonMeleeDamage.damage),
m_spellInfo(spellNonMeleeDamage.spellInfo), m_schoolMask(SpellSchoolMask(spellNonMeleeDamage.schoolMask)), m_damageType(damageType),
m_absorb(spellNonMeleeDamage.absorb), m_resist(spellNonMeleeDamage.resist), m_block(spellNonMeleeDamage.blocked),
m_cleanDamage(spellNonMeleeDamage.cleanDamage)
{ {
m_absorb = 0;
m_resist = 0;
m_block = 0;
} }
void DamageInfo::ModifyDamage(int32 amount) void DamageInfo::ModifyDamage(int32 amount)
@@ -153,6 +160,11 @@ void DamageInfo::BlockDamage(uint32 amount)
m_damage -= amount; m_damage -= amount;
} }
uint32 DamageInfo::GetUnmitigatedDamage() const
{
return m_damage + m_cleanDamage + m_absorb + m_resist;
}
ProcEventInfo::ProcEventInfo(Unit* actor, Unit* actionTarget, Unit* procTarget, uint32 typeMask, uint32 spellTypeMask, uint32 spellPhaseMask, uint32 hitMask, Spell const* spell, DamageInfo* damageInfo, HealInfo* healInfo, SpellInfo const* triggeredByAuraSpell, int8 procAuraEffectIndex) ProcEventInfo::ProcEventInfo(Unit* actor, Unit* actionTarget, Unit* procTarget, uint32 typeMask, uint32 spellTypeMask, uint32 spellPhaseMask, uint32 hitMask, Spell const* spell, DamageInfo* damageInfo, HealInfo* healInfo, SpellInfo const* triggeredByAuraSpell, int8 procAuraEffectIndex)
: _actor(actor), _actionTarget(actionTarget), _procTarget(procTarget), _typeMask(typeMask), _spellTypeMask(spellTypeMask), _spellPhaseMask(spellPhaseMask), : _actor(actor), _actionTarget(actionTarget), _procTarget(procTarget), _typeMask(typeMask), _spellTypeMask(spellTypeMask), _spellPhaseMask(spellPhaseMask),
_hitMask(hitMask), _spell(spell), _damageInfo(damageInfo), _healInfo(healInfo), _triggeredByAuraSpell(triggeredByAuraSpell), _procAuraEffectIndex(procAuraEffectIndex) _hitMask(hitMask), _spell(spell), _damageInfo(damageInfo), _healInfo(healInfo), _triggeredByAuraSpell(triggeredByAuraSpell), _procAuraEffectIndex(procAuraEffectIndex)
@@ -810,13 +822,16 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage
} }
else else
{ {
DamageInfo sharedDamageInfo(attacker, shareDamageTarget, shareDamage, spellProto, damageSchoolMask, damagetype);
Unit::CalcAbsorbResist(sharedDamageInfo, true);
shareAbsorb = sharedDamageInfo.GetAbsorb();
shareResist = sharedDamageInfo.GetResist();
shareDamage = sharedDamageInfo.GetDamage();
Unit::DealDamageMods(shareDamageTarget, shareDamage, &shareAbsorb); Unit::DealDamageMods(shareDamageTarget, shareDamage, &shareAbsorb);
Unit::CalcAbsorbResist(attacker, shareDamageTarget, damageSchoolMask, damagetype, shareDamage, &shareAbsorb, &shareResist, spellProto, true);
shareDamage -= std::min(shareAbsorb, shareDamage);
} }
if (attacker && shareDamageTarget->GetTypeId() == TYPEID_PLAYER) if (attacker && shareDamageTarget->GetTypeId() == TYPEID_PLAYER)
attacker->SendSpellNonMeleeDamageLog(shareDamageTarget, spell->Id, shareDamage + shareAbsorb + shareResist, damageSchoolMask, shareAbsorb, shareResist, damagetype == DIRECT_DAMAGE, 0, false); attacker->SendSpellNonMeleeDamageLog(shareDamageTarget, spell, shareDamage, damageSchoolMask, shareAbsorb, shareResist, damagetype == DIRECT_DAMAGE, 0, false);
Unit::DealDamage(attacker, shareDamageTarget, shareDamage, cleanDamage, NODAMAGE, damageSchoolMask, spellProto, false); Unit::DealDamage(attacker, shareDamageTarget, shareDamage, cleanDamage, NODAMAGE, damageSchoolMask, spellProto, false);
} }
@@ -1180,8 +1195,16 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama
SpellSchoolMask damageSchoolMask = SpellSchoolMask(damageInfo->schoolMask); SpellSchoolMask damageSchoolMask = SpellSchoolMask(damageInfo->schoolMask);
uint32 crTypeMask = victim->GetCreatureTypeMask(); uint32 crTypeMask = victim->GetCreatureTypeMask();
// Script Hook For CalculateSpellDamageTaken -- Allow scripts to change the Damage post class mitigation calculations
sScriptMgr->ModifySpellDamageTaken(damageInfo->target, damageInfo->attacker, damage);
if (Unit::IsDamageReducedByArmor(damageSchoolMask, spellInfo)) if (Unit::IsDamageReducedByArmor(damageSchoolMask, spellInfo))
damage = Unit::CalcArmorReducedDamage(this, victim, damage, spellInfo, 0, attackType); {
damageInfo->damage = Unit::CalcArmorReducedDamage(this, victim, damage, spellInfo, 0, attackType);
damageInfo->cleanDamage += damage - damageInfo->damage;
}
else
damageInfo->damage = damage;
bool blocked = false; bool blocked = false;
// Per-school calc // Per-school calc
@@ -1203,11 +1226,11 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama
damageInfo->HitInfo |= SPELL_HIT_TYPE_CRIT; damageInfo->HitInfo |= SPELL_HIT_TYPE_CRIT;
// Calculate crit bonus // Calculate crit bonus
uint32 crit_bonus = damage; uint32 crit_bonus = damageInfo->damage;
// Apply crit_damage bonus for melee spells // Apply crit_damage bonus for melee spells
if (Player* modOwner = GetSpellModOwner()) if (Player* modOwner = GetSpellModOwner())
modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CRIT_DAMAGE_BONUS, crit_bonus); modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CRIT_DAMAGE_BONUS, crit_bonus);
damage += crit_bonus; damageInfo->damage += crit_bonus;
// Apply SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE or SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE // Apply SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE or SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE
float critPctDamageMod = 0.0f; float critPctDamageMod = 0.0f;
@@ -1223,7 +1246,7 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama
critPctDamageMod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, crTypeMask); critPctDamageMod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, crTypeMask);
if (critPctDamageMod != 0) if (critPctDamageMod != 0)
AddPct(damage, critPctDamageMod); AddPct(damageInfo->damage, critPctDamageMod);
} }
// Spell weapon based damage CAN BE crit & blocked at same time // Spell weapon based damage CAN BE crit & blocked at same time
@@ -1232,19 +1255,26 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama
damageInfo->blocked = victim->GetShieldBlockValue(); damageInfo->blocked = victim->GetShieldBlockValue();
// double blocked amount if block is critical // double blocked amount if block is critical
if (victim->isBlockCritical()) if (victim->isBlockCritical())
damageInfo->blocked += damageInfo->blocked; damageInfo->blocked *= 2;
if (damage < int32(damageInfo->blocked)) if (damage < int32(damageInfo->blocked))
damageInfo->blocked = uint32(damage); damageInfo->blocked = uint32(damage);
damage -= damageInfo->blocked;
damageInfo->damage -= damageInfo->blocked;
damageInfo->cleanDamage += damageInfo->blocked;
} }
int32 resilienceReduction = damageInfo->damage;
if (CanApplyResilience()) if (CanApplyResilience())
{ {
if (attackType != RANGED_ATTACK) if (attackType != RANGED_ATTACK)
Unit::ApplyResilience(victim, nullptr, &damage, crit, CR_CRIT_TAKEN_MELEE); Unit::ApplyResilience(victim, nullptr, &resilienceReduction, crit, CR_CRIT_TAKEN_MELEE);
else else
Unit::ApplyResilience(victim, nullptr, &damage, crit, CR_CRIT_TAKEN_RANGED); Unit::ApplyResilience(victim, nullptr, &resilienceReduction, crit, CR_CRIT_TAKEN_RANGED);
} }
resilienceReduction = damageInfo->damage - resilienceReduction;
damageInfo->damage -= resilienceReduction;
damageInfo->cleanDamage += resilienceReduction;
break; break;
} }
// Magical Attacks // Magical Attacks
@@ -1255,30 +1285,33 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama
if (crit) if (crit)
{ {
damageInfo->HitInfo |= SPELL_HIT_TYPE_CRIT; damageInfo->HitInfo |= SPELL_HIT_TYPE_CRIT;
damage = Unit::SpellCriticalDamageBonus(this, spellInfo, damage, victim); damageInfo->damage = Unit::SpellCriticalDamageBonus(this, spellInfo, damageInfo->damage, victim);
} }
int32 resilienceReduction = damageInfo->damage;
if (CanApplyResilience()) if (CanApplyResilience())
Unit::ApplyResilience(victim, nullptr, &damage, crit, CR_CRIT_TAKEN_SPELL); Unit::ApplyResilience(victim, nullptr, &resilienceReduction, crit, CR_CRIT_TAKEN_SPELL);
resilienceReduction = damageInfo->damage - resilienceReduction;
damageInfo->damage -= resilienceReduction;
damageInfo->cleanDamage += resilienceReduction;
break; break;
} }
default: default:
break; break;
} }
// Script Hook For CalculateSpellDamageTaken -- Allow scripts to change the Damage post class mitigation calculations
sScriptMgr->ModifySpellDamageTaken(damageInfo->target, damageInfo->attacker, damage);
// Calculate absorb resist // Calculate absorb resist
if (damage > 0) if (int32(damageInfo->damage) > 0)
{ {
Unit::CalcAbsorbResist(this, victim, damageSchoolMask, SPELL_DIRECT_DAMAGE, damage, &damageInfo->absorb, &damageInfo->resist, spellInfo); DamageInfo dmgInfo(*damageInfo, SPELL_DIRECT_DAMAGE);
damage -= damageInfo->absorb + damageInfo->resist; Unit::CalcAbsorbResist(dmgInfo);
damageInfo->absorb = dmgInfo.GetAbsorb();
damageInfo->resist = dmgInfo.GetResist();
damage = dmgInfo.GetDamage();
} }
else else
damage = 0; damageInfo->damage = 0;
damageInfo->damage = std::max(damage, 0);
} }
void Unit::DealSpellDamage(SpellNonMeleeDamage* damageInfo, bool durabilityLoss) void Unit::DealSpellDamage(SpellNonMeleeDamage* damageInfo, bool durabilityLoss)
@@ -1294,10 +1327,10 @@ void Unit::DealSpellDamage(SpellNonMeleeDamage* damageInfo, bool durabilityLoss)
if (!victim->IsAlive() || victim->IsInFlight() || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks())) if (!victim->IsAlive() || victim->IsInFlight() || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks()))
return; return;
SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(damageInfo->SpellID); SpellInfo const* spellProto = damageInfo->spellInfo;
if (spellProto == nullptr) if (!spellProto)
{ {
LOG_DEBUG("entities.unit", "Unit::DealSpellDamage has wrong damageInfo->SpellID: %u", damageInfo->SpellID); LOG_DEBUG("entities.unit", "Unit::DealSpellDamage has wrong damageInfo");
return; return;
} }
@@ -1504,7 +1537,11 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
{ {
damageInfo->procVictim |= PROC_FLAG_TAKEN_DAMAGE; damageInfo->procVictim |= PROC_FLAG_TAKEN_DAMAGE;
// Calculate absorb & resists // Calculate absorb & resists
Unit::CalcAbsorbResist(this, damageInfo->target, SpellSchoolMask(damageInfo->damageSchoolMask), DIRECT_DAMAGE, damageInfo->damage, &damageInfo->absorb, &damageInfo->resist);
DamageInfo dmgInfo(*damageInfo);
Unit::CalcAbsorbResist(dmgInfo);
damageInfo->absorb = dmgInfo.GetAbsorb();
damageInfo->resist = dmgInfo.GetResist();
if (damageInfo->absorb) if (damageInfo->absorb)
{ {
@@ -1515,7 +1552,7 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
if (damageInfo->resist) if (damageInfo->resist)
damageInfo->HitInfo |= (damageInfo->damage - damageInfo->resist == 0 ? HITINFO_FULL_RESIST : HITINFO_PARTIAL_RESIST); damageInfo->HitInfo |= (damageInfo->damage - damageInfo->resist == 0 ? HITINFO_FULL_RESIST : HITINFO_PARTIAL_RESIST);
damageInfo->damage -= damageInfo->absorb + damageInfo->resist; damageInfo->damage = dmgInfo.GetDamage();
} }
else // Impossible get negative result but.... else // Impossible get negative result but....
damageInfo->damage = 0; damageInfo->damage = 0;
@@ -1628,9 +1665,11 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
damage = this->SpellDamageBonusTaken(caster, i_spellProto, damage, SPELL_DIRECT_DAMAGE); damage = this->SpellDamageBonusTaken(caster, i_spellProto, damage, SPELL_DIRECT_DAMAGE);
uint32 absorb = 0; uint32 absorb = 0;
uint32 resist = 0;
Unit::CalcAbsorbResist(victim, this, i_spellProto->GetSchoolMask(), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist, i_spellProto); DamageInfo dmgInfo(victim, this, damage, i_spellProto, i_spellProto->GetSchoolMask(), SPELL_DIRECT_DAMAGE);
damage -= absorb + resist; Unit::CalcAbsorbResist(dmgInfo);
absorb = dmgInfo.GetAbsorb();
damage = dmgInfo.GetDamage();
Unit::DealDamageMods(this, damage, &absorb); Unit::DealDamageMods(this, damage, &absorb);
@@ -1804,13 +1843,17 @@ float Unit::GetEffectiveResistChance(Unit const* owner, SpellSchoolMask schoolMa
return victimResistance / (victimResistance + resistanceConstant); return victimResistance / (victimResistance + resistanceConstant);
} }
void Unit::CalcAbsorbResist(Unit* attacker, Unit* victim, SpellSchoolMask schoolMask, DamageEffectType damagetype, const uint32 damage, uint32* absorb, uint32* resist, SpellInfo const* spellInfo, bool Splited) void Unit::CalcAbsorbResist(DamageInfo& dmgInfo, bool Splited)
{ {
Unit* victim = dmgInfo.GetVictim();
Unit* attacker = dmgInfo.GetAttacker();
uint32 damage = dmgInfo.GetDamage();
SpellSchoolMask schoolMask = dmgInfo.GetSchoolMask();
SpellInfo const* spellInfo = dmgInfo.GetSpellInfo();
if (!victim || !victim->IsAlive() || !damage) if (!victim || !victim->IsAlive() || !damage)
return; return;
DamageInfo dmgInfo = DamageInfo(attacker, victim, damage, spellInfo, schoolMask, damagetype);
// Magic damage, check for resists // Magic damage, check for resists
// Ignore spells that cant be resisted // Ignore spells that cant be resisted
// Xinef: holy resistance exists for npcs // Xinef: holy resistance exists for npcs
@@ -2043,25 +2086,28 @@ void Unit::CalcAbsorbResist(Unit* attacker, Unit* victim, SpellSchoolMask school
uint32 splitted_resist = 0; uint32 splitted_resist = 0;
uint32 procAttacker = 0, procVictim = 0, procEx = PROC_EX_NORMAL_HIT; uint32 procAttacker = 0, procVictim = 0, procEx = PROC_EX_NORMAL_HIT;
DamageInfo splittedDmgInfo(attacker, caster, splitted, spellInfo, schoolMask, dmgInfo.GetDamageType());
if (caster->IsImmunedToDamageOrSchool(schoolMask)) if (caster->IsImmunedToDamageOrSchool(schoolMask))
{ {
procEx |= PROC_EX_IMMUNE; procEx |= PROC_EX_IMMUNE;
splitted_absorb = splitted; splittedDmgInfo.AbsorbDamage(splitted);
splitted = 0;
} }
else else
{ {
Unit::CalcAbsorbResist(splittedDmgInfo, true);
Unit::DealDamageMods(caster, splitted, &splitted_absorb); Unit::DealDamageMods(caster, splitted, &splitted_absorb);
Unit::CalcAbsorbResist(attacker, caster, schoolMask, damagetype, splitted, &splitted_absorb, &splitted_resist, spellInfo, true);
splitted -= std::min(splitted_absorb, splitted);
} }
splitted_absorb = splittedDmgInfo.GetAbsorb();
splitted_resist = splittedDmgInfo.GetResist();
splitted = splittedDmgInfo.GetDamage();
// create procs // create procs
createProcFlags(spellInfo, BASE_ATTACK, false, procAttacker, procVictim); createProcFlags(spellInfo, BASE_ATTACK, false, procAttacker, procVictim);
caster->ProcDamageAndSpellFor(true, attacker, procVictim, procEx, BASE_ATTACK, spellInfo, splitted); caster->ProcDamageAndSpellFor(true, attacker, procVictim, procEx, BASE_ATTACK, spellInfo, splitted, nullptr, -1, nullptr, &splittedDmgInfo);
if (attacker) if (attacker)
attacker->SendSpellNonMeleeDamageLog(caster, (*itr)->GetSpellInfo()->Id, splitted + splitted_absorb, schoolMask, splitted_absorb, 0, false, 0, false); attacker->SendSpellNonMeleeDamageLog(caster, (*itr)->GetSpellInfo(), splitted, schoolMask, splitted_absorb, splitted_resist, false, 0, false);
CleanDamage cleanDamage = CleanDamage(splitted, 0, BASE_ATTACK, MELEE_HIT_NORMAL); CleanDamage cleanDamage = CleanDamage(splitted, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
Unit::DealDamage(attacker, caster, splitted, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*itr)->GetSpellInfo(), false); Unit::DealDamage(attacker, caster, splitted, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*itr)->GetSpellInfo(), false);
@@ -2111,50 +2157,51 @@ void Unit::CalcAbsorbResist(Unit* attacker, Unit* victim, SpellSchoolMask school
uint32 splitted_resist = 0; uint32 splitted_resist = 0;
uint32 procAttacker = 0, procVictim = 0, procEx = PROC_EX_NORMAL_HIT; uint32 procAttacker = 0, procVictim = 0, procEx = PROC_EX_NORMAL_HIT;
DamageInfo splittedDmgInfo(attacker, caster, splitted, spellInfo, splitSchoolMask, dmgInfo.GetDamageType());
if (caster->IsImmunedToDamageOrSchool(schoolMask)) if (caster->IsImmunedToDamageOrSchool(schoolMask))
{ {
procEx |= PROC_EX_IMMUNE; procEx |= PROC_EX_IMMUNE;
splitted_absorb = splitted; splittedDmgInfo.AbsorbDamage(splitted);
splitted = 0;
} }
else else
{ {
Unit::CalcAbsorbResist(splittedDmgInfo, true);
Unit::DealDamageMods(caster, splitted, &splitted_absorb); Unit::DealDamageMods(caster, splitted, &splitted_absorb);
Unit::CalcAbsorbResist(attacker, caster, splitSchoolMask, damagetype, splitted, &splitted_absorb, &splitted_resist, spellInfo, true);
splitted -= std::min(splitted_absorb, splitted);
} }
splitted_absorb = splittedDmgInfo.GetAbsorb();
splitted_resist = splittedDmgInfo.GetResist();
splitted = splittedDmgInfo.GetDamage();
// create procs // create procs
createProcFlags(spellInfo, BASE_ATTACK, false, procAttacker, procVictim); createProcFlags(spellInfo, BASE_ATTACK, false, procAttacker, procVictim);
caster->ProcDamageAndSpellFor(true, attacker, procVictim, procEx, BASE_ATTACK, spellInfo, splitted); caster->ProcDamageAndSpellFor(true, attacker, procVictim, procEx, BASE_ATTACK, spellInfo, splitted);
if (attacker) if (attacker)
attacker->SendSpellNonMeleeDamageLog(caster, splitSpellInfo->Id, splitted + splitted_absorb, splitSchoolMask, splitted_absorb, 0, false, 0, false); attacker->SendSpellNonMeleeDamageLog(caster, splitSpellInfo, splitted, splitSchoolMask, splitted_absorb, splitted_resist, false, 0, false);
CleanDamage cleanDamage = CleanDamage(splitted, 0, BASE_ATTACK, MELEE_HIT_NORMAL); CleanDamage cleanDamage = CleanDamage(splitted, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
Unit::DealDamage(attacker, caster, splitted, &cleanDamage, DIRECT_DAMAGE, splitSchoolMask, splitSpellInfo, false); Unit::DealDamage(attacker, caster, splitted, &cleanDamage, DIRECT_DAMAGE, splitSchoolMask, splitSpellInfo, false);
} }
} }
*resist = dmgInfo.GetResist();
*absorb = dmgInfo.GetAbsorb();
} }
void Unit::CalcHealAbsorb(Unit const* victim, const SpellInfo* healSpell, uint32& healAmount, uint32& absorb) void Unit::CalcHealAbsorb(HealInfo& healInfo)
{ {
if (!healAmount) if (!healInfo.GetHeal())
return; return;
int32 RemainingHeal = healAmount; int32 const healing = static_cast<int32>(healInfo.GetHeal());
int32 absorbAmount = 0;
// Need remove expired auras after // Need remove expired auras after
bool existExpired = false; bool existExpired = false;
// absorb without mana cost // absorb without mana cost
AuraEffectList const& vHealAbsorb = victim->GetAuraEffectsByType(SPELL_AURA_SCHOOL_HEAL_ABSORB); AuraEffectList const& vHealAbsorb = healInfo.GetTarget()->GetAuraEffectsByType(SPELL_AURA_SCHOOL_HEAL_ABSORB);
for (AuraEffectList::const_iterator i = vHealAbsorb.begin(); i != vHealAbsorb.end() && RemainingHeal > 0; ++i) for (AuraEffectList::const_iterator i = vHealAbsorb.begin(); i != vHealAbsorb.end() && absorbAmount <= healing; ++i)
{ {
if (!((*i)->GetMiscValue() & healSpell->SchoolMask)) if (!((*i)->GetMiscValue() & healInfo.GetSpellInfo()->SchoolMask))
continue; continue;
// Max Amount can be absorbed by this aura // Max Amount can be absorbed by this aura
@@ -2169,10 +2216,10 @@ void Unit::CalcHealAbsorb(Unit const* victim, const SpellInfo* healSpell, uint32
// currentAbsorb - damage can be absorbed by shield // currentAbsorb - damage can be absorbed by shield
// If need absorb less damage // If need absorb less damage
if (RemainingHeal < currentAbsorb) if (healing < currentAbsorb + absorbAmount)
currentAbsorb = RemainingHeal; currentAbsorb = healing - absorbAmount;
RemainingHeal -= currentAbsorb; absorbAmount += currentAbsorb;
// Reduce shield amount // Reduce shield amount
(*i)->SetAmount((*i)->GetAmount() - currentAbsorb); (*i)->SetAmount((*i)->GetAmount() - currentAbsorb);
@@ -2190,16 +2237,16 @@ void Unit::CalcHealAbsorb(Unit const* victim, const SpellInfo* healSpell, uint32
++i; ++i;
if (auraEff->GetAmount() <= 0) if (auraEff->GetAmount() <= 0)
{ {
uint32 removedAuras = victim->m_removedAurasCount; uint32 removedAuras = healInfo.GetTarget()->m_removedAurasCount;
auraEff->GetBase()->Remove(AURA_REMOVE_BY_ENEMY_SPELL); auraEff->GetBase()->Remove(AURA_REMOVE_BY_ENEMY_SPELL);
if (removedAuras + 1 < victim->m_removedAurasCount) if (removedAuras + 1 < healInfo.GetTarget()->m_removedAurasCount)
i = vHealAbsorb.begin(); i = vHealAbsorb.begin();
} }
} }
} }
absorb = RemainingHeal > 0 ? (healAmount - RemainingHeal) : healAmount; if (absorbAmount > 0)
healAmount = RemainingHeal; healInfo.AbsorbHeal(absorbAmount);
} }
void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType, bool extra) void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType, bool extra)
@@ -2239,7 +2286,10 @@ void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType, bool extr
//TriggerAurasProcOnEvent(damageInfo); //TriggerAurasProcOnEvent(damageInfo);
DealMeleeDamage(&damageInfo, true); DealMeleeDamage(&damageInfo, true);
ProcDamageAndSpell(damageInfo.target, damageInfo.procAttacker, damageInfo.procVictim, damageInfo.procEx, damageInfo.damage, damageInfo.attackType);
DamageInfo dmgInfo(damageInfo);
ProcDamageAndSpell(damageInfo.target, damageInfo.procAttacker, damageInfo.procVictim, damageInfo.procEx, damageInfo.damage,
damageInfo.attackType, nullptr, nullptr, -1, nullptr, &dmgInfo);
if (GetTypeId() == TYPEID_PLAYER) if (GetTypeId() == TYPEID_PLAYER)
LOG_DEBUG("entities.unit", "AttackerStateUpdate: (Player) %s attacked %s for %u dmg, absorbed %u, blocked %u, resisted %u.", LOG_DEBUG("entities.unit", "AttackerStateUpdate: (Player) %s attacked %s for %u dmg, absorbed %u, blocked %u, resisted %u.",
@@ -5627,7 +5677,7 @@ void Unit::SendSpellNonMeleeReflectLog(SpellNonMeleeDamage* log, Unit* attacker)
} }
data << log->target->GetPackGUID(); data << log->target->GetPackGUID();
data << attacker->GetPackGUID(); data << attacker->GetPackGUID();
data << uint32(log->SpellID); data << uint32(log->spellInfo->Id);
data << uint32(damage); // damage amount data << uint32(damage); // damage amount
int32 overkill = damage - log->target->GetHealth(); int32 overkill = damage - log->target->GetHealth();
data << uint32(overkill > 0 ? overkill : 0); // overkill data << uint32(overkill > 0 ? overkill : 0); // overkill
@@ -5655,7 +5705,7 @@ void Unit::SendSpellNonMeleeDamageLog(SpellNonMeleeDamage* log)
} }
data << log->target->GetPackGUID(); data << log->target->GetPackGUID();
data << log->attacker->GetPackGUID(); data << log->attacker->GetPackGUID();
data << uint32(log->SpellID); data << uint32(log->spellInfo->Id);
data << uint32(damage); // damage amount data << uint32(damage); // damage amount
int32 overkill = damage - log->target->GetHealth(); int32 overkill = damage - log->target->GetHealth();
data << uint32(overkill > 0 ? overkill : 0); // overkill data << uint32(overkill > 0 ? overkill : 0); // overkill
@@ -5670,10 +5720,10 @@ void Unit::SendSpellNonMeleeDamageLog(SpellNonMeleeDamage* log)
SendMessageToSet(&data, true); SendMessageToSet(&data, true);
} }
void Unit::SendSpellNonMeleeDamageLog(Unit* target, uint32 SpellID, uint32 Damage, SpellSchoolMask damageSchoolMask, uint32 AbsorbedDamage, uint32 Resist, bool PhysicalDamage, uint32 Blocked, bool CriticalHit) void Unit::SendSpellNonMeleeDamageLog(Unit* target, SpellInfo const* spellInfo, uint32 Damage, SpellSchoolMask damageSchoolMask, uint32 AbsorbedDamage, uint32 Resist, bool PhysicalDamage, uint32 Blocked, bool CriticalHit)
{ {
SpellNonMeleeDamage log(this, target, SpellID, damageSchoolMask); SpellNonMeleeDamage log(this, target, spellInfo, damageSchoolMask);
log.damage = Damage - AbsorbedDamage - Resist - Blocked; log.damage = Damage;
log.absorb = AbsorbedDamage; log.absorb = AbsorbedDamage;
log.resist = Resist; log.resist = Resist;
log.physicalLog = PhysicalDamage; log.physicalLog = PhysicalDamage;
@@ -5684,15 +5734,15 @@ void Unit::SendSpellNonMeleeDamageLog(Unit* target, uint32 SpellID, uint32 Damag
SendSpellNonMeleeDamageLog(&log); SendSpellNonMeleeDamageLog(&log);
} }
void Unit::ProcDamageAndSpell(Unit* victim, uint32 procAttacker, uint32 procVictim, uint32 procExtra, uint32 amount, WeaponAttackType attType, SpellInfo const* procSpellInfo, SpellInfo const* procAura, int8 procAuraEffectIndex, Spell const* procSpell) void Unit::ProcDamageAndSpell(Unit* victim, uint32 procAttacker, uint32 procVictim, uint32 procExtra, uint32 amount, WeaponAttackType attType, SpellInfo const* procSpellInfo, SpellInfo const* procAura, int8 procAuraEffectIndex, Spell const* procSpell, DamageInfo* damageInfo, HealInfo* healInfo)
{ {
// Not much to do if no flags are set. // Not much to do if no flags are set.
if (procAttacker) if (procAttacker)
ProcDamageAndSpellFor(false, victim, procAttacker, procExtra, attType, procSpellInfo, amount, procAura, procAuraEffectIndex, procSpell); ProcDamageAndSpellFor(false, victim, procAttacker, procExtra, attType, procSpellInfo, amount, procAura, procAuraEffectIndex, procSpell, damageInfo, healInfo);
// Now go on with a victim's events'n'auras // Now go on with a victim's events'n'auras
// Not much to do if no flags are set or there is no victim // Not much to do if no flags are set or there is no victim
if (victim && victim->IsAlive() && procVictim) if (victim && victim->IsAlive() && procVictim)
victim->ProcDamageAndSpellFor(true, this, procVictim, procExtra, attType, procSpellInfo, amount, procAura, procAuraEffectIndex, procSpell); victim->ProcDamageAndSpellFor(true, this, procVictim, procExtra, attType, procSpellInfo, amount, procAura, procAuraEffectIndex, procSpell, damageInfo, healInfo);
} }
void Unit::SendPeriodicAuraLog(SpellPeriodicAuraLogInfo* pInfo) void Unit::SendPeriodicAuraLog(SpellPeriodicAuraLogInfo* pInfo)
@@ -10508,16 +10558,17 @@ void Unit::SendHealSpellLog(Unit* victim, uint32 SpellID, uint32 Damage, uint32
SendMessageToSet(&data, true); SendMessageToSet(&data, true);
} }
int32 Unit::HealBySpell(Unit* victim, SpellInfo const* spellInfo, uint32 addHealth, bool critical) int32 Unit::HealBySpell(HealInfo& healInfo, bool critical)
{ {
uint32 absorb = 0; uint32 heal = healInfo.GetHeal();
sScriptMgr->ModifyHealRecieved(this, healInfo.GetTarget(), heal);
healInfo.SetHeal(heal);
// calculate heal absorb and reduce healing // calculate heal absorb and reduce healing
CalcHealAbsorb(victim, spellInfo, addHealth, absorb); CalcHealAbsorb(healInfo);
sScriptMgr->ModifyHealRecieved(this, victim, addHealth); int32 gain = Unit::DealHeal(healInfo.GetHealer(), healInfo.GetTarget(), healInfo.GetHeal());
SendHealSpellLog(healInfo.GetTarget(), healInfo.GetSpellInfo()->Id, healInfo.GetHeal(), uint32(healInfo.GetHeal() - gain), healInfo.GetAbsorb(), critical);
int32 gain = Unit::DealHeal(this, victim, addHealth);
SendHealSpellLog(victim, spellInfo->Id, addHealth, uint32(addHealth - gain), absorb, critical);
return gain; return gain;
} }
@@ -15302,7 +15353,7 @@ uint32 createProcExtendMask(SpellNonMeleeDamage* damageInfo, SpellMissInfo missC
return procEx; return procEx;
} }
void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, SpellInfo const* procSpellInfo, uint32 damage, SpellInfo const* procAura, int8 procAuraEffectIndex, Spell const* procSpell) void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, SpellInfo const* procSpellInfo, uint32 damage, SpellInfo const* procAura, int8 procAuraEffectIndex, Spell const* procSpell, DamageInfo* damageInfo, HealInfo* healInfo)
{ {
// Player is loaded now - do not allow passive spell casts to proc // Player is loaded now - do not allow passive spell casts to proc
if (GetTypeId() == TYPEID_PLAYER && ToPlayer()->GetSession()->PlayerLoading()) if (GetTypeId() == TYPEID_PLAYER && ToPlayer()->GetSession()->PlayerLoading())
@@ -15397,9 +15448,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
Unit* actor = isVictim ? target : this; Unit* actor = isVictim ? target : this;
Unit* actionTarget = !isVictim ? target : this; Unit* actionTarget = !isVictim ? target : this;
DamageInfo damageInfo = DamageInfo(actor, actionTarget, damage, procSpellInfo, procSpellInfo ? SpellSchoolMask(procSpellInfo->SchoolMask) : SPELL_SCHOOL_MASK_NORMAL, SPELL_DIRECT_DAMAGE); ProcEventInfo eventInfo = ProcEventInfo(actor, actionTarget, target, procFlag, 0, 0, procExtra, procSpell, damageInfo, healInfo, procAura, procAuraEffectIndex);
HealInfo healInfo = HealInfo(actor, actionTarget, damage, procSpellInfo, procSpellInfo ? SpellSchoolMask(procSpellInfo->SchoolMask) : SPELL_SCHOOL_MASK_NORMAL);
ProcEventInfo eventInfo = ProcEventInfo(actor, actionTarget, target, procFlag, 0, 0, procExtra, procSpell, &damageInfo, &healInfo, procAura, procAuraEffectIndex);
ProcTriggeredList procTriggered; ProcTriggeredList procTriggered;
// Fill procTriggered list // Fill procTriggered list
+24 -14
View File
@@ -893,6 +893,7 @@ struct CleanDamage
}; };
struct CalcDamageInfo; struct CalcDamageInfo;
struct SpellNonMeleeDamage;
class DamageInfo class DamageInfo
{ {
@@ -907,9 +908,11 @@ private:
uint32 m_absorb; uint32 m_absorb;
uint32 m_resist; uint32 m_resist;
uint32 m_block; uint32 m_block;
uint32 m_cleanDamage;
public: public:
explicit DamageInfo(Unit* _attacker, Unit* _victim, uint32 _damage, SpellInfo const* _spellInfo, SpellSchoolMask _schoolMask, DamageEffectType _damageType); explicit DamageInfo(Unit* _attacker, Unit* _victim, uint32 _damage, SpellInfo const* _spellInfo, SpellSchoolMask _schoolMask, DamageEffectType _damageType, uint32 cleanDamage = 0);
explicit DamageInfo(CalcDamageInfo& dmgInfo); explicit DamageInfo(CalcDamageInfo& dmgInfo);
DamageInfo(SpellNonMeleeDamage const& spellNonMeleeDamage, DamageEffectType damageType);
void ModifyDamage(int32 amount); void ModifyDamage(int32 amount);
void AbsorbDamage(uint32 amount); void AbsorbDamage(uint32 amount);
@@ -926,6 +929,8 @@ public:
[[nodiscard]] uint32 GetAbsorb() const { return m_absorb; }; [[nodiscard]] uint32 GetAbsorb() const { return m_absorb; };
[[nodiscard]] uint32 GetResist() const { return m_resist; }; [[nodiscard]] uint32 GetResist() const { return m_resist; };
[[nodiscard]] uint32 GetBlock() const { return m_block; }; [[nodiscard]] uint32 GetBlock() const { return m_block; };
[[nodiscard]] uint32 GetUnmitigatedDamage() const;
}; };
class HealInfo class HealInfo
@@ -950,6 +955,11 @@ public:
m_heal -= amount; m_heal -= amount;
} }
void SetHeal(uint32 amount)
{
m_heal = amount;
}
[[nodiscard]] Unit* GetHealer() const { return m_healer; } [[nodiscard]] Unit* GetHealer() const { return m_healer; }
[[nodiscard]] Unit* GetTarget() const { return m_target; } [[nodiscard]] Unit* GetTarget() const { return m_target; }
[[nodiscard]] uint32 GetHeal() const { return m_heal; } [[nodiscard]] uint32 GetHeal() const { return m_heal; }
@@ -1020,21 +1030,21 @@ struct CalcDamageInfo
// Spell damage info structure based on structure sending in SMSG_SPELLNONMELEEDAMAGELOG opcode // Spell damage info structure based on structure sending in SMSG_SPELLNONMELEEDAMAGELOG opcode
struct SpellNonMeleeDamage struct SpellNonMeleeDamage
{ {
SpellNonMeleeDamage(Unit* _attacker, Unit* _target, uint32 _SpellID, uint32 _schoolMask) SpellNonMeleeDamage(Unit* _attacker, Unit* _target, SpellInfo const* _spellInfo, uint32 _schoolMask)
: target(_target), attacker(_attacker), SpellID(_SpellID), damage(0), overkill(0), schoolMask(_schoolMask), : target(_target), attacker(_attacker), spellInfo(_spellInfo), damage(0), overkill(0), schoolMask(_schoolMask),
absorb(0), resist(0), physicalLog(false), unused(false), blocked(0), HitInfo(0), cleanDamage(0) absorb(0), resist(0), physicalLog(false), unused(false), blocked(0), HitInfo(0), cleanDamage(0)
{} {}
Unit* target; Unit* target;
Unit* attacker; Unit* attacker;
uint32 SpellID; SpellInfo const* spellInfo;
uint32 damage; uint32 damage;
uint32 overkill; uint32 overkill;
uint32 schoolMask; uint32 schoolMask;
uint32 absorb; uint32 absorb;
uint32 resist; uint32 resist;
bool physicalLog; bool physicalLog;
bool unused; bool unused;
uint32 blocked; uint32 blocked;
uint32 HitInfo; uint32 HitInfo;
// Used for help // Used for help
@@ -1642,8 +1652,8 @@ public:
static void Kill(Unit* killer, Unit* victim, bool durabilityLoss = true, WeaponAttackType attackType = BASE_ATTACK, SpellInfo const* spellProto = nullptr); static void Kill(Unit* killer, Unit* victim, bool durabilityLoss = true, WeaponAttackType attackType = BASE_ATTACK, SpellInfo const* spellProto = nullptr);
static int32 DealHeal(Unit* healer, Unit* victim, uint32 addhealth); static int32 DealHeal(Unit* healer, Unit* victim, uint32 addhealth);
void ProcDamageAndSpell(Unit* victim, uint32 procAttacker, uint32 procVictim, uint32 procEx, uint32 amount, WeaponAttackType attType = BASE_ATTACK, SpellInfo const* procSpellInfo = nullptr, SpellInfo const* procAura = nullptr, int8 procAuraEffectIndex = -1, Spell const* procSpell = nullptr); void ProcDamageAndSpell(Unit* victim, uint32 procAttacker, uint32 procVictim, uint32 procEx, uint32 amount, WeaponAttackType attType = BASE_ATTACK, SpellInfo const* procSpellInfo = nullptr, SpellInfo const* procAura = nullptr, int8 procAuraEffectIndex = -1, Spell const* procSpell = nullptr, DamageInfo* damageInfo = nullptr, HealInfo* healInfo = nullptr);
void ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, SpellInfo const* procSpellInfo, uint32 damage, SpellInfo const* procAura = nullptr, int8 procAuraEffectIndex = -1, Spell const* procSpell = nullptr); void ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, SpellInfo const* procSpellInfo, uint32 damage, SpellInfo const* procAura = nullptr, int8 procAuraEffectIndex = -1, Spell const* procSpell = nullptr, DamageInfo* damageInfo = nullptr, HealInfo* healInfo = nullptr);
void GetProcAurasTriggeredOnEvent(std::list<AuraApplication*>& aurasTriggeringProc, std::list<AuraApplication*>* procAuras, ProcEventInfo eventInfo); void GetProcAurasTriggeredOnEvent(std::list<AuraApplication*>& aurasTriggeringProc, std::list<AuraApplication*>* procAuras, ProcEventInfo eventInfo);
void TriggerAurasProcOnEvent(CalcDamageInfo& damageInfo); void TriggerAurasProcOnEvent(CalcDamageInfo& damageInfo);
@@ -1791,7 +1801,7 @@ public:
bool isInAccessiblePlaceFor(Creature const* c) const; bool isInAccessiblePlaceFor(Creature const* c) const;
void SendHealSpellLog(Unit* victim, uint32 SpellID, uint32 Damage, uint32 OverHeal, uint32 Absorb, bool critical = false); void SendHealSpellLog(Unit* victim, uint32 SpellID, uint32 Damage, uint32 OverHeal, uint32 Absorb, bool critical = false);
int32 HealBySpell(Unit* victim, SpellInfo const* spellInfo, uint32 addHealth, bool critical = false); int32 HealBySpell(HealInfo& healInfo, bool critical = false);
void SendEnergizeSpellLog(Unit* victim, uint32 SpellID, uint32 Damage, Powers powertype); void SendEnergizeSpellLog(Unit* victim, uint32 SpellID, uint32 Damage, Powers powertype);
void EnergizeBySpell(Unit* victim, uint32 SpellID, uint32 Damage, Powers powertype); void EnergizeBySpell(Unit* victim, uint32 SpellID, uint32 Damage, Powers powertype);
@@ -1820,7 +1830,7 @@ public:
void SendAttackStateUpdate(uint32 HitInfo, Unit* target, uint8 SwingType, SpellSchoolMask damageSchoolMask, uint32 Damage, uint32 AbsorbDamage, uint32 Resist, VictimState TargetState, uint32 BlockedAmount); void SendAttackStateUpdate(uint32 HitInfo, Unit* target, uint8 SwingType, SpellSchoolMask damageSchoolMask, uint32 Damage, uint32 AbsorbDamage, uint32 Resist, VictimState TargetState, uint32 BlockedAmount);
void SendSpellNonMeleeDamageLog(SpellNonMeleeDamage* log); void SendSpellNonMeleeDamageLog(SpellNonMeleeDamage* log);
void SendSpellNonMeleeReflectLog(SpellNonMeleeDamage* log, Unit* attacker); void SendSpellNonMeleeReflectLog(SpellNonMeleeDamage* log, Unit* attacker);
void SendSpellNonMeleeDamageLog(Unit* target, uint32 SpellID, uint32 Damage, SpellSchoolMask damageSchoolMask, uint32 AbsorbedDamage, uint32 Resist, bool PhysicalDamage, uint32 Blocked, bool CriticalHit = false); void SendSpellNonMeleeDamageLog(Unit* target, SpellInfo const* spellInfo, uint32 Damage, SpellSchoolMask damageSchoolMask, uint32 AbsorbedDamage, uint32 Resist, bool PhysicalDamage, uint32 Blocked, bool CriticalHit = false);
void SendPeriodicAuraLog(SpellPeriodicAuraLogInfo* pInfo); void SendPeriodicAuraLog(SpellPeriodicAuraLogInfo* pInfo);
void SendSpellMiss(Unit* target, uint32 spellID, SpellMissInfo missInfo); void SendSpellMiss(Unit* target, uint32 spellID, SpellMissInfo missInfo);
void SendSpellDamageResist(Unit* target, uint32 spellId); void SendSpellDamageResist(Unit* target, uint32 spellId);
@@ -2307,8 +2317,8 @@ public:
// redefined in Creature // redefined in Creature
static bool IsDamageReducedByArmor(SpellSchoolMask damageSchoolMask, SpellInfo const* spellInfo = nullptr, uint8 effIndex = MAX_SPELL_EFFECTS); static bool IsDamageReducedByArmor(SpellSchoolMask damageSchoolMask, SpellInfo const* spellInfo = nullptr, uint8 effIndex = MAX_SPELL_EFFECTS);
static uint32 CalcArmorReducedDamage(Unit const* attacker, Unit const* victim, const uint32 damage, SpellInfo const* spellInfo, uint8 attackerLevel = 0, WeaponAttackType attackType = MAX_ATTACK); static uint32 CalcArmorReducedDamage(Unit const* attacker, Unit const* victim, const uint32 damage, SpellInfo const* spellInfo, uint8 attackerLevel = 0, WeaponAttackType attackType = MAX_ATTACK);
static void CalcAbsorbResist(Unit* attacker, Unit* victim, SpellSchoolMask schoolMask, DamageEffectType damagetype, const uint32 damage, uint32* absorb, uint32* resist, SpellInfo const* spellInfo = nullptr, bool Splited = false); static void CalcAbsorbResist(DamageInfo& dmgInfo, bool Splited = false);
static void CalcHealAbsorb(Unit const* victim, const SpellInfo* spellProto, uint32& healAmount, uint32& absorb); static void CalcHealAbsorb(HealInfo& healInfo);
void UpdateSpeed(UnitMoveType mtype, bool forced); void UpdateSpeed(UnitMoveType mtype, bool forced);
[[nodiscard]] float GetSpeed(UnitMoveType mtype) const; [[nodiscard]] float GetSpeed(UnitMoveType mtype) const;
@@ -5933,7 +5933,8 @@ void AuraEffect::HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster)
if (caster) if (caster)
{ {
int32 heal = caster->CountPctFromMaxHealth(10); int32 heal = caster->CountPctFromMaxHealth(10);
caster->HealBySpell(target, auraSpellInfo, heal); HealInfo healInfo(caster, target, heal, auraSpellInfo, auraSpellInfo->GetSchoolMask());
caster->HealBySpell(healInfo);
if (int32 mana = caster->GetMaxPower(POWER_MANA)) if (int32 mana = caster->GetMaxPower(POWER_MANA))
{ {
@@ -6272,8 +6273,6 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
} }
} }
uint32 absorb = 0;
uint32 resist = 0;
CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL); CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
// ignore non positive values (can be result apply spellmods to aura damage // ignore non positive values (can be result apply spellmods to aura damage
@@ -6333,23 +6332,33 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
if ((crit = roll_chance_f(GetCritChance()))) if ((crit = roll_chance_f(GetCritChance())))
damage = Unit::SpellCriticalDamageBonus(caster, m_spellInfo, damage, target); damage = Unit::SpellCriticalDamageBonus(caster, m_spellInfo, damage, target);
int32 dmg = damage;
if (CanApplyResilience())
Unit::ApplyResilience(target, nullptr, &dmg, crit, CR_CRIT_TAKEN_SPELL);
damage = dmg;
Unit::CalcAbsorbResist(caster, target, GetSpellInfo()->GetSchoolMask(), DOT, damage, &absorb, &resist, GetSpellInfo());
LOG_DEBUG("spells.aura.effect", "PeriodicTick: %s attacked %s for %u dmg inflicted by %u abs is %u",
GetCasterGUID().ToString().c_str(), target->GetGUID().ToString().c_str(), damage, GetId(), absorb);
Unit::DealDamageMods(target, damage, &absorb);
// Auras reducing damage from AOE spells // Auras reducing damage from AOE spells
if (GetSpellInfo()->Effects[GetEffIndex()].IsAreaAuraEffect() || GetSpellInfo()->Effects[GetEffIndex()].IsTargetingArea() || GetSpellInfo()->Effects[GetEffIndex()].Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA) // some persistent area auras have targets like A=53 B=28 if (GetSpellInfo()->Effects[GetEffIndex()].IsAreaAuraEffect() || GetSpellInfo()->Effects[GetEffIndex()].IsTargetingArea() || GetSpellInfo()->Effects[GetEffIndex()].Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA) // some persistent area auras have targets like A=53 B=28
{ {
damage = target->CalculateAOEDamageReduction(damage, GetSpellInfo()->SchoolMask, caster); damage = target->CalculateAOEDamageReduction(damage, GetSpellInfo()->SchoolMask, caster);
} }
if (CanApplyResilience())
{
int32 resilienceReduction = damage;
Unit::ApplyResilience(target, nullptr, &resilienceReduction, crit, CR_CRIT_TAKEN_SPELL);
resilienceReduction = damage - resilienceReduction;
damage -= resilienceReduction;
cleanDamage.mitigated_damage += resilienceReduction;
}
DamageInfo dmgInfo(caster, target, damage, GetSpellInfo(), GetSpellInfo()->GetSchoolMask(), DOT, cleanDamage.mitigated_damage);
Unit::CalcAbsorbResist(dmgInfo);
uint32 absorb = dmgInfo.GetAbsorb();
uint32 resist = dmgInfo.GetResist();
damage = dmgInfo.GetDamage();
LOG_DEBUG("spells.aura.effect", "PeriodicTick: %s attacked %s for %u dmg inflicted by %u abs is %u",
GetCasterGUID().ToString().c_str(), target->GetGUID().ToString().c_str(), damage, GetId(), absorb);
Unit::DealDamageMods(target, damage, &absorb);
// Set trigger flag // Set trigger flag
uint32 procAttacker = PROC_FLAG_DONE_PERIODIC; uint32 procAttacker = PROC_FLAG_DONE_PERIODIC;
uint32 procVictim = PROC_FLAG_TAKEN_PERIODIC; uint32 procVictim = PROC_FLAG_TAKEN_PERIODIC;
@@ -6357,7 +6366,6 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
if (absorb > 0) if (absorb > 0)
procEx |= PROC_EX_ABSORB; procEx |= PROC_EX_ABSORB;
damage = (damage <= absorb + resist) ? 0 : (damage - absorb - resist);
if (damage) if (damage)
procVictim |= PROC_FLAG_TAKEN_DAMAGE; procVictim |= PROC_FLAG_TAKEN_DAMAGE;
@@ -6370,7 +6378,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
Unit::DealDamage(caster, target, damage, &cleanDamage, DOT, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), true); Unit::DealDamage(caster, target, damage, &cleanDamage, DOT, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), true);
// allow null caster to call this function // allow null caster to call this function
caster->ProcDamageAndSpell(target, caster ? procAttacker : 0, procVictim, procEx, damage, BASE_ATTACK, GetSpellInfo(), nullptr, GetEffIndex()); caster->ProcDamageAndSpell(target, caster ? procAttacker : 0, procVictim, procEx, damage, BASE_ATTACK, GetSpellInfo(), nullptr, GetEffIndex(), nullptr, &dmgInfo);
} }
void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) const void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) const
@@ -6388,8 +6396,6 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
caster->SpellHitResult(target, GetSpellInfo(), false) != SPELL_MISS_NONE) caster->SpellHitResult(target, GetSpellInfo(), false) != SPELL_MISS_NONE)
return; return;
uint32 absorb = 0;
uint32 resist = 0;
CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL); CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
uint32 damage = std::max(GetAmount(), 0); uint32 damage = std::max(GetAmount(), 0);
@@ -6413,12 +6419,22 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
damage = damageReductedArmor; damage = damageReductedArmor;
} }
int32 dmg = damage;
if (CanApplyResilience()) if (CanApplyResilience())
Unit::ApplyResilience(target, nullptr, &dmg, crit, CR_CRIT_TAKEN_SPELL); {
damage = dmg; int32 resilienceReduction = damage;
Unit::ApplyResilience(target, nullptr, &resilienceReduction, crit, CR_CRIT_TAKEN_SPELL);
Unit::CalcAbsorbResist(caster, target, GetSpellInfo()->GetSchoolMask(), DOT, damage, &absorb, &resist, m_spellInfo); resilienceReduction = damage - resilienceReduction;
damage -= resilienceReduction;
cleanDamage.mitigated_damage += resilienceReduction;
}
DamageInfo dmgInfo(caster, target, damage, GetSpellInfo(), GetSpellInfo()->GetSchoolMask(), DOT, cleanDamage.mitigated_damage);
Unit::CalcAbsorbResist(dmgInfo);
uint32 absorb = dmgInfo.GetAbsorb();
uint32 resist = dmgInfo.GetResist();
damage = dmgInfo.GetDamage();
// Set trigger flag // Set trigger flag
uint32 procAttacker = PROC_FLAG_DONE_PERIODIC; uint32 procAttacker = PROC_FLAG_DONE_PERIODIC;
@@ -6427,23 +6443,26 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
if (absorb > 0) if (absorb > 0)
procEx |= PROC_EX_ABSORB; procEx |= PROC_EX_ABSORB;
damage = (damage <= absorb + resist) ? 0 : (damage - absorb - resist); if (dmgInfo.GetDamage())
if (damage)
procVictim |= PROC_FLAG_TAKEN_DAMAGE; procVictim |= PROC_FLAG_TAKEN_DAMAGE;
if (target->GetHealth() < damage) if (target->GetHealth() < dmgInfo.GetDamage())
damage = target->GetHealth(); {
dmgInfo.ModifyDamage(dmgInfo.GetDamage() - target->GetHealth());
}
damage = dmgInfo.GetDamage();
LOG_DEBUG("spells.aura.effect", "PeriodicTick: %s health leech of %s for %u dmg inflicted by %u abs is %u", LOG_DEBUG("spells.aura.effect", "PeriodicTick: %s health leech of %s for %u dmg inflicted by %u abs is %u",
GetCasterGUID().ToString().c_str(), target->GetGUID().ToString().c_str(), damage, GetId(), absorb); GetCasterGUID().ToString().c_str(), target->GetGUID().ToString().c_str(), damage, GetId(), absorb);
if (caster) if (caster)
caster->SendSpellNonMeleeDamageLog(target, GetId(), damage + absorb + resist, GetSpellInfo()->GetSchoolMask(), absorb, resist, false, 0, crit); caster->SendSpellNonMeleeDamageLog(target, GetSpellInfo(), damage, GetSpellInfo()->GetSchoolMask(), absorb, resist, false, 0, crit);
int32 new_damage; int32 new_damage;
new_damage = Unit::DealDamage(caster, target, damage, &cleanDamage, DOT, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), false); new_damage = Unit::DealDamage(caster, target, damage, &cleanDamage, DOT, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), false);
// allow null caster to call this function // allow null caster to call this function
caster->ProcDamageAndSpell(target, caster ? procAttacker : 0, procVictim, procEx, damage, BASE_ATTACK, GetSpellInfo(), nullptr, GetEffIndex()); caster->ProcDamageAndSpell(target, caster ? procAttacker : 0, procVictim, procEx, damage, BASE_ATTACK, GetSpellInfo(), nullptr, GetEffIndex(), nullptr, &dmgInfo);
if (!caster || !caster->IsAlive()) if (!caster || !caster->IsAlive())
return; return;
@@ -6453,7 +6472,8 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
uint32 heal = uint32(caster->SpellHealingBonusDone(caster, GetSpellInfo(), uint32(new_damage * gainMultiplier), DOT, 0.0f, GetBase()->GetStackAmount())); uint32 heal = uint32(caster->SpellHealingBonusDone(caster, GetSpellInfo(), uint32(new_damage * gainMultiplier), DOT, 0.0f, GetBase()->GetStackAmount()));
heal = uint32(caster->SpellHealingBonusTaken(caster, GetSpellInfo(), heal, DOT, GetBase()->GetStackAmount())); heal = uint32(caster->SpellHealingBonusTaken(caster, GetSpellInfo(), heal, DOT, GetBase()->GetStackAmount()));
int32 gain = caster->HealBySpell(caster, GetSpellInfo(), heal); HealInfo healInfo(caster, caster, heal, GetSpellInfo(), GetSpellInfo()->GetSchoolMask());
int32 gain = caster->HealBySpell(healInfo);
caster->getHostileRefMgr().threatAssist(caster, gain * 0.5f, GetSpellInfo()); caster->getHostileRefMgr().threatAssist(caster, gain * 0.5f, GetSpellInfo());
} }
@@ -6482,7 +6502,8 @@ void AuraEffect::HandlePeriodicHealthFunnelAuraTick(Unit* target, Unit* caster)
damage = int32(damage * gainMultiplier); damage = int32(damage * gainMultiplier);
caster->HealBySpell(target, GetSpellInfo(), damage); HealInfo healInfo(caster, target, damage, GetSpellInfo(), GetSpellInfo()->GetSchoolMask());
caster->HealBySpell(healInfo);
} }
void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const
@@ -6579,16 +6600,17 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const
LOG_DEBUG("spells.aura.effect", "PeriodicTick: %s heal of %s for %u health inflicted by %u", LOG_DEBUG("spells.aura.effect", "PeriodicTick: %s heal of %s for %u health inflicted by %u",
GetCasterGUID().ToString().c_str(), target->GetGUID().ToString().c_str(), damage, GetId()); GetCasterGUID().ToString().c_str(), target->GetGUID().ToString().c_str(), damage, GetId());
uint32 absorb = 0;
uint32 heal = uint32(damage); uint32 heal = uint32(damage);
// Script Hook For HandlePeriodicDamageAurasTick -- Allow scripts to change the Damage pre class mitigation calculations // Script Hook For HandlePeriodicDamageAurasTick -- Allow scripts to change the Damage pre class mitigation calculations
sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, heal); sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, heal);
Unit::CalcHealAbsorb(target, GetSpellInfo(), heal, absorb); HealInfo healInfo(caster, target, heal, GetSpellInfo(), GetSpellInfo()->GetSchoolMask());
int32 gain = Unit::DealHeal(caster, target, heal); Unit::CalcHealAbsorb(healInfo);
int32 gain = Unit::DealHeal(caster, target, healInfo.GetHeal());
SpellPeriodicAuraLogInfo pInfo(this, heal, heal - gain, absorb, 0, 0.0f, crit); SpellPeriodicAuraLogInfo pInfo(this, healInfo.GetHeal(), healInfo.GetHeal() - gain, healInfo.GetAbsorb(), 0, 0.0f, crit);
target->SendPeriodicAuraLog(&pInfo); target->SendPeriodicAuraLog(&pInfo);
if (caster) if (caster)
@@ -6610,20 +6632,20 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const
uint32 absorb2 = 0; uint32 absorb2 = 0;
Unit::DealDamageMods(caster, manaPerSecond, &absorb2); Unit::DealDamageMods(caster, manaPerSecond, &absorb2);
CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL); CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
Unit::DealDamage(caster, caster, manaPerSecond, &cleanDamage, SELF_DAMAGE, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), true); Unit::DealDamage(caster, caster, manaPerSecond, &cleanDamage, SELF_DAMAGE, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), true);
} }
uint32 procAttacker = PROC_FLAG_DONE_PERIODIC; uint32 procAttacker = PROC_FLAG_DONE_PERIODIC;
uint32 procVictim = PROC_FLAG_TAKEN_PERIODIC; uint32 procVictim = PROC_FLAG_TAKEN_PERIODIC;
uint32 procEx = (crit ? PROC_EX_CRITICAL_HIT : PROC_EX_NORMAL_HIT) | PROC_EX_INTERNAL_HOT; uint32 procEx = (crit ? PROC_EX_CRITICAL_HIT : PROC_EX_NORMAL_HIT) | PROC_EX_INTERNAL_HOT;
if (absorb > 0) if (healInfo.GetAbsorb() > 0)
procEx |= PROC_EX_ABSORB; procEx |= PROC_EX_ABSORB;
// ignore item heals // ignore item heals
if (!haveCastItem && GetAuraType() != SPELL_AURA_OBS_MOD_HEALTH) // xinef: dont allow obs_mod_health to proc spells, this is passive regeneration and not hot if (!haveCastItem && GetAuraType() != SPELL_AURA_OBS_MOD_HEALTH) // xinef: dont allow obs_mod_health to proc spells, this is passive regeneration and not hot
// xinef: allow null caster to proc // xinef: allow null caster to proc
caster->ProcDamageAndSpell(target, caster ? procAttacker : 0, procVictim, procEx, damage, BASE_ATTACK, GetSpellInfo(), nullptr, GetEffIndex()); caster->ProcDamageAndSpell(target, caster ? procAttacker : 0, procVictim, procEx, heal, BASE_ATTACK, GetSpellInfo(), nullptr, GetEffIndex(), nullptr, nullptr, &healInfo);
} }
void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) const void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) const
@@ -6793,7 +6815,7 @@ void AuraEffect::HandlePeriodicPowerBurnAuraTick(Unit* target, Unit* caster) con
SpellInfo const* spellProto = GetSpellInfo(); SpellInfo const* spellProto = GetSpellInfo();
// maybe has to be sent different to client, but not by SMSG_PERIODICAURALOG // maybe has to be sent different to client, but not by SMSG_PERIODICAURALOG
SpellNonMeleeDamage damageInfo(caster, target, spellProto->Id, spellProto->SchoolMask); SpellNonMeleeDamage damageInfo(caster, target, spellProto, spellProto->SchoolMask);
// no SpellDamageBonus for burn mana // no SpellDamageBonus for burn mana
caster->CalculateSpellDamageTaken(&damageInfo, int32(gain * dmgMultiplier), spellProto); caster->CalculateSpellDamageTaken(&damageInfo, int32(gain * dmgMultiplier), spellProto);
@@ -6809,7 +6831,9 @@ void AuraEffect::HandlePeriodicPowerBurnAuraTick(Unit* target, Unit* caster) con
procVictim |= PROC_FLAG_TAKEN_DAMAGE; procVictim |= PROC_FLAG_TAKEN_DAMAGE;
caster->DealSpellDamage(&damageInfo, true); caster->DealSpellDamage(&damageInfo, true);
caster->ProcDamageAndSpell(damageInfo.target, procAttacker, procVictim, procEx, damageInfo.damage, BASE_ATTACK, spellProto, nullptr, GetEffIndex());
DamageInfo dmgInfo(damageInfo, DOT);
caster->ProcDamageAndSpell(damageInfo.target, procAttacker, procVictim, procEx, damageInfo.damage, BASE_ATTACK, spellProto, nullptr, GetEffIndex(), nullptr, &dmgInfo);
} }
void AuraEffect::HandleProcTriggerSpellAuraProc(AuraApplication* aurApp, ProcEventInfo& eventInfo) void AuraEffect::HandleProcTriggerSpellAuraProc(AuraApplication* aurApp, ProcEventInfo& eventInfo)
@@ -6854,7 +6878,7 @@ void AuraEffect::HandleProcTriggerDamageAuraProc(AuraApplication* aurApp, ProcEv
{ {
Unit* target = aurApp->GetTarget(); Unit* target = aurApp->GetTarget();
Unit* triggerTarget = eventInfo.GetProcTarget(); Unit* triggerTarget = eventInfo.GetProcTarget();
SpellNonMeleeDamage damageInfo(target, triggerTarget, GetId(), GetSpellInfo()->SchoolMask); SpellNonMeleeDamage damageInfo(target, triggerTarget, GetSpellInfo(), GetSpellInfo()->SchoolMask);
uint32 damage = target->SpellDamageBonusDone(triggerTarget, GetSpellInfo(), GetAmount(), SPELL_DIRECT_DAMAGE); uint32 damage = target->SpellDamageBonusDone(triggerTarget, GetSpellInfo(), GetAmount(), SPELL_DIRECT_DAMAGE);
damage = triggerTarget->SpellDamageBonusTaken(target, GetSpellInfo(), damage, SPELL_DIRECT_DAMAGE); damage = triggerTarget->SpellDamageBonusTaken(target, GetSpellInfo(), damage, SPELL_DIRECT_DAMAGE);
target->CalculateSpellDamageTaken(&damageInfo, damage, GetSpellInfo()); target->CalculateSpellDamageTaken(&damageInfo, damage, GetSpellInfo());
+17 -7
View File
@@ -2571,6 +2571,8 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
else else
procEx |= PROC_EX_NORMAL_HIT; procEx |= PROC_EX_NORMAL_HIT;
HealInfo healInfo(caster, unitTarget, addhealth, m_spellInfo, m_spellInfo->GetSchoolMask());
// Xinef: override with forced crit, only visual result // Xinef: override with forced crit, only visual result
if (GetSpellValue()->ForcedCritResult) if (GetSpellValue()->ForcedCritResult)
{ {
@@ -2578,7 +2580,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
procEx |= PROC_EX_CRITICAL_HIT; procEx |= PROC_EX_CRITICAL_HIT;
} }
int32 gain = caster->HealBySpell(unitTarget, m_spellInfo, addhealth, crit); int32 gain = caster->HealBySpell(healInfo, crit);
unitTarget->getHostileRefMgr().threatAssist(caster, float(gain) * 0.5f, m_spellInfo); unitTarget->getHostileRefMgr().threatAssist(caster, float(gain) * 0.5f, m_spellInfo);
m_healing = gain; m_healing = gain;
@@ -2588,13 +2590,14 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
// Do triggers for unit (reflect triggers passed on hit phase for correct drop charge) // Do triggers for unit (reflect triggers passed on hit phase for correct drop charge)
if (canEffectTrigger) if (canEffectTrigger)
caster->ProcDamageAndSpell(unitTarget, procAttacker, procVictim, procEx, addhealth, m_attackType, m_spellInfo, m_triggeredByAuraSpell, m_triggeredByAuraEffectIndex, this); caster->ProcDamageAndSpell(unitTarget, procAttacker, procVictim, procEx, addhealth, m_attackType, m_spellInfo, m_triggeredByAuraSpell,
m_triggeredByAuraEffectIndex, this, nullptr, &healInfo);
} }
// Do damage and triggers // Do damage and triggers
else if (m_damage > 0) else if (m_damage > 0)
{ {
// Fill base damage struct (unitTarget - is real spell target) // Fill base damage struct (unitTarget - is real spell target)
SpellNonMeleeDamage damageInfo(caster, unitTarget, m_spellInfo->Id, m_spellSchoolMask); SpellNonMeleeDamage damageInfo(caster, unitTarget, m_spellInfo, m_spellSchoolMask);
// Add bonuses and fill damageInfo struct // Add bonuses and fill damageInfo struct
// Dancing Rune Weapon... // Dancing Rune Weapon...
@@ -2641,7 +2644,8 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
healthGain = m_caster->SpellHealingBonusDone(m_caster, m_spellInfo, healthGain, HEAL); healthGain = m_caster->SpellHealingBonusDone(m_caster, m_spellInfo, healthGain, HEAL);
healthGain = m_caster->SpellHealingBonusTaken(m_caster, m_spellInfo, healthGain, HEAL); healthGain = m_caster->SpellHealingBonusTaken(m_caster, m_spellInfo, healthGain, HEAL);
m_caster->HealBySpell(m_caster, m_spellInfo, uint32(healthGain)); HealInfo healInfo(m_caster, m_caster, healthGain, m_spellInfo, m_spellInfo->GetSchoolMask());
m_caster->HealBySpell(healInfo);
} }
} }
@@ -2662,7 +2666,10 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
// Do triggers for unit (reflect triggers passed on hit phase for correct drop charge) // Do triggers for unit (reflect triggers passed on hit phase for correct drop charge)
if (canEffectTrigger) if (canEffectTrigger)
{ {
caster->ProcDamageAndSpell(unitTarget, procAttacker, procVictim, procEx, damageInfo.damage, m_attackType, m_spellInfo, m_triggeredByAuraSpell, m_triggeredByAuraEffectIndex, this); DamageInfo dmgInfo(damageInfo, SPELL_DIRECT_DAMAGE);
caster->ProcDamageAndSpell(unitTarget, procAttacker, procVictim, procEx, damageInfo.damage, m_attackType, m_spellInfo, m_triggeredByAuraSpell,
m_triggeredByAuraEffectIndex, this, &dmgInfo);
if (caster->GetTypeId() == TYPEID_PLAYER && m_spellInfo->HasAttribute(SPELL_ATTR0_CANCELS_AUTO_ATTACK_COMBAT) == 0 && if (caster->GetTypeId() == TYPEID_PLAYER && m_spellInfo->HasAttribute(SPELL_ATTR0_CANCELS_AUTO_ATTACK_COMBAT) == 0 &&
m_spellInfo->HasAttribute(SPELL_ATTR4_SUPRESS_WEAPON_PROCS) == 0 && (m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MELEE || m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_RANGED)) m_spellInfo->HasAttribute(SPELL_ATTR4_SUPRESS_WEAPON_PROCS) == 0 && (m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MELEE || m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_RANGED))
caster->ToPlayer()->CastItemCombatSpell(unitTarget, m_attackType, procVictim, procEx); caster->ToPlayer()->CastItemCombatSpell(unitTarget, m_attackType, procVictim, procEx);
@@ -2674,12 +2681,15 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
else else
{ {
// Fill base damage struct (unitTarget - is real spell target) // Fill base damage struct (unitTarget - is real spell target)
SpellNonMeleeDamage damageInfo(caster, unitTarget, m_spellInfo->Id, m_spellSchoolMask); SpellNonMeleeDamage damageInfo(caster, unitTarget, m_spellInfo, m_spellSchoolMask);
procEx |= createProcExtendMask(&damageInfo, missInfo); procEx |= createProcExtendMask(&damageInfo, missInfo);
// Do triggers for unit (reflect triggers passed on hit phase for correct drop charge) // Do triggers for unit (reflect triggers passed on hit phase for correct drop charge)
if (canEffectTrigger) if (canEffectTrigger)
{ {
caster->ProcDamageAndSpell(unitTarget, procAttacker, procVictim, procEx, 0, m_attackType, m_spellInfo, m_triggeredByAuraSpell, m_triggeredByAuraEffectIndex, this); DamageInfo dmgInfo(damageInfo, NODAMAGE);
caster->ProcDamageAndSpell(unitTarget, procAttacker, procVictim, procEx, 0, m_attackType, m_spellInfo, m_triggeredByAuraSpell,
m_triggeredByAuraEffectIndex, this, &dmgInfo);
// Xinef: eg. rogue poisons can proc off cheap shot, etc. so this block should be here also // Xinef: eg. rogue poisons can proc off cheap shot, etc. so this block should be here also
// Xinef: ofc count only spells that HIT the target, little hack used to fool the system // Xinef: ofc count only spells that HIT the target, little hack used to fool the system
if ((procEx & PROC_EX_NORMAL_HIT || procEx & PROC_EX_CRITICAL_HIT) && caster->GetTypeId() == TYPEID_PLAYER && m_spellInfo->HasAttribute(SPELL_ATTR0_CANCELS_AUTO_ATTACK_COMBAT) == 0 && if ((procEx & PROC_EX_NORMAL_HIT || procEx & PROC_EX_CRITICAL_HIT) && caster->GetTypeId() == TYPEID_PLAYER && m_spellInfo->HasAttribute(SPELL_ATTR0_CANCELS_AUTO_ATTACK_COMBAT) == 0 &&
+14 -7
View File
@@ -302,14 +302,21 @@ void Spell::EffectEnvironmentalDMG(SpellEffIndex /*effIndex*/)
if (!unitTarget || !unitTarget->IsAlive()) if (!unitTarget || !unitTarget->IsAlive())
return; return;
uint32 absorb = 0; if (unitTarget->IsPlayer())
uint32 resist = 0;
Unit::CalcAbsorbResist(m_caster, unitTarget, m_spellInfo->GetSchoolMask(), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist, m_spellInfo);
m_caster->SendSpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage + absorb + resist, m_spellInfo->GetSchoolMask(), absorb, resist, false, 0, false);
if (unitTarget->GetTypeId() == TYPEID_PLAYER)
unitTarget->ToPlayer()->EnvironmentalDamage(DAMAGE_FIRE, damage); unitTarget->ToPlayer()->EnvironmentalDamage(DAMAGE_FIRE, damage);
else
{
DamageInfo dmgInfo(m_caster, unitTarget, damage, m_spellInfo, m_spellInfo->GetSchoolMask(), SPELL_DIRECT_DAMAGE);
uint32 absorb = dmgInfo.GetAbsorb();
uint32 resist = dmgInfo.GetResist();
uint32 envDamage = dmgInfo.GetDamage();
Unit::DealDamageMods(unitTarget, envDamage, &absorb);
damage = envDamage;
m_caster->SendSpellNonMeleeDamageLog(unitTarget, m_spellInfo, damage, m_spellInfo->GetSchoolMask(), absorb, resist, false, 0, false);
}
} }
void Spell::EffectSchoolDMG(SpellEffIndex effIndex) void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
-1
View File
@@ -3201,7 +3201,6 @@ void SpellMgr::LoadSpellCustomAttr()
spellInfo->AttributesCu |= SPELL_ATTR0_CU_IGNORE_ARMOR; spellInfo->AttributesCu |= SPELL_ATTR0_CU_IGNORE_ARMOR;
break; break;
case 64422: // Sonic Screech (Auriaya) case 64422: // Sonic Screech (Auriaya)
case 13877: // Blade Flurry (Rogue Spell) should ignore armor and share damage to 2nd mob
spellInfo->AttributesCu |= SPELL_ATTR0_CU_SHARE_DAMAGE; spellInfo->AttributesCu |= SPELL_ATTR0_CU_SHARE_DAMAGE;
spellInfo->AttributesCu |= SPELL_ATTR0_CU_IGNORE_ARMOR; spellInfo->AttributesCu |= SPELL_ATTR0_CU_IGNORE_ARMOR;
break; break;
@@ -850,10 +850,15 @@ public:
uint32 resist = 0; uint32 resist = 0;
CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL); CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
int32 dmg = urand(2925, 3075) * (caster->GetMap()->GetDifficulty() - 1); int32 dmg = urand(2925, 3075) * (caster->GetMap()->GetDifficulty() - 1);
uint32 damage = dmg;
int32 resilienceReduction = damage;
if (caster->CanApplyResilience()) if (caster->CanApplyResilience())
Unit::ApplyResilience(plr, nullptr, &dmg, false, CR_CRIT_TAKEN_SPELL); Unit::ApplyResilience(plr, nullptr, &dmg, false, CR_CRIT_TAKEN_SPELL);
uint32 damage = dmg; resilienceReduction = damage - resilienceReduction;
Unit::CalcAbsorbResist(caster, plr, GetSpellInfo()->GetSchoolMask(), DOT, damage, &absorb, &resist, GetSpellInfo()); damage -= resilienceReduction;
uint32 mitigated_damage = resilienceReduction;
DamageInfo dmgInfo(caster, plr, damage, GetSpellInfo(), GetSpellInfo()->GetSchoolMask(), DOT, mitigated_damage);
Unit::CalcAbsorbResist(dmgInfo);
Unit::DealDamageMods(plr, damage, &absorb); Unit::DealDamageMods(plr, damage, &absorb);
int32 overkill = damage - plr->GetHealth(); int32 overkill = damage - plr->GetHealth();
if (overkill < 0) if (overkill < 0)
@@ -855,7 +855,7 @@ public:
uint32 damage = uint32( (GetEffectValue() / _targetCount) * (1.0f - ResistFactor) ); uint32 damage = uint32( (GetEffectValue() / _targetCount) * (1.0f - ResistFactor) );
SpellNonMeleeDamage damageInfo(GetCaster(), GetHitUnit(), GetSpellInfo()->Id, GetSpellInfo()->SchoolMask); SpellNonMeleeDamage damageInfo(GetCaster(), GetHitUnit(), GetSpellInfo(), GetSpellInfo()->SchoolMask);
damageInfo.damage = damage; damageInfo.damage = damage;
GetCaster()->SendSpellNonMeleeDamageLog(&damageInfo); GetCaster()->SendSpellNonMeleeDamageLog(&damageInfo);
GetCaster()->DealSpellDamage(&damageInfo, false); GetCaster()->DealSpellDamage(&damageInfo, false);
+1 -1
View File
@@ -414,7 +414,7 @@ public:
bool CheckProc(ProcEventInfo& eventInfo) bool CheckProc(ProcEventInfo& eventInfo)
{ {
SpellInfo const* spellInfo = eventInfo.GetDamageInfo()->GetSpellInfo(); SpellInfo const* spellInfo = eventInfo.GetSpellInfo();
if (!spellInfo) if (!spellInfo)
return false; return false;
+1 -3
View File
@@ -146,9 +146,7 @@ public:
Unit* procTarget = ObjectAccessor::GetUnit(*GetTarget(), _procTargetGUID); Unit* procTarget = ObjectAccessor::GetUnit(*GetTarget(), _procTargetGUID);
if (procTarget && eventInfo.GetDamageInfo()) if (procTarget && eventInfo.GetDamageInfo())
{ {
int32 damage = eventInfo.GetDamageInfo()->GetDamage(); int32 damage = eventInfo.GetDamageInfo()->GetUnmitigatedDamage();
// Xinef: Include AOE Damage Reduction auras
damage = procTarget->CalculateAOEDamageReduction(damage, SPELL_SCHOOL_MASK_NORMAL, GetTarget());
CustomSpellValues values; CustomSpellValues values;
values.AddSpellMod(SPELLVALUE_BASE_POINT0, damage); values.AddSpellMod(SPELLVALUE_BASE_POINT0, damage);
+5 -2
View File
@@ -818,8 +818,11 @@ public:
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{ {
PreventDefaultAction(); PreventDefaultAction();
int32 damage = eventInfo.GetDamageInfo()->GetDamage(); if (eventInfo.GetDamageInfo())
GetTarget()->CastCustomSpell(_procTarget, SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK, &damage, 0, 0, true, nullptr, aurEff); {
int32 damage = eventInfo.GetDamageInfo()->GetUnmitigatedDamage();
GetTarget()->CastCustomSpell(_procTarget, SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK, &damage, 0, 0, true, nullptr, aurEff);
}
} }
void Register() override void Register() override