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
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 283 additions and 169 deletions

View file

@ -784,12 +784,21 @@ uint32 Player::EnvironmentalDamage(EnviromentalDamage type, uint32 damage)
// Absorb, resist some environmental damage type
uint32 absorb = 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);

View file

@ -109,21 +109,28 @@ static bool isAlwaysTriggeredAura[TOTAL_AURAS];
// Prepare lists
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_damageType(_damageType), m_attackType(BASE_ATTACK)
m_damageType(_damageType), m_attackType(BASE_ATTACK), m_cleanDamage(cleanDamage)
{
m_absorb = 0;
m_resist = 0;
m_block = 0;
}
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_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)
@ -153,6 +160,11 @@ void DamageInfo::BlockDamage(uint32 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)
: _actor(actor), _actionTarget(actionTarget), _procTarget(procTarget), _typeMask(typeMask), _spellTypeMask(spellTypeMask), _spellPhaseMask(spellPhaseMask),
_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
{
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::CalcAbsorbResist(attacker, shareDamageTarget, damageSchoolMask, damagetype, shareDamage, &shareAbsorb, &shareResist, spellProto, true);
shareDamage -= std::min(shareAbsorb, shareDamage);
}
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);
}
@ -1180,8 +1195,16 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama
SpellSchoolMask damageSchoolMask = SpellSchoolMask(damageInfo->schoolMask);
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))
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;
// Per-school calc
@ -1203,11 +1226,11 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama
damageInfo->HitInfo |= SPELL_HIT_TYPE_CRIT;
// Calculate crit bonus
uint32 crit_bonus = damage;
uint32 crit_bonus = damageInfo->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;
damageInfo->damage += crit_bonus;
// Apply SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE or SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE
float critPctDamageMod = 0.0f;
@ -1223,7 +1246,7 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama
critPctDamageMod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, crTypeMask);
if (critPctDamageMod != 0)
AddPct(damage, critPctDamageMod);
AddPct(damageInfo->damage, critPctDamageMod);
}
// 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();
// double blocked amount if block is critical
if (victim->isBlockCritical())
damageInfo->blocked += damageInfo->blocked;
damageInfo->blocked *= 2;
if (damage < int32(damageInfo->blocked))
damageInfo->blocked = uint32(damage);
damage -= damageInfo->blocked;
damageInfo->damage -= damageInfo->blocked;
damageInfo->cleanDamage += damageInfo->blocked;
}
int32 resilienceReduction = damageInfo->damage;
if (CanApplyResilience())
{
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
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;
}
// Magical Attacks
@ -1255,30 +1285,33 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama
if (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())
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;
}
default:
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
if (damage > 0)
if (int32(damageInfo->damage) > 0)
{
Unit::CalcAbsorbResist(this, victim, damageSchoolMask, SPELL_DIRECT_DAMAGE, damage, &damageInfo->absorb, &damageInfo->resist, spellInfo);
damage -= damageInfo->absorb + damageInfo->resist;
DamageInfo dmgInfo(*damageInfo, SPELL_DIRECT_DAMAGE);
Unit::CalcAbsorbResist(dmgInfo);
damageInfo->absorb = dmgInfo.GetAbsorb();
damageInfo->resist = dmgInfo.GetResist();
damage = dmgInfo.GetDamage();
}
else
damage = 0;
damageInfo->damage = std::max(damage, 0);
damageInfo->damage = 0;
}
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()))
return;
SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(damageInfo->SpellID);
if (spellProto == nullptr)
SpellInfo const* spellProto = damageInfo->spellInfo;
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;
}
@ -1504,7 +1537,11 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
{
damageInfo->procVictim |= PROC_FLAG_TAKEN_DAMAGE;
// 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)
{
@ -1515,7 +1552,7 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
if (damageInfo->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....
damageInfo->damage = 0;
@ -1628,9 +1665,11 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
damage = this->SpellDamageBonusTaken(caster, i_spellProto, damage, SPELL_DIRECT_DAMAGE);
uint32 absorb = 0;
uint32 resist = 0;
Unit::CalcAbsorbResist(victim, this, i_spellProto->GetSchoolMask(), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist, i_spellProto);
damage -= absorb + resist;
DamageInfo dmgInfo(victim, this, damage, i_spellProto, i_spellProto->GetSchoolMask(), SPELL_DIRECT_DAMAGE);
Unit::CalcAbsorbResist(dmgInfo);
absorb = dmgInfo.GetAbsorb();
damage = dmgInfo.GetDamage();
Unit::DealDamageMods(this, damage, &absorb);
@ -1804,13 +1843,17 @@ float Unit::GetEffectiveResistChance(Unit const* owner, SpellSchoolMask schoolMa
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)
return;
DamageInfo dmgInfo = DamageInfo(attacker, victim, damage, spellInfo, schoolMask, damagetype);
// Magic damage, check for resists
// Ignore spells that cant be resisted
// Xinef: holy resistance exists for npcs
@ -2043,25 +2086,28 @@ void Unit::CalcAbsorbResist(Unit* attacker, Unit* victim, SpellSchoolMask school
uint32 splitted_resist = 0;
uint32 procAttacker = 0, procVictim = 0, procEx = PROC_EX_NORMAL_HIT;
DamageInfo splittedDmgInfo(attacker, caster, splitted, spellInfo, schoolMask, dmgInfo.GetDamageType());
if (caster->IsImmunedToDamageOrSchool(schoolMask))
{
procEx |= PROC_EX_IMMUNE;
splitted_absorb = splitted;
splitted = 0;
splittedDmgInfo.AbsorbDamage(splitted);
}
else
{
Unit::CalcAbsorbResist(splittedDmgInfo, true);
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
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)
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);
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 procAttacker = 0, procVictim = 0, procEx = PROC_EX_NORMAL_HIT;
DamageInfo splittedDmgInfo(attacker, caster, splitted, spellInfo, splitSchoolMask, dmgInfo.GetDamageType());
if (caster->IsImmunedToDamageOrSchool(schoolMask))
{
procEx |= PROC_EX_IMMUNE;
splitted_absorb = splitted;
splitted = 0;
splittedDmgInfo.AbsorbDamage(splitted);
}
else
{
Unit::CalcAbsorbResist(splittedDmgInfo, true);
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
createProcFlags(spellInfo, BASE_ATTACK, false, procAttacker, procVictim);
caster->ProcDamageAndSpellFor(true, attacker, procVictim, procEx, BASE_ATTACK, spellInfo, splitted);
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);
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;
int32 RemainingHeal = healAmount;
int32 const healing = static_cast<int32>(healInfo.GetHeal());
int32 absorbAmount = 0;
// Need remove expired auras after
bool existExpired = false;
// absorb without mana cost
AuraEffectList const& vHealAbsorb = victim->GetAuraEffectsByType(SPELL_AURA_SCHOOL_HEAL_ABSORB);
for (AuraEffectList::const_iterator i = vHealAbsorb.begin(); i != vHealAbsorb.end() && RemainingHeal > 0; ++i)
AuraEffectList const& vHealAbsorb = healInfo.GetTarget()->GetAuraEffectsByType(SPELL_AURA_SCHOOL_HEAL_ABSORB);
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;
// 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
// If need absorb less damage
if (RemainingHeal < currentAbsorb)
currentAbsorb = RemainingHeal;
if (healing < currentAbsorb + absorbAmount)
currentAbsorb = healing - absorbAmount;
RemainingHeal -= currentAbsorb;
absorbAmount += currentAbsorb;
// Reduce shield amount
(*i)->SetAmount((*i)->GetAmount() - currentAbsorb);
@ -2190,16 +2237,16 @@ void Unit::CalcHealAbsorb(Unit const* victim, const SpellInfo* healSpell, uint32
++i;
if (auraEff->GetAmount() <= 0)
{
uint32 removedAuras = victim->m_removedAurasCount;
uint32 removedAuras = healInfo.GetTarget()->m_removedAurasCount;
auraEff->GetBase()->Remove(AURA_REMOVE_BY_ENEMY_SPELL);
if (removedAuras + 1 < victim->m_removedAurasCount)
if (removedAuras + 1 < healInfo.GetTarget()->m_removedAurasCount)
i = vHealAbsorb.begin();
}
}
}
absorb = RemainingHeal > 0 ? (healAmount - RemainingHeal) : healAmount;
healAmount = RemainingHeal;
if (absorbAmount > 0)
healInfo.AbsorbHeal(absorbAmount);
}
void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType, bool extra)
@ -2239,7 +2286,10 @@ void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType, bool extr
//TriggerAurasProcOnEvent(damageInfo);
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)
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 << attacker->GetPackGUID();
data << uint32(log->SpellID);
data << uint32(log->spellInfo->Id);
data << uint32(damage); // damage amount
int32 overkill = damage - log->target->GetHealth();
data << uint32(overkill > 0 ? overkill : 0); // overkill
@ -5655,7 +5705,7 @@ void Unit::SendSpellNonMeleeDamageLog(SpellNonMeleeDamage* log)
}
data << log->target->GetPackGUID();
data << log->attacker->GetPackGUID();
data << uint32(log->SpellID);
data << uint32(log->spellInfo->Id);
data << uint32(damage); // damage amount
int32 overkill = damage - log->target->GetHealth();
data << uint32(overkill > 0 ? overkill : 0); // overkill
@ -5670,10 +5720,10 @@ void Unit::SendSpellNonMeleeDamageLog(SpellNonMeleeDamage* log)
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);
log.damage = Damage - AbsorbedDamage - Resist - Blocked;
SpellNonMeleeDamage log(this, target, spellInfo, damageSchoolMask);
log.damage = Damage;
log.absorb = AbsorbedDamage;
log.resist = Resist;
log.physicalLog = PhysicalDamage;
@ -5684,15 +5734,15 @@ void Unit::SendSpellNonMeleeDamageLog(Unit* target, uint32 SpellID, uint32 Damag
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.
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
// Not much to do if no flags are set or there is no victim
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)
@ -10508,16 +10558,17 @@ void Unit::SendHealSpellLog(Unit* victim, uint32 SpellID, uint32 Damage, uint32
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
CalcHealAbsorb(victim, spellInfo, addHealth, absorb);
CalcHealAbsorb(healInfo);
sScriptMgr->ModifyHealRecieved(this, victim, addHealth);
int32 gain = Unit::DealHeal(this, victim, addHealth);
SendHealSpellLog(victim, spellInfo->Id, addHealth, uint32(addHealth - gain), absorb, critical);
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);
return gain;
}
@ -15302,7 +15353,7 @@ uint32 createProcExtendMask(SpellNonMeleeDamage* damageInfo, SpellMissInfo missC
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
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* actionTarget = !isVictim ? target : this;
DamageInfo damageInfo = DamageInfo(actor, actionTarget, damage, procSpellInfo, procSpellInfo ? SpellSchoolMask(procSpellInfo->SchoolMask) : SPELL_SCHOOL_MASK_NORMAL, SPELL_DIRECT_DAMAGE);
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);
ProcEventInfo eventInfo = ProcEventInfo(actor, actionTarget, target, procFlag, 0, 0, procExtra, procSpell, damageInfo, healInfo, procAura, procAuraEffectIndex);
ProcTriggeredList procTriggered;
// Fill procTriggered list

