diff options
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); } }; |