diff options
| -rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 21 | ||||
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 150 | ||||
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 6 | ||||
| -rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 38 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 16 | ||||
| -rw-r--r-- | src/server/scripts/Commands/cs_misc.cpp | 19 |
6 files changed, 128 insertions, 122 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 59b109ab754..ba85f57b7a2 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -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); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index ca470012c41..637ade0ab90 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -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; diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 20cdc75c001..95e447bfb5e 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -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; diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index fabdbe44334..08061ac0b34 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -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()) diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index f321925aa8c..8f25b3f7a5a 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -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) diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 16217fbaea6..1e4daaea2d2 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -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; } |