View file

@ -893,6 +893,7 @@ struct CleanDamage
};
struct CalcDamageInfo;
struct SpellNonMeleeDamage;
class DamageInfo
{
@ -907,9 +908,11 @@ private:
uint32 m_absorb;
uint32 m_resist;
uint32 m_block;
uint32 m_cleanDamage;
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);
DamageInfo(SpellNonMeleeDamage const& spellNonMeleeDamage, DamageEffectType damageType);
void ModifyDamage(int32 amount);
void AbsorbDamage(uint32 amount);
@ -926,6 +929,8 @@ public:
[[nodiscard]] uint32 GetAbsorb() const { return m_absorb; };
[[nodiscard]] uint32 GetResist() const { return m_resist; };
[[nodiscard]] uint32 GetBlock() const { return m_block; };
[[nodiscard]] uint32 GetUnmitigatedDamage() const;
};
class HealInfo
@ -950,6 +955,11 @@ public:
m_heal -= amount;
}
void SetHeal(uint32 amount)
{
m_heal = amount;
}
[[nodiscard]] Unit* GetHealer() const { return m_healer; }
[[nodiscard]] Unit* GetTarget() const { return m_target; }
[[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
struct SpellNonMeleeDamage
{
SpellNonMeleeDamage(Unit* _attacker, Unit* _target, uint32 _SpellID, uint32 _schoolMask)
: target(_target), attacker(_attacker), SpellID(_SpellID), damage(0), overkill(0), schoolMask(_schoolMask),
SpellNonMeleeDamage(Unit* _attacker, Unit* _target, SpellInfo const* _spellInfo, uint32 _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)
{}
Unit* target;
Unit* attacker;
uint32 SpellID;
Unit* target;
Unit* attacker;
SpellInfo const* spellInfo;
uint32 damage;
uint32 overkill;
uint32 schoolMask;
uint32 absorb;
uint32 resist;
bool physicalLog;
bool unused;
bool physicalLog;
bool unused;
uint32 blocked;
uint32 HitInfo;
// 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 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 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 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, DamageInfo* damageInfo = nullptr, HealInfo* healInfo = nullptr);
void GetProcAurasTriggeredOnEvent(std::list<AuraApplication*>& aurasTriggeringProc, std::list<AuraApplication*>* procAuras, ProcEventInfo eventInfo);
void TriggerAurasProcOnEvent(CalcDamageInfo& damageInfo);
@ -1791,7 +1801,7 @@ public:
bool isInAccessiblePlaceFor(Creature const* c) const;
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 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 SendSpellNonMeleeDamageLog(SpellNonMeleeDamage* log);
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 SendSpellMiss(Unit* target, uint32 spellID, SpellMissInfo missInfo);
void SendSpellDamageResist(Unit* target, uint32 spellId);
@ -2307,8 +2317,8 @@ public:
// redefined in Creature
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 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 CalcHealAbsorb(Unit const* victim, const SpellInfo* spellProto, uint32& healAmount, uint32& absorb);
static void CalcAbsorbResist(DamageInfo& dmgInfo, bool Splited = false);
static void CalcHealAbsorb(HealInfo& healInfo);
void UpdateSpeed(UnitMoveType mtype, bool forced);
[[nodiscard]] float GetSpeed(UnitMoveType mtype) const;

View file

@ -5933,7 +5933,8 @@ void AuraEffect::HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster)
if (caster)
{
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))
{
@ -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);
// 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())))
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
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);
}
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
uint32 procAttacker = PROC_FLAG_DONE_PERIODIC;
uint32 procVictim = PROC_FLAG_TAKEN_PERIODIC;
@ -6357,7 +6366,6 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
if (absorb > 0)
procEx |= PROC_EX_ABSORB;
damage = (damage <= absorb + resist) ? 0 : (damage - absorb - resist);
if (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);
// 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
@ -6388,8 +6396,6 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
caster->SpellHitResult(target, GetSpellInfo(), false) != SPELL_MISS_NONE)
return;
uint32 absorb = 0;
uint32 resist = 0;
CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
uint32 damage = std::max(GetAmount(), 0);
@ -6413,12 +6419,22 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
damage = damageReductedArmor;
}
int32 dmg = damage;
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
uint32 procAttacker = PROC_FLAG_DONE_PERIODIC;
@ -6427,23 +6443,26 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
if (absorb > 0)
procEx |= PROC_EX_ABSORB;
damage = (damage <= absorb + resist) ? 0 : (damage - absorb - resist);
if (damage)
if (dmgInfo.GetDamage())
procVictim |= PROC_FLAG_TAKEN_DAMAGE;
if (target->GetHealth() < damage)
damage = target->GetHealth();
if (target->GetHealth() < dmgInfo.GetDamage())
{
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",
GetCasterGUID().ToString().c_str(), target->GetGUID().ToString().c_str(), damage, GetId(), absorb);
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;
new_damage = Unit::DealDamage(caster, target, damage, &cleanDamage, DOT, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), false);
// 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())
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()));
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());
}
@ -6482,7 +6502,8 @@ void AuraEffect::HandlePeriodicHealthFunnelAuraTick(Unit* target, Unit* caster)
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
@ -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",
GetCasterGUID().ToString().c_str(), target->GetGUID().ToString().c_str(), damage, GetId());
uint32 absorb = 0;
uint32 heal = uint32(damage);
// Script Hook For HandlePeriodicDamageAurasTick -- Allow scripts to change the Damage pre class mitigation calculations
sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, heal);
Unit::CalcHealAbsorb(target, GetSpellInfo(), heal, absorb);
int32 gain = Unit::DealHeal(caster, target, heal);
HealInfo healInfo(caster, target, heal, GetSpellInfo(), GetSpellInfo()->GetSchoolMask());
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);
if (caster)
@ -6610,20 +6632,20 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const
uint32 absorb2 = 0;
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);
}
uint32 procAttacker = PROC_FLAG_DONE_PERIODIC;
uint32 procVictim = PROC_FLAG_TAKEN_PERIODIC;
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;
// 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
// 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
@ -6793,7 +6815,7 @@ void AuraEffect::HandlePeriodicPowerBurnAuraTick(Unit* target, Unit* caster) con
SpellInfo const* spellProto = GetSpellInfo();
// 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
caster->CalculateSpellDamageTaken(&damageInfo, int32(gain * dmgMultiplier), spellProto);
@ -6809,7 +6831,9 @@ void AuraEffect::HandlePeriodicPowerBurnAuraTick(Unit* target, Unit* caster) con
procVictim |= PROC_FLAG_TAKEN_DAMAGE;
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)
@ -6854,7 +6878,7 @@ void AuraEffect::HandleProcTriggerDamageAuraProc(AuraApplication* aurApp, ProcEv
{
Unit* target = aurApp->GetTarget();
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);
damage = triggerTarget->SpellDamageBonusTaken(target, GetSpellInfo(), damage, SPELL_DIRECT_DAMAGE);
target->CalculateSpellDamageTaken(&damageInfo, damage, GetSpellInfo());

View file

@ -2571,6 +2571,8 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
else
procEx |= PROC_EX_NORMAL_HIT;
HealInfo healInfo(caster, unitTarget, addhealth, m_spellInfo, m_spellInfo->GetSchoolMask());
// Xinef: override with forced crit, only visual result
if (GetSpellValue()->ForcedCritResult)
{
@ -2578,7 +2580,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
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);
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)
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
else if (m_damage > 0)
{
// 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
// 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->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)
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 &&
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);
@ -2674,12 +2681,15 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
else
{
// 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);
// Do triggers for unit (reflect triggers passed on hit phase for correct drop charge)
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: 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 &&

View file

@ -302,14 +302,21 @@ void Spell::EffectEnvironmentalDMG(SpellEffIndex /*effIndex*/)
if (!unitTarget || !unitTarget->IsAlive())
return;
uint32 absorb = 0;
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)
if (unitTarget->IsPlayer())
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)

View file

@ -3201,7 +3201,6 @@ void SpellMgr::LoadSpellCustomAttr()
spellInfo->AttributesCu |= SPELL_ATTR0_CU_IGNORE_ARMOR;
break;
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_IGNORE_ARMOR;
break;

View file

@ -850,10 +850,15 @@ public:
uint32 resist = 0;
CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
int32 dmg = urand(2925, 3075) * (caster->GetMap()->GetDifficulty() - 1);
uint32 damage = dmg;
int32 resilienceReduction = damage;
if (caster->CanApplyResilience())
Unit::ApplyResilience(plr, nullptr, &dmg, false, CR_CRIT_TAKEN_SPELL);
uint32 damage = dmg;
Unit::CalcAbsorbResist(caster, plr, GetSpellInfo()->GetSchoolMask(), DOT, damage, &absorb, &resist, GetSpellInfo());
resilienceReduction = damage - resilienceReduction;
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);
int32 overkill = damage - plr->GetHealth();
if (overkill < 0)

View file

@ -855,7 +855,7 @@ public:
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;
GetCaster()->SendSpellNonMeleeDamageLog(&damageInfo);
GetCaster()->DealSpellDamage(&damageInfo, false);

View file

@ -414,7 +414,7 @@ public:
bool CheckProc(ProcEventInfo& eventInfo)
{
SpellInfo const* spellInfo = eventInfo.GetDamageInfo()->GetSpellInfo();
SpellInfo const* spellInfo = eventInfo.GetSpellInfo();
if (!spellInfo)
return false;

View file

@ -146,9 +146,7 @@ public:
Unit* procTarget = ObjectAccessor::GetUnit(*GetTarget(), _procTargetGUID);
if (procTarget && eventInfo.GetDamageInfo())
{
int32 damage = eventInfo.GetDamageInfo()->GetDamage();
// Xinef: Include AOE Damage Reduction auras
damage = procTarget->CalculateAOEDamageReduction(damage, SPELL_SCHOOL_MASK_NORMAL, GetTarget());
int32 damage = eventInfo.GetDamageInfo()->GetUnmitigatedDamage();
CustomSpellValues values;
values.AddSpellMod(SPELLVALUE_BASE_POINT0, damage);

View file

@ -818,8 +818,11 @@ public:
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
int32 damage = eventInfo.GetDamageInfo()->GetDamage();
GetTarget()->CastCustomSpell(_procTarget, SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK, &damage, 0, 0, true, nullptr, aurEff);
if (eventInfo.GetDamageInfo())
{
int32 damage = eventInfo.GetDamageInfo()->GetUnmitigatedDamage();
GetTarget()->CastCustomSpell(_procTarget, SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK, &damage, 0, 0, true, nullptr, aurEff);
}
}
void Register() override