From c81f48197d4f7ea0fa4c4dd4f7bd54c64839f93d Mon Sep 17 00:00:00 2001 From: ariel- Date: Sun, 8 May 2022 20:55:54 +0200 Subject: [PATCH] Core/Spells: calculate crit chance only for spells that do damage/healing --- src/server/game/Entities/Unit/Unit.cpp | 8 ++--- src/server/game/Entities/Unit/Unit.h | 4 +-- .../game/Spells/Auras/SpellAuraEffects.cpp | 8 +++-- src/server/game/Spells/Auras/SpellAuras.cpp | 3 ++ src/server/game/Spells/SpellInfo.h | 1 + src/server/game/Spells/SpellMgr.cpp | 30 +++++++++++++++++++ 6 files changed, 46 insertions(+), 8 deletions(-) diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 65f5d9ac01..8ab84c4b2c 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -7106,14 +7106,14 @@ int32 Unit::SpellBaseDamageBonusTaken(SpellInfo const* spellInfo) const return TakenAdvertisedBenefit; } -float Unit::SpellCritChanceDone(SpellInfo const* spellInfo, SpellSchoolMask schoolMask, WeaponAttackType attackType /*= BASE_ATTACK*/) const +float Unit::SpellCritChanceDone(SpellInfo const* spellInfo, SpellSchoolMask schoolMask, WeaponAttackType attackType /*= BASE_ATTACK*/, bool isPeriodic /*= false*/) const { //! Mobs can't crit with spells. (Except player controlled) if (GetTypeId() == TYPEID_UNIT && !GetSpellModOwner()) return 0.0f; // not critting spell - if (spellInfo->HasAttribute(SPELL_ATTR2_CANT_CRIT)) + if (!isPeriodic && !spellInfo->HasAttribute(SPELL_ATTR0_CU_CAN_CRIT)) return 0.0f; float crit_chance = 0.0f; @@ -7152,10 +7152,10 @@ float Unit::SpellCritChanceDone(SpellInfo const* spellInfo, SpellSchoolMask scho return std::max(crit_chance, 0.0f); } -float Unit::SpellCritChanceTaken(Unit const* caster, SpellInfo const* spellInfo, SpellSchoolMask schoolMask, float doneChance, WeaponAttackType attackType /*= BASE_ATTACK*/) const +float Unit::SpellCritChanceTaken(Unit const* caster, SpellInfo const* spellInfo, SpellSchoolMask schoolMask, float doneChance, WeaponAttackType attackType /*= BASE_ATTACK*/, bool isPeriodic /*= false*/) const { // not critting spell - if (spellInfo->HasAttribute(SPELL_ATTR2_CANT_CRIT)) + if (!isPeriodic && !spellInfo->HasAttribute(SPELL_ATTR0_CU_CAN_CRIT)) return 0.0f; float crit_chance = doneChance; diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 2a9a1a2a6e..54cd8b7e00 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1649,8 +1649,8 @@ class TC_GAME_API Unit : public WorldObject bool isSpellBlocked(Unit* victim, SpellInfo const* spellProto); bool isBlockCritical(); - float SpellCritChanceDone(SpellInfo const* spellInfo, SpellSchoolMask schoolMask, WeaponAttackType attackType = BASE_ATTACK) const; - float SpellCritChanceTaken(Unit const* caster, SpellInfo const* spellInfo, SpellSchoolMask schoolMask, float doneChance, WeaponAttackType attackType = BASE_ATTACK) const; + float SpellCritChanceDone(SpellInfo const* spellInfo, SpellSchoolMask schoolMask, WeaponAttackType attackType = BASE_ATTACK, bool isPeriodic = false) const; + float SpellCritChanceTaken(Unit const* caster, SpellInfo const* spellInfo, SpellSchoolMask schoolMask, float doneChance, WeaponAttackType attackType = BASE_ATTACK, bool isPeriodic = false) const; static uint32 SpellCriticalDamageBonus(Unit const* caster, SpellInfo const* spellProto, uint32 damage); static uint32 SpellCriticalHealingBonus(Unit const* caster, uint32 damage); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 0aa0c481c1..bcb72b58bc 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -1002,8 +1002,7 @@ void AuraEffect::UpdatePeriodic(Unit* caster) float AuraEffect::GetCritChanceFor(Unit const* caster, Unit const* target) const { - float crit = caster->SpellCritChanceDone(GetSpellInfo(), GetSpellInfo()->GetSchoolMask(), GetSpellInfo()->GetAttackType()); - return target->SpellCritChanceTaken(caster, GetSpellInfo(), GetSpellInfo()->GetSchoolMask(), crit, GetSpellInfo()->GetAttackType()); + return target->SpellCritChanceTaken(caster, GetSpellInfo(), GetSpellInfo()->GetSchoolMask(), GetBase()->GetCritChance(), GetSpellInfo()->GetAttackType(), true); } bool AuraEffect::IsAffectingSpell(SpellInfo const* spell) const @@ -1143,6 +1142,11 @@ bool AuraEffect::CheckEffectProc(AuraApplication* aurApp, ProcEventInfo& eventIn return false; break; } + case SPELL_AURA_MOD_SPELL_CRIT_CHANCE: + // skip spells that can't crit + if (!spellInfo || !spellInfo->HasAttribute(SPELL_ATTR0_CU_CAN_CRIT)) + return false; + break; default: break; } diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index e50f943a4c..1f04dc7e15 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -407,6 +407,9 @@ bool Aura::CanPeriodicTickCrit(Unit const* caster) const if (m_spellInfo->HasAttribute(SPELL_ATTR8_PERIODIC_CAN_CRIT)) return true; + if (m_spellInfo->HasAttribute(SPELL_ATTR2_CANT_CRIT)) + return false; + return caster->HasAuraTypeWithAffectMask(SPELL_AURA_ABILITY_PERIODIC_CRIT, GetSpellInfo()); } diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index ecd47ae4c8..fe443147e4 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -188,6 +188,7 @@ enum SpellCustomAttributes SPELL_ATTR0_CU_NO_INITIAL_THREAT = 0x00000010, SPELL_ATTR0_CU_AURA_CC = 0x00000020, SPELL_ATTR0_CU_DONT_BREAK_STEALTH = 0x00000040, + SPELL_ATTR0_CU_CAN_CRIT = 0x00000080, SPELL_ATTR0_CU_DIRECT_DAMAGE = 0x00000100, SPELL_ATTR0_CU_CHARGE = 0x00000200, SPELL_ATTR0_CU_PICKPOCKET = 0x00000400, diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 56b599a262..46e066afde 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -2690,6 +2690,22 @@ void SpellMgr::LoadSpellInfoCustomAttributes() break; } + switch (spellInfo->Effects[j].Effect) + { + case SPELL_EFFECT_SCHOOL_DAMAGE: + case SPELL_EFFECT_HEALTH_LEECH: + case SPELL_EFFECT_HEAL: + case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: + case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: + case SPELL_EFFECT_WEAPON_DAMAGE: + case SPELL_EFFECT_POWER_BURN: + case SPELL_EFFECT_HEAL_MECHANICAL: + case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: + case SPELL_EFFECT_HEAL_PCT: + spellInfo->AttributesCu |= SPELL_ATTR0_CU_CAN_CRIT; + break; + } + switch (spellInfo->Effects[j].Effect) { case SPELL_EFFECT_SCHOOL_DAMAGE: @@ -2903,6 +2919,20 @@ void SpellMgr::LoadSpellInfoCustomAttributes() spellInfo->AttributesCu &= ~SPELL_ATTR0_CU_BINARY_SPELL; } + // remove attribute from spells that can't crit + for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i) + { + spellInfo = mSpellInfoMap[i]; + if (!spellInfo) + continue; + + if (!spellInfo->HasAttribute(SPELL_ATTR0_CU_CAN_CRIT)) + continue; + + if (spellInfo->HasAttribute(SPELL_ATTR2_CANT_CRIT)) + spellInfo->AttributesCu &= ~SPELL_ATTR0_CU_CAN_CRIT; + } + // add custom attribute to liquid auras for (LiquidTypeEntry const* liquid : sLiquidTypeStore) {