mirror of
https://github.com/araxiaonline/TrinityCore.git
synced 2026-06-21 15:27:47 -04:00
Core/Spells: use DamageInfo struct to calc spell absorbs and resists, and use calculated proc hitMask on aura ticks
Closes #18135
This commit is contained in:
@@ -939,12 +939,21 @@ uint32 Player::EnvironmentalDamage(EnviromentalDamage type, uint32 damage)
|
||||
// Absorb, resist some environmental damage type
|
||||
uint32 absorb = 0;
|
||||
uint32 resist = 0;
|
||||
if (type == DAMAGE_LAVA)
|
||||
CalcAbsorbResist(this, SPELL_SCHOOL_MASK_FIRE, DIRECT_DAMAGE, damage, &absorb, &resist);
|
||||
else if (type == DAMAGE_SLIME)
|
||||
CalcAbsorbResist(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, BASE_ATTACK);
|
||||
CalcAbsorbResist(dmgInfo);
|
||||
absorb = dmgInfo.GetAbsorb();
|
||||
resist = dmgInfo.GetResist();
|
||||
damage = dmgInfo.GetDamage();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
DealDamageMods(this, damage, &absorb);
|
||||
|
||||
|
||||
@@ -646,7 +646,7 @@ bool Unit::HasBreakableByDamageCrowdControlAura(Unit* excludeCasterChannel) cons
|
||||
|| HasBreakableByDamageAuraType(SPELL_AURA_TRANSFORM, excludeAura));
|
||||
}
|
||||
|
||||
void Unit::DealDamageMods(Unit* victim, uint32 &damage, uint32* absorb)
|
||||
void Unit::DealDamageMods(Unit const* victim, uint32 &damage, uint32* absorb) const
|
||||
{
|
||||
if (!victim || !victim->IsAlive() || victim->HasUnitState(UNIT_STATE_IN_FLIGHT) || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks()))
|
||||
{
|
||||
@@ -1155,7 +1155,7 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama
|
||||
ApplyResilience(victim, nullptr, &damage, crit, CR_CRIT_TAKEN_RANGED);
|
||||
break;
|
||||
}
|
||||
// Magical Attacks
|
||||
// Magical Attacks
|
||||
case SPELL_DAMAGE_CLASS_NONE:
|
||||
case SPELL_DAMAGE_CLASS_MAGIC:
|
||||
{
|
||||
@@ -1178,15 +1178,13 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama
|
||||
sScriptMgr->ModifySpellDamageTaken(damageInfo->target, damageInfo->attacker, damage);
|
||||
|
||||
// Calculate absorb resist
|
||||
if (damage > 0)
|
||||
{
|
||||
CalcAbsorbResist(victim, damageSchoolMask, SPELL_DIRECT_DAMAGE, damage, &damageInfo->absorb, &damageInfo->resist, spellInfo);
|
||||
damage -= damageInfo->absorb + damageInfo->resist;
|
||||
}
|
||||
else
|
||||
if (damage < 0)
|
||||
damage = 0;
|
||||
|
||||
damageInfo->damage = damage;
|
||||
DamageInfo dmgInfo(*damageInfo, SPELL_DIRECT_DAMAGE, BASE_ATTACK, PROC_HIT_NONE);
|
||||
CalcAbsorbResist(dmgInfo);
|
||||
damageInfo->damage = dmgInfo.GetDamage();
|
||||
}
|
||||
|
||||
void Unit::DealSpellDamage(SpellNonMeleeDamage* damageInfo, bool durabilityLoss)
|
||||
@@ -1396,15 +1394,17 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
|
||||
{
|
||||
damageInfo->procVictim |= PROC_FLAG_TAKEN_DAMAGE;
|
||||
// Calculate absorb & resists
|
||||
CalcAbsorbResist(damageInfo->target, SpellSchoolMask(damageInfo->damageSchoolMask), DIRECT_DAMAGE, damageInfo->damage, &damageInfo->absorb, &damageInfo->resist);
|
||||
DamageInfo dmgInfo(*damageInfo);
|
||||
CalcAbsorbResist(dmgInfo);
|
||||
damageInfo->absorb = dmgInfo.GetAbsorb();
|
||||
damageInfo->resist = dmgInfo.GetResist();
|
||||
damageInfo->damage = dmgInfo.GetDamage();
|
||||
|
||||
if (damageInfo->absorb)
|
||||
damageInfo->HitInfo |= (damageInfo->damage - damageInfo->absorb == 0 ? HITINFO_FULL_ABSORB : HITINFO_PARTIAL_ABSORB);
|
||||
|
||||
if (damageInfo->resist)
|
||||
damageInfo->HitInfo |= (damageInfo->damage - damageInfo->resist == 0 ? HITINFO_FULL_RESIST : HITINFO_PARTIAL_RESIST);
|
||||
|
||||
damageInfo->damage -= damageInfo->absorb + damageInfo->resist;
|
||||
}
|
||||
else // Impossible get negative result but....
|
||||
damageInfo->damage = 0;
|
||||
@@ -1731,57 +1731,49 @@ uint32 Unit::CalcSpellResistance(Unit* victim, SpellSchoolMask schoolMask, Spell
|
||||
return resistance * 10;
|
||||
}
|
||||
|
||||
void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffectType damagetype, uint32 const damage, uint32* absorb, uint32* resist, SpellInfo const* spellInfo /*= NULL*/)
|
||||
void Unit::CalcAbsorbResist(DamageInfo& damageInfo)
|
||||
{
|
||||
if (!victim || !victim->IsAlive() || !damage)
|
||||
if (!damageInfo.GetVictim() || !damageInfo.GetVictim()->IsAlive() || !damageInfo.GetDamage())
|
||||
return;
|
||||
|
||||
DamageInfo dmgInfo = DamageInfo(this, victim, damage, spellInfo, schoolMask, damagetype, BASE_ATTACK);
|
||||
|
||||
uint32 spellResistance = CalcSpellResistance(victim, schoolMask, spellInfo);
|
||||
dmgInfo.ResistDamage(CalculatePct(damage, spellResistance));
|
||||
uint32 spellResistance = CalcSpellResistance(damageInfo.GetVictim(), damageInfo.GetSchoolMask(), damageInfo.GetSpellInfo());
|
||||
damageInfo.ResistDamage(CalculatePct(damageInfo.GetDamage(), spellResistance));
|
||||
|
||||
// Ignore Absorption Auras
|
||||
float auraAbsorbMod = 0;
|
||||
AuraEffectList const& AbsIgnoreAurasA = GetAuraEffectsByType(SPELL_AURA_MOD_TARGET_ABSORB_SCHOOL);
|
||||
for (AuraEffectList::const_iterator itr = AbsIgnoreAurasA.begin(); itr != AbsIgnoreAurasA.end(); ++itr)
|
||||
float auraAbsorbMod(GetMaxPositiveAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_ABSORB_SCHOOL, damageInfo.GetSchoolMask()));
|
||||
|
||||
AuraEffectList const& abilityAbsorbAuras = GetAuraEffectsByType(SPELL_AURA_MOD_TARGET_ABILITY_ABSORB_SCHOOL);
|
||||
for (AuraEffect const* aurEff : abilityAbsorbAuras)
|
||||
{
|
||||
if (!((*itr)->GetMiscValue() & schoolMask))
|
||||
if (!(aurEff->GetMiscValue() & damageInfo.GetSchoolMask()))
|
||||
continue;
|
||||
|
||||
if ((*itr)->GetAmount() > auraAbsorbMod)
|
||||
auraAbsorbMod = float((*itr)->GetAmount());
|
||||
}
|
||||
|
||||
AuraEffectList const& AbsIgnoreAurasB = GetAuraEffectsByType(SPELL_AURA_MOD_TARGET_ABILITY_ABSORB_SCHOOL);
|
||||
for (AuraEffectList::const_iterator itr = AbsIgnoreAurasB.begin(); itr != AbsIgnoreAurasB.end(); ++itr)
|
||||
{
|
||||
if (!((*itr)->GetMiscValue() & schoolMask))
|
||||
if (!aurEff->IsAffectedOnSpell(damageInfo.GetSpellInfo()))
|
||||
continue;
|
||||
|
||||
if (((*itr)->GetAmount() > auraAbsorbMod) && (*itr)->IsAffectedOnSpell(spellInfo))
|
||||
auraAbsorbMod = float((*itr)->GetAmount());
|
||||
if ((aurEff->GetAmount() > auraAbsorbMod))
|
||||
auraAbsorbMod = float(aurEff->GetAmount());
|
||||
}
|
||||
|
||||
RoundToInterval(auraAbsorbMod, 0.0f, 100.0f);
|
||||
|
||||
int32 absorbIgnoringDamage = CalculatePct(dmgInfo.GetDamage(), auraAbsorbMod);
|
||||
dmgInfo.ModifyDamage(-absorbIgnoringDamage);
|
||||
int32 absorbIgnoringDamage = CalculatePct(damageInfo.GetDamage(), auraAbsorbMod);
|
||||
damageInfo.ModifyDamage(-absorbIgnoringDamage);
|
||||
|
||||
// We're going to call functions which can modify content of the list during iteration over it's elements
|
||||
// Let's copy the list so we can prevent iterator invalidation
|
||||
AuraEffectList vSchoolAbsorbCopy(victim->GetAuraEffectsByType(SPELL_AURA_SCHOOL_ABSORB));
|
||||
AuraEffectList vSchoolAbsorbCopy(damageInfo.GetVictim()->GetAuraEffectsByType(SPELL_AURA_SCHOOL_ABSORB));
|
||||
vSchoolAbsorbCopy.sort(Trinity::AbsorbAuraOrderPred());
|
||||
|
||||
// absorb without mana cost
|
||||
for (AuraEffectList::iterator itr = vSchoolAbsorbCopy.begin(); (itr != vSchoolAbsorbCopy.end()) && (dmgInfo.GetDamage() > 0); ++itr)
|
||||
for (AuraEffectList::iterator itr = vSchoolAbsorbCopy.begin(); (itr != vSchoolAbsorbCopy.end()) && (damageInfo.GetDamage() > 0); ++itr)
|
||||
{
|
||||
AuraEffect* absorbAurEff = *itr;
|
||||
// Check if aura was removed during iteration - we don't need to work on such auras
|
||||
AuraApplication const* aurApp = absorbAurEff->GetBase()->GetApplicationOfTarget(victim->GetGUID());
|
||||
AuraApplication const* aurApp = absorbAurEff->GetBase()->GetApplicationOfTarget(damageInfo.GetVictim()->GetGUID());
|
||||
if (!aurApp)
|
||||
continue;
|
||||
if (!(absorbAurEff->GetMiscValue() & schoolMask))
|
||||
if (!(absorbAurEff->GetMiscValue() & damageInfo.GetSchoolMask()))
|
||||
continue;
|
||||
|
||||
// get amount which can be still absorbed by the aura
|
||||
@@ -1794,19 +1786,19 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe
|
||||
|
||||
bool defaultPrevented = false;
|
||||
|
||||
absorbAurEff->GetBase()->CallScriptEffectAbsorbHandlers(absorbAurEff, aurApp, dmgInfo, tempAbsorb, defaultPrevented);
|
||||
absorbAurEff->GetBase()->CallScriptEffectAbsorbHandlers(absorbAurEff, aurApp, damageInfo, tempAbsorb, defaultPrevented);
|
||||
currentAbsorb = tempAbsorb;
|
||||
|
||||
if (defaultPrevented)
|
||||
continue;
|
||||
|
||||
// absorb must be smaller than the damage itself
|
||||
currentAbsorb = RoundToInterval(currentAbsorb, 0, int32(dmgInfo.GetDamage()));
|
||||
currentAbsorb = RoundToInterval(currentAbsorb, 0, int32(damageInfo.GetDamage()));
|
||||
|
||||
dmgInfo.AbsorbDamage(currentAbsorb);
|
||||
damageInfo.AbsorbDamage(currentAbsorb);
|
||||
|
||||
tempAbsorb = currentAbsorb;
|
||||
absorbAurEff->GetBase()->CallScriptEffectAfterAbsorbHandlers(absorbAurEff, aurApp, dmgInfo, tempAbsorb);
|
||||
absorbAurEff->GetBase()->CallScriptEffectAfterAbsorbHandlers(absorbAurEff, aurApp, damageInfo, tempAbsorb);
|
||||
|
||||
// Check if our aura is using amount to count damage
|
||||
if (absorbAurEff->GetAmount() >= 0)
|
||||
@@ -1820,16 +1812,16 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe
|
||||
}
|
||||
|
||||
// absorb by mana cost
|
||||
AuraEffectList vManaShieldCopy(victim->GetAuraEffectsByType(SPELL_AURA_MANA_SHIELD));
|
||||
for (AuraEffectList::const_iterator itr = vManaShieldCopy.begin(); (itr != vManaShieldCopy.end()) && (dmgInfo.GetDamage() > 0); ++itr)
|
||||
AuraEffectList vManaShieldCopy(damageInfo.GetVictim()->GetAuraEffectsByType(SPELL_AURA_MANA_SHIELD));
|
||||
for (AuraEffectList::const_iterator itr = vManaShieldCopy.begin(); (itr != vManaShieldCopy.end()) && (damageInfo.GetDamage() > 0); ++itr)
|
||||
{
|
||||
AuraEffect* absorbAurEff = *itr;
|
||||
// Check if aura was removed during iteration - we don't need to work on such auras
|
||||
AuraApplication const* aurApp = absorbAurEff->GetBase()->GetApplicationOfTarget(victim->GetGUID());
|
||||
AuraApplication const* aurApp = absorbAurEff->GetBase()->GetApplicationOfTarget(damageInfo.GetVictim()->GetGUID());
|
||||
if (!aurApp)
|
||||
continue;
|
||||
// check damage school mask
|
||||
if (!(absorbAurEff->GetMiscValue() & schoolMask))
|
||||
if (!(absorbAurEff->GetMiscValue() & damageInfo.GetSchoolMask()))
|
||||
continue;
|
||||
|
||||
// get amount which can be still absorbed by the aura
|
||||
@@ -1842,14 +1834,14 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe
|
||||
|
||||
bool defaultPrevented = false;
|
||||
|
||||
absorbAurEff->GetBase()->CallScriptEffectManaShieldHandlers(absorbAurEff, aurApp, dmgInfo, tempAbsorb, defaultPrevented);
|
||||
absorbAurEff->GetBase()->CallScriptEffectManaShieldHandlers(absorbAurEff, aurApp, damageInfo, tempAbsorb, defaultPrevented);
|
||||
currentAbsorb = tempAbsorb;
|
||||
|
||||
if (defaultPrevented)
|
||||
continue;
|
||||
|
||||
// absorb must be smaller than the damage itself
|
||||
currentAbsorb = RoundToInterval(currentAbsorb, 0, int32(dmgInfo.GetDamage()));
|
||||
currentAbsorb = RoundToInterval(currentAbsorb, 0, int32(damageInfo.GetDamage()));
|
||||
|
||||
int32 manaReduction = currentAbsorb;
|
||||
|
||||
@@ -1857,15 +1849,15 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe
|
||||
if (float manaMultiplier = absorbAurEff->GetSpellInfo()->Effects[absorbAurEff->GetEffIndex()].CalcValueMultiplier(absorbAurEff->GetCaster()))
|
||||
manaReduction = int32(float(manaReduction) * manaMultiplier);
|
||||
|
||||
int32 manaTaken = -victim->ModifyPower(POWER_MANA, -manaReduction);
|
||||
int32 manaTaken = -damageInfo.GetVictim()->ModifyPower(POWER_MANA, -manaReduction);
|
||||
|
||||
// take case when mana has ended up into account
|
||||
currentAbsorb = currentAbsorb ? int32(float(currentAbsorb) * (float(manaTaken) / float(manaReduction))) : 0;
|
||||
|
||||
dmgInfo.AbsorbDamage(currentAbsorb);
|
||||
damageInfo.AbsorbDamage(currentAbsorb);
|
||||
|
||||
tempAbsorb = currentAbsorb;
|
||||
absorbAurEff->GetBase()->CallScriptEffectAfterManaShieldHandlers(absorbAurEff, aurApp, dmgInfo, tempAbsorb);
|
||||
absorbAurEff->GetBase()->CallScriptEffectAfterManaShieldHandlers(absorbAurEff, aurApp, damageInfo, tempAbsorb);
|
||||
|
||||
// Check if our aura is using amount to count damage
|
||||
if (absorbAurEff->GetAmount() >= 0)
|
||||
@@ -1876,39 +1868,39 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe
|
||||
}
|
||||
}
|
||||
|
||||
dmgInfo.ModifyDamage(absorbIgnoringDamage);
|
||||
damageInfo.ModifyDamage(absorbIgnoringDamage);
|
||||
|
||||
// split damage auras - only when not damaging self
|
||||
if (victim != this)
|
||||
if (damageInfo.GetVictim() != this)
|
||||
{
|
||||
// We're going to call functions which can modify content of the list during iteration over it's elements
|
||||
// Let's copy the list so we can prevent iterator invalidation
|
||||
AuraEffectList vSplitDamageFlatCopy(victim->GetAuraEffectsByType(SPELL_AURA_SPLIT_DAMAGE_FLAT));
|
||||
for (AuraEffectList::iterator itr = vSplitDamageFlatCopy.begin(); (itr != vSplitDamageFlatCopy.end()) && (dmgInfo.GetDamage() > 0); ++itr)
|
||||
AuraEffectList vSplitDamageFlatCopy(damageInfo.GetVictim()->GetAuraEffectsByType(SPELL_AURA_SPLIT_DAMAGE_FLAT));
|
||||
for (AuraEffectList::iterator itr = vSplitDamageFlatCopy.begin(); (itr != vSplitDamageFlatCopy.end()) && (damageInfo.GetDamage() > 0); ++itr)
|
||||
{
|
||||
// Check if aura was removed during iteration - we don't need to work on such auras
|
||||
if (!((*itr)->GetBase()->IsAppliedOnTarget(victim->GetGUID())))
|
||||
if (!((*itr)->GetBase()->IsAppliedOnTarget(damageInfo.GetVictim()->GetGUID())))
|
||||
continue;
|
||||
// check damage school mask
|
||||
if (!((*itr)->GetMiscValue() & schoolMask))
|
||||
if (!((*itr)->GetMiscValue() & damageInfo.GetSchoolMask()))
|
||||
continue;
|
||||
|
||||
// Damage can be splitted only if aura has an alive caster
|
||||
Unit* caster = (*itr)->GetCaster();
|
||||
if (!caster || (caster == victim) || !caster->IsInWorld() || !caster->IsAlive())
|
||||
if (!caster || (caster == damageInfo.GetVictim()) || !caster->IsInWorld() || !caster->IsAlive())
|
||||
continue;
|
||||
|
||||
int32 splitDamage = (*itr)->GetAmount();
|
||||
|
||||
// absorb must be smaller than the damage itself
|
||||
splitDamage = RoundToInterval(splitDamage, 0, int32(dmgInfo.GetDamage()));
|
||||
splitDamage = RoundToInterval(splitDamage, 0, int32(damageInfo.GetDamage()));
|
||||
|
||||
dmgInfo.AbsorbDamage(splitDamage);
|
||||
damageInfo.AbsorbDamage(splitDamage);
|
||||
|
||||
// check if caster is immune to damage
|
||||
if (caster->IsImmunedToDamage(schoolMask))
|
||||
if (caster->IsImmunedToDamage(damageInfo.GetSchoolMask()))
|
||||
{
|
||||
victim->SendSpellMiss(caster, (*itr)->GetSpellInfo()->Id, SPELL_MISS_IMMUNE);
|
||||
damageInfo.GetVictim()->SendSpellMiss(caster, (*itr)->GetSpellInfo()->Id, SPELL_MISS_IMMUNE);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1916,66 +1908,62 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe
|
||||
uint32 splitted_absorb = 0;
|
||||
DealDamageMods(caster, splitted, &splitted_absorb);
|
||||
|
||||
SendSpellNonMeleeDamageLog(caster, (*itr)->GetSpellInfo()->Id, splitted, schoolMask, splitted_absorb, 0, false, 0, false);
|
||||
SendSpellNonMeleeDamageLog(caster, (*itr)->GetSpellInfo()->Id, splitted, damageInfo.GetSchoolMask(), splitted_absorb, 0, false, 0, false);
|
||||
|
||||
CleanDamage cleanDamage = CleanDamage(splitted, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
|
||||
DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*itr)->GetSpellInfo(), false);
|
||||
DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, damageInfo.GetSchoolMask(), (*itr)->GetSpellInfo(), false);
|
||||
}
|
||||
|
||||
// We're going to call functions which can modify content of the list during iteration over it's elements
|
||||
// Let's copy the list so we can prevent iterator invalidation
|
||||
AuraEffectList vSplitDamagePctCopy(victim->GetAuraEffectsByType(SPELL_AURA_SPLIT_DAMAGE_PCT));
|
||||
for (AuraEffectList::iterator itr = vSplitDamagePctCopy.begin(); itr != vSplitDamagePctCopy.end() && dmgInfo.GetDamage() > 0; ++itr)
|
||||
AuraEffectList vSplitDamagePctCopy(damageInfo.GetVictim()->GetAuraEffectsByType(SPELL_AURA_SPLIT_DAMAGE_PCT));
|
||||
for (AuraEffectList::iterator itr = vSplitDamagePctCopy.begin(); itr != vSplitDamagePctCopy.end() && damageInfo.GetDamage() > 0; ++itr)
|
||||
{
|
||||
// Check if aura was removed during iteration - we don't need to work on such auras
|
||||
AuraApplication const* aurApp = (*itr)->GetBase()->GetApplicationOfTarget(victim->GetGUID());
|
||||
AuraApplication const* aurApp = (*itr)->GetBase()->GetApplicationOfTarget(damageInfo.GetVictim()->GetGUID());
|
||||
if (!aurApp)
|
||||
continue;
|
||||
|
||||
// check damage school mask
|
||||
if (!((*itr)->GetMiscValue() & schoolMask))
|
||||
if (!((*itr)->GetMiscValue() & damageInfo.GetSchoolMask()))
|
||||
continue;
|
||||
|
||||
// Damage can be splitted only if aura has an alive caster
|
||||
Unit* caster = (*itr)->GetCaster();
|
||||
if (!caster || (caster == victim) || !caster->IsInWorld() || !caster->IsAlive())
|
||||
if (!caster || (caster == damageInfo.GetVictim()) || !caster->IsInWorld() || !caster->IsAlive())
|
||||
continue;
|
||||
|
||||
uint32 splitDamage = CalculatePct(dmgInfo.GetDamage(), (*itr)->GetAmount());
|
||||
uint32 splitDamage = CalculatePct(damageInfo.GetDamage(), (*itr)->GetAmount());
|
||||
|
||||
(*itr)->GetBase()->CallScriptEffectSplitHandlers((*itr), aurApp, dmgInfo, splitDamage);
|
||||
(*itr)->GetBase()->CallScriptEffectSplitHandlers((*itr), aurApp, damageInfo, splitDamage);
|
||||
|
||||
// absorb must be smaller than the damage itself
|
||||
splitDamage = RoundToInterval(splitDamage, uint32(0), uint32(dmgInfo.GetDamage()));
|
||||
splitDamage = RoundToInterval(splitDamage, uint32(0), uint32(damageInfo.GetDamage()));
|
||||
|
||||
dmgInfo.AbsorbDamage(splitDamage);
|
||||
damageInfo.AbsorbDamage(splitDamage);
|
||||
|
||||
// check if caster is immune to damage
|
||||
if (caster->IsImmunedToDamage(schoolMask))
|
||||
if (caster->IsImmunedToDamage(damageInfo.GetSchoolMask()))
|
||||
{
|
||||
victim->SendSpellMiss(caster, (*itr)->GetSpellInfo()->Id, SPELL_MISS_IMMUNE);
|
||||
damageInfo.GetVictim()->SendSpellMiss(caster, (*itr)->GetSpellInfo()->Id, SPELL_MISS_IMMUNE);
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32 split_absorb = 0;
|
||||
DealDamageMods(caster, splitDamage, &split_absorb);
|
||||
|
||||
SendSpellNonMeleeDamageLog(caster, (*itr)->GetSpellInfo()->Id, splitDamage, schoolMask, split_absorb, 0, false, 0, false);
|
||||
SendSpellNonMeleeDamageLog(caster, (*itr)->GetSpellInfo()->Id, splitDamage, damageInfo.GetSchoolMask(), split_absorb, 0, false, 0, false);
|
||||
|
||||
CleanDamage cleanDamage = CleanDamage(splitDamage, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
|
||||
DealDamage(caster, splitDamage, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*itr)->GetSpellInfo(), false);
|
||||
DealDamage(caster, splitDamage, &cleanDamage, DIRECT_DAMAGE, damageInfo.GetSchoolMask(), (*itr)->GetSpellInfo(), false);
|
||||
|
||||
// break 'Fear' and similar auras
|
||||
DamageInfo damageInfo(caster, this, splitDamage, (*itr)->GetSpellInfo(), schoolMask, DIRECT_DAMAGE, BASE_ATTACK);
|
||||
ProcSkillsAndAuras(caster, PROC_FLAG_NONE, PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG, PROC_SPELL_TYPE_DAMAGE, PROC_SPELL_PHASE_HIT, PROC_HIT_NONE, nullptr, &damageInfo, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
*resist = dmgInfo.GetResist();
|
||||
*absorb = dmgInfo.GetAbsorb();
|
||||
}
|
||||
|
||||
void Unit::CalcHealAbsorb(HealInfo& healInfo)
|
||||
void Unit::CalcHealAbsorb(HealInfo& healInfo) const
|
||||
{
|
||||
if (!healInfo.GetHeal())
|
||||
return;
|
||||
|
||||
@@ -1433,7 +1433,7 @@ class TC_GAME_API Unit : public WorldObject
|
||||
void Dismount();
|
||||
|
||||
uint16 GetMaxSkillValueForLevel(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; }
|
||||
void DealDamageMods(Unit* victim, uint32 &damage, uint32* absorb);
|
||||
void DealDamageMods(Unit const* victim, uint32 &damage, uint32* absorb) const;
|
||||
uint32 DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDamage = NULL, DamageEffectType damagetype = DIRECT_DAMAGE, SpellSchoolMask damageSchoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellInfo const* spellProto = NULL, bool durabilityLoss = true);
|
||||
void Kill(Unit* victim, bool durabilityLoss = true);
|
||||
void KillSelf(bool durabilityLoss = true) { Kill(this, durabilityLoss); }
|
||||
@@ -2033,8 +2033,8 @@ class TC_GAME_API Unit : public WorldObject
|
||||
static bool IsDamageReducedByArmor(SpellSchoolMask damageSchoolMask, SpellInfo const* spellInfo = NULL, uint8 effIndex = MAX_SPELL_EFFECTS);
|
||||
uint32 CalcArmorReducedDamage(Unit* victim, const uint32 damage, SpellInfo const* spellInfo, WeaponAttackType attackType = MAX_ATTACK);
|
||||
uint32 CalcSpellResistance(Unit* victim, SpellSchoolMask schoolMask, SpellInfo const* spellInfo) const;
|
||||
void CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffectType damagetype, uint32 const damage, uint32* absorb, uint32* resist, SpellInfo const* spellInfo = NULL);
|
||||
void CalcHealAbsorb(HealInfo& healInfo);
|
||||
void CalcAbsorbResist(DamageInfo& damageInfo);
|
||||
void CalcHealAbsorb(HealInfo& healInfo) const;
|
||||
|
||||
void UpdateSpeed(UnitMoveType mtype);
|
||||
float GetSpeed(UnitMoveType mtype) const;
|
||||
|
||||
@@ -5846,8 +5846,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);
|
||||
|
||||
// AOE spells are not affected by the new periodic system.
|
||||
@@ -5942,13 +5940,16 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
|
||||
damage = caster->SpellCriticalDamageBonus(m_spellInfo, damage, target);
|
||||
|
||||
int32 dmg = damage;
|
||||
|
||||
if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE))
|
||||
caster->ApplyResilience(target, NULL, &dmg, crit, CR_CRIT_TAKEN_SPELL);
|
||||
caster->ApplyResilience(target, nullptr, &dmg, crit, CR_CRIT_TAKEN_SPELL);
|
||||
damage = dmg;
|
||||
|
||||
caster->CalcAbsorbResist(target, GetSpellInfo()->GetSchoolMask(), DOT, damage, &absorb, &resist, GetSpellInfo());
|
||||
DamageInfo damageInfo(caster, target, damage, GetSpellInfo(), GetSpellInfo()->GetSchoolMask(), DOT, BASE_ATTACK);
|
||||
caster->CalcAbsorbResist(damageInfo);
|
||||
damage = damageInfo.GetDamage();
|
||||
|
||||
uint32 absorb = damageInfo.GetAbsorb();
|
||||
uint32 resist = damageInfo.GetResist();
|
||||
TC_LOG_DEBUG("spells.periodic", "PeriodicTick: %s attacked %s for %u dmg inflicted by %u absorb is %u",
|
||||
GetCasterGUID().ToString().c_str(), target->GetGUID().ToString().c_str(), damage, GetId(), absorb);
|
||||
|
||||
@@ -5957,8 +5958,10 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
|
||||
// Set trigger flag
|
||||
uint32 procAttacker = PROC_FLAG_DONE_PERIODIC;
|
||||
uint32 procVictim = PROC_FLAG_TAKEN_PERIODIC;
|
||||
uint32 hitMask = crit ? PROC_HIT_CRITICAL : PROC_HIT_NORMAL;
|
||||
damage = (damage <= absorb+resist) ? 0 : (damage-absorb-resist);
|
||||
uint32 hitMask = damageInfo.GetHitMask();
|
||||
if (!hitMask)
|
||||
hitMask = crit ? PROC_HIT_CRITICAL : PROC_HIT_NORMAL;
|
||||
|
||||
if (damage)
|
||||
procVictim |= PROC_FLAG_TAKEN_DAMAGE;
|
||||
|
||||
@@ -5969,7 +5972,6 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
|
||||
SpellPeriodicAuraLogInfo pInfo(this, damage, overkill, absorb, resist, 0.0f, crit);
|
||||
target->SendPeriodicAuraLog(&pInfo);
|
||||
|
||||
DamageInfo damageInfo(caster, target, damage, GetSpellInfo(), GetSpellInfo()->GetSchoolMask(), DOT, BASE_ATTACK);
|
||||
caster->ProcSkillsAndAuras(target, procAttacker, procVictim, PROC_SPELL_TYPE_DAMAGE, PROC_SPELL_PHASE_NONE, hitMask, nullptr, &damageInfo, nullptr);
|
||||
|
||||
caster->DealDamage(target, damage, &cleanDamage, DOT, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), true);
|
||||
@@ -5990,8 +5992,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);
|
||||
|
||||
bool isAreaAura = m_spellInfo->Effects[m_effIndex].IsAreaAuraEffect() || m_spellInfo->Effects[m_effIndex].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA);
|
||||
@@ -6034,29 +6034,33 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
|
||||
|
||||
int32 dmg = damage;
|
||||
if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE))
|
||||
caster->ApplyResilience(target, NULL, &dmg, crit, CR_CRIT_TAKEN_SPELL);
|
||||
caster->ApplyResilience(target, nullptr, &dmg, crit, CR_CRIT_TAKEN_SPELL);
|
||||
damage = dmg;
|
||||
|
||||
caster->CalcAbsorbResist(target, GetSpellInfo()->GetSchoolMask(), DOT, damage, &absorb, &resist, m_spellInfo);
|
||||
DamageInfo damageInfo(caster, target, damage, GetSpellInfo(), GetSpellInfo()->GetSchoolMask(), DOT, BASE_ATTACK);
|
||||
caster->CalcAbsorbResist(damageInfo);
|
||||
|
||||
uint32 absorb = damageInfo.GetAbsorb();
|
||||
uint32 resist = damageInfo.GetResist();
|
||||
TC_LOG_DEBUG("spells.periodic", "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);
|
||||
|
||||
// SendSpellNonMeleeDamageLog expects non-absorbed/non-resisted damage
|
||||
caster->SendSpellNonMeleeDamageLog(target, GetId(), damage, GetSpellInfo()->GetSchoolMask(), absorb, resist, false, 0, crit);
|
||||
damage = damageInfo.GetDamage();
|
||||
|
||||
// Set trigger flag
|
||||
uint32 procAttacker = PROC_FLAG_DONE_PERIODIC;
|
||||
uint32 procVictim = PROC_FLAG_TAKEN_PERIODIC;
|
||||
uint32 hitMask = crit ? PROC_HIT_CRITICAL : PROC_HIT_NORMAL;
|
||||
damage = (damage <= absorb+resist) ? 0 : (damage-absorb-resist);
|
||||
uint32 hitMask = damageInfo.GetHitMask();
|
||||
if (!hitMask)
|
||||
hitMask = crit ? PROC_HIT_CRITICAL : PROC_HIT_NORMAL;
|
||||
|
||||
if (damage)
|
||||
procVictim |= PROC_FLAG_TAKEN_DAMAGE;
|
||||
|
||||
if (caster->IsAlive())
|
||||
{
|
||||
DamageInfo damageInfo(caster, target, damage, GetSpellInfo(), GetSpellInfo()->GetSchoolMask(), DOT, BASE_ATTACK);
|
||||
caster->ProcSkillsAndAuras(target, procAttacker, procVictim, PROC_SPELL_TYPE_DAMAGE, PROC_SPELL_PHASE_NONE, hitMask, nullptr, &damageInfo, nullptr);
|
||||
}
|
||||
|
||||
int32 new_damage = caster->DealDamage(target, damage, &cleanDamage, DOT, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), false);
|
||||
if (caster->IsAlive())
|
||||
|
||||
@@ -292,14 +292,18 @@ void Spell::EffectEnvironmentalDMG(SpellEffIndex /*effIndex*/)
|
||||
if (!unitTarget || !unitTarget->IsAlive())
|
||||
return;
|
||||
|
||||
uint32 absorb = 0;
|
||||
uint32 resist = 0;
|
||||
|
||||
m_caster->CalcAbsorbResist(unitTarget, m_spellInfo->GetSchoolMask(), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist, m_spellInfo);
|
||||
|
||||
m_caster->SendSpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage, m_spellInfo->GetSchoolMask(), absorb, resist, false, 0, false);
|
||||
// CalcAbsorbResist already in Player::EnvironmentalDamage
|
||||
if (unitTarget->GetTypeId() == TYPEID_PLAYER)
|
||||
unitTarget->ToPlayer()->EnvironmentalDamage(DAMAGE_FIRE, damage);
|
||||
else
|
||||
{
|
||||
DamageInfo damageInfo(m_caster, unitTarget, damage, m_spellInfo, m_spellInfo->GetSchoolMask(), SPELL_DIRECT_DAMAGE, BASE_ATTACK);
|
||||
m_caster->CalcAbsorbResist(damageInfo);
|
||||
|
||||
uint32 absorb = damageInfo.GetAbsorb();
|
||||
uint32 resist = damageInfo.GetResist();
|
||||
m_caster->SendSpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage, m_spellInfo->GetSchoolMask(), absorb, resist, false, 0, false);
|
||||
}
|
||||
}
|
||||
|
||||
void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
|
||||
|
||||
@@ -2268,19 +2268,20 @@ public:
|
||||
// melee damage by specific school
|
||||
if (!spellStr)
|
||||
{
|
||||
uint32 absorb = 0;
|
||||
uint32 resist = 0;
|
||||
Player* attacker = handler->GetSession()->GetPlayer();
|
||||
DamageInfo dmgInfo(attacker, target, damage, nullptr, schoolmask, SPELL_DIRECT_DAMAGE, BASE_ATTACK);
|
||||
attacker->CalcAbsorbResist(dmgInfo);
|
||||
|
||||
handler->GetSession()->GetPlayer()->CalcAbsorbResist(target, schoolmask, SPELL_DIRECT_DAMAGE, damage, &absorb, &resist);
|
||||
|
||||
if (damage <= absorb + resist)
|
||||
if (!dmgInfo.GetDamage())
|
||||
return true;
|
||||
|
||||
damage -= absorb + resist;
|
||||
damage = dmgInfo.GetDamage();
|
||||
|
||||
handler->GetSession()->GetPlayer()->DealDamageMods(target, damage, &absorb);
|
||||
handler->GetSession()->GetPlayer()->DealDamage(target, damage, NULL, DIRECT_DAMAGE, schoolmask, NULL, false);
|
||||
handler->GetSession()->GetPlayer()->SendAttackStateUpdate (HITINFO_AFFECTS_VICTIM, target, 1, schoolmask, damage, absorb, resist, VICTIMSTATE_HIT, 0);
|
||||
uint32 absorb = dmgInfo.GetAbsorb();
|
||||
uint32 resist = dmgInfo.GetResist();
|
||||
attacker->DealDamageMods(target, damage, &absorb);
|
||||
attacker->DealDamage(target, damage, nullptr, DIRECT_DAMAGE, schoolmask, nullptr, false);
|
||||
attacker->SendAttackStateUpdate(HITINFO_AFFECTS_VICTIM, target, 0, schoolmask, damage, absorb, resist, VICTIMSTATE_HIT, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user