diff options
author | ariel- <ariel-@users.noreply.github.com> | 2018-01-13 06:45:21 -0300 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2021-06-13 00:59:13 +0200 |
commit | fccf1a8c62820004df92b9ac567ba75f7281e6e2 (patch) | |
tree | 063326fad1f3fa51c633e4b8d0c7745341ec113e /src | |
parent | fa4e2d3935b0184623a6d816dc25a41bad30b1d8 (diff) |
Core/Auras: removed caster dependency from core
- Decoupled Unit logic: split of spell critical chance into done (caster bonuses) and taken (target bonuses), this allows to precalculate caster bonuses on aura apply and then check victim's auras on damage/healing calc
- Made static a bunch of methods (they no longer have this pointer because they are now called from periodic handlers which may or may not have an active caster in world)
- Simplified all AuraEffect bonuses into AuraEffect::_amount, no more duplicated code
- Critical chance and whether or not caster is player owned unit (for resilience calcs) is now saved one level upper, on Aura itself (it's impossible as of 3.3.5 to have different effects with different critical chances)
- Minor cleanup of SPELL_DAMAGE_CLASS_NONE and Arcane Potency (#18813) crit handling
Closes #19876
(cherry picked from commit cb9e72e521d3cc415dd15bf6912c87f89e41b92a)
Diffstat (limited to 'src')
59 files changed, 657 insertions, 643 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 008b5c12956..b780408e67a 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -648,7 +648,7 @@ uint32 Player::EnvironmentalDamage(EnviromentalDamage type, uint32 damage) 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); + Unit::CalcAbsorbResist(dmgInfo); absorb = dmgInfo.GetAbsorb(); resist = dmgInfo.GetResist(); damage = dmgInfo.GetDamage(); @@ -658,7 +658,7 @@ uint32 Player::EnvironmentalDamage(EnviromentalDamage type, uint32 damage) break; } - DealDamageMods(this, damage, &absorb); + Unit::DealDamageMods(nullptr, this, damage, &absorb); WorldPackets::CombatLog::EnvironmentalDamageLog packet; packet.Victim = GetGUID(); @@ -667,7 +667,7 @@ uint32 Player::EnvironmentalDamage(EnviromentalDamage type, uint32 damage) packet.Absorbed = absorb; packet.Resisted = resist; - uint32 final_damage = DealDamage(this, damage, nullptr, SELF_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); + uint32 final_damage = Unit::DealDamage(this, this, damage, nullptr, SELF_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); packet.LogData.Initialize(this); SendCombatLogMessage(&packet); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 6298598605a..7d10604eea1 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1960,6 +1960,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> uint32 GetBaseSpellPowerBonus() const { return m_baseSpellPower; } int32 GetSpellPenetrationItemMod() const { return m_spellPenetrationItemMod; } + bool CanApplyResilience() const override { return true; } + float GetExpertiseDodgeOrParryReduction(WeaponAttackType attType) const; void UpdateBlockPercentage(); void UpdateCritPercentage(WeaponAttackType attType); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 33c528d54f7..9bb993c6ed1 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -669,7 +669,7 @@ bool Unit::HasBreakableByDamageCrowdControlAura(Unit* excludeCasterChannel) cons || HasBreakableByDamageAuraType(SPELL_AURA_TRANSFORM, excludeAura)); } -void Unit::DealDamageMods(Unit const* victim, uint32 &damage, uint32* absorb) const +/*static*/ void Unit::DealDamageMods(Unit const* attacker, Unit const* victim, uint32& damage, uint32* absorb) { if (!victim || !victim->IsAlive() || victim->HasUnitState(UNIT_STATE_IN_FLIGHT) || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks())) { @@ -679,21 +679,22 @@ void Unit::DealDamageMods(Unit const* victim, uint32 &damage, uint32* absorb) co return; } - damage *= GetDamageMultiplierForTarget(victim); + if (attacker) + damage *= attacker->GetDamageMultiplierForTarget(victim); } -uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellInfo const* spellProto, bool durabilityLoss) +/*static*/ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellInfo const* spellProto, bool durabilityLoss) { if (victim->IsAIEnabled) - victim->GetAI()->DamageTaken(this, damage); + victim->GetAI()->DamageTaken(attacker, damage); - if (IsAIEnabled) - GetAI()->DamageDealt(victim, damage, damagetype); + if (attacker && attacker->IsAIEnabled) + attacker->GetAI()->DamageDealt(victim, damage, damagetype); // Hook for OnDamage Event - sScriptMgr->OnDamage(this, victim, damage); + sScriptMgr->OnDamage(attacker, victim, damage); - if (victim->GetTypeId() == TYPEID_PLAYER && this != victim) + if (victim->GetTypeId() == TYPEID_PLAYER && attacker != victim) { // Signal to pets that their owner was attacked - except when DOT. if (damagetype != DOT) @@ -701,7 +702,7 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam for (Unit* controlled : victim->m_Controlled) if (Creature* cControlled = controlled->ToCreature()) if (cControlled->IsAIEnabled) - cControlled->AI()->OwnerAttackedBy(this); + cControlled->AI()->OwnerAttackedBy(attacker); } if (victim->ToPlayer()->GetCommandStatus(CHEAT_GOD)) @@ -720,7 +721,7 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam victim->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Damage, 0); if (!damage && damagetype != DOT && cleanDamage && cleanDamage->absorbed_damage) - if (victim != this && victim->GetTypeId() == TYPEID_PLAYER) + if (victim != attacker && victim->GetTypeId() == TYPEID_PLAYER) if (Spell* spell = victim->m_currentSpells[CURRENT_GENERIC_SPELL]) if (spell->getState() == SPELL_STATE_PREPARING && spell->m_spellInfo->InterruptFlags.HasFlag(SpellInterruptFlags::DamageAbsorb)) victim->InterruptNonMeleeSpells(false); @@ -746,35 +747,35 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam uint32 share = CalculatePct(damage, (*i)->GetAmount()); /// @todo check packets if damage is done by victim, or by attacker of victim - DealDamageMods(shareDamageTarget, share, nullptr); - DealDamage(shareDamageTarget, share, nullptr, NODAMAGE, spell->GetSchoolMask(), spell, false); + Unit::DealDamageMods(attacker, shareDamageTarget, share, nullptr); + Unit::DealDamage(attacker, shareDamageTarget, share, nullptr, NODAMAGE, spell->GetSchoolMask(), spell, false); } } // Rage from Damage made (only from direct weapon damage) - if (cleanDamage && (cleanDamage->attackType == BASE_ATTACK || cleanDamage->attackType == OFF_ATTACK) && damagetype == DIRECT_DAMAGE && this != victim && GetPowerType() == POWER_RAGE) + if (attacker && cleanDamage && (cleanDamage->attackType == BASE_ATTACK || cleanDamage->attackType == OFF_ATTACK) && damagetype == DIRECT_DAMAGE && attacker != victim && attacker->GetPowerType() == POWER_RAGE) { - uint32 rage = uint32(GetBaseAttackTime(cleanDamage->attackType) / 1000.f * 1.75f); + uint32 rage = uint32(attacker->GetBaseAttackTime(cleanDamage->attackType) / 1000.f * 1.75f); if (cleanDamage->attackType == OFF_ATTACK) rage /= 2; - RewardRage(rage); + attacker->RewardRage(rage); } if (!damage) return 0; - TC_LOG_DEBUG("entities.unit", "DealDamageStart"); - uint32 health = victim->GetHealth(); - TC_LOG_DEBUG("entities.unit", "%s dealt %u damage to %s", GetGUID().ToString().c_str(), damage, victim->GetGUID().ToString().c_str()); // duel ends when player has 1 or less hp bool duel_hasEnded = false; bool duel_wasMounted = false; if (victim->GetTypeId() == TYPEID_PLAYER && victim->ToPlayer()->duel && damage >= (health-1)) { + if (!attacker) + return 0; + // prevent kill only if killed in duel and killed by opponent or opponent controlled creature - if (victim->ToPlayer()->duel->opponent == this || victim->ToPlayer()->duel->opponent->GetGUID() == GetOwnerGUID()) + if (victim->ToPlayer()->duel->opponent == attacker || victim->ToPlayer()->duel->opponent->GetGUID() == attacker->GetOwnerGUID()) damage = health - 1; duel_hasEnded = true; @@ -785,8 +786,11 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam if (victimRider && victimRider->duel && victimRider->duel->isMounted) { + if (!attacker) + return 0; + // prevent kill only if killed in duel and killed by opponent or opponent controlled creature - if (victimRider->duel->opponent == this || victimRider->duel->opponent->GetGUID() == GetCharmerGUID()) + if (victimRider->duel->opponent == attacker || victimRider->duel->opponent->GetGUID() == attacker->GetCharmerGUID()) damage = health - 1; duel_wasMounted = true; @@ -794,30 +798,32 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam } } - if (GetTypeId() == TYPEID_PLAYER && this != victim) + if (attacker && attacker != victim) { - Player* killer = ToPlayer(); - - // in bg, count dmg if victim is also a player - if (victim->GetTypeId() == TYPEID_PLAYER) - if (Battleground* bg = killer->GetBattleground()) - bg->UpdatePlayerScore(killer, SCORE_DAMAGE_DONE, damage); + if (Player* killer = attacker->ToPlayer()) + { + // in bg, count dmg if victim is also a player + if (victim->GetTypeId() == TYPEID_PLAYER) + if (Battleground* bg = killer->GetBattleground()) + bg->UpdatePlayerScore(killer, SCORE_DAMAGE_DONE, damage); - killer->UpdateCriteria(CRITERIA_TYPE_DAMAGE_DONE, health > damage ? damage : health, 0, 0, victim); - killer->UpdateCriteria(CRITERIA_TYPE_HIGHEST_HIT_DEALT, damage); + killer->UpdateCriteria(CRITERIA_TYPE_DAMAGE_DONE, health > damage ? damage : health, 0, 0, victim); + killer->UpdateCriteria(CRITERIA_TYPE_HIGHEST_HIT_DEALT, damage); + } } if (victim->GetTypeId() == TYPEID_PLAYER) victim->ToPlayer()->UpdateCriteria(CRITERIA_TYPE_HIGHEST_HIT_RECEIVED, damage); - damage /= victim->GetHealthMultiplierForTarget(this); + if (attacker) + damage /= victim->GetHealthMultiplierForTarget(attacker); if (victim->GetTypeId() != TYPEID_PLAYER && (!victim->IsControlledByPlayer() || victim->IsVehicle())) { if (!victim->ToCreature()->hasLootRecipient()) - victim->ToCreature()->SetLootRecipient(this); + victim->ToCreature()->SetLootRecipient(attacker); - if (IsControlledByPlayer()) + if (!attacker || attacker->IsControlledByPlayer()) victim->ToCreature()->LowerPlayerDamageReq(health < damage ? health : damage); } @@ -828,15 +834,13 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam { killed = true; - TC_LOG_DEBUG("entities.unit", "DealDamage: victim just died"); - - if (victim->GetTypeId() == TYPEID_PLAYER && victim != this) + if (victim->GetTypeId() == TYPEID_PLAYER && victim != attacker) victim->ToPlayer()->UpdateCriteria(CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED, health); if (damagetype != NODAMAGE && damagetype != SELF_DAMAGE && victim->HasAuraType(SPELL_AURA_SCHOOL_ABSORB_OVERKILL)) { AuraEffectList vAbsorbOverkill = victim->GetAuraEffectsByType(SPELL_AURA_SCHOOL_ABSORB_OVERKILL); - DamageInfo damageInfo = DamageInfo(this, victim, damage, spellProto, damageSchoolMask, damagetype, + DamageInfo damageInfo = DamageInfo(attacker, victim, damage, spellProto, damageSchoolMask, damagetype, cleanDamage ? cleanDamage->attackType : BASE_ATTACK); for (AuraEffect* absorbAurEff : vAbsorbOverkill) { @@ -879,7 +883,7 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam if (currentAbsorb) { WorldPackets::CombatLog::SpellAbsorbLog absorbLog; - absorbLog.Attacker = GetGUID(); + absorbLog.Attacker = attacker ? attacker->GetGUID() : ObjectGuid::Empty; absorbLog.Victim = victim->GetGUID(); absorbLog.Caster = base->GetCasterGUID(); absorbLog.AbsorbedSpellID = spellProto ? spellProto->Id : 0; @@ -887,7 +891,7 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam absorbLog.Absorbed = currentAbsorb; absorbLog.OriginalDamage = damageInfo.GetOriginalDamage(); absorbLog.LogData.Initialize(victim); - SendCombatLogMessage(&absorbLog); + victim->SendCombatLogMessage(&absorbLog); } } @@ -896,11 +900,9 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam } if (killed) - Kill(victim, durabilityLoss, skipSettingDeathState); + Unit::Kill(attacker, victim, durabilityLoss, skipSettingDeathState); else { - TC_LOG_DEBUG("entities.unit", "DealDamageAlive"); - if (victim->GetTypeId() == TYPEID_PLAYER) victim->ToPlayer()->UpdateCriteria(CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED, damage); @@ -915,7 +917,8 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam if (damagetype != DOT && damage > 0 && !victim->GetOwnerGUID().IsPlayer() && (!spellProto || !spellProto->HasAura(SPELL_AURA_DAMAGE_SHIELD))) victim->ToCreature()->SetLastDamagedTime(GameTime::GetGameTime() + MAX_AGGRO_RESET_TIME); - victim->GetThreatManager().AddThreat(this, float(damage), spellProto); + if (attacker) + victim->GetThreatManager().AddThreat(attacker, float(damage), spellProto); } else // victim is a player { @@ -927,19 +930,19 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam } } - if (GetTypeId() == TYPEID_PLAYER) + if (attacker && attacker->GetTypeId() == TYPEID_PLAYER) { // random durability for items (HIT DONE) if (roll_chance_f(sWorld->getRate(RATE_DURABILITY_LOSS_DAMAGE))) { EquipmentSlots slot = EquipmentSlots(urand(0, EQUIPMENT_SLOT_END-1)); - ToPlayer()->DurabilityPointLossForEquipSlot(slot); + attacker->ToPlayer()->DurabilityPointLossForEquipSlot(slot); } } if (damagetype != NODAMAGE) { - if (victim != this + if (victim != attacker && (!spellProto || !(spellProto->HasAttribute(SPELL_ATTR7_NO_PUSHBACK_ON_DAMAGE) || spellProto->HasAttribute(SPELL_ATTR3_TREAT_AS_PERIODIC)))) { if (damagetype != DOT) @@ -1011,8 +1014,6 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam } } - TC_LOG_DEBUG("entities.unit", "DealDamageEnd returned %d damage", damage); - return damage; } @@ -1079,8 +1080,8 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama // Spells with SPELL_ATTR4_FIXED_DAMAGE ignore resilience because their damage is based off another spell's damage. if (!spellInfo->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE)) { - if (IsDamageReducedByArmor(damageSchoolMask, spellInfo)) - damage = CalcArmorReducedDamage(damageInfo->attacker, victim, damage, spellInfo, attackType); + if (Unit::IsDamageReducedByArmor(damageSchoolMask, spellInfo)) + damage = Unit::CalcArmorReducedDamage(damageInfo->attacker, victim, damage, spellInfo, attackType); bool blocked = false; // Per-school calc @@ -1135,7 +1136,8 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama damage -= damageInfo->blocked; } - ApplyResilience(victim, &damage); + if (CanApplyResilience()) + Unit::ApplyResilience(victim, &damage); break; } // Magical Attacks @@ -1146,10 +1148,11 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama if (crit) { damageInfo->HitInfo |= SPELL_HIT_TYPE_CRIT; - damage = SpellCriticalDamageBonus(spellInfo, damage, victim); + damage = Unit::SpellCriticalDamageBonus(this, spellInfo, damage, victim); } - ApplyResilience(victim, &damage); + if (CanApplyResilience()) + Unit::ApplyResilience(victim, &damage); break; } @@ -1168,7 +1171,7 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama damageInfo->damage = damage; damageInfo->originalDamage = damage; DamageInfo dmgInfo(*damageInfo, SPELL_DIRECT_DAMAGE, BASE_ATTACK, PROC_HIT_NONE); - CalcAbsorbResist(dmgInfo); + Unit::CalcAbsorbResist(dmgInfo); damageInfo->absorb = dmgInfo.GetAbsorb(); damageInfo->resist = dmgInfo.GetResist(); @@ -1201,7 +1204,7 @@ void Unit::DealSpellDamage(SpellNonMeleeDamage const* damageInfo, bool durabilit // Call default DealDamage CleanDamage cleanDamage(damageInfo->cleanDamage, damageInfo->absorb, BASE_ATTACK, MELEE_HIT_NORMAL); - DealDamage(victim, damageInfo->damage, &cleanDamage, SPELL_DIRECT_DAMAGE, SpellSchoolMask(damageInfo->schoolMask), damageInfo->Spell, durabilityLoss); + Unit::DealDamage(this, victim, damageInfo->damage, &cleanDamage, SPELL_DIRECT_DAMAGE, SpellSchoolMask(damageInfo->schoolMask), damageInfo->Spell, durabilityLoss); } /// @todo for melee need create structure as in @@ -1266,9 +1269,9 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam sScriptMgr->ModifyMeleeDamage(damageInfo->target, damageInfo->attacker, damage); // Calculate armor reduction - if (IsDamageReducedByArmor((SpellSchoolMask)(damageInfo->damageSchoolMask))) + if (Unit::IsDamageReducedByArmor((SpellSchoolMask)(damageInfo->damageSchoolMask))) { - damageInfo->damage = CalcArmorReducedDamage(damageInfo->attacker, damageInfo->target, damage, nullptr, damageInfo->attackType); + damageInfo->damage = Unit::CalcArmorReducedDamage(damageInfo->attacker, damageInfo->target, damage, nullptr, damageInfo->attackType); damageInfo->cleanDamage += damage - damageInfo->damage; } else @@ -1364,7 +1367,8 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam damageInfo->HitInfo |= HITINFO_AFFECTS_VICTIM; int32 resilienceReduction = damageInfo->damage; - ApplyResilience(victim, &resilienceReduction); + if (CanApplyResilience()) + Unit::ApplyResilience(victim, &resilienceReduction); resilienceReduction = damageInfo->damage - resilienceReduction; damageInfo->damage -= resilienceReduction; damageInfo->cleanDamage += resilienceReduction; @@ -1376,7 +1380,7 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam damageInfo->procVictim |= PROC_FLAG_TAKEN_DAMAGE; // Calculate absorb & resists DamageInfo dmgInfo(*damageInfo); - CalcAbsorbResist(dmgInfo); + Unit::CalcAbsorbResist(dmgInfo); damageInfo->absorb = dmgInfo.GetAbsorb(); damageInfo->resist = dmgInfo.GetResist(); @@ -1440,7 +1444,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss) // Call default DealDamage CleanDamage cleanDamage(damageInfo->cleanDamage, damageInfo->absorb, damageInfo->attackType, damageInfo->hitOutCome); - DealDamage(victim, damageInfo->damage, &cleanDamage, DIRECT_DAMAGE, SpellSchoolMask(damageInfo->damageSchoolMask), nullptr, durabilityLoss); + Unit::DealDamage(this, victim, damageInfo->damage, &cleanDamage, DIRECT_DAMAGE, SpellSchoolMask(damageInfo->damageSchoolMask), nullptr, durabilityLoss); // If this is a creature and it attacks from behind it has a probability to daze it's victim if ((damageInfo->hitOutCome == MELEE_HIT_CRIT || damageInfo->hitOutCome == MELEE_HIT_CRUSHING || damageInfo->hitOutCome == MELEE_HIT_NORMAL || damageInfo->hitOutCome == MELEE_HIT_GLANCING) && @@ -1500,13 +1504,13 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss) if (Unit* caster = aurEff->GetCaster()) { damage = caster->SpellDamageBonusDone(this, spellInfo, damage, SPELL_DIRECT_DAMAGE, aurEff->GetSpellEffectInfo()); - damage = this->SpellDamageBonusTaken(caster, spellInfo, damage, SPELL_DIRECT_DAMAGE, aurEff->GetSpellEffectInfo()); + damage = SpellDamageBonusTaken(caster, spellInfo, damage, SPELL_DIRECT_DAMAGE, aurEff->GetSpellEffectInfo()); } DamageInfo damageInfo(this, victim, damage, spellInfo, spellInfo->GetSchoolMask(), SPELL_DIRECT_DAMAGE, BASE_ATTACK); victim->CalcAbsorbResist(damageInfo); damage = damageInfo.GetDamage(); - victim->DealDamageMods(this, damage, nullptr); + Unit::DealDamageMods(victim, this, damage, nullptr); WorldPackets::CombatLog::SpellDamageShield damageShield; damageShield.Attacker = victim->GetGUID(); @@ -1518,7 +1522,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss) damageShield.SchoolMask = spellInfo->SchoolMask; damageShield.LogAbsorbed = damageInfo.GetAbsorb(); - victim->DealDamage(this, damage, nullptr, SPELL_DIRECT_DAMAGE, spellInfo->GetSchoolMask(), spellInfo, true); + Unit::DealDamage(victim, this, damage, nullptr, SPELL_DIRECT_DAMAGE, spellInfo->GetSchoolMask(), spellInfo, true); damageShield.LogData.Initialize(this); victim->SendCombatLogMessage(&damageShield); @@ -1539,7 +1543,7 @@ void Unit::HandleEmoteCommand(uint32 anim_id, Trinity::IteratorPair<int32 const* SendMessageToSet(packet.Write(), true); } -bool Unit::IsDamageReducedByArmor(SpellSchoolMask schoolMask, SpellInfo const* spellInfo /*= nullptr*/, int8 effIndex /*= -1*/) +/*static*/ bool Unit::IsDamageReducedByArmor(SpellSchoolMask schoolMask, SpellInfo const* spellInfo /*= nullptr*/, int8 effIndex /*= -1*/) { // only physical spells damage gets reduced by armor if ((schoolMask & SPELL_SCHOOL_MASK_NORMAL) == 0) @@ -1566,58 +1570,63 @@ bool Unit::IsDamageReducedByArmor(SpellSchoolMask schoolMask, SpellInfo const* s return true; } -uint32 Unit::CalcArmorReducedDamage(Unit* attacker, Unit* victim, const uint32 damage, SpellInfo const* spellInfo, WeaponAttackType /*attackType*/) const +/*static*/ uint32 Unit::CalcArmorReducedDamage(Unit const* attacker, Unit* victim, uint32 damage, SpellInfo const* spellInfo, uint8 attackerLevel /*= 0*/, WeaponAttackType /*attackType*/ /*= MAX_ATTACK*/) { float armor = float(victim->GetArmor()); - armor *= victim->GetArmorMultiplierForTarget(attacker); + if (attacker) + { + armor *= victim->GetArmorMultiplierForTarget(attacker); - // bypass enemy armor by SPELL_AURA_BYPASS_ARMOR_FOR_CASTER - int32 armorBypassPct = 0; - AuraEffectList const & reductionAuras = victim->GetAuraEffectsByType(SPELL_AURA_BYPASS_ARMOR_FOR_CASTER); - for (AuraEffectList::const_iterator i = reductionAuras.begin(); i != reductionAuras.end(); ++i) - if ((*i)->GetCasterGUID() == GetGUID()) - armorBypassPct += (*i)->GetAmount(); - armor = CalculatePct(armor, 100 - std::min(armorBypassPct, 100)); + // bypass enemy armor by SPELL_AURA_BYPASS_ARMOR_FOR_CASTER + int32 armorBypassPct = 0; + AuraEffectList const & reductionAuras = victim->GetAuraEffectsByType(SPELL_AURA_BYPASS_ARMOR_FOR_CASTER); + for (AuraEffectList::const_iterator i = reductionAuras.begin(); i != reductionAuras.end(); ++i) + if ((*i)->GetCasterGUID() == attacker->GetGUID()) + armorBypassPct += (*i)->GetAmount(); + armor = CalculatePct(armor, 100 - std::min(armorBypassPct, 100)); - // Ignore enemy armor by SPELL_AURA_MOD_TARGET_RESISTANCE aura - armor += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, SPELL_SCHOOL_MASK_NORMAL); + // Ignore enemy armor by SPELL_AURA_MOD_TARGET_RESISTANCE aura + armor += attacker->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, SPELL_SCHOOL_MASK_NORMAL); - if (spellInfo) - if (Player* modOwner = GetSpellModOwner()) - modOwner->ApplySpellMod(spellInfo, SpellModOp::TargetResistance, armor); + if (spellInfo) + if (Player* modOwner = attacker->GetSpellModOwner()) + modOwner->ApplySpellMod(spellInfo, SpellModOp::TargetResistance, armor); - AuraEffectList const& resIgnoreAuras = GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST); - for (AuraEffectList::const_iterator j = resIgnoreAuras.begin(); j != resIgnoreAuras.end(); ++j) - { - if ((*j)->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL && (*j)->IsAffectingSpell(spellInfo)) - armor = std::floor(AddPct(armor, -(*j)->GetAmount())); - } + AuraEffectList const& resIgnoreAuras = attacker->GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST); + for (AuraEffect const* aurEff : resIgnoreAuras) + { + if (aurEff->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL && aurEff->IsAffectingSpell(spellInfo)) + armor = std::floor(AddPct(armor, -aurEff->GetAmount())); + } - // Apply Player CR_ARMOR_PENETRATION rating - if (GetTypeId() == TYPEID_PLAYER) - { - float arpPct = ToPlayer()->GetRatingBonusValue(CR_ARMOR_PENETRATION); + // Apply Player CR_ARMOR_PENETRATION rating + if (attacker->GetTypeId() == TYPEID_PLAYER) + { + float arpPct = attacker->ToPlayer()->GetRatingBonusValue(CR_ARMOR_PENETRATION); - // no more than 100% - RoundToInterval(arpPct, 0.f, 100.f); + // no more than 100% + RoundToInterval(arpPct, 0.f, 100.f); - float maxArmorPen = 0.f; - if (victim->GetLevelForTarget(attacker) < 60) - maxArmorPen = float(400 + 85 * victim->GetLevelForTarget(attacker)); - else - maxArmorPen = 400 + 85 * victim->GetLevelForTarget(attacker) + 4.5f * 85 * (victim->GetLevelForTarget(attacker) - 59); + float maxArmorPen = 0.f; + if (victim->GetLevelForTarget(attacker) < 60) + maxArmorPen = float(400 + 85 * victim->GetLevelForTarget(attacker)); + else + maxArmorPen = 400 + 85 * victim->GetLevelForTarget(attacker) + 4.5f * 85 * (victim->GetLevelForTarget(attacker) - 59); - // Cap armor penetration to this number - maxArmorPen = std::min((armor + maxArmorPen) / 3.f, armor); - // Figure out how much armor do we ignore - armor -= CalculatePct(maxArmorPen, arpPct); + // Cap armor penetration to this number + maxArmorPen = std::min((armor + maxArmorPen) / 3.f, armor); + // Figure out how much armor do we ignore + armor -= CalculatePct(maxArmorPen, arpPct); + } } if (G3D::fuzzyLe(armor, 0.0f)) return damage; - uint8 attackerLevel = attacker->GetLevelForTarget(victim); + if (attacker) + attackerLevel = attacker->GetLevelForTarget(victim); + // Expansion and ContentTuningID necessary? Does Player get a ContentTuningID too ? float armorConstant = sDB2Manager.EvaluateExpectedStat(ExpectedStatType::ArmorConstant, attackerLevel, -2, 0, Classes(attacker->getClass())); @@ -1628,7 +1637,7 @@ uint32 Unit::CalcArmorReducedDamage(Unit* attacker, Unit* victim, const uint32 d return std::max<uint32>(damage * (1.0f - mitigation), 1); } -uint32 Unit::CalcSpellResistedDamage(Unit* attacker, Unit* victim, uint32 damage, SpellSchoolMask schoolMask, SpellInfo const* spellInfo) +/*static*/ uint32 Unit::CalcSpellResistedDamage(Unit const* attacker, Unit* victim, uint32 damage, SpellSchoolMask schoolMask, SpellInfo const* spellInfo) { // Magic damage, check for resists if (!(schoolMask & SPELL_SCHOOL_MASK_MAGIC)) @@ -1649,8 +1658,7 @@ uint32 Unit::CalcSpellResistedDamage(Unit* attacker, Unit* victim, uint32 damage return 0; } - float const averageResist = CalculateAverageResistReduction(schoolMask, victim, spellInfo); - + float const averageResist = Unit::CalculateAverageResistReduction(attacker, schoolMask, victim, spellInfo); float discreteResistProbability[11] = { }; if (averageResist <= 0.1f) { @@ -1677,7 +1685,8 @@ uint32 Unit::CalcSpellResistedDamage(Unit* attacker, Unit* victim, uint32 damage { int32 ignoredResistance = 0; - ignoredResistance += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_IGNORE_TARGET_RESIST, schoolMask); + if (attacker) + ignoredResistance += attacker->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_IGNORE_TARGET_RESIST, schoolMask); ignoredResistance = std::min<int32>(ignoredResistance, 100); ApplyPct(damageResisted, 100 - ignoredResistance); @@ -1685,7 +1694,7 @@ uint32 Unit::CalcSpellResistedDamage(Unit* attacker, Unit* victim, uint32 damage // Spells with melee and magic school mask, decide whether resistance or armor absorb is higher if (spellInfo && spellInfo->HasAttribute(SPELL_ATTR0_CU_SCHOOLMASK_NORMAL_WITH_MAGIC)) { - uint32 damageAfterArmor = CalcArmorReducedDamage(attacker, victim, damage, spellInfo, BASE_ATTACK); + uint32 damageAfterArmor = Unit::CalcArmorReducedDamage(attacker, victim, damage, spellInfo, BASE_ATTACK); float armorReduction = damage - damageAfterArmor; // pick the lower one, the weakest resistance counts @@ -1697,20 +1706,22 @@ uint32 Unit::CalcSpellResistedDamage(Unit* attacker, Unit* victim, uint32 damage return uint32(damageResisted); } -float Unit::CalculateAverageResistReduction(SpellSchoolMask schoolMask, Unit const* victim, SpellInfo const* spellInfo) const +/*static*/ float Unit::CalculateAverageResistReduction(Unit const* attacker, SpellSchoolMask schoolMask, Unit const* victim, SpellInfo const* spellInfo /*= nullptr*/) { float victimResistance = float(victim->GetResistance(schoolMask)); - - // pets inherit 100% of masters penetration - // excluding traps - Player const* player = GetSpellModOwner(); - if (player && GetEntry() != WORLD_TRIGGER) + if (attacker) { - victimResistance += float(player->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, schoolMask)); - victimResistance -= float(player->GetSpellPenetrationItemMod()); + // pets inherit 100% of masters penetration + // excluding traps + Player const* player = attacker->GetSpellModOwner(); + if (player && attacker->GetEntry() != WORLD_TRIGGER) + { + victimResistance += float(player->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, schoolMask)); + victimResistance -= float(player->GetSpellPenetrationItemMod()); + } + else + victimResistance += float(attacker->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, schoolMask)); } - else - victimResistance += float(GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, schoolMask)); // holy resistance exists in pve and comes from level difference, ignore template values if (schoolMask & SPELL_SCHOOL_MASK_HOLY) @@ -1723,12 +1734,12 @@ float Unit::CalculateAverageResistReduction(SpellSchoolMask schoolMask, Unit con victimResistance = std::max(victimResistance, 0.0f); // level-based resistance does not apply to binary spells, and cannot be overcome by spell penetration - if (!spellInfo || !spellInfo->HasAttribute(SPELL_ATTR0_CU_BINARY_SPELL)) - victimResistance += std::max((float(victim->GetLevelForTarget(this)) - float(GetLevelForTarget(victim))) * 5.0f, 0.0f); + if (attacker && (!spellInfo || !spellInfo->HasAttribute(SPELL_ATTR0_CU_BINARY_SPELL))) + victimResistance += std::max((float(victim->GetLevelForTarget(attacker)) - float(attacker->GetLevelForTarget(victim))) * 5.0f, 0.0f); static uint32 const bossLevel = 83; static float const bossResistanceConstant = 510.0f; - uint32 level = victim->GetLevelForTarget(this); + uint32 level = attacker ? victim->GetLevelForTarget(attacker) : victim->getLevel(); float resistanceConstant = 0.0f; if (level == bossLevel) @@ -1739,16 +1750,18 @@ float Unit::CalculateAverageResistReduction(SpellSchoolMask schoolMask, Unit con return victimResistance / (victimResistance + resistanceConstant); } -void Unit::CalcAbsorbResist(DamageInfo& damageInfo) +/*static*/ void Unit::CalcAbsorbResist(DamageInfo& damageInfo) { if (!damageInfo.GetVictim() || !damageInfo.GetVictim()->IsAlive() || !damageInfo.GetDamage()) return; - uint32 resistedDamage = CalcSpellResistedDamage(damageInfo.GetAttacker(), damageInfo.GetVictim(), damageInfo.GetDamage(), damageInfo.GetSchoolMask(), damageInfo.GetSpellInfo()); + uint32 resistedDamage = Unit::CalcSpellResistedDamage(damageInfo.GetAttacker(), damageInfo.GetVictim(), damageInfo.GetDamage(), damageInfo.GetSchoolMask(), damageInfo.GetSpellInfo()); damageInfo.ResistDamage(resistedDamage); // Ignore Absorption Auras - float auraAbsorbMod(GetMaxPositiveAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_ABSORB_SCHOOL, damageInfo.GetSchoolMask())); + float auraAbsorbMod = 0.f; + if (Unit* attacker = damageInfo.GetAttacker()) + auraAbsorbMod = attacker->GetMaxPositiveAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_ABSORB_SCHOOL, damageInfo.GetSchoolMask()); RoundToInterval(auraAbsorbMod, 0.0f, 100.0f); @@ -1808,7 +1821,7 @@ void Unit::CalcAbsorbResist(DamageInfo& damageInfo) if (currentAbsorb) { WorldPackets::CombatLog::SpellAbsorbLog absorbLog; - absorbLog.Attacker = damageInfo.GetAttacker()->GetGUID(); + absorbLog.Attacker = damageInfo.GetAttacker() ? damageInfo.GetAttacker()->GetGUID() : ObjectGuid::Empty; absorbLog.Victim = damageInfo.GetVictim()->GetGUID(); absorbLog.Caster = absorbAurEff->GetBase()->GetCasterGUID(); absorbLog.AbsorbedSpellID = damageInfo.GetSpellInfo() ? damageInfo.GetSpellInfo()->Id : 0; @@ -1816,7 +1829,7 @@ void Unit::CalcAbsorbResist(DamageInfo& damageInfo) absorbLog.Absorbed = currentAbsorb; absorbLog.OriginalDamage = damageInfo.GetOriginalDamage(); absorbLog.LogData.Initialize(damageInfo.GetVictim()); - SendCombatLogMessage(&absorbLog); + damageInfo.GetVictim()->SendCombatLogMessage(&absorbLog); } } @@ -1879,7 +1892,7 @@ void Unit::CalcAbsorbResist(DamageInfo& damageInfo) if (currentAbsorb) { WorldPackets::CombatLog::SpellAbsorbLog absorbLog; - absorbLog.Attacker = damageInfo.GetAttacker()->GetGUID(); + absorbLog.Attacker = damageInfo.GetAttacker() ? damageInfo.GetAttacker()->GetGUID() : ObjectGuid::Empty; absorbLog.Victim = damageInfo.GetVictim()->GetGUID(); absorbLog.Caster = absorbAurEff->GetBase()->GetCasterGUID(); absorbLog.AbsorbedSpellID = damageInfo.GetSpellInfo() ? damageInfo.GetSpellInfo()->Id : 0; @@ -1887,14 +1900,14 @@ void Unit::CalcAbsorbResist(DamageInfo& damageInfo) absorbLog.Absorbed = currentAbsorb; absorbLog.OriginalDamage = damageInfo.GetOriginalDamage(); absorbLog.LogData.Initialize(damageInfo.GetVictim()); - SendCombatLogMessage(&absorbLog); + damageInfo.GetVictim()->SendCombatLogMessage(&absorbLog); } } damageInfo.ModifyDamage(absorbIgnoringDamage); // split damage auras - only when not damaging self - if (damageInfo.GetVictim() != this) + if (damageInfo.GetVictim() != damageInfo.GetAttacker()) { // 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 @@ -1932,23 +1945,23 @@ void Unit::CalcAbsorbResist(DamageInfo& damageInfo) } uint32 split_absorb = 0; - DealDamageMods(caster, splitDamage, &split_absorb); + Unit::DealDamageMods(damageInfo.GetAttacker(), caster, splitDamage, &split_absorb); - SpellNonMeleeDamage log(this, caster, (*itr)->GetSpellInfo(), (*itr)->GetBase()->GetSpellVisual(), damageInfo.GetSchoolMask(), (*itr)->GetBase()->GetCastGUID()); + SpellNonMeleeDamage log(damageInfo.GetAttacker(), caster, (*itr)->GetSpellInfo(), (*itr)->GetBase()->GetSpellVisual(), damageInfo.GetSchoolMask(), (*itr)->GetBase()->GetCastGUID()); CleanDamage cleanDamage = CleanDamage(splitDamage, 0, BASE_ATTACK, MELEE_HIT_NORMAL); - DealDamage(caster, splitDamage, &cleanDamage, DIRECT_DAMAGE, damageInfo.GetSchoolMask(), (*itr)->GetSpellInfo(), false); + Unit::DealDamage(damageInfo.GetAttacker(), caster, splitDamage, &cleanDamage, DIRECT_DAMAGE, damageInfo.GetSchoolMask(), (*itr)->GetSpellInfo(), false); log.damage = splitDamage; log.originalDamage = splitDamage; log.absorb = split_absorb; - SendSpellNonMeleeDamageLog(&log); + caster->SendSpellNonMeleeDamageLog(&log); // break 'Fear' and similar auras - 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); + Unit::ProcSkillsAndAuras(damageInfo.GetAttacker(), 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); } } } -void Unit::CalcHealAbsorb(HealInfo& healInfo) const +/*static*/ void Unit::CalcHealAbsorb(HealInfo& healInfo) { if (!healInfo.GetHeal()) return; @@ -2061,13 +2074,13 @@ void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType, bool extr CalcDamageInfo damageInfo; CalculateMeleeDamage(victim, 0, &damageInfo, attType); // Send log damage message to client - DealDamageMods(victim, damageInfo.damage, &damageInfo.absorb); + Unit::DealDamageMods(damageInfo.attacker, victim, damageInfo.damage, &damageInfo.absorb); SendAttackStateUpdate(&damageInfo); DealMeleeDamage(&damageInfo, true); DamageInfo dmgInfo(damageInfo); - ProcSkillsAndAuras(damageInfo.target, damageInfo.procAttacker, damageInfo.procVictim, PROC_SPELL_TYPE_NONE, PROC_SPELL_PHASE_NONE, dmgInfo.GetHitMask(), nullptr, &dmgInfo, nullptr); + Unit::ProcSkillsAndAuras(damageInfo.attacker, damageInfo.target, damageInfo.procAttacker, damageInfo.procVictim, PROC_SPELL_TYPE_NONE, PROC_SPELL_PHASE_NONE, dmgInfo.GetHitMask(), nullptr, &dmgInfo, nullptr); TC_LOG_DEBUG("entities.unit", "AttackerStateUpdate: %s attacked %s for %u dmg, absorbed %u, blocked %u, resisted %u.", GetGUID().ToString().c_str(), victim->GetGUID().ToString().c_str(), damageInfo.damage, damageInfo.absorb, damageInfo.blocked_amount, damageInfo.resist); @@ -2150,7 +2163,7 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(Unit const* victim, WeaponAttackTy int32 miss_chance = int32(MeleeSpellMissChance(victim, attType, nullptr) * 100.0f); // Critical hit chance - int32 crit_chance = int32(GetUnitCriticalChance(attType, victim) + GetTotalAuraModifier(SPELL_AURA_MOD_AUTOATTACK_CRIT_CHANCE) * 100.0f); + int32 crit_chance = int32((GetUnitCriticalChanceAgainst(attType, victim) + GetTotalAuraModifier(SPELL_AURA_MOD_AUTOATTACK_CRIT_CHANCE)) * 100.0f); int32 dodge_chance = int32(GetUnitDodgeChance(attType, victim) * 100.0f); int32 block_chance = int32(GetUnitBlockChance(attType, victim) * 100.0f); @@ -2781,7 +2794,7 @@ float Unit::GetUnitBlockChance(WeaponAttackType /*attType*/, Unit const* victim) return std::max(chance, 0.0f); } -float Unit::GetUnitCriticalChance(WeaponAttackType attackType, Unit const* victim) const +float Unit::GetUnitCriticalChanceDone(WeaponAttackType attackType) const { float chance = 0.0f; if (Player const* thisPlayer = ToPlayer()) @@ -2813,35 +2826,48 @@ float Unit::GetUnitCriticalChance(WeaponAttackType attackType, Unit const* victi } } + return chance; +} + +float Unit::GetUnitCriticalChanceTaken(Unit const* attacker, WeaponAttackType attackType, float critDone) const +{ + float chance = critDone; + // flat aura mods if (attackType == RANGED_ATTACK) - chance += victim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_CHANCE); + chance += GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_CHANCE); else - chance += victim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_CHANCE); + chance += GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_CHANCE); - chance += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_CHANCE_VERSUS_TARGET_HEALTH, [victim](AuraEffect const* aurEff) + chance += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_CHANCE_VERSUS_TARGET_HEALTH, [this](AuraEffect const* aurEff) { - return !victim->HealthBelowPct(aurEff->GetMiscValueB()); + return !HealthBelowPct(aurEff->GetMiscValueB()); }); - chance += victim->GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER, [this](AuraEffect const* aurEff) -> bool + chance += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER, [attacker](AuraEffect const* aurEff) -> bool { - return aurEff->GetCasterGUID() == GetGUID(); + return aurEff->GetCasterGUID() == attacker->GetGUID(); }); - if (TempSummon const* tempSummon = ToTempSummon()) + if (TempSummon const* tempSummon = attacker->ToTempSummon()) { - chance += victim->GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER_PET, [tempSummon](AuraEffect const* aurEff) -> bool + chance += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER_PET, [tempSummon](AuraEffect const* aurEff) -> bool { return aurEff->GetCasterGUID() == tempSummon->GetSummonerGUID(); }); } - chance += victim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE); + chance += GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE); return std::max(chance, 0.0f); } +float Unit::GetUnitCriticalChanceAgainst(WeaponAttackType attackType, Unit const* victim) const +{ + float chance = GetUnitCriticalChanceDone(attackType); + return victim->GetUnitCriticalChanceTaken(this, attackType, chance); +} + void Unit::_DeleteRemovedAuras() { while (!m_removedAuras.empty()) @@ -3416,7 +3442,6 @@ void Unit::_ApplyAura(AuraApplication * aurApp, uint32 effMask) if (aurApp->GetRemoveMode()) return; - aura->HandleAuraSpecificPeriodics(aurApp, caster); aura->HandleAuraSpecificMods(aurApp, caster, true, false); // apply effects of the aura @@ -5312,16 +5337,17 @@ void Unit::SendSpellNonMeleeDamageLog(SpellNonMeleeDamage const* log) SendCombatLogMessage(&packet); } -void Unit::ProcSkillsAndAuras(Unit* actionTarget, uint32 typeMaskActor, uint32 typeMaskActionTarget, uint32 spellTypeMask, uint32 spellPhaseMask, uint32 hitMask, Spell* spell, DamageInfo* damageInfo, HealInfo* healInfo) +/*static*/ void Unit::ProcSkillsAndAuras(Unit* actor, Unit* actionTarget, uint32 typeMaskActor, uint32 typeMaskActionTarget, uint32 spellTypeMask, uint32 spellPhaseMask, uint32 hitMask, Spell* spell, DamageInfo* damageInfo, HealInfo* healInfo) { WeaponAttackType attType = damageInfo ? damageInfo->GetAttackType() : BASE_ATTACK; - if (typeMaskActor) - ProcSkillsAndReactives(false, actionTarget, typeMaskActor, hitMask, attType); + if (typeMaskActor && actor) + actor->ProcSkillsAndReactives(false, actionTarget, typeMaskActor, hitMask, attType); if (typeMaskActionTarget && actionTarget) - actionTarget->ProcSkillsAndReactives(true, this, typeMaskActionTarget, hitMask, attType); + actionTarget->ProcSkillsAndReactives(true, actor, typeMaskActionTarget, hitMask, attType); - TriggerAurasProcOnEvent(nullptr, nullptr, actionTarget, typeMaskActor, typeMaskActionTarget, spellTypeMask, spellPhaseMask, hitMask, spell, damageInfo, healInfo); + if (actor) + actor->TriggerAurasProcOnEvent(nullptr, nullptr, actionTarget, typeMaskActor, typeMaskActionTarget, spellTypeMask, spellPhaseMask, hitMask, spell, damageInfo, healInfo); } void Unit::SendPeriodicAuraLog(SpellPeriodicAuraLogInfo* info) @@ -6431,39 +6457,45 @@ void Unit::SetCharm(Unit* charm, bool apply) UpdatePetCombatState(); } -void Unit::DealHeal(HealInfo& healInfo) +/*static*/ void Unit::DealHeal(HealInfo& healInfo) { int32 gain = 0; + Unit* healer = healInfo.GetHealer(); Unit* victim = healInfo.GetTarget(); uint32 addhealth = healInfo.GetHeal(); - if (victim->IsAIEnabled) - victim->GetAI()->HealReceived(this, addhealth); + if (healer) + { + if (victim->IsAIEnabled) + victim->GetAI()->HealReceived(healer, addhealth); - if (IsAIEnabled) - GetAI()->HealDone(victim, addhealth); + if (healer->IsAIEnabled) + healer->GetAI()->HealDone(victim, addhealth); + } if (addhealth) gain = victim->ModifyHealth(int32(addhealth)); // Hook for OnHeal Event - sScriptMgr->OnHeal(this, victim, (uint32&)gain); - - Unit* unit = this; + sScriptMgr->OnHeal(healer, victim, (uint32&)gain); - if (GetTypeId() == TYPEID_UNIT && IsTotem()) - unit = GetOwner(); + Unit* unit = healer; + if (healer && healer->GetTypeId() == TYPEID_UNIT && healer->IsTotem()) + unit = healer->GetOwner(); - if (Player* player = unit->ToPlayer()) + if (unit) { - if (Battleground* bg = player->GetBattleground()) - bg->UpdatePlayerScore(player, SCORE_HEALING_DONE, gain); + if (Player* player = unit->ToPlayer()) + { + if (Battleground* bg = player->GetBattleground()) + bg->UpdatePlayerScore(player, SCORE_HEALING_DONE, gain); - // use the actual gain, as the overheal shall not be counted, skip gain 0 (it ignored anyway in to criteria) - if (gain) - player->UpdateCriteria(CRITERIA_TYPE_HEALING_DONE, gain, 0, 0, victim); + // use the actual gain, as the overheal shall not be counted, skip gain 0 (it ignored anyway in to criteria) + if (gain) + player->UpdateCriteria(CRITERIA_TYPE_HEALING_DONE, gain, 0, 0, victim); - player->UpdateCriteria(CRITERIA_TYPE_HIGHEST_HEAL_CAST, addhealth); + player->UpdateCriteria(CRITERIA_TYPE_HIGHEST_HEAL_CAST, addhealth); + } } if (Player* player = victim->ToPlayer()) @@ -6718,9 +6750,8 @@ void Unit::SendHealSpellLog(HealInfo& healInfo, bool critical /*= false*/) int32 Unit::HealBySpell(HealInfo& healInfo, bool critical /*= false*/) { // calculate heal absorb and reduce healing - CalcHealAbsorb(healInfo); - - DealHeal(healInfo); + Unit::CalcHealAbsorb(healInfo); + Unit::DealHeal(healInfo); SendHealSpellLog(healInfo, critical); return healInfo.GetEffectiveHeal(); } @@ -6746,7 +6777,7 @@ void Unit::EnergizeBySpell(Unit* victim, SpellInfo const* spellInfo, int32 damag SendEnergizeSpellLog(victim, spellInfo->Id, gain, overEnergize, powerType); } -uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, SpellEffectInfo const* effect, uint32 stack) const +uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, SpellEffectInfo const* effect, uint32 stack /*= 1*/) const { if (!spellProto || !victim || damagetype == DIRECT_DAMAGE) return pdamage; @@ -6761,6 +6792,7 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin return owner->SpellDamageBonusDone(victim, spellProto, pdamage, damagetype, effect, stack); int32 DoneTotal = 0; + float DoneTotalMod = SpellDamagePctDone(victim, spellProto, damagetype); // Done fixed damage bonus auras int32 DoneAdvertisedBenefit = SpellBaseDamageBonusDone(spellProto->GetSchoolMask()); @@ -6808,16 +6840,11 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin DoneTotal += int32(DoneAdvertisedBenefit * coeff * stack); } - // Done Percentage for DOT is already calculated, no need to do it again. The percentage mod is applied in Aura::HandleAuraSpecificMods. - float tmpDamage = (int32(pdamage) + DoneTotal) * (damagetype == DOT ? 1.0f : SpellDamagePctDone(victim, spellProto, damagetype)); + float tmpDamage = float(int32(pdamage) + DoneTotal) * DoneTotalMod; + // apply spellmod to Done damage (flat and pct) if (Player* modOwner = GetSpellModOwner()) - { - if (damagetype == DOT) - modOwner->ApplySpellMod(spellProto, SpellModOp::PeriodicHealingAndDamage, tmpDamage); - else - modOwner->ApplySpellMod(spellProto, SpellModOp::HealingAndDamage, tmpDamage); - } + modOwner->ApplySpellMod(spellProto, damagetype == DOT ? SpellModOp::PeriodicHealingAndDamage : SpellModOp::HealingAndDamage, tmpDamage); return uint32(std::max(tmpDamage, 0.0f)); } @@ -6827,13 +6854,18 @@ float Unit::SpellDamagePctDone(Unit* victim, SpellInfo const* spellProto, Damage if (!spellProto || !victim || damagetype == DIRECT_DAMAGE) return 1.0f; + // Some spells don't benefit from done mods + if (spellProto->HasAttribute(SPELL_ATTR3_NO_DONE_BONUS)) + return 1.0f; + // Some spells don't benefit from pct done mods if (spellProto->HasAttribute(SPELL_ATTR6_IGNORE_CASTER_DAMAGE_MODIFIERS)) return 1.0f; - // For totems pct done mods are calculated when its calculation is run on the player in SpellDamageBonusDone. + // For totems get damage bonus from owner if (GetTypeId() == TYPEID_UNIT && IsTotem()) - return 1.0f; + if (Unit* owner = GetOwner()) + return owner->SpellDamagePctDone(victim, spellProto, damagetype); // Done total percent damage auras float DoneTotalMod = 1.0f; @@ -7040,41 +7072,19 @@ int32 Unit::SpellBaseDamageBonusTaken(SpellSchoolMask schoolMask) const return GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_DAMAGE_TAKEN, schoolMask); } -bool Unit::IsSpellCrit(Unit* victim, Spell* spell, AuraEffect const* aurEff, SpellSchoolMask schoolMask, WeaponAttackType attackType /*= BASE_ATTACK*/) const -{ - return roll_chance_f(GetUnitSpellCriticalChance(victim, spell, aurEff, schoolMask, attackType)); -} - -float Unit::GetUnitSpellCriticalChance(Unit* victim, Spell* spell, AuraEffect const* aurEff, SpellSchoolMask schoolMask, WeaponAttackType attackType /*= BASE_ATTACK*/) const +float Unit::SpellCritChanceDone(SpellInfo const* spellInfo, SpellSchoolMask schoolMask, WeaponAttackType attackType /*= BASE_ATTACK*/) const { - SpellInfo const* spellProto = spell ? spell->GetSpellInfo() : aurEff->GetSpellInfo(); - //! Mobs can't crit with spells. Player Totems can - //! Fire Elemental (from totem) can too - but this part is a hack and needs more research - if (GetGUID().IsCreatureOrVehicle() && !(IsTotem() && GetOwnerGUID().IsPlayer()) && GetEntry() != 15438) + //! Mobs can't crit with spells. (Except player controlled) + if (GetTypeId() == TYPEID_UNIT && !GetSpellModOwner()) return 0.0f; // not critting spell - if ((spellProto->HasAttribute(SPELL_ATTR2_CANT_CRIT))) + if (spellInfo->HasAttribute(SPELL_ATTR2_CANT_CRIT)) return 0.0f; float crit_chance = 0.0f; - switch (spellProto->DmgClass) + switch (spellInfo->DmgClass) { - case SPELL_DAMAGE_CLASS_NONE: - // We need more spells to find a general way (if there is any) - switch (spellProto->Id) - { - case 379: // Earth Shield - case 33778: // Lifebloom Final Bloom - case 64844: // Divine Hymn - case 71607: // Item - Bauble of True Blood 10m - case 71646: // Item - Bauble of True Blood 25m - break; - default: - return 0.0f; - } - // Do not add a break here, case fallthrough is intentional! Adding a break will make above spells unable to crit. - /* fallthrough */ case SPELL_DAMAGE_CLASS_MAGIC: { if (schoolMask & SPELL_SCHOOL_MASK_NORMAL) @@ -7084,25 +7094,58 @@ float Unit::GetUnitSpellCriticalChance(Unit* victim, Spell* spell, AuraEffect co crit_chance = thisPlayer->m_activePlayerData->SpellCritPercentage; else crit_chance = (float)m_baseSpellCritChance; + break; + } + case SPELL_DAMAGE_CLASS_MELEE: + case SPELL_DAMAGE_CLASS_RANGED: + { + crit_chance += GetUnitCriticalChanceDone(attackType); + break; + } + case SPELL_DAMAGE_CLASS_NONE: + default: + return 0.0f; + } + // percent done + // only players use intelligence for critical chance computations + if (Player* modOwner = GetSpellModOwner()) + modOwner->ApplySpellMod(spellInfo, SpellModOp::CritChance, crit_chance); + + return std::max(crit_chance, 0.0f); +} + +float Unit::SpellCritChanceTaken(Unit const* caster, Spell* spell, AuraEffect const* aurEff, SpellSchoolMask /*schoolMask*/, float doneChance, WeaponAttackType attackType /*= BASE_ATTACK*/) const +{ + SpellInfo const* spellInfo = spell ? spell->GetSpellInfo() : aurEff->GetSpellInfo(); + // not critting spell + if (spellInfo->HasAttribute(SPELL_ATTR2_CANT_CRIT)) + return 0.0f; + + float crit_chance = doneChance; + switch (spellInfo->DmgClass) + { + case SPELL_DAMAGE_CLASS_MAGIC: + { // taken - if (victim) + if (!spellInfo->IsPositive()) + { + // Modify critical chance by victim SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE + crit_chance += GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE); + } + + if (caster) { - if (!spellProto->IsPositive()) - { - // Modify critical chance by victim SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE - crit_chance += victim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE); - } // scripted (increase crit chance ... against ... target by x% - AuraEffectList const& mOverrideClassScript = GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + AuraEffectList const& mOverrideClassScript = caster->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); for (AuraEffect const* aurEff : mOverrideClassScript) { - if (!aurEff->IsAffectingSpell(spellProto)) + if (!aurEff->IsAffectingSpell(spellInfo)) continue; switch (aurEff->GetMiscValue()) { case 911: // Shatter - if (victim->HasAuraState(AURA_STATE_FROZEN, spellProto, this)) + if (HasAuraState(AURA_STATE_FROZEN, spellInfo, caster)) { crit_chance *= 1.5f; if (AuraEffect const* eff = aurEff->GetBase()->GetEffect(EFFECT_1)) @@ -7114,19 +7157,19 @@ float Unit::GetUnitSpellCriticalChance(Unit* victim, Spell* spell, AuraEffect co } } // Custom crit by class - switch (spellProto->SpellFamilyName) + switch (spellInfo->SpellFamilyName) { case SPELLFAMILY_ROGUE: // Shiv-applied poisons can't crit - if (FindCurrentSpellBySpellId(5938)) + if (caster->FindCurrentSpellBySpellId(5938)) crit_chance = 0.0f; break; case SPELLFAMILY_SHAMAN: // Lava Burst - if (spellProto->SpellFamilyFlags[1] & 0x00001000) + if (spellInfo->SpellFamilyFlags[1] & 0x00001000) { - if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_SHAMAN, flag128(0x10000000, 0, 0), GetGUID())) - if (victim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE) > -100) + if (GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_SHAMAN, flag128(0x10000000, 0, 0), caster->GetGUID())) + if (GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE) > -100) return 100.0f; break; } @@ -7134,48 +7177,44 @@ float Unit::GetUnitSpellCriticalChance(Unit* victim, Spell* spell, AuraEffect co } // Spell crit suppression - if (victim->GetTypeId() == TYPEID_UNIT) + if (GetTypeId() == TYPEID_UNIT) { - int32 const levelDiff = static_cast<int32>(victim->GetLevelForTarget(this)) - getLevel(); + int32 const levelDiff = static_cast<int32>(GetLevelForTarget(caster)) - caster->getLevel(); crit_chance -= levelDiff * 1.0f; } } break; } case SPELL_DAMAGE_CLASS_MELEE: + /// Intentional fallback. Calculate critical strike chance for both Ranged and Melee spells case SPELL_DAMAGE_CLASS_RANGED: - { - if (victim) - crit_chance += GetUnitCriticalChance(attackType, victim); + if (caster) + crit_chance = GetUnitCriticalChanceTaken(caster, attackType, crit_chance); break; - } + case SPELL_DAMAGE_CLASS_NONE: default: - return 0.0f; + return 0.f; } - // percent done - // only players use intelligence for critical chance computations - if (Player* modOwner = GetSpellModOwner()) - modOwner->ApplySpellMod(spellProto, SpellModOp::CritChance, crit_chance); // for this types the bonus was already added in GetUnitCriticalChance, do not add twice - if (spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE && spellProto->DmgClass != SPELL_DAMAGE_CLASS_RANGED) + if (caster && spellInfo->DmgClass != SPELL_DAMAGE_CLASS_MELEE && spellInfo->DmgClass != SPELL_DAMAGE_CLASS_RANGED) { - crit_chance += victim->GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER_WITH_ABILITIES, [this, spellProto](AuraEffect const* aurEff) -> bool + crit_chance += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER_WITH_ABILITIES, [caster, spellInfo](AuraEffect const* aurEff) -> bool { - return aurEff->GetCasterGUID() == GetGUID() && aurEff->IsAffectingSpell(spellProto); + return aurEff->GetCasterGUID() == caster->GetGUID() && aurEff->IsAffectingSpell(spellInfo); }); - crit_chance += victim->GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER, [this](AuraEffect const* aurEff) -> bool + crit_chance += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER, [caster](AuraEffect const* aurEff) -> bool { - return aurEff->GetCasterGUID() != GetGUID(); + return aurEff->GetCasterGUID() == caster->GetGUID(); }); - crit_chance += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_CHANCE_VERSUS_TARGET_HEALTH, [victim](AuraEffect const* aurEff) + crit_chance += caster->GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_CHANCE_VERSUS_TARGET_HEALTH, [this](AuraEffect const* aurEff) { - return !victim->HealthBelowPct(aurEff->GetMiscValueB()); + return !HealthBelowPct(aurEff->GetMiscValueB()); }); - if (TempSummon const* tempSummon = ToTempSummon()) + if (TempSummon const* tempSummon = caster->ToTempSummon()) { - crit_chance += victim->GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER_PET, [tempSummon](AuraEffect const* aurEff) -> bool + crit_chance += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER_PET, [tempSummon](AuraEffect const* aurEff) -> bool { return aurEff->GetCasterGUID() == tempSummon->GetSummonerGUID(); }); @@ -7184,57 +7223,62 @@ float Unit::GetUnitSpellCriticalChance(Unit* victim, Spell* spell, AuraEffect co // call script handlers if (spell) - spell->CallScriptCalcCritChanceHandlers(victim, crit_chance); + spell->CallScriptCalcCritChanceHandlers(this, crit_chance); else - aurEff->GetBase()->CallScriptEffectCalcCritChanceHandlers(aurEff, aurEff->GetBase()->GetApplicationOfTarget(victim->GetGUID()), victim, crit_chance); + aurEff->GetBase()->CallScriptEffectCalcCritChanceHandlers(aurEff, aurEff->GetBase()->GetApplicationOfTarget(GetGUID()), this, crit_chance); return std::max(crit_chance, 0.0f); } -uint32 Unit::SpellCriticalDamageBonus(SpellInfo const* spellProto, uint32 damage, Unit* victim) +/*static*/ uint32 Unit::SpellCriticalDamageBonus(Unit const* caster, SpellInfo const* spellProto, uint32 damage, Unit* victim) { // Calculate critical bonus int32 crit_bonus = damage * 2; float crit_mod = 0.0f; - crit_mod += (GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS, spellProto->GetSchoolMask()) - 1.0f) * 100; + if (caster) + { + crit_mod += (caster->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS, spellProto->GetSchoolMask()) - 1.0f) * 100; - if (crit_bonus != 0) - AddPct(crit_bonus, crit_mod); + if (crit_bonus != 0) + AddPct(crit_bonus, crit_mod); - AddPct(crit_bonus, victim->GetTotalAuraModifier(SPELL_AURA_MOD_CRITICAL_DAMAGE_TAKEN_FROM_CASTER, [&](AuraEffect const* aurEff) - { - return aurEff->GetCasterGUID() == GetGUID(); - })); + AddPct(crit_bonus, victim->GetTotalAuraModifier(SPELL_AURA_MOD_CRITICAL_DAMAGE_TAKEN_FROM_CASTER, [&](AuraEffect const* aurEff) + { + return aurEff->GetCasterGUID() == caster->GetGUID(); + })); - crit_bonus -= damage; + crit_bonus -= damage; - // adds additional damage to critBonus (from talents) - if (Player* modOwner = GetSpellModOwner()) - modOwner->ApplySpellMod(spellProto, SpellModOp::CritDamageAndHealing, crit_bonus); + // adds additional damage to critBonus (from talents) + if (Player* modOwner = caster->GetSpellModOwner()) + modOwner->ApplySpellMod(spellProto, SpellModOp::CritDamageAndHealing, crit_bonus); - crit_bonus += damage; + crit_bonus += damage; + } return crit_bonus; } -uint32 Unit::SpellCriticalHealingBonus(SpellInfo const* spellProto, uint32 damage, Unit* /*victim*/) +/*static*/ uint32 Unit::SpellCriticalHealingBonus(Unit const* caster, SpellInfo const* spellProto, uint32 damage, Unit* /*victim*/) { // Calculate critical bonus int32 crit_bonus = damage; // adds additional damage to critBonus (from talents) - if (Player* modOwner = GetSpellModOwner()) - modOwner->ApplySpellMod(spellProto, SpellModOp::CritDamageAndHealing, crit_bonus); + if (caster) + if (Player* modOwner = caster->GetSpellModOwner()) + modOwner->ApplySpellMod(spellProto, SpellModOp::CritDamageAndHealing, crit_bonus); damage += crit_bonus; - damage = int32(float(damage) * GetTotalAuraMultiplier(SPELL_AURA_MOD_CRITICAL_HEALING_AMOUNT)); + if (caster) + damage = int32(float(damage) * caster->GetTotalAuraMultiplier(SPELL_AURA_MOD_CRITICAL_HEALING_AMOUNT)); return damage; } -uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, SpellEffectInfo const* spellEffect, uint32 stack) const +uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, SpellEffectInfo const* spellEffect, uint32 stack /*= 1*/) const { // For totems get healing bonus from owner (statue isn't totem in fact) if (GetTypeId() == TYPEID_UNIT && IsTotem()) @@ -7246,18 +7290,20 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui return healamount; int32 DoneTotal = 0; + float DoneTotalMod = SpellHealingPctDone(victim, spellProto); // done scripted mod (take it from owner) Unit const* owner = GetOwner() ? GetOwner() : this; AuraEffectList const& mOverrideClassScript= owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); - for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i) + for (AuraEffect const* aurEff : mOverrideClassScript) { - if (!(*i)->IsAffectingSpell(spellProto)) + if (!aurEff->IsAffectingSpell(spellProto)) continue; - switch ((*i)->GetMiscValue()) + + switch (aurEff->GetMiscValue()) { case 3736: // Hateful Totem of the Third Wind / Increased Lesser Healing Wave / LK Arena (4/5/6) Totem of the Third Wind / Savage Totem of the Third Wind - DoneTotal += (*i)->GetAmount(); + DoneTotal += aurEff->GetAmount(); break; default: break; @@ -7310,24 +7356,28 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui DoneTotal = 0; } - // Done Percentage for DOT is already calculated, no need to do it again. The percentage mod is applied in Aura::HandleAuraSpecificMods. - float heal = float(int32(healamount) + DoneTotal) * (damagetype == DOT ? 1.0f : SpellHealingPctDone(victim, spellProto)); + float heal = float(int32(healamount) + DoneTotal) * DoneTotalMod; + // apply spellmod to Done amount if (Player* modOwner = GetSpellModOwner()) - { - if (damagetype == DOT) - modOwner->ApplySpellMod(spellProto, SpellModOp::PeriodicHealingAndDamage, heal); - else - modOwner->ApplySpellMod(spellProto, SpellModOp::HealingAndDamage, heal); - } + modOwner->ApplySpellMod(spellProto, damagetype == DOT ? SpellModOp::PeriodicHealingAndDamage : SpellModOp::HealingAndDamage, heal); return uint32(std::max(heal, 0.0f)); } float Unit::SpellHealingPctDone(Unit* victim, SpellInfo const* spellProto) const { - // For totems pct done mods are calculated when its calculation is run on the player in SpellHealingBonusDone. + // For totems get healing bonus from owner if (GetTypeId() == TYPEID_UNIT && IsTotem()) + if (Unit* owner = GetOwner()) + return owner->SpellHealingPctDone(victim, spellProto); + + // Some spells don't benefit from done mods + if (spellProto->HasAttribute(SPELL_ATTR3_NO_DONE_BONUS)) + return 1.0f; + + // Some spells don't benefit from done mods + if (spellProto->HasAttribute(SPELL_ATTR6_IGNORE_HEALING_MODIFIERS)) return 1.0f; // No bonus healing for potion spells @@ -8947,7 +8997,7 @@ void Unit::AtEnterCombat() InterruptNonMeleeSpells(false); RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::EnteringCombat); - ProcSkillsAndAuras(nullptr, PROC_FLAG_ENTER_COMBAT, PROC_FLAG_NONE, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_NONE, PROC_HIT_NONE, nullptr, nullptr, nullptr); + Unit::ProcSkillsAndAuras(this, nullptr, PROC_FLAG_ENTER_COMBAT, PROC_FLAG_NONE, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_NONE, PROC_HIT_NONE, nullptr, nullptr, nullptr); } void Unit::AtExitCombat() @@ -11307,14 +11357,20 @@ void Unit::SetMeleeAnimKitId(uint16 animKitId) SendMessageToSet(data.Write(), true); } -void Unit::Kill(Unit* victim, bool durabilityLoss /*= true*/, bool skipSettingDeathState /*= false*/) +/*static*/ void Unit::Kill(Unit* attacker, Unit* victim, bool durabilityLoss /*= true*/, bool skipSettingDeathState /*= false*/) { // Prevent killing unit twice (and giving reward from kill twice) if (!victim->GetHealth()) return; + if (attacker && !attacker->IsInMap(victim)) + attacker = nullptr; + // find player: owner of controlled `this` or `this` itself maybe - Player* player = GetCharmerOrOwnerPlayerOrPlayerItself(); + Player* player = nullptr; + if (attacker) + player = attacker->GetCharmerOrOwnerPlayerOrPlayerItself(); + Creature* creature = victim->ToCreature(); bool isRewardAllowed = true; @@ -11382,7 +11438,7 @@ void Unit::Kill(Unit* victim, bool durabilityLoss /*= true*/, bool skipSettingDe Loot* loot = &creature->loot; loot->clear(); if (uint32 lootid = creature->GetCreatureTemplate()->lootid) - loot->FillLoot(lootid, LootTemplates_Creature, looter, false, false, creature->GetLootMode(), GetMap()->GetDifficultyLootItemContext()); + loot->FillLoot(lootid, LootTemplates_Creature, looter, false, false, creature->GetLootMode(), creature->GetMap()->GetDifficultyLootItemContext()); if (creature->GetLootMode() > 0) loot->generateMoneyLoot(creature->GetCreatureTemplate()->mingold, creature->GetCreatureTemplate()->maxgold); @@ -11404,23 +11460,24 @@ void Unit::Kill(Unit* victim, bool durabilityLoss /*= true*/, bool skipSettingDe } // Do KILL and KILLED procs. KILL proc is called only for the unit who landed the killing blow (and its owner - for pets and totems) regardless of who tapped the victim - if (IsPet() || IsTotem()) + if (attacker && (attacker->IsPet() || attacker->IsTotem())) { // proc only once for victim - if (Unit* owner = GetOwner()) - owner->ProcSkillsAndAuras(victim, PROC_FLAG_KILL, PROC_FLAG_NONE, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_NONE, PROC_HIT_NONE, nullptr, nullptr, nullptr); + if (Unit* owner = attacker->GetOwner()) + Unit::ProcSkillsAndAuras(owner, victim, PROC_FLAG_KILL, PROC_FLAG_NONE, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_NONE, PROC_HIT_NONE, nullptr, nullptr, nullptr); } if (!victim->IsCritter()) - ProcSkillsAndAuras(victim, PROC_FLAG_KILL, PROC_FLAG_KILLED, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_NONE, PROC_HIT_NONE, nullptr, nullptr, nullptr); + Unit::ProcSkillsAndAuras(attacker, victim, PROC_FLAG_KILL, PROC_FLAG_KILLED, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_NONE, PROC_HIT_NONE, nullptr, nullptr, nullptr); // Proc auras on death - must be before aura/combat remove - victim->ProcSkillsAndAuras(victim, PROC_FLAG_NONE, PROC_FLAG_DEATH, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_NONE, PROC_HIT_NONE, nullptr, nullptr, nullptr); + Unit::ProcSkillsAndAuras(victim, victim, PROC_FLAG_NONE, PROC_FLAG_DEATH, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_NONE, PROC_HIT_NONE, nullptr, nullptr, nullptr); // update get killing blow achievements, must be done before setDeathState to be able to require auras on target // and before Spirit of Redemption as it also removes auras - if (Player* killerPlayer = GetCharmerOrOwnerPlayerOrPlayerItself()) - killerPlayer->UpdateCriteria(CRITERIA_TYPE_GET_KILLING_BLOWS, 1, 0, 0, victim); + if (attacker) + if (Player* killerPlayer = attacker->GetCharmerOrOwnerPlayerOrPlayerItself()) + killerPlayer->UpdateCriteria(CRITERIA_TYPE_GET_KILLING_BLOWS, 1, 0, 0, victim); if (!skipSettingDeathState) { @@ -11454,11 +11511,11 @@ void Unit::Kill(Unit* victim, bool durabilityLoss /*= true*/, bool skipSettingDe // Durability loss is calculated more accurately again for each item in Player::DurabilityLoss plrVictim->DurabilityLossAll(baseLoss, false); // durability lost message - SendDurabilityLoss(plrVictim, loss); + plrVictim->SendDurabilityLoss(plrVictim, loss); } // Call KilledUnit for creatures - if (GetTypeId() == TYPEID_UNIT && IsAIEnabled) - ToCreature()->AI()->KilledUnit(victim); + if (attacker && attacker->GetTypeId() == TYPEID_UNIT && attacker->IsAIEnabled) + attacker->ToCreature()->AI()->KilledUnit(victim); // last damage from non duel opponent or opponent controlled creature if (plrVictim->duel) @@ -11484,31 +11541,30 @@ void Unit::Kill(Unit* victim, bool durabilityLoss /*= true*/, bool skipSettingDe } // Call KilledUnit for creatures, this needs to be called after the lootable flag is set - if (GetTypeId() == TYPEID_UNIT && IsAIEnabled) - ToCreature()->AI()->KilledUnit(victim); + if (attacker && attacker->GetTypeId() == TYPEID_UNIT && attacker->IsAIEnabled) + attacker->ToCreature()->AI()->KilledUnit(victim); // Call creature just died function if (creature->IsAIEnabled) - creature->AI()->JustDied(this); + creature->AI()->JustDied(attacker); if (TempSummon* summon = creature->ToTempSummon()) if (Unit* summoner = summon->GetSummoner()) if (summoner->ToCreature() && summoner->IsAIEnabled) - summoner->ToCreature()->AI()->SummonedCreatureDies(creature, this); + summoner->ToCreature()->AI()->SummonedCreatureDies(creature, attacker); // Dungeon specific stuff, only applies to players killing creatures if (creature->GetInstanceId()) { Map* instanceMap = creature->GetMap(); - Player* creditedPlayer = GetCharmerOrOwnerPlayerOrPlayerItself(); - /// @todo do instance binding anyway if the charmer/owner is offline - if (instanceMap->IsDungeon() && (creditedPlayer || this == victim)) + /// @todo do instance binding anyway if the charmer/owner is offline + if (instanceMap->IsDungeon() && ((attacker && attacker->GetCharmerOrOwnerPlayerOrPlayerItself()) || attacker == victim)) { if (instanceMap->IsRaidOrHeroicDungeon()) { if (creature->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_INSTANCE_BIND) - ((InstanceMap*)instanceMap)->PermBindAllPlayers(); + instanceMap->ToInstanceMap()->PermBindAllPlayers(); } else { @@ -11525,7 +11581,7 @@ void Unit::Kill(Unit* victim, bool durabilityLoss /*= true*/, bool skipSettingDe // outdoor pvp things, do these after setting the death state, else the player activity notify won't work... doh... // handle player kill only if not suicide (spirit of redemption for example) - if (player && this != victim) + if (player && attacker != victim) { if (OutdoorPvP* pvp = player->GetOutdoorPvP()) pvp->HandleKill(player, victim); @@ -11551,26 +11607,29 @@ void Unit::Kill(Unit* victim, bool durabilityLoss /*= true*/, bool skipSettingDe } // achievement stuff - if (victim->GetTypeId() == TYPEID_PLAYER) + if (attacker && victim->GetTypeId() == TYPEID_PLAYER) { - if (GetTypeId() == TYPEID_UNIT) - victim->ToPlayer()->UpdateCriteria(CRITERIA_TYPE_KILLED_BY_CREATURE, GetEntry()); - else if (GetTypeId() == TYPEID_PLAYER && victim != this) - victim->ToPlayer()->UpdateCriteria(CRITERIA_TYPE_KILLED_BY_PLAYER, 1, ToPlayer()->GetTeam()); + if (attacker->GetTypeId() == TYPEID_UNIT) + victim->ToPlayer()->UpdateCriteria(CRITERIA_TYPE_KILLED_BY_CREATURE, attacker->GetEntry()); + else if (attacker->GetTypeId() == TYPEID_PLAYER && victim != attacker) + victim->ToPlayer()->UpdateCriteria(CRITERIA_TYPE_KILLED_BY_PLAYER, 1, attacker->ToPlayer()->GetTeam()); } // Hook for OnPVPKill Event - if (Player* killerPlr = ToPlayer()) - { - if (Player* killedPlr = victim->ToPlayer()) - sScriptMgr->OnPVPKill(killerPlr, killedPlr); - else if (Creature* killedCre = victim->ToCreature()) - sScriptMgr->OnCreatureKill(killerPlr, killedCre); - } - else if (Creature* killerCre = ToCreature()) + if (attacker) { - if (Player* killed = victim->ToPlayer()) - sScriptMgr->OnPlayerKilledByCreature(killerCre, killed); + if (Player* killerPlr = attacker->ToPlayer()) + { + if (Player* killedPlr = victim->ToPlayer()) + sScriptMgr->OnPVPKill(killerPlr, killedPlr); + else if (Creature* killedCre = victim->ToCreature()) + sScriptMgr->OnCreatureKill(killerPlr, killedCre); + } + else if (Creature* killerCre = attacker->ToCreature()) + { + if (Player* killed = victim->ToPlayer()) + sScriptMgr->OnPlayerKilledByCreature(killerCre, killed); + } } } @@ -12422,21 +12481,26 @@ void Unit::CancelSpellMissiles(uint32 spellId, bool reverseMissile /*= false*/) } } -void Unit::ApplyResilience(Unit const* victim, int32* damage) const +bool Unit::CanApplyResilience() const { - // player mounted on multi-passenger mount is also classified as vehicle - if (IsVehicle() || (victim->IsVehicle() && victim->GetTypeId() != TYPEID_PLAYER)) - return; + return !IsVehicle() && GetOwnerGUID().IsPlayer(); +} - // Don't consider resilience if not in PvP - player or pet - if (!GetCharmerOrOwnerPlayerOrPlayerItself()) +/*static*/ void Unit::ApplyResilience(Unit const* victim, int32* damage) +{ + // player mounted on multi-passenger mount is also classified as vehicle + if (victim->IsVehicle() && victim->GetTypeId() != TYPEID_PLAYER) return; Unit const* target = nullptr; if (victim->GetTypeId() == TYPEID_PLAYER) target = victim; - else if (victim->GetTypeId() == TYPEID_UNIT && victim->GetOwner() && victim->GetOwner()->GetTypeId() == TYPEID_PLAYER) - target = victim->GetOwner(); + else // victim->GetTypeId() == TYPEID_UNIT + { + if (Unit* owner = victim->GetOwner()) + if (owner->GetTypeId() == TYPEID_PLAYER) + target = owner; + } if (!target) return; @@ -12444,6 +12508,15 @@ void Unit::ApplyResilience(Unit const* victim, int32* damage) const *damage -= target->GetDamageReduction(*damage); } +int32 Unit::CalculateAOEAvoidance(int32 damage, uint32 schoolMask, Unit* caster) const +{ + damage = int32(float(damage) * GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, schoolMask)); + if (caster->GetTypeId() == TYPEID_UNIT) + damage = int32(float(damage) * GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE, schoolMask)); + + return damage; +} + // Melee based spells can be miss, parry or dodge on this step // Crit or block - determined on damage calculation phase! (and can be both in some time) float Unit::MeleeSpellMissChance(Unit const* victim, WeaponAttackType attType, SpellInfo const* spellInfo) const diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index dda4b56ab43..af2557b4f99 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -879,7 +879,7 @@ class TC_GAME_API Unit : public WorldObject int32 GetResistance(SpellSchoolMask mask) const; void SetResistance(SpellSchools school, int32 val) { SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::Resistances, school), val); } void SetBonusResistanceMod(SpellSchools school, int32 val) { SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::BonusResistanceMods, school), val); } - float CalculateAverageResistReduction(SpellSchoolMask schoolMask, Unit const* victim, SpellInfo const* spellInfo = nullptr) const; + static float CalculateAverageResistReduction(Unit const* attacker, SpellSchoolMask schoolMask, Unit const* victim, SpellInfo const* spellInfo = nullptr); uint64 GetHealth() const { return m_unitData->Health; } uint64 GetMaxHealth() const { return m_unitData->MaxHealth; } @@ -1019,13 +1019,13 @@ class TC_GAME_API Unit : public WorldObject uint16 GetMeleeAnimKitId() const override { return _meleeAnimKitId; } uint16 GetMaxSkillValueForLevel(Unit const* target = nullptr) const { return (target ? GetLevelForTarget(target) : getLevel()) * 5; } - void DealDamageMods(Unit const* victim, uint32 &damage, uint32* absorb) const; - uint32 DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDamage = nullptr, DamageEffectType damagetype = DIRECT_DAMAGE, SpellSchoolMask damageSchoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellInfo const* spellProto = nullptr, bool durabilityLoss = true); - void Kill(Unit* victim, bool durabilityLoss = true, bool skipSettingDeathState = false); - void KillSelf(bool durabilityLoss = true, bool skipSettingDeathState = false) { Kill(this, durabilityLoss, skipSettingDeathState); } - void DealHeal(HealInfo& healInfo); + static void DealDamageMods(Unit const* attacker, Unit const* victim, uint32& damage, uint32* absorb); + static uint32 DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage const* cleanDamage = nullptr, DamageEffectType damagetype = DIRECT_DAMAGE, SpellSchoolMask damageSchoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellInfo const* spellProto = nullptr, bool durabilityLoss = true); + static void Kill(Unit* attacker, Unit* victim, bool durabilityLoss = true, bool skipSettingDeathState = false); + void KillSelf(bool durabilityLoss = true, bool skipSettingDeathState = false) { Unit::Kill(this, this, durabilityLoss, skipSettingDeathState); } + static void DealHeal(HealInfo& healInfo); - void ProcSkillsAndAuras(Unit* actionTarget, uint32 typeMaskActor, uint32 typeMaskActionTarget, + static void ProcSkillsAndAuras(Unit* actor, Unit* actionTarget, uint32 typeMaskActor, uint32 typeMaskActionTarget, uint32 spellTypeMask, uint32 spellPhaseMask, uint32 hitMask, Spell* spell, DamageInfo* damageInfo, HealInfo* healInfo); @@ -1051,7 +1051,10 @@ class TC_GAME_API Unit : public WorldObject // player or player's pet resilience (-1%) uint32 GetDamageReduction(uint32 damage) const { return GetCombatRatingDamageReduction(CR_RESILIENCE_PLAYER_DAMAGE, 1.0f, 100.0f, damage); } - void ApplyResilience(Unit const* victim, int32* damage) const; + virtual bool CanApplyResilience() const; + static void ApplyResilience(Unit const* victim, int32* damage); + + int32 CalculateAOEAvoidance(int32 damage, uint32 schoolMask, Unit* caster) const; float MeleeSpellMissChance(Unit const* victim, WeaponAttackType attType, SpellInfo const* spellInfo) const; SpellMissInfo MeleeSpellHitResult(Unit* victim, SpellInfo const* spellInfo) const; @@ -1062,7 +1065,9 @@ class TC_GAME_API Unit : public WorldObject float GetUnitParryChance(WeaponAttackType attType, Unit const* victim) const; float GetUnitBlockChance(WeaponAttackType attType, Unit const* victim) const; float GetUnitMissChance(WeaponAttackType attType) const; - float GetUnitCriticalChance(WeaponAttackType attackType, Unit const* victim) const; + float GetUnitCriticalChanceDone(WeaponAttackType attackType) const; + float GetUnitCriticalChanceTaken(Unit const* attacker, WeaponAttackType attackType, float critDone) const; + float GetUnitCriticalChanceAgainst(WeaponAttackType attackType, Unit const* victim) const; int32 GetMechanicResistChance(SpellInfo const* spellInfo) const; bool CanUseAttackType(uint8 attacktype) const; @@ -1701,10 +1706,10 @@ class TC_GAME_API Unit : public WorldObject bool isSpellBlocked(Unit* victim, SpellInfo const* spellProto, WeaponAttackType attackType = BASE_ATTACK); bool isBlockCritical(); - bool IsSpellCrit(Unit* victim, Spell* spell, AuraEffect const* aurEff, SpellSchoolMask schoolMask, WeaponAttackType attackType = BASE_ATTACK) const; - float GetUnitSpellCriticalChance(Unit* victim, Spell* spell, AuraEffect const* aurEff, SpellSchoolMask schoolMask, WeaponAttackType attackType = BASE_ATTACK) const; - uint32 SpellCriticalDamageBonus(SpellInfo const* spellProto, uint32 damage, Unit* victim); - uint32 SpellCriticalHealingBonus(SpellInfo const* spellProto, uint32 damage, Unit* victim); + float SpellCritChanceDone(SpellInfo const* spellInfo, SpellSchoolMask schoolMask, WeaponAttackType attackType = BASE_ATTACK) const; + float SpellCritChanceTaken(Unit const* caster, Spell* spell, AuraEffect const* aurEff, SpellSchoolMask schoolMask, float doneChance, WeaponAttackType attackType = BASE_ATTACK) const; + static uint32 SpellCriticalDamageBonus(Unit const* caster, SpellInfo const* spellProto, uint32 damage, Unit* victim); + static uint32 SpellCriticalHealingBonus(Unit const* caster, SpellInfo const* spellProto, uint32 damage, Unit* victim); uint32 GetCastingTimeForBonus(SpellInfo const* spellProto, DamageEffectType damagetype, uint32 CastingTime) const; float CalculateDefaultCoefficient(SpellInfo const* spellInfo, DamageEffectType damagetype) const; @@ -1721,11 +1726,11 @@ class TC_GAME_API Unit : public WorldObject bool IsImmunedToDamage(SpellInfo const* spellInfo) const; virtual bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, Unit* caster) const; // redefined in Creature - bool IsDamageReducedByArmor(SpellSchoolMask damageSchoolMask, SpellInfo const* spellInfo = nullptr, int8 effIndex = -1); - uint32 CalcArmorReducedDamage(Unit* attacker, Unit* victim, const uint32 damage, SpellInfo const* spellInfo, WeaponAttackType attackType = MAX_ATTACK) const; - uint32 CalcSpellResistedDamage(Unit* attacker, Unit* victim, uint32 damage, SpellSchoolMask schoolMask, SpellInfo const* spellInfo); - void CalcAbsorbResist(DamageInfo& damageInfo); - void CalcHealAbsorb(HealInfo& healInfo) const; + static bool IsDamageReducedByArmor(SpellSchoolMask damageSchoolMask, SpellInfo const* spellInfo = nullptr, int8 effIndex = -1); + static uint32 CalcArmorReducedDamage(Unit const* attacker, Unit* victim, uint32 damage, SpellInfo const* spellInfo, uint8 attackerLevel = 0, WeaponAttackType attackType = MAX_ATTACK); + static uint32 CalcSpellResistedDamage(Unit const* attacker, Unit* victim, uint32 damage, SpellSchoolMask schoolMask, SpellInfo const* spellInfo); + static void CalcAbsorbResist(DamageInfo& damageInfo); + static void CalcHealAbsorb(HealInfo& healInfo); void UpdateSpeed(UnitMoveType mtype); float GetSpeed(UnitMoveType mtype) const; diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index d8dd7070786..9fe6808defb 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -454,7 +454,7 @@ void WorldSession::HandleMovementOpcode(OpcodeClient opcode, MovementInfo& movem if (opcode == CMSG_MOVE_JUMP) { plrMover->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags2::Jump); - plrMover->ProcSkillsAndAuras(nullptr, PROC_FLAG_JUMP, PROC_FLAG_NONE, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_NONE, PROC_HIT_NONE, nullptr, nullptr, nullptr); + Unit::ProcSkillsAndAuras(plrMover, nullptr, PROC_FLAG_JUMP, PROC_FLAG_NONE, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_NONE, PROC_HIT_NONE, nullptr, nullptr, nullptr); } } } diff --git a/src/server/game/Instances/InstanceScript.cpp b/src/server/game/Instances/InstanceScript.cpp index 228e59b4fc8..32d219fa03a 100644 --- a/src/server/game/Instances/InstanceScript.cpp +++ b/src/server/game/Instances/InstanceScript.cpp @@ -382,7 +382,7 @@ bool InstanceScript::SetBossState(uint32 id, EncounterState state) for (Map::PlayerList::const_iterator i = playerList.begin(); i != playerList.end(); ++i) if (Player* player = i->GetSource()) if (player->IsAlive()) - player->ProcSkillsAndAuras(nullptr, PROC_FLAG_ENCOUNTER_START, PROC_FLAG_NONE, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_NONE, PROC_HIT_NONE, nullptr, nullptr, nullptr); + Unit::ProcSkillsAndAuras(player, nullptr, PROC_FLAG_ENCOUNTER_START, PROC_FLAG_NONE, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_NONE, PROC_HIT_NONE, nullptr, nullptr, nullptr); break; } case FAIL: diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 1a6100e1ce8..6373a39c3b4 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -576,13 +576,12 @@ NonDefaultConstructible<pAuraEffectHandler> AuraEffectHandler[TOTAL_AURAS]= AuraEffect::AuraEffect(Aura* base, SpellEffectInfo const* spellEfffectInfo, int32 *baseAmount, Unit* caster) : m_base(base), m_spellInfo(base->GetSpellInfo()), m_effectInfo(spellEfffectInfo), m_spellmod(nullptr), m_baseAmount(baseAmount ? *baseAmount : spellEfffectInfo->CalcBaseValue(caster, base->GetType() == UNIT_AURA_TYPE ? base->GetOwner()->ToUnit() : nullptr, base->GetCastItemId(), base->GetCastItemLevel())), -m_damage(0), m_critChance(0.0f), m_donePct(1.0f), -_periodicTimer(0), _period(0), _ticksDone(0), +_amount(), _periodicTimer(0), _period(0), _ticksDone(0), m_canBeRecalculated(true), m_isPeriodic(false) { CalculatePeriodic(caster, true, false); - m_amount = CalculateAmount(caster); + _amount = CalculateAmount(caster); CalculateSpellMod(); } @@ -815,7 +814,7 @@ void AuraEffect::ChangeAmount(int32 newAmount, bool mark, bool onStackOrReapply, if (handleMask & AURA_EFFECT_HANDLE_CHANGE_AMOUNT) { if (!mark) - m_amount = newAmount; + _amount = newAmount; else SetAmount(newAmount); CalculateSpellMod(); @@ -975,6 +974,11 @@ void AuraEffect::Update(uint32 diff, Unit* caster) } } +float AuraEffect::GetCritChanceFor(Unit const* caster, Unit const* target) const +{ + return target->SpellCritChanceTaken(caster, nullptr, this, GetSpellInfo()->GetSchoolMask(), GetBase()->CalcPeriodicCritChance(caster), GetSpellInfo()->GetAttackType()); +} + bool AuraEffect::IsAffectingSpell(SpellInfo const* spell) const { if (!spell) @@ -2920,7 +2924,7 @@ void AuraEffect::HandleAuraControlVehicle(AuraApplication const* aurApp, uint8 m // so this break such spells or most of them. // Current formula about m_amount: effect base points + dieside - 1 // TO DO: Reasearch more about 0/0 and fix it. - caster->_EnterVehicle(target->GetVehicleKit(), m_amount - 1, aurApp); + caster->_EnterVehicle(target->GetVehicleKit(), GetAmount() - 1, aurApp); } else { @@ -2929,7 +2933,7 @@ void AuraEffect::HandleAuraControlVehicle(AuraApplication const* aurApp, uint8 m if (GetId() == 53111) // Devour Humanoid { - target->Kill(caster); + Unit::Kill(target, caster); if (caster->GetTypeId() == TYPEID_UNIT) caster->ToCreature()->DespawnOrUnsummon(); } @@ -3357,7 +3361,7 @@ void AuraEffect::HandleModPercentStat(AuraApplication const* aurApp, uint8 mode, if (GetMiscValue() == i || GetMiscValue() == -1) { if (apply) - target->ApplyStatPctModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(m_amount)); + target->ApplyStatPctModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(GetAmount())); else { float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_PERCENT_STAT, [i](AuraEffect const* aurEff) -> bool @@ -3517,7 +3521,7 @@ void AuraEffect::HandleModStatBonusPercent(AuraApplication const* aurApp, uint8 { if (GetMiscValue() == i || GetMiscValue() == -1) { - target->HandleStatFlatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT_EXCLUDE_CREATE, float(m_amount), apply); + target->HandleStatFlatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT_EXCLUDE_CREATE, float(GetAmount()), apply); target->UpdateStatBuffMod(Stats(i)); } } @@ -3532,7 +3536,7 @@ void AuraEffect::HandleOverrideSpellPowerByAttackPower(AuraApplication const* au if (!target) return; - target->ApplyModOverrideSpellPowerByAPPercent(float(m_amount), apply); + target->ApplyModOverrideSpellPowerByAPPercent(float(GetAmount()), apply); target->UpdateSpellDamageAndHealingBonus(); } @@ -3545,7 +3549,7 @@ void AuraEffect::HandleOverrideAttackPowerBySpellPower(AuraApplication const* au if (!target) return; - target->ApplyModOverrideAPBySpellPowerPercent(float(m_amount), apply); + target->ApplyModOverrideAPBySpellPowerPercent(float(GetAmount()), apply); target->UpdateAttackPowerAndDamage(); target->UpdateAttackPowerAndDamage(true); } @@ -4060,7 +4064,7 @@ void AuraEffect::HandleModCombatSpeedPct(AuraApplication const* aurApp, uint8 mo target->ApplyAttackTimePercentMod(OFF_ATTACK, float(spellGroupVal), !apply); target->ApplyAttackTimePercentMod(RANGED_ATTACK, float(spellGroupVal), !apply); } - target->ApplyCastTimePercentMod(float(m_amount), apply); + target->ApplyCastTimePercentMod(float(GetAmount()), apply); target->ApplyAttackTimePercentMod(BASE_ATTACK, float(GetAmount()), apply); target->ApplyAttackTimePercentMod(OFF_ATTACK, float(GetAmount()), apply); target->ApplyAttackTimePercentMod(RANGED_ATTACK, float(GetAmount()), apply); @@ -4736,7 +4740,7 @@ void AuraEffect::HandleChannelDeathItem(AuraApplication const* aurApp, uint8 mod //Adding items uint32 noSpaceForCount = 0; - uint32 count = m_amount; + uint32 count = GetAmount(); ItemPosCountVec dest; InventoryResult msg = plCaster->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, GetSpellEffectInfo()->ItemType, count, &noSpaceForCount); @@ -4784,7 +4788,7 @@ void AuraEffect::HandleForceReaction(AuraApplication const* aurApp, uint8 mode, return; uint32 factionId = GetMiscValue(); - ReputationRank factionRank = ReputationRank(m_amount); + ReputationRank factionRank = ReputationRank(GetAmount()); player->GetReputationMgr().ApplyForceReaction(factionId, factionRank, apply); player->GetReputationMgr().SendForceReactions(); @@ -5138,7 +5142,10 @@ void AuraEffect::HandlePeriodicTriggerSpellWithValueAuraTick(Unit* target, Unit* void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const { - if (!caster || !target->IsAlive()) + // dynobj auras must always have a caster + ASSERT(GetSpellEffectInfo()->Effect != SPELL_EFFECT_PERSISTENT_AREA_AURA || caster); + + if (!target->IsAlive()) return; if (target->HasUnitState(UNIT_STATE_ISOLATED) || target->IsImmunedToDamage(GetSpellInfo())) @@ -5154,38 +5161,27 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL); - // AOE spells are not affected by the new periodic system. - bool isAreaAura = GetSpellEffectInfo()->IsAreaAuraEffect() || GetSpellEffectInfo()->IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA); // ignore negative values (can be result apply spellmods to aura damage - uint32 damage = isAreaAura ? std::max(GetAmount(), 0) : m_damage; + uint32 damage = std::max(GetAmount(), 0); // Script Hook For HandlePeriodicDamageAurasTick -- Allow scripts to change the Damage pre class mitigation calculations - if (isAreaAura) - sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage); + sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage); switch (GetAuraType()) { case SPELL_AURA_PERIODIC_DAMAGE: { - if (isAreaAura) - damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), damage, DOT, GetSpellEffectInfo(), GetBase()->GetStackAmount()) * caster->SpellDamagePctDone(target, m_spellInfo, DOT); + if (caster) + damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), damage, DOT, GetSpellEffectInfo(), GetBase()->GetStackAmount()); damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT, GetSpellEffectInfo(), GetBase()->GetStackAmount()); - // Calculate armor mitigation - if (caster->IsDamageReducedByArmor(GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), GetEffIndex())) - { - uint32 damageReductedArmor = caster->CalcArmorReducedDamage(caster, target, damage, GetSpellInfo()); - cleanDamage.mitigated_damage += damage - damageReductedArmor; - damage = damageReductedArmor; - } - // There is a Chance to make a Soul Shard when Drain soul does damage - if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellInfo()->SpellFamilyFlags[0] & 0x00004000)) + if (caster && GetSpellInfo()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellInfo()->SpellFamilyFlags[0] & 0x00004000)) { if (caster->GetTypeId() == TYPEID_PLAYER && caster->ToPlayer()->isHonorOrXPTarget(target)) caster->CastSpell(caster, 95810, this); } - if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_GENERIC) + else if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_GENERIC) { switch (GetId()) { @@ -5205,44 +5201,49 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const { WeaponAttackType attackType = GetSpellInfo()->GetAttackType(); - int32 weaponDamage = CalculatePct(caster->CalculateDamage(attackType, false, true), GetAmount()); + damage = CalculatePct(caster->CalculateDamage(attackType, false, true), GetAmount()); // Add melee damage bonuses (also check for negative) - uint32 damageBonusDone = caster->MeleeDamageBonusDone(target, std::max(weaponDamage, 0), attackType, DOT, GetSpellInfo()); + if (caster) + damage = caster->MeleeDamageBonusDone(target, damage, attackType, DOT, GetSpellInfo()); - damage = target->MeleeDamageBonusTaken(caster, damageBonusDone, attackType, DOT, GetSpellInfo()); + damage = target->MeleeDamageBonusTaken(caster, damage, attackType, DOT, GetSpellInfo()); break; } case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: // ceil obtained value, it may happen that 10 ticks for 10% damage may not kill owner damage = uint32(ceil(CalculatePct<float, float>(target->GetMaxHealth(), damage))); + damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT, GetSpellEffectInfo(), GetBase()->GetStackAmount()); break; default: break; } - if (!m_spellInfo->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE)) + bool crit = roll_chance_f(GetCritChanceFor(caster, target)); + if (crit) + damage = Unit::SpellCriticalDamageBonus(caster, m_spellInfo, damage, target); + + // Calculate armor mitigation + if (Unit::IsDamageReducedByArmor(GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), GetEffIndex())) { - if (GetSpellEffectInfo()->IsTargetingArea() || isAreaAura) - { - damage = int32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask)); - if (caster->GetTypeId() != TYPEID_PLAYER) - damage = int32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask)); - } + uint32 damageReductedArmor = Unit::CalcArmorReducedDamage(caster, target, damage, GetSpellInfo(), GetBase()->GetCasterLevel()); + cleanDamage.mitigated_damage += damage - damageReductedArmor; + damage = damageReductedArmor; } - bool crit = roll_chance_f(isAreaAura ? caster->GetUnitSpellCriticalChance(target, nullptr, this, m_spellInfo->GetSchoolMask()) : m_critChance); - - if (crit) - damage = caster->SpellCriticalDamageBonus(m_spellInfo, damage, target); + if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE)) + { + if (GetSpellEffectInfo()->IsTargetingArea() || GetSpellEffectInfo()->IsAreaAuraEffect() || GetSpellEffectInfo()->Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA) + damage = target->CalculateAOEAvoidance(damage, m_spellInfo->SchoolMask, caster); + } int32 dmg = damage; - if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE)) - caster->ApplyResilience(target, &dmg); + if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE) && caster && caster->CanApplyResilience()) + Unit::ApplyResilience(target, &dmg); damage = dmg; DamageInfo damageInfo(caster, target, damage, GetSpellInfo(), GetSpellInfo()->GetSchoolMask(), DOT, BASE_ATTACK); - caster->CalcAbsorbResist(damageInfo); + Unit::CalcAbsorbResist(damageInfo); damage = damageInfo.GetDamage(); uint32 absorb = damageInfo.GetAbsorb(); @@ -5250,7 +5251,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const 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); - caster->DealDamageMods(target, damage, &absorb); + Unit::DealDamageMods(caster, target, damage, &absorb); // Set trigger flag uint32 procAttacker = PROC_FLAG_DONE_PERIODIC; @@ -5268,9 +5269,9 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const SpellPeriodicAuraLogInfo pInfo(this, damage, dmg, overkill, absorb, resist, 0.0f, crit); - caster->DealDamage(target, damage, &cleanDamage, DOT, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), true); + Unit::DealDamage(caster, target, damage, &cleanDamage, DOT, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), true); - caster->ProcSkillsAndAuras(target, procAttacker, procVictim, PROC_SPELL_TYPE_DAMAGE, PROC_SPELL_PHASE_NONE, hitMask, nullptr, &damageInfo, nullptr); + Unit::ProcSkillsAndAuras(caster, target, procAttacker, procVictim, PROC_SPELL_TYPE_DAMAGE, PROC_SPELL_PHASE_NONE, hitMask, nullptr, &damageInfo, nullptr); target->SendPeriodicAuraLog(&pInfo); } @@ -5282,7 +5283,10 @@ bool AuraEffect::IsAreaAuraEffect() const void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) const { - if (!caster || !target->IsAlive()) + // dynobj auras must always have a caster + ASSERT(GetSpellEffectInfo()->Effect != SPELL_EFFECT_PERSISTENT_AREA_AURA || caster); + + if (!target->IsAlive()) return; if (target->HasUnitState(UNIT_STATE_ISOLATED) || target->IsImmunedToDamage(GetSpellInfo())) @@ -5297,46 +5301,38 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL); - bool isAreaAura = GetSpellEffectInfo()->IsAreaAuraEffect() || GetSpellEffectInfo()->IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA); // ignore negative values (can be result apply spellmods to aura damage - uint32 damage = isAreaAura ? std::max(GetAmount(), 0) : m_damage; + uint32 damage = std::max(GetAmount(), 0); - if (isAreaAura) - { - // Script Hook For HandlePeriodicDamageAurasTick -- Allow scripts to change the Damage pre class mitigation calculations - sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage); - damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), damage, DOT, GetSpellEffectInfo(), GetBase()->GetStackAmount()) * caster->SpellDamagePctDone(target, m_spellInfo, DOT); - } + if (caster) + damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), damage, DOT, GetSpellEffectInfo(), GetBase()->GetStackAmount()); damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT, GetSpellEffectInfo(), GetBase()->GetStackAmount()); + bool crit = roll_chance_f(GetCritChanceFor(caster, target)); + if (crit) + damage = Unit::SpellCriticalDamageBonus(caster, m_spellInfo, damage, target); + // Calculate armor mitigation - if (caster->IsDamageReducedByArmor(GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), GetEffIndex())) + if (Unit::IsDamageReducedByArmor(GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), GetEffIndex())) { - uint32 damageReductedArmor = caster->CalcArmorReducedDamage(caster, target, damage, GetSpellInfo()); + uint32 damageReductedArmor = Unit::CalcArmorReducedDamage(caster, target, damage, GetSpellInfo(), GetBase()->GetCasterLevel()); cleanDamage.mitigated_damage += damage - damageReductedArmor; damage = damageReductedArmor; } - if (!m_spellInfo->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE)) - if (GetSpellEffectInfo()->IsTargetingArea() || isAreaAura) - { - damage = int32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask)); - if (caster->GetTypeId() != TYPEID_PLAYER) - damage = int32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask)); - } - - bool crit = roll_chance_f(isAreaAura ? caster->GetUnitSpellCriticalChance(target, nullptr, this, m_spellInfo->GetSchoolMask()) : m_critChance); - - if (crit) - damage = caster->SpellCriticalDamageBonus(m_spellInfo, damage, target); + if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE)) + { + if (GetSpellEffectInfo()->IsTargetingArea() || GetSpellEffectInfo()->IsAreaAuraEffect() || GetSpellEffectInfo()->Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA) + damage = target->CalculateAOEAvoidance(damage, m_spellInfo->SchoolMask, caster); + } int32 dmg = damage; - if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE)) - caster->ApplyResilience(target, &dmg); + if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE) && caster && caster->CanApplyResilience()) + Unit::ApplyResilience(target, &dmg); damage = dmg; DamageInfo damageInfo(caster, target, damage, GetSpellInfo(), GetSpellInfo()->GetSchoolMask(), DOT, BASE_ATTACK); - caster->CalcAbsorbResist(damageInfo); + Unit::CalcAbsorbResist(damageInfo); uint32 absorb = damageInfo.GetAbsorb(); uint32 resist = damageInfo.GetResist(); @@ -5363,22 +5359,22 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c procVictim |= PROC_FLAG_TAKEN_DAMAGE; } - int32 new_damage = caster->DealDamage(target, damage, &cleanDamage, DOT, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), false); - if (caster->IsAlive()) - { - caster->ProcSkillsAndAuras(target, procAttacker, procVictim, PROC_SPELL_TYPE_DAMAGE, PROC_SPELL_PHASE_NONE, hitMask, nullptr, &damageInfo, nullptr); + int32 new_damage = Unit::DealDamage(caster, target, damage, &cleanDamage, DOT, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), false); + if (!caster || !caster->IsAlive()) + return; - float gainMultiplier = GetSpellEffectInfo()->CalcValueMultiplier(caster); + Unit::ProcSkillsAndAuras(caster, target, procAttacker, procVictim, PROC_SPELL_TYPE_DAMAGE, PROC_SPELL_PHASE_NONE, hitMask, nullptr, &damageInfo, nullptr); - uint32 heal = uint32(caster->SpellHealingBonusDone(caster, GetSpellInfo(), uint32(new_damage * gainMultiplier), DOT, GetSpellEffectInfo(), GetBase()->GetStackAmount())); - heal = uint32(caster->SpellHealingBonusTaken(caster, GetSpellInfo(), heal, DOT, GetSpellEffectInfo(), GetBase()->GetStackAmount())); + float gainMultiplier = GetSpellEffectInfo()->CalcValueMultiplier(caster); - HealInfo healInfo(caster, caster, heal, GetSpellInfo(), GetSpellInfo()->GetSchoolMask()); - caster->HealBySpell(healInfo); + uint32 heal = caster->SpellHealingBonusDone(caster, GetSpellInfo(), uint32(new_damage * gainMultiplier), DOT, GetSpellEffectInfo(), GetBase()->GetStackAmount()); + heal = caster->SpellHealingBonusTaken(caster, GetSpellInfo(), heal, DOT, GetSpellEffectInfo(), GetBase()->GetStackAmount()); - caster->GetThreatManager().ForwardThreatForAssistingMe(caster, healInfo.GetEffectiveHeal()*0.5f, GetSpellInfo()); - caster->ProcSkillsAndAuras(caster, PROC_FLAG_DONE_PERIODIC, PROC_FLAG_TAKEN_PERIODIC, PROC_SPELL_TYPE_HEAL, PROC_SPELL_PHASE_NONE, hitMask, nullptr, nullptr, &healInfo); - } + HealInfo healInfo(caster, caster, heal, GetSpellInfo(), GetSpellInfo()->GetSchoolMask()); + caster->HealBySpell(healInfo); + + caster->GetThreatManager().ForwardThreatForAssistingMe(caster, healInfo.GetEffectiveHeal() * 0.5f, GetSpellInfo()); + Unit::ProcSkillsAndAuras(caster, caster, PROC_FLAG_DONE_PERIODIC, PROC_FLAG_TAKEN_PERIODIC, PROC_SPELL_TYPE_HEAL, PROC_SPELL_PHASE_NONE, hitMask, nullptr, nullptr, &healInfo); caster->SendSpellNonMeleeDamageLog(&log); } @@ -5410,12 +5406,15 @@ void AuraEffect::HandlePeriodicHealthFunnelAuraTick(Unit* target, Unit* caster) HealInfo healInfo(caster, target, damage, GetSpellInfo(), GetSpellInfo()->GetSchoolMask()); caster->HealBySpell(healInfo); - caster->ProcSkillsAndAuras(target, PROC_FLAG_DONE_PERIODIC, PROC_FLAG_TAKEN_PERIODIC, PROC_SPELL_TYPE_HEAL, PROC_SPELL_PHASE_NONE, PROC_HIT_NORMAL, nullptr, nullptr, &healInfo); + Unit::ProcSkillsAndAuras(caster, target, PROC_FLAG_DONE_PERIODIC, PROC_FLAG_TAKEN_PERIODIC, PROC_SPELL_TYPE_HEAL, PROC_SPELL_PHASE_NONE, PROC_HIT_NORMAL, nullptr, nullptr, &healInfo); } void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const { - if (!caster || !target->IsAlive()) + // dynobj auras must always have a caster + ASSERT(GetSpellEffectInfo()->Effect != SPELL_EFFECT_PERSISTENT_AREA_AURA || caster); + + if (!target->IsAlive()) return; if (target->HasUnitState(UNIT_STATE_ISOLATED)) @@ -5425,51 +5424,26 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const } // heal for caster damage (must be alive) - if (target != caster && GetSpellInfo()->HasAttribute(SPELL_ATTR2_HEALTH_FUNNEL) && !caster->IsAlive()) + if (target != caster && GetSpellInfo()->HasAttribute(SPELL_ATTR2_HEALTH_FUNNEL) && (!caster || !caster->IsAlive())) return; // don't regen when permanent aura target has full power if (GetBase()->IsPermanent() && target->IsFullHealth()) return; - bool isAreaAura = GetSpellEffectInfo()->IsAreaAuraEffect() || GetSpellEffectInfo()->IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA); // ignore negative values (can be result apply spellmods to aura damage - int32 damage = isAreaAura ? std::max(GetAmount(), 0) : m_damage; + uint32 damage = std::max(GetAmount(), 0); if (GetAuraType() == SPELL_AURA_OBS_MOD_HEALTH) - { - // Taken mods - float TakenTotalMod = 1.0f; - - // Tenacity increase healing % taken - if (AuraEffect const* Tenacity = target->GetAuraEffect(58549, 0)) - AddPct(TakenTotalMod, Tenacity->GetAmount()); - - // Healing taken percent - float minval = (float)target->GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HEALING_PCT); - if (minval) - AddPct(TakenTotalMod, minval); - - float maxval = (float)target->GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HEALING_PCT); - if (maxval) - AddPct(TakenTotalMod, maxval); - - TakenTotalMod = std::max(TakenTotalMod, 0.0f); - damage = uint32(target->CountPctFromMaxHealth(damage)); - damage = uint32(damage * TakenTotalMod); - } - else - { - if (isAreaAura) - damage = caster->SpellHealingBonusDone(target, GetSpellInfo(), damage, DOT, GetSpellEffectInfo(), GetBase()->GetStackAmount()) * caster->SpellHealingPctDone(target, m_spellInfo); - damage = target->SpellHealingBonusTaken(caster, GetSpellInfo(), damage, DOT, GetSpellEffectInfo(), GetBase()->GetStackAmount()); - } + else if (caster) + damage = caster->SpellHealingBonusDone(target, GetSpellInfo(), damage, DOT, GetSpellEffectInfo(), GetBase()->GetStackAmount()); - bool crit = roll_chance_f(isAreaAura ? caster->GetUnitSpellCriticalChance(target, nullptr, this, m_spellInfo->GetSchoolMask()) : m_critChance); + damage = target->SpellHealingBonusTaken(caster, GetSpellInfo(), damage, DOT, GetSpellEffectInfo(), GetBase()->GetStackAmount()); + bool crit = roll_chance_f(GetCritChanceFor(caster, target)); if (crit) - damage = caster->SpellCriticalHealingBonus(m_spellInfo, damage, target); + damage = Unit::SpellCriticalHealingBonus(caster, m_spellInfo, damage, target); TC_LOG_DEBUG("spells.periodic", "PeriodicTick: %s heal of %s for %u health inflicted by %u", GetCasterGUID().ToString().c_str(), target->GetGUID().ToString().c_str(), damage, GetId()); @@ -5477,13 +5451,14 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const uint32 heal = damage; HealInfo healInfo(caster, target, damage, GetSpellInfo(), GetSpellInfo()->GetSchoolMask()); - caster->CalcHealAbsorb(healInfo); - caster->DealHeal(healInfo); + Unit::CalcHealAbsorb(healInfo); + Unit::DealHeal(healInfo); SpellPeriodicAuraLogInfo pInfo(this, heal, damage, heal - healInfo.GetEffectiveHeal(), healInfo.GetAbsorb(), 0, 0.0f, crit); target->SendPeriodicAuraLog(&pInfo); - target->GetThreatManager().ForwardThreatForAssistingMe(caster, float(healInfo.GetEffectiveHeal())*0.5f, GetSpellInfo()); + if (caster) + target->GetThreatManager().ForwardThreatForAssistingMe(caster, healInfo.GetEffectiveHeal() * 0.5f, GetSpellInfo()); // %-based heal - does not proc auras if (GetAuraType() == SPELL_AURA_OBS_MOD_HEALTH) @@ -5494,7 +5469,7 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const uint32 hitMask = crit ? PROC_HIT_CRITICAL : PROC_HIT_NORMAL; // ignore item heals if (GetBase()->GetCastItemGUID().IsEmpty()) - caster->ProcSkillsAndAuras(target, procAttacker, procVictim, PROC_SPELL_TYPE_HEAL, PROC_SPELL_PHASE_NONE, hitMask, nullptr, nullptr, &healInfo); + Unit::ProcSkillsAndAuras(caster, target, procAttacker, procVictim, PROC_SPELL_TYPE_HEAL, PROC_SPELL_PHASE_NONE, hitMask, nullptr, nullptr, &healInfo); } void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) const @@ -5515,7 +5490,7 @@ void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) con return; // ignore negative values (can be result apply spellmods to aura damage - int32 drainAmount = std::max(m_amount, 0); + int32 drainAmount = std::max(GetAmount(), 0); TC_LOG_DEBUG("spells.periodic", "PeriodicTick: %s power leech of %s for %u dmg inflicted by %u", GetCasterGUID().ToString().c_str(), target->GetGUID().ToString().c_str(), drainAmount, GetId()); @@ -5578,7 +5553,7 @@ void AuraEffect::HandleObsModPowerAuraTick(Unit* target, Unit* caster) const return; // ignore negative values (can be result apply spellmods to aura damage - uint32 amount = std::max(m_amount, 0) * target->GetMaxPower(powerType) /100; + uint32 amount = std::max(GetAmount(), 0) * target->GetMaxPower(powerType) /100; TC_LOG_DEBUG("spells.periodic", "PeriodicTick: %s energize %s for %u dmg inflicted by %u", GetCasterGUID().ToString().c_str(), target->GetGUID().ToString().c_str(), amount, GetId()); @@ -5608,7 +5583,7 @@ void AuraEffect::HandlePeriodicEnergizeAuraTick(Unit* target, Unit* caster) cons return; // ignore negative values (can be result apply spellmods to aura damage - int32 amount = std::max(m_amount, 0); + int32 amount = std::max(GetAmount(), 0); SpellPeriodicAuraLogInfo pInfo(this, amount, amount, 0, 0, 0, 0.0f, false); @@ -5636,7 +5611,7 @@ void AuraEffect::HandlePeriodicPowerBurnAuraTick(Unit* target, Unit* caster) con } // ignore negative values (can be result apply spellmods to aura damage - int32 damage = std::max(m_amount, 0); + int32 damage = std::max(GetAmount(), 0); uint32 gain = uint32(-target->ModifyPower(powerType, -damage)); @@ -5648,7 +5623,7 @@ void AuraEffect::HandlePeriodicPowerBurnAuraTick(Unit* target, Unit* caster) con // no SpellDamageBonus for burn mana caster->CalculateSpellDamageTaken(&damageInfo, int32(gain * dmgMultiplier), spellProto); - caster->DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb); + Unit::DealDamageMods(damageInfo.attacker, damageInfo.target, damageInfo.damage, &damageInfo.absorb); // Set trigger flag uint32 procAttacker = PROC_FLAG_DONE_PERIODIC; @@ -5664,7 +5639,7 @@ void AuraEffect::HandlePeriodicPowerBurnAuraTick(Unit* target, Unit* caster) con caster->DealSpellDamage(&damageInfo, true); DamageInfo dotDamageInfo(damageInfo, DOT, BASE_ATTACK, hitMask); - caster->ProcSkillsAndAuras(target, procAttacker, procVictim, spellTypeMask, PROC_SPELL_PHASE_NONE, hitMask, nullptr, &dotDamageInfo, nullptr); + Unit::ProcSkillsAndAuras(caster, target, procAttacker, procVictim, spellTypeMask, PROC_SPELL_PHASE_NONE, hitMask, nullptr, &dotDamageInfo, nullptr); caster->SendSpellNonMeleeDamageLog(&damageInfo); } @@ -5725,7 +5700,7 @@ void AuraEffect::HandleProcTriggerDamageAuraProc(AuraApplication* aurApp, ProcEv uint32 damage = target->SpellDamageBonusDone(triggerTarget, GetSpellInfo(), GetAmount(), SPELL_DIRECT_DAMAGE, GetSpellEffectInfo()); damage = triggerTarget->SpellDamageBonusTaken(target, GetSpellInfo(), damage, SPELL_DIRECT_DAMAGE, GetSpellEffectInfo()); target->CalculateSpellDamageTaken(&damageInfo, damage, GetSpellInfo()); - target->DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb); + Unit::DealDamageMods(damageInfo.attacker, damageInfo.target, damageInfo.damage, &damageInfo.absorb); TC_LOG_DEBUG("spells", "AuraEffect::HandleProcTriggerDamageAuraProc: Triggering %u spell damage from aura %u proc", damage, GetId()); target->DealSpellDamage(&damageInfo, true); target->SendSpellNonMeleeDamageLog(&damageInfo); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h index ff6cba63688..51e8d738cff 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.h +++ b/src/server/game/Spells/Auras/SpellAuraEffects.h @@ -54,8 +54,8 @@ class TC_GAME_API AuraEffect int32 GetMiscValueB() const { return GetSpellEffectInfo()->MiscValueB; } int32 GetMiscValue() const { return GetSpellEffectInfo()->MiscValue; } AuraType GetAuraType() const { return (AuraType)GetSpellEffectInfo()->ApplyAuraName; } - int32 GetAmount() const { return m_amount; } - void SetAmount(int32 amount) { m_amount = amount; m_canBeRecalculated = false;} + int32 GetAmount() const { return _amount; } + void SetAmount(int32 amount) { _amount = amount; m_canBeRecalculated = false; } int32 GetPeriodicTimer() const { return _periodicTimer; } void SetPeriodicTimer(int32 periodicTimer) { _periodicTimer = periodicTimer; } @@ -72,13 +72,6 @@ class TC_GAME_API AuraEffect void HandleEffect(Unit* target, uint8 mode, bool apply, AuraEffect const* triggeredBy = nullptr); void ApplySpellMod(Unit* target, bool apply, AuraEffect const* triggeredBy = nullptr); - void SetDamage(int32 val) { m_damage = val; } - int32 GetDamage() const { return m_damage; } - void SetCritChance(float val) { m_critChance = val; } - float GetCritChance() const { return m_critChance; } - void SetDonePct(float val) { m_donePct = val; } - float GetDonePct() const { return m_donePct; } - void Update(uint32 diff, Unit* caster); uint32 GetTickNumber() const { return _ticksDone; } @@ -116,10 +109,7 @@ class TC_GAME_API AuraEffect SpellModifier* m_spellmod; int32 const m_baseAmount; - int32 m_amount; - int32 m_damage; - float m_critChance; - float m_donePct; + int32 _amount; // periodic stuff int32 _periodicTimer; @@ -129,6 +119,8 @@ class TC_GAME_API AuraEffect bool m_canBeRecalculated; bool m_isPeriodic; + float GetCritChanceFor(Unit const* caster, Unit const* target) const; + public: // aura effect apply/remove handlers void HandleNULL(AuraApplication const* /*aurApp*/, uint8 /*mode*/, bool /*apply*/) const diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index aaba2370cc4..fe1ed0caefe 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -386,6 +386,19 @@ void Aura::_InitEffects(uint32 effMask, Unit* caster, int32 *baseAmount) _effects[effect->EffectIndex] = new AuraEffect(this, effect, baseAmount ? baseAmount + effect->EffectIndex : nullptr, caster); } +float Aura::CalcPeriodicCritChance(Unit const* caster) const +{ + if (!caster) + return 0.0f; + + Player* modOwner = caster->GetSpellModOwner(); + if (!modOwner) + return 0.0f; + + float critChance = modOwner->SpellCritChanceDone(GetSpellInfo(), GetSpellInfo()->GetSchoolMask(), GetSpellInfo()->GetAttackType()); + return std::max(0.0f, critChance); +} + Aura::~Aura() { // unload scripts @@ -916,13 +929,8 @@ void Aura::SetStackAmount(uint8 stackAmount) effect->ChangeAmount(effect->CalculateAmount(caster), false, true); for (std::list<AuraApplication*>::const_iterator apptItr = applications.begin(); apptItr != applications.end(); ++apptItr) - { if (!(*apptItr)->GetRemoveMode()) - { - HandleAuraSpecificPeriodics(*apptItr, caster); HandleAuraSpecificMods(*apptItr, caster, true, true); - } - } SetNeedClientUpdateForTargets(); } @@ -1419,55 +1427,6 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b } } -void Aura::HandleAuraSpecificPeriodics(AuraApplication const* aurApp, Unit* caster) -{ - Unit* target = aurApp->GetTarget(); - - if (!caster || aurApp->GetRemoveMode()) - return; - - for (AuraEffect* effect : GetAuraEffects()) - { - if (!effect || effect->IsAreaAuraEffect() || effect->IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) - continue; - - switch (effect->GetSpellEffectInfo()->ApplyAuraName) - { - case SPELL_AURA_PERIODIC_DAMAGE: - case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: - case SPELL_AURA_PERIODIC_LEECH: - { - // ignore non positive values (can be result apply spellmods to aura damage - uint32 damage = std::max(effect->GetAmount(), 0); - - // Script Hook For HandlePeriodicDamageAurasTick -- Allow scripts to change the Damage pre class mitigation calculations - sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage); - - effect->SetDonePct(caster->SpellDamagePctDone(target, m_spellInfo, DOT)); // Calculate done percentage first! - effect->SetDamage(caster->SpellDamageBonusDone(target, m_spellInfo, damage, DOT, effect->GetSpellEffectInfo(), GetStackAmount()) * effect->GetDonePct()); - effect->SetCritChance(caster->GetUnitSpellCriticalChance(target, nullptr, effect, m_spellInfo->GetSchoolMask())); - break; - } - case SPELL_AURA_PERIODIC_HEAL: - case SPELL_AURA_OBS_MOD_HEALTH: - { - // ignore non positive values (can be result apply spellmods to aura damage - uint32 damage = std::max(effect->GetAmount(), 0); - - // Script Hook For HandlePeriodicDamageAurasTick -- Allow scripts to change the Damage pre class mitigation calculations - sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage); - - effect->SetDonePct(caster->SpellHealingPctDone(target, m_spellInfo)); // Calculate done percentage first! - effect->SetDamage(caster->SpellHealingBonusDone(target, m_spellInfo, damage, DOT, effect->GetSpellEffectInfo(), GetStackAmount()) * effect->GetDonePct()); - effect->SetCritChance(caster->GetUnitSpellCriticalChance(target, nullptr, effect, m_spellInfo->GetSchoolMask())); - break; - } - default: - break; - } - } -} - bool Aura::CanBeAppliedOn(Unit* target) { // unit not in world or during remove from world @@ -1853,7 +1812,7 @@ float Aura::CalcPPMProcChance(Unit* actor) const using FSeconds = std::chrono::duration<float, Seconds::period>; // Formula see http://us.battle.net/wow/en/forum/topic/8197741003#1 - float ppm = m_spellInfo->CalcProcPPM(actor, m_castItemLevel); + float ppm = m_spellInfo->CalcProcPPM(actor, GetCastItemLevel()); float averageProcInterval = 60.0f / ppm; std::chrono::steady_clock::time_point currentTime = GameTime::GetGameTimeSteadyPoint(); @@ -2068,7 +2027,7 @@ void Aura::CallScriptEffectCalcSpellModHandlers(AuraEffect const* aurEff, SpellM } } -void Aura::CallScriptEffectCalcCritChanceHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, Unit* victim, float& critChance) +void Aura::CallScriptEffectCalcCritChanceHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, Unit const* victim, float& critChance) { for (AuraScript* loadedScript : m_loadedScripts) { diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h index acb1ff5bf3f..7f55bc70fb1 100644 --- a/src/server/game/Spells/Auras/SpellAuras.h +++ b/src/server/game/Spells/Auras/SpellAuras.h @@ -90,7 +90,6 @@ class TC_GAME_API AuraApplication void ClientUpdate(bool remove = false); }; -#pragma pack(push, 1) // Structure representing database aura primary key fields struct AuraKey { @@ -101,7 +100,9 @@ struct AuraKey bool operator<(AuraKey const& right) const { - return memcmp(this, &right, sizeof(*this)) < 0; + auto comparisonTuple = [](AuraKey const& k) { return std::tie(k.Caster, k.Item, k.SpellId, k.EffectMask); }; + + return comparisonTuple(*this) < comparisonTuple(right); } }; @@ -110,7 +111,6 @@ struct AuraLoadEffectInfo std::array<int32, MAX_SPELL_EFFECTS> Amounts; std::array<int32, MAX_SPELL_EFFECTS> BaseAmounts; }; -#pragma pack(pop) class TC_GAME_API Aura { @@ -182,7 +182,6 @@ class TC_GAME_API Aura uint8 GetStackAmount() const { return m_stackAmount; } void SetStackAmount(uint8 num); bool ModStackAmount(int32 num, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT, bool resetPeriodicTimer = true); - uint32 CalcMaxStackAmount() const; bool IsUsingStacks() const; @@ -223,6 +222,8 @@ class TC_GAME_API Aura void SetLoadedState(int32 maxDuration, int32 duration, int32 charges, uint8 stackAmount, uint32 recalculateMask, int32* amount); // helpers for aura effects + float CalcPeriodicCritChance(Unit const* caster) const; + bool HasEffect(uint8 effIndex) const { return GetEffect(effIndex) != nullptr; } bool HasEffectType(AuraType type) const; static bool EffectTypeNeedsSendingAmount(AuraType type); @@ -240,7 +241,6 @@ class TC_GAME_API Aura void SetNeedClientUpdateForTargets() const; void HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, bool apply, bool onReapply); - void HandleAuraSpecificPeriodics(AuraApplication const* aurApp, Unit* caster); bool CanBeAppliedOn(Unit* target); bool CheckAreaTarget(Unit* target); bool CanStackWith(Aura const* existingAura) const; @@ -271,7 +271,7 @@ class TC_GAME_API Aura void CallScriptEffectCalcAmountHandlers(AuraEffect const* aurEff, int32 & amount, bool & canBeRecalculated); void CallScriptEffectCalcPeriodicHandlers(AuraEffect const* aurEff, bool & isPeriodic, int32 & amplitude); void CallScriptEffectCalcSpellModHandlers(AuraEffect const* aurEff, SpellModifier* & spellMod); - void CallScriptEffectCalcCritChanceHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, Unit* victim, float& critChance); + void CallScriptEffectCalcCritChanceHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, Unit const* victim, float& critChance); void CallScriptEffectAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & absorbAmount, bool & defaultPrevented); void CallScriptEffectAfterAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & absorbAmount); void CallScriptEffectManaShieldHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & absorbAmount, bool & defaultPrevented); diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index f9d166338c0..e66482430fc 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2074,7 +2074,7 @@ class ProcReflectDelayed : public BasicEvent uint32 const spellPhaseMask = PROC_SPELL_PHASE_NONE; uint32 const hitMask = PROC_HIT_REFLECT; - caster->ProcSkillsAndAuras(_victim, typeMaskActor, typeMaskActionTarget, spellTypeMask, spellPhaseMask, hitMask, nullptr, nullptr, nullptr); + Unit::ProcSkillsAndAuras(caster, _victim, typeMaskActor, typeMaskActionTarget, spellTypeMask, spellPhaseMask, hitMask, nullptr, nullptr, nullptr); return true; } @@ -2473,7 +2473,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) if (crit) { hitMask |= PROC_HIT_CRITICAL; - addhealth = caster->SpellCriticalHealingBonus(m_spellInfo, addhealth, nullptr); + addhealth = Unit::SpellCriticalHealingBonus(caster, m_spellInfo, addhealth, nullptr); } else hitMask |= PROC_HIT_NORMAL; @@ -2485,7 +2485,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) // Do triggers for unit if (canEffectTrigger) - caster->ProcSkillsAndAuras(unitTarget, procAttacker, procVictim, PROC_SPELL_TYPE_HEAL, PROC_SPELL_PHASE_HIT, hitMask, this, nullptr, &healInfo); + Unit::ProcSkillsAndAuras(caster, unitTarget, procAttacker, procVictim, PROC_SPELL_TYPE_HEAL, PROC_SPELL_PHASE_HIT, hitMask, this, nullptr, &healInfo); } // Do damage and triggers else if (m_damage > 0) @@ -2505,7 +2505,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) { // Add bonuses and fill damageInfo struct caster->CalculateSpellDamageTaken(&damageInfo, m_damage, m_spellInfo, m_attackType, target->crit); - caster->DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb); + Unit::DealDamageMods(damageInfo.attacker, damageInfo.target, damageInfo.damage, &damageInfo.absorb); hitMask |= createProcHitMask(&damageInfo, missInfo); procVictim |= PROC_FLAG_TAKEN_DAMAGE; @@ -2522,7 +2522,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) if (canEffectTrigger) { DamageInfo spellDamageInfo(damageInfo, SPELL_DIRECT_DAMAGE, m_attackType, hitMask); - caster->ProcSkillsAndAuras(unitTarget, procAttacker, procVictim, PROC_SPELL_TYPE_DAMAGE, PROC_SPELL_PHASE_HIT, hitMask, this, &spellDamageInfo, nullptr); + Unit::ProcSkillsAndAuras(caster, unitTarget, procAttacker, procVictim, PROC_SPELL_TYPE_DAMAGE, PROC_SPELL_PHASE_HIT, hitMask, this, &spellDamageInfo, nullptr); if (caster->GetTypeId() == TYPEID_PLAYER && !m_spellInfo->HasAttribute(SPELL_ATTR0_STOP_ATTACK_TARGET) && !m_spellInfo->HasAttribute(SPELL_ATTR4_SUPPRESS_WEAPON_PROCS) && (m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MELEE || m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_RANGED)) @@ -2539,7 +2539,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) if (canEffectTrigger) { DamageInfo spellNoDamageInfo(damageInfo, NODAMAGE, m_attackType, hitMask); - caster->ProcSkillsAndAuras(unitTarget, procAttacker, procVictim, PROC_SPELL_TYPE_NO_DMG_HEAL, PROC_SPELL_PHASE_HIT, hitMask, this, &spellNoDamageInfo, nullptr); + Unit::ProcSkillsAndAuras(caster, unitTarget, procAttacker, procVictim, PROC_SPELL_TYPE_NO_DMG_HEAL, PROC_SPELL_PHASE_HIT, hitMask, this, &spellNoDamageInfo, nullptr); if (caster->GetTypeId() == TYPEID_PLAYER && !m_spellInfo->HasAttribute(SPELL_ATTR0_STOP_ATTACK_TARGET) && !m_spellInfo->HasAttribute(SPELL_ATTR4_SUPPRESS_WEAPON_PROCS) && (m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MELEE || m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_RANGED)) @@ -3442,7 +3442,7 @@ void Spell::_cast(bool skipCheck) if (!(_triggeredCastFlags & TRIGGERED_IGNORE_AURA_INTERRUPT_FLAGS) && !m_spellInfo->HasAttribute(SPELL_ATTR2_IGNORE_ACTION_AURA_INTERRUPT_FLAGS)) m_originalCaster->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::ActionDelayed); - m_originalCaster->ProcSkillsAndAuras(nullptr, procAttacker, PROC_FLAG_NONE, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_CAST, hitMask, this, nullptr, nullptr); + Unit::ProcSkillsAndAuras(m_originalCaster, nullptr, procAttacker, PROC_FLAG_NONE, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_CAST, hitMask, this, nullptr, nullptr); // Call CreatureAI hook OnSuccessfulSpellCast if (Creature* caster = m_originalCaster->ToCreature()) @@ -3667,7 +3667,7 @@ void Spell::_handle_finish_phase() procAttacker = IsPositive() ? PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS : PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_NEG; } - m_originalCaster->ProcSkillsAndAuras(nullptr, procAttacker, PROC_FLAG_NONE, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_FINISH, m_hitMask, this, nullptr, nullptr); + Unit::ProcSkillsAndAuras(m_originalCaster, nullptr, procAttacker, PROC_FLAG_NONE, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_FINISH, m_hitMask, this, nullptr, nullptr); } void Spell::SendSpellCooldown() @@ -7477,9 +7477,7 @@ void Spell::DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier) { if (effect->IsTargetingArea() || effect->IsAreaAuraEffect() || effect->IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) { - m_damage = int32(float(m_damage) * unit->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask)); - if (m_caster->GetTypeId() != TYPEID_PLAYER) - m_damage = int32(float(m_damage) * unit->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask)); + m_damage = unit->CalculateAOEAvoidance(m_damage, m_spellInfo->SchoolMask, m_caster); if (m_caster->GetTypeId() == TYPEID_PLAYER) { @@ -7499,7 +7497,8 @@ void Spell::DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier) } } - targetInfo.crit = m_caster->IsSpellCrit(unit, this, nullptr, m_spellSchoolMask, m_attackType); + float critChance = m_caster->SpellCritChanceDone(m_spellInfo, m_spellSchoolMask, m_attackType); + targetInfo.crit = roll_chance_f(unit->SpellCritChanceTaken(m_caster, this, nullptr, m_spellSchoolMask, critChance, m_attackType)); } SpellCastResult Spell::CanOpenLock(uint32 effIndex, uint32 lockId, SkillType& skillId, int32& reqSkillValue, int32& skillValue) @@ -7782,7 +7781,7 @@ void Spell::CallScriptAfterHitHandlers() } } -void Spell::CallScriptCalcCritChanceHandlers(Unit* victim, float& critChance) +void Spell::CallScriptCalcCritChanceHandlers(Unit const* victim, float& critChance) { for (SpellScript* loadedScript : m_loadedScripts) { diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index a817e1dfc17..5966a8b1193 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -852,7 +852,7 @@ class TC_GAME_API Spell void CallScriptOnHitHandlers(); void CallScriptAfterHitHandlers(); public: - void CallScriptCalcCritChanceHandlers(Unit* victim, float& chance); + void CallScriptCalcCritChanceHandlers(Unit const* victim, float& chance); protected: void CallScriptObjectAreaTargetSelectHandlers(std::list<WorldObject*>& targets, SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType); void CallScriptObjectTargetSelectHandlers(WorldObject*& target, SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index e544e0ebfb2..a5620b9293c 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -420,10 +420,9 @@ void Spell::EffectInstaKill(SpellEffIndex /*effIndex*/) data.Target = unitTarget->GetGUID(); data.Caster = m_caster->GetGUID(); data.SpellID = m_spellInfo->Id; - m_caster->SendMessageToSet(data.Write(), true); - m_caster->DealDamage(unitTarget, unitTarget->GetHealth(), nullptr, NODAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); + Unit::DealDamage(m_caster, unitTarget, unitTarget->GetHealth(), nullptr, NODAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); } void Spell::EffectEnvironmentalDMG(SpellEffIndex /*effIndex*/) @@ -440,7 +439,7 @@ void Spell::EffectEnvironmentalDMG(SpellEffIndex /*effIndex*/) else { DamageInfo damageInfo(m_caster, unitTarget, damage, m_spellInfo, m_spellInfo->GetSchoolMask(), SPELL_DIRECT_DAMAGE, BASE_ATTACK); - m_caster->CalcAbsorbResist(damageInfo); + Unit::CalcAbsorbResist(damageInfo); SpellNonMeleeDamage log(m_caster, unitTarget, m_spellInfo, m_SpellVisual, m_spellInfo->GetSchoolMask(), m_castId); log.damage = damageInfo.GetDamage(); @@ -1075,7 +1074,7 @@ void Spell::EffectPowerDrain(SpellEffIndex effIndex) return; // add spell damage bonus - uint32 bonus = m_caster->SpellDamageBonusDone(unitTarget, m_spellInfo, (uint32)damage, SPELL_DIRECT_DAMAGE, effectInfo); + uint32 bonus = m_caster->SpellDamageBonusDone(unitTarget, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE, effectInfo); damage = bonus + uint32(bonus * variance); damage = unitTarget->SpellDamageBonusTaken(m_caster, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE, effectInfo); @@ -1203,9 +1202,8 @@ void Spell::EffectHeal(SpellEffIndex /*effIndex*/) addhealth = caster->SpellHealingBonusDone(unitTarget, m_spellInfo, int32(caster->CountPctFromMaxHealth(damage)), HEAL, effectInfo); else { - addhealth = caster->SpellHealingBonusDone(unitTarget, m_spellInfo, addhealth, HEAL, effectInfo); uint32 bonus = caster->SpellHealingBonusDone(unitTarget, m_spellInfo, addhealth, HEAL, effectInfo); - damage = bonus + uint32(bonus * variance); + addhealth = bonus + uint32(bonus * variance); } addhealth = unitTarget->SpellHealingBonusTaken(caster, m_spellInfo, addhealth, HEAL, effectInfo); @@ -1231,9 +1229,7 @@ void Spell::EffectHealPct(SpellEffIndex /*effIndex*/) return; uint32 heal = m_originalCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, unitTarget->CountPctFromMaxHealth(damage), HEAL, effectInfo); - heal = unitTarget->SpellHealingBonusTaken(m_originalCaster, m_spellInfo, heal, HEAL, effectInfo); - - m_healing += heal; + m_healing += unitTarget->SpellHealingBonusTaken(m_originalCaster, m_spellInfo, heal, HEAL, effectInfo); } void Spell::EffectHealMechanical(SpellEffIndex /*effIndex*/) @@ -2969,10 +2965,10 @@ void Spell::EffectInterruptCast(SpellEffIndex effIndex) int32 duration = m_spellInfo->GetDuration(); unitTarget->GetSpellHistory()->LockSpellSchool(curSpellInfo->GetSchoolMask(), unitTarget->ModSpellDuration(m_spellInfo, unitTarget, duration, false, 1 << effIndex)); if (m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC) - m_originalCaster->ProcSkillsAndAuras(unitTarget, PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_NEG, PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG, + Unit::ProcSkillsAndAuras(m_originalCaster, unitTarget, PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_NEG, PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_HIT, PROC_HIT_INTERRUPT, nullptr, nullptr, nullptr); else if (m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MELEE) - m_originalCaster->ProcSkillsAndAuras(unitTarget, PROC_FLAG_DONE_SPELL_MELEE_DMG_CLASS, PROC_FLAG_TAKEN_SPELL_MELEE_DMG_CLASS, + Unit::ProcSkillsAndAuras(m_originalCaster, unitTarget, PROC_FLAG_DONE_SPELL_MELEE_DMG_CLASS, PROC_FLAG_TAKEN_SPELL_MELEE_DMG_CLASS, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_HIT, PROC_HIT_INTERRUPT, nullptr, nullptr, nullptr); } ExecuteLogEffectInterruptCast(effIndex, unitTarget, curSpellInfo->Id); @@ -3589,7 +3585,7 @@ void Spell::EffectStuck(SpellEffIndex /*effIndex*/) // the player dies if hearthstone is in cooldown, else the player is teleported to home if (player->GetSpellHistory()->HasCooldown(8690)) { - player->Kill(player); + player->KillSelf(); return; } diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index be712095f14..be77f4af514 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3341,6 +3341,19 @@ void SpellMgr::LoadSpellInfoCorrections() }); } + // Allows those to crit + ApplySpellFix({ + 379, // Earth Shield + 71607, // Item - Bauble of True Blood 10m + 71646, // Item - Bauble of True Blood 25m + 71610, // Item - Althor's Abacus trigger 10m + 71641 // Item - Althor's Abacus trigger 25m + }, [](SpellInfo* spellInfo) + { + // We need more spells to find a general way (if there is any) + spellInfo->DmgClass = SPELL_DAMAGE_CLASS_MAGIC; + }); + ApplySpellFix({ 63026, // Summon Aspirant Test NPC (HACK: Target shouldn't be changed) 63137 // Summon Valiant Test (HACK: Target shouldn't be changed; summon position should be untied from spell destination) diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp index 294028d8882..d437790b48b 100644 --- a/src/server/game/Spells/SpellScript.cpp +++ b/src/server/game/Spells/SpellScript.cpp @@ -249,7 +249,7 @@ SpellScript::OnCalcCritChanceHandler::OnCalcCritChanceHandler(SpellOnCalcCritCha _onCalcCritChanceHandlerScript = onCalcCritChanceHandlerScript; } -void SpellScript::OnCalcCritChanceHandler::Call(SpellScript* spellScript, Unit* victim, float& critChance) const +void SpellScript::OnCalcCritChanceHandler::Call(SpellScript* spellScript, Unit const* victim, float& critChance) const { (spellScript->*_onCalcCritChanceHandlerScript)(victim, critChance); } @@ -952,7 +952,7 @@ AuraScript::EffectCalcCritChanceHandler::EffectCalcCritChanceHandler(AuraEffectC _effectHandlerScript = effectHandlerScript; } -void AuraScript::EffectCalcCritChanceHandler::Call(AuraScript* auraScript, AuraEffect const* aurEff, Unit* victim, float& critChance) const +void AuraScript::EffectCalcCritChanceHandler::Call(AuraScript* auraScript, AuraEffect const* aurEff, Unit const* victim, float& critChance) const { (auraScript->*_effectHandlerScript)(aurEff, victim, critChance); } diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h index fc665f0947a..2a52b953266 100644 --- a/src/server/game/Spells/SpellScript.h +++ b/src/server/game/Spells/SpellScript.h @@ -193,7 +193,7 @@ class TC_GAME_API SpellScript : public _SpellScript typedef void(CLASSNAME::*SpellBeforeHitFnType)(SpellMissInfo missInfo); \ typedef void(CLASSNAME::*SpellHitFnType)(); \ typedef void(CLASSNAME::*SpellCastFnType)(); \ - typedef void(CLASSNAME::*SpellOnCalcCritChanceFnType)(Unit* victim, float& chance); \ + typedef void(CLASSNAME::*SpellOnCalcCritChanceFnType)(Unit const* victim, float& chance); \ typedef void(CLASSNAME::*SpellObjectAreaTargetSelectFnType)(std::list<WorldObject*>&); \ typedef void(CLASSNAME::*SpellObjectTargetSelectFnType)(WorldObject*&); \ typedef void(CLASSNAME::*SpellDestinationTargetSelectFnType)(SpellDestination&); @@ -251,7 +251,7 @@ class TC_GAME_API SpellScript : public _SpellScript { public: OnCalcCritChanceHandler(SpellOnCalcCritChanceFnType onCalcCritChanceHandlerScript); - void Call(SpellScript* spellScript, Unit* victim, float& critChance) const; + void Call(SpellScript* spellScript, Unit const* victim, float& critChance) const; private: SpellOnCalcCritChanceFnType _onCalcCritChanceHandlerScript; }; @@ -563,7 +563,7 @@ class TC_GAME_API AuraScript : public _SpellScript typedef void(CLASSNAME::*AuraEffectCalcAmountFnType)(AuraEffect const*, int32 &, bool &); \ typedef void(CLASSNAME::*AuraEffectCalcPeriodicFnType)(AuraEffect const*, bool &, int32 &); \ typedef void(CLASSNAME::*AuraEffectCalcSpellModFnType)(AuraEffect const*, SpellModifier* &); \ - typedef void(CLASSNAME::*AuraEffectCalcCritChanceFnType)(AuraEffect const*, Unit*, float&); \ + typedef void(CLASSNAME::*AuraEffectCalcCritChanceFnType)(AuraEffect const*, Unit const*, float&); \ typedef void(CLASSNAME::*AuraEffectAbsorbFnType)(AuraEffect*, DamageInfo &, uint32 &); \ typedef void(CLASSNAME::*AuraEffectSplitFnType)(AuraEffect*, DamageInfo &, uint32 &); \ typedef bool(CLASSNAME::*AuraCheckProcFnType)(ProcEventInfo&); \ @@ -641,7 +641,7 @@ class TC_GAME_API AuraScript : public _SpellScript { public: EffectCalcCritChanceHandler(AuraEffectCalcCritChanceFnType effectHandlerScript, uint8 effIndex, uint16 effName); - void Call(AuraScript* auraScript, AuraEffect const* aurEff, Unit* victim, float& critChance) const; + void Call(AuraScript* auraScript, AuraEffect const* aurEff, Unit const* victim, float& critChance) const; private: AuraEffectCalcCritChanceFnType _effectHandlerScript; }; diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 4cc34449eb0..7f534f71b9f 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -648,9 +648,9 @@ public: if (target->IsAlive()) { if (sWorld->getBoolConfig(CONFIG_DIE_COMMAND_MODE)) - handler->GetSession()->GetPlayer()->Kill(target); + Unit::Kill(handler->GetSession()->GetPlayer(), target); else - handler->GetSession()->GetPlayer()->DealDamage(target, target->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); + Unit::DealDamage(handler->GetSession()->GetPlayer(), target, target->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); } return true; @@ -2408,7 +2408,7 @@ public: // flat melee damage without resistence/etc reduction if (!schoolStr) { - handler->GetSession()->GetPlayer()->DealDamage(target, damage, nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); + Unit::DealDamage(handler->GetSession()->GetPlayer(), target, damage, nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); if (target != handler->GetSession()->GetPlayer()) handler->GetSession()->GetPlayer()->SendAttackStateUpdate (HITINFO_AFFECTS_VICTIM, target, 1, SPELL_SCHOOL_MASK_NORMAL, damage, 0, 0, VICTIMSTATE_HIT, 0); return true; @@ -2420,8 +2420,8 @@ public: SpellSchoolMask schoolmask = SpellSchoolMask(1 << school); - if (handler->GetSession()->GetPlayer()->IsDamageReducedByArmor(schoolmask)) - damage = handler->GetSession()->GetPlayer()->CalcArmorReducedDamage(handler->GetSession()->GetPlayer(), target, damage, nullptr, BASE_ATTACK); + if (Unit::IsDamageReducedByArmor(schoolmask)) + damage = Unit::CalcArmorReducedDamage(handler->GetSession()->GetPlayer(), target, damage, nullptr, BASE_ATTACK); char* spellStr = strtok((char*)nullptr, " "); @@ -2431,7 +2431,7 @@ public: if (!spellStr) { DamageInfo dmgInfo(attacker, target, damage, nullptr, schoolmask, SPELL_DIRECT_DAMAGE, BASE_ATTACK); - attacker->CalcAbsorbResist(dmgInfo); + Unit::CalcAbsorbResist(dmgInfo); if (!dmgInfo.GetDamage()) return true; @@ -2440,8 +2440,8 @@ public: uint32 absorb = dmgInfo.GetAbsorb(); uint32 resist = dmgInfo.GetResist(); - attacker->DealDamageMods(target, damage, &absorb); - attacker->DealDamage(target, damage, nullptr, DIRECT_DAMAGE, schoolmask, nullptr, false); + Unit::DealDamageMods(attacker, target, damage, &absorb); + Unit::DealDamage(attacker, target, damage, nullptr, DIRECT_DAMAGE, schoolmask, nullptr, false); attacker->SendAttackStateUpdate(HITINFO_AFFECTS_VICTIM, target, 0, schoolmask, damage, absorb, resist, VICTIMSTATE_HIT, 0); return true; } @@ -2457,9 +2457,9 @@ public: if (!spellInfo) return false; - SpellNonMeleeDamage damageInfo(attacker, target, spellInfo, { spellInfo->GetSpellXSpellVisualId(handler->GetSession()->GetPlayer()),0 }, spellInfo->SchoolMask); + SpellNonMeleeDamage damageInfo(attacker, target, spellInfo, { spellInfo->GetSpellXSpellVisualId(handler->GetSession()->GetPlayer()), 0 }, spellInfo->SchoolMask); damageInfo.damage = damage; - attacker->DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb); + Unit::DealDamageMods(damageInfo.attacker, damageInfo.target, damageInfo.damage, &damageInfo.absorb); target->DealSpellDamage(&damageInfo, true); target->SendSpellNonMeleeDamageLog(&damageInfo); return true; diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp index d2bd0d01504..0a4392d8ef2 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp @@ -157,7 +157,7 @@ class boss_ragnaros : public CreatureScript case EVENT_INTRO_4: Talk(SAY_ARRIVAL5_RAG); if (Creature* executus = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_MAJORDOMO_EXECUTUS))) - me->Kill(executus); + Unit::Kill(me, executus); break; case EVENT_INTRO_5: me->SetReactState(REACT_AGGRESSIVE); diff --git a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp index 66efdc34ede..8c8ab02a9dd 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp @@ -579,7 +579,7 @@ public: } case 15: if (Creature* arca = ObjectAccessor::GetCreature(*me, ArcanagosGUID)) - arca->DealDamage(arca, arca->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); + arca->KillSelf(); return 5000; default: return 9999999; diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp index 6e0d047514e..b41a3d78c81 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp @@ -570,7 +570,7 @@ public: { //spell Burn should possible do this, but it doesn't, so do this for now. uint16 dmg = urand(1650, 2050); - me->DealDamage(me, dmg, nullptr, DOT, SPELL_SCHOOL_MASK_FIRE, nullptr, false); + Unit::DealDamage(me, me, dmg, nullptr, DOT, SPELL_SCHOOL_MASK_FIRE, nullptr, false); BurnTimer += 2000; } BurnTimer -= diff; diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp index aa2cf832825..f9c2d609406 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp @@ -142,7 +142,7 @@ public: case 6: Talk(SAY_PERSUADED6); - player->Kill(me); + Unit::Kill(player, me); speechCounter = 0; player->GroupEventHappens(QUEST_HOW_TO_WIN_FRIENDS, me); return; diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp index d21be4f569f..cb899bd4e3d 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp @@ -233,7 +233,7 @@ public: ++IntroPhase; break; case 7: - me->Kill(Madrigosa); + Unit::Kill(me, Madrigosa); Madrigosa->AI()->Talk(YELL_MADR_DEATH); me->SetFullHealth(); me->AttackStop(); diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp index 2336a3d4177..cb38c495583 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp @@ -217,7 +217,7 @@ public: summon->CastSpell(summon, SPELL_FOG_CHARM, true); summon->CastSpell(summon, SPELL_FOG_CHARM2, true); } - me->DealDamage(caster, caster->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); + Unit::DealDamage(me, caster, caster->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); } } diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp index da24c72d8dd..c971dbf1dcb 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp @@ -477,7 +477,7 @@ struct boss_sathrovarr : public BossAI if (spell->Id == SPELL_TAP_CHECK_DAMAGE) { DoCastSelf(SPELL_TELEPORT_BACK, true); - caster->Kill(me); + Unit::Kill(caster, me); } } diff --git a/src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp b/src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp index 7ab80813107..6a2c7f188d8 100644 --- a/src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp +++ b/src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp @@ -58,7 +58,7 @@ public: void DoDie() { //summoner dies here - me->DealDamage(me, me->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); + me->KillSelf(); //override any database `spawntimesecs` to prevent duplicated summons uint32 rTime = me->GetRespawnDelay(); if (rTime < 600) diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp index 6e5bccf0b22..87e7d87458d 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp @@ -390,7 +390,7 @@ public: DoSpawnCreature(NPC_ANCIENT_WISP, float(rand32() % 40), float(rand32() % 40), 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); ++WispCount; if (WispCount >= 30) - me->DealDamage(me, me->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); + me->KillSelf(); events.ScheduleEvent(EVENT_SUMMON_WHISP, 1500); break; default: diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp index 5a7ff84108f..ca6ae33eeaa 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp @@ -296,7 +296,7 @@ class instance_culling_of_stratholme : public InstanceMapScript if (Creature* infinite = instance->GetCreature(_infiniteGUID)) { if (Creature* guardian = infinite->FindNearestCreature(NPC_GUARDIAN_OF_TIME, 100.0f)) - infinite->Kill(guardian); + Unit::Kill(infinite, guardian); if (Creature* rift = infinite->FindNearestCreature(NPC_TIME_RIFT, 100.0f)) { diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp index c9fb3b273d9..e62b3ad2372 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp @@ -79,7 +79,7 @@ public: if (me->IsWithinDistInMap(who, 20.0f)) { Talk(SAY_BANISH); - me->DealDamage(who, who->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); + Unit::DealDamage(me, who, who->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); } } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_chrono_lord_deja.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_chrono_lord_deja.cpp index 2e2a6f321b4..6f0aeba2bd2 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_chrono_lord_deja.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_chrono_lord_deja.cpp @@ -82,7 +82,7 @@ public: if (me->IsWithinDistInMap(who, 20.0f)) { Talk(SAY_BANISH); - me->DealDamage(who, who->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); + Unit::DealDamage(me, who, who->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); } } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp index 9463a72ef51..eb768a27d88 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp @@ -93,7 +93,7 @@ public: { Talk(SAY_BANISH); - me->DealDamage(who, who->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); + Unit::DealDamage(me, who, who->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); } } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp index bf355e9b5d1..054d3928748 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp @@ -181,7 +181,7 @@ public: { if (medivh->IsAlive()) { - medivh->DealDamage(medivh, medivh->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); + medivh->KillSelf(); m_auiEncounter[0] = FAIL; m_auiEncounter[1] = NOT_STARTED; } diff --git a/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp b/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp index b084f7cf2bc..3da118111cf 100644 --- a/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp +++ b/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp @@ -231,7 +231,7 @@ public: me->SetDisableGravity(false); me->SetAnimTier(UNIT_BYTE1_FLAG_NONE, false); if (Creature* trigger = ObjectAccessor::GetCreature(*me, triggerGUID)) - me->Kill(trigger); + Unit::Kill(me, trigger); me->SetReactState(REACT_AGGRESSIVE); // tank selection based on phase one. If tank is not there i take nearest one if (Unit* tank = ObjectAccessor::GetUnit(*me, tankGUID)) diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp index 9defa281c0d..62c20793c97 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp @@ -101,7 +101,7 @@ class boss_buru : public CreatureScript { if (action == ACTION_EXPLODE) if (_phase == PHASE_EGG) - me->DealDamage(me, 45000); + Unit::DealDamage(me, me, 45000); } void KilledUnit(Unit* victim) override diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp index 49392be4ee4..6fa10647d47 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp @@ -284,7 +284,7 @@ class npc_glob_of_viscidus : public CreatureScript { Viscidus->SetVisible(true); if (Viscidus->GetVictim()) - Viscidus->EnsureVictim()->Kill(Viscidus); + Unit::Kill(Viscidus->EnsureVictim(), Viscidus); } else { diff --git a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp index 190034b6228..b67d6df83a3 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp @@ -815,7 +815,7 @@ public: me->SummonCreature(NPC_TWILIGHT_WHELP, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); else me->SummonCreature(NPC_SARTHARION_TWILIGHT_WHELP, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); - me->DealDamage(me, me->GetHealth()); + me->KillSelf(); } void JustSummoned(Creature* who) override diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_baltharus_the_warborn.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_baltharus_the_warborn.cpp index 3934e636e1a..cbe62f4f6cc 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_baltharus_the_warborn.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_baltharus_the_warborn.cpp @@ -273,7 +273,7 @@ class npc_baltharus_the_warborn_clone : public CreatureScript { // This is here because DamageTaken wont trigger if the damage is deadly. if (Creature* baltharus = instance->GetCreature(DATA_BALTHARUS_THE_WARBORN)) - killer->Kill(baltharus); + Unit::Kill(killer, baltharus); } void UpdateAI(uint32 diff) override diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp index 7f7ed99314a..2251d623f4d 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp @@ -452,7 +452,7 @@ class boss_twilight_halion : public CreatureScript halion->LowerPlayerDamageReq(halion->GetMaxHealth()); if (halion->IsAlive()) - killer->Kill(halion); + Unit::Kill(killer, halion); } if (Creature* controller = instance->GetCreature(DATA_HALION_CONTROLLER)) diff --git a/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp b/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp index b6cebf1c172..f6835e0dbea 100644 --- a/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp +++ b/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp @@ -265,7 +265,7 @@ class boss_drakkari_elemental : public CreatureScript Talk(EMOTE_ACTIVATE_ALTAR); if (Creature* colossus = instance->GetCreature(DATA_DRAKKARI_COLOSSUS)) - killer->Kill(colossus); + Unit::Kill(killer, colossus); } void UpdateAI(uint32 diff) override diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp index c9790455396..024ed6b8731 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp @@ -330,7 +330,7 @@ class boss_blood_council_controller : public CreatureScript // Make sure looting is allowed if (me->IsDamageEnoughForLootingAndReward()) prince->LowerPlayerDamageReq(prince->GetMaxHealth()); - killer->Kill(prince); + Unit::Kill(killer, prince); } } } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp index 3030f3145a6..a05607623cb 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp @@ -373,7 +373,7 @@ class boss_valithria_dreamwalker : public CreatureScript lichKing->CastSpell(lichKing, SPELL_SPAWN_CHEST, false); if (Creature* trigger = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VALITHRIA_TRIGGER))) - me->Kill(trigger); + Unit::Kill(me, trigger); } } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp index 0fae791b82e..75f71b16024 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp @@ -881,7 +881,7 @@ class boss_sister_svalna : public CreatureScript switch (spell->Id) { case SPELL_IMPALING_SPEAR_KILL: - me->Kill(target); + Unit::Kill(me, target); break; case SPELL_IMPALING_SPEAR: if (TempSummon* summon = target->SummonCreature(NPC_IMPALING_SPEAR, *target)) diff --git a/src/server/scripts/Northrend/IsleOfConquest/boss_ioc_horde_alliance.cpp b/src/server/scripts/Northrend/IsleOfConquest/boss_ioc_horde_alliance.cpp index 9434f49803e..570f21b0d34 100644 --- a/src/server/scripts/Northrend/IsleOfConquest/boss_ioc_horde_alliance.cpp +++ b/src/server/scripts/Northrend/IsleOfConquest/boss_ioc_horde_alliance.cpp @@ -71,7 +71,7 @@ public: void SpellHit(Unit* caster, SpellInfo const* /*spell*/) override { if (caster->IsVehicle()) - me->Kill(caster); + Unit::Kill(me, caster); } void UpdateAI(uint32 diff) override diff --git a/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp index 00aecb3312c..2f1d0566a0f 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp @@ -130,7 +130,7 @@ class boss_faerlina : public CreatureScript { ++_frenzyDispels; Talk(EMOTE_WIDOW_EMBRACE, caster); - me->Kill(caster); + Unit::Kill(me, caster); } } diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp index f17ed5148f5..4d5113b1d1e 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp @@ -555,7 +555,7 @@ public: me->SetStandState(UNIT_STAND_STATE_STAND); instance->HandleGameObject(instance->GetGuidData(DATA_GO_SKY_FLOOR), true); if (Creature* temp = ObjectAccessor::GetCreature(*me, uiControllerGUID)) - temp->DealDamage(temp, temp->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); + temp->KillSelf(); bIsBattle = true; SetEscortPaused(false); JumpToNextStep(6500); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp index 567a365efd9..7940d0b25e2 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp @@ -1196,7 +1196,7 @@ class spell_algalon_collapse : public SpellScriptLoader void HandlePeriodic(AuraEffect const* /*aurEff*/) { PreventDefaultAction(); - GetTarget()->DealDamage(GetTarget(), GetTarget()->CountPctFromMaxHealth(1), nullptr, NODAMAGE); + Unit::DealDamage(GetTarget(), GetTarget(), GetTarget()->CountPctFromMaxHealth(1), nullptr, NODAMAGE); } void Register() override diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp index 2076946b2ba..2e9fa68bc89 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp @@ -366,9 +366,9 @@ static bool IsEncounterFinished(Unit* who) vx001->GetStandState() == UNIT_STAND_STATE_DEAD && aerial->GetStandState() == UNIT_STAND_STATE_DEAD) { - who->Kill(mkii); - who->Kill(vx001); - who->Kill(aerial); + Unit::Kill(who, mkii); + Unit::Kill(who, vx001); + Unit::Kill(who, aerial); mkii->DespawnOrUnsummon(120000); vx001->DespawnOrUnsummon(120000); aerial->DespawnOrUnsummon(120000); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp index ebf04754986..236353877e2 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp @@ -695,7 +695,7 @@ class npc_boombot : public CreatureScript instakill.SpellID = SPELL_BOOM; me->SendMessageToSet(instakill.Write(), false); - me->DealDamage(me, me->GetHealth(), nullptr, NODAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); + me->KillSelf(); damage = 0; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp index d6ea96a1ec8..9a8399068e2 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp @@ -948,7 +948,7 @@ class boss_yogg_saron : public CreatureScript Talk(SAY_YOGG_SARON_DEATH); if (Creature* creature = _instance->GetCreature(DATA_VOICE_OF_YOGG_SARON)) - me->Kill(creature); + Unit::Kill(me, creature); for (uint8 i = DATA_SARA; i <= DATA_BRAIN_OF_YOGG_SARON; ++i) if (Creature* creature = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(i))) @@ -3104,7 +3104,7 @@ class spell_yogg_saron_titanic_storm : public SpellScriptLoader // 64172 void HandleScript(SpellEffIndex /*effIndex*/) { if (Unit* target = GetHitUnit()) - GetCaster()->Kill(target); + Unit::Kill(GetCaster(), target); } void Register() override diff --git a/src/server/scripts/Northrend/zone_borean_tundra.cpp b/src/server/scripts/Northrend/zone_borean_tundra.cpp index ad80e29881c..2f41372df6d 100644 --- a/src/server/scripts/Northrend/zone_borean_tundra.cpp +++ b/src/server/scripts/Northrend/zone_borean_tundra.cpp @@ -149,7 +149,7 @@ public: DoCast(me, SPELL_EXPLODE_CART, true); if (Unit* worm = me->FindNearestCreature(NPC_SCOURGED_BURROWER, 3.0f)) { - me->Kill(worm); + Unit::Kill(me, worm); worm->RemoveDynamicFlag(UNIT_DYNFLAG_LOOTABLE); } phaseTimer = 2000; diff --git a/src/server/scripts/Northrend/zone_grizzly_hills.cpp b/src/server/scripts/Northrend/zone_grizzly_hills.cpp index 9fd63359db2..021fb8e7701 100644 --- a/src/server/scripts/Northrend/zone_grizzly_hills.cpp +++ b/src/server/scripts/Northrend/zone_grizzly_hills.cpp @@ -134,7 +134,7 @@ public: { if (Creature* RWORG = ObjectAccessor::GetCreature(*me, _RavenousworgGUID)) { - RWORG->Kill(Mrfloppy); + Unit::Kill(RWORG, Mrfloppy); Mrfloppy->ExitVehicle(); RWORG->SetFaction(FACTION_MONSTER); RWORG->GetMotionMaster()->MovePoint(0, RWORG->GetPositionX()+10, RWORG->GetPositionY()+80, RWORG->GetPositionZ()); diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp index 85fa9eb3f90..5406c35e176 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp @@ -348,7 +348,7 @@ public: Creature* Pet = ObjectAccessor::GetCreature(*me, SummonedPet); if (Pet && Pet->IsAlive()) - Pet->DealDamage(Pet, Pet->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); + Pet->KillSelf(); SummonedPet.Clear(); diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp index 97888f62955..57bd9af5500 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp @@ -157,7 +157,7 @@ public: AttackStart(owner); } else if (owner && owner->isDead()) { - me->DealDamage(me, me->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); + me->KillSelf(); return; } } diff --git a/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/boss_ahune.cpp b/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/boss_ahune.cpp index fe6268da9e8..e4f54514d94 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/boss_ahune.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/boss_ahune.cpp @@ -202,9 +202,9 @@ public: instance->DoCastSpellOnPlayers(SPELL_AHUNE_ACHIEVEMENT); if (Creature* ahuneBunny = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_AHUNE_BUNNY))) - me->Kill(ahuneBunny); + Unit::Kill(me, ahuneBunny); if (Creature* frozenCore = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FROZEN_CORE))) - me->Kill(frozenCore); + Unit::Kill(me, frozenCore); Map::PlayerList const& players = me->GetMap()->GetPlayers(); if (!players.isEmpty()) @@ -317,7 +317,7 @@ public: void JustDied(Unit* /*killer*/) override { if (Creature* ahune = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_AHUNE))) - me->Kill(ahune); + Unit::Kill(me, ahune); DoCast(SPELL_SUMMON_LOOT_MISSILE); DoCast(SPELL_MINION_DESPAWNER); diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp index 63503c6bbe6..4cceca72229 100644 --- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp @@ -125,7 +125,7 @@ class boss_shattered_executioner : public CreatureScript if (type == DATA_PRISONERS_EXECUTED && data <= 3) { if (Creature* victim = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FIRST_PRISONER + data - 1))) - me->Kill(victim); + Unit::Kill(me, victim); if (data == 1) { diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp index 07ce00a4a63..366de0b1ad1 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp @@ -550,7 +550,7 @@ class npc_ember_of_alar : public CreatureScript if (toDie) { - me->DealDamage(me, me->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); + me->KillSelf(); //me->SetVisibility(VISIBILITY_OFF); } diff --git a/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp b/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp index 455360570ca..c630d2f37e8 100644 --- a/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp +++ b/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp @@ -108,7 +108,7 @@ class npc_warp_splinter_treant : public CreatureScript { int32 CurrentHP_Treant = (int32)me->GetHealth(); Warp->CastSpell(Warp, SPELL_HEAL_FATHER, CastSpellExtraArgs(me->GetGUID()).AddSpellBP0(CurrentHP_Treant)); - me->DealDamage(me, me->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); + me->KillSelf(); return; } me->GetMotionMaster()->MoveFollow(Warp, 0, 0); diff --git a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp index 6cced21f333..d9e5e030a86 100644 --- a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp +++ b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp @@ -552,7 +552,7 @@ public: player->KilledMonsterCredit(23209); } PoisonTimer = 0; - me->DealDamage(me, me->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); + me->KillSelf(); } else PoisonTimer -= diff; } if (!UpdateVictim()) diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp index 0f59df198c1..12ff19eb64c 100644 --- a/src/server/scripts/Spells/spell_dk.cpp +++ b/src/server/scripts/Spells/spell_dk.cpp @@ -286,7 +286,7 @@ class spell_dk_dancing_rune_weapon : public AuraScript int32 amount = static_cast<int32>(damageInfo->GetDamage()) / 2; SpellNonMeleeDamage log(drw, drw->GetVictim(), spellInfo, { spellInfo->GetSpellXSpellVisualId(drw), 0 }, spellInfo->GetSchoolMask()); log.damage = amount; - drw->DealDamage(drw->GetVictim(), amount, nullptr, SPELL_DIRECT_DAMAGE, spellInfo->GetSchoolMask(), spellInfo, true); + Unit::DealDamage(drw, drw->GetVictim(), amount, nullptr, SPELL_DIRECT_DAMAGE, spellInfo->GetSchoolMask(), spellInfo, true); drw->SendSpellNonMeleeDamageLog(&log); } diff --git a/src/server/scripts/Spells/spell_monk.cpp b/src/server/scripts/Spells/spell_monk.cpp index b12aa458e68..721ca1f829e 100644 --- a/src/server/scripts/Spells/spell_monk.cpp +++ b/src/server/scripts/Spells/spell_monk.cpp @@ -309,7 +309,7 @@ class spell_monk_stagger_damage_aura : public AuraScript if (AuraEffect* auraEff = auraStagger->GetEffect(AuraStaggerEffectTotal)) { float total = float(auraEff->GetAmount()); - float tickDamage = float(aurEff->GetDamage()); + float tickDamage = float(aurEff->GetAmount()); auraEff->ChangeAmount(total - tickDamage); } } @@ -382,7 +382,7 @@ private: if (auraDamage) if (AuraEffect* eff = auraDamage->GetEffect(AuraStaggerEffectTick)) - eff->SetDamage(tickDamage); + eff->ChangeAmount(tickDamage); } }; |