From 2da82e5169d1f3a800d5e43265b797e0f6ef8d73 Mon Sep 17 00:00:00 2001 From: ratkosrb Date: Thu, 19 Dec 2024 14:23:50 +0200 Subject: [PATCH] Unify crit chance storage for players and creatures. --- src/game/Objects/Player.cpp | 50 +------------------ src/game/Objects/Player.h | 7 --- src/game/Objects/Unit.cpp | 90 ++++++++++++++++++++++++++++++---- src/game/Objects/Unit.h | 7 ++- src/game/Spells/SpellAuras.cpp | 10 +--- src/game/StatSystem.cpp | 30 ++---------- 6 files changed, 93 insertions(+), 101 deletions(-) diff --git a/src/game/Objects/Player.cpp b/src/game/Objects/Player.cpp index 57229585cec..65eb8d8aa48 100644 --- a/src/game/Objects/Player.cpp +++ b/src/game/Objects/Player.cpp @@ -580,8 +580,6 @@ Player::Player(WorldSession* session) : Unit(), m_modManaRegen = 0; m_modManaRegenInterrupt = 0; m_carryHealthRegen = 0; - for (float & s : m_SpellCritPercentage) - s = 0.0f; m_regenTimer = 0; m_weaponChangeTimer = 0; @@ -3794,7 +3792,7 @@ void Player::InitStatsForLevel(bool reapplyMods) SetFloatValue(PLAYER_RANGED_CRIT_PERCENTAGE, 0.0f); // Init spell schools (will be recalculated in UpdateAllStats() at loading and in _ApplyAllStatBonuses() at reset - for (float & i : m_SpellCritPercentage) + for (float & i : m_modSpellCritChance) i = 0.0f; SetFloatValue(PLAYER_PARRY_PERCENTAGE, 0.0f); @@ -5707,52 +5705,6 @@ float Player::GetDodgeFromAgility() const return GetStat(STAT_AGILITY) / classrate; } -float Player::GetSpellCritFromIntellect() const -{ -// Chance to crit is computed from INT and LEVEL as follows: - // chance = base + INT / (rate0 + rate1 * LEVEL) - // The formula keeps the crit chance at %5 on every level unless the player - // increases his intelligence by other means (enchants, buffs, talents, ...) - - //[TZERO] from mangos 3462 for 1.12 MUST BE CHECKED - - static const struct - { - float base; - float rate0, rate1; - } - crit_data[MAX_CLASSES] = - { - { 0.0f, 0.0f, 10.0f }, // 0: unused - { 0.0f, 0.0f, 10.0f }, // 1: warrior - { 3.70f, 14.77f, 0.65f }, // 2: paladin - { 0.0f, 0.0f, 10.0f }, // 3: hunter - { 0.0f, 0.0f, 10.0f }, // 4: rogue - { 2.97f, 10.03f, 0.82f }, // 5: priest - { 0.0f, 0.0f, 10.0f }, // 6: unused - { 3.54f, 11.51f, 0.80f }, // 7: shaman - { 3.70f, 14.77f, 0.65f }, // 8: mage - { 3.18f, 11.30f, 0.82f }, // 9: warlock - { 0.0f, 0.0f, 10.0f }, // 10: unused - { 3.33f, 12.41f, 0.79f } // 11: druid - }; - float crit_chance; - - // only players use intelligence for critical chance computations - if (GetTypeId() == TYPEID_PLAYER) - { - int my_class = GetClass(); - float crit_ratio = crit_data[my_class].rate0 + crit_data[my_class].rate1 * GetLevel(); - crit_chance = crit_data[my_class].base + GetStat(STAT_INTELLECT) / crit_ratio; - } - else - crit_chance = m_baseSpellCritChance; - - crit_chance = crit_chance > 0.0 ? crit_chance : 0.0; - - return crit_chance; -} - void Player::SetRegularAttackTime(bool resetTimer) { for (int i = 0; i < MAX_ATTACK; ++i) diff --git a/src/game/Objects/Player.h b/src/game/Objects/Player.h index 5d05139876f..64733a92b7c 100644 --- a/src/game/Objects/Player.h +++ b/src/game/Objects/Player.h @@ -1631,7 +1631,6 @@ class Player final: public Unit private: float m_modManaRegen; float m_modManaRegenInterrupt; - float m_SpellCritPercentage[MAX_SPELL_SCHOOL]; float m_carryHealthRegen; ObjectGuid m_comboTargetGuid; int8 m_comboPoints; @@ -1652,7 +1651,6 @@ class Player final: public Unit static float GetManaBonusFromIntellect(float intellect); float GetMeleeCritFromAgility() const; float GetDodgeFromAgility() const; - float GetSpellCritFromIntellect() const; void InitStatBuffMods() { for (int i = STAT_STRENGTH; i < MAX_STATS; ++i) SetFloatValue(PLAYER_FIELD_POSSTAT0 + i, 0); @@ -1696,8 +1694,6 @@ class Player final: public Unit void UpdateAllCritPercentages(); void UpdateParryPercentage(); void UpdateDodgePercentage(); - void UpdateAllSpellCritChances(); - void UpdateSpellCritChance(uint32 school); void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, float& min_damage, float& max_damage, uint8 index = 0) const; float GetWeaponBasedAuraModifier(WeaponAttackType attType, AuraType auraType) const final; @@ -1740,9 +1736,6 @@ class Player final: public Unit void UpdateEquipSpellsAtFormChange(); void outDebugStatsValues() const; - float GetSpellCritPercent(SpellSchools school) const { return m_SpellCritPercentage[school]; } - void SetSpellCritPercent(SpellSchools school, float percent) { m_SpellCritPercentage[school] = percent; } - /*********************************************************/ /*** SKILLS SYSTEM ***/ /*********************************************************/ diff --git a/src/game/Objects/Unit.cpp b/src/game/Objects/Unit.cpp index f9a780f1cea..8415299480b 100644 --- a/src/game/Objects/Unit.cpp +++ b/src/game/Objects/Unit.cpp @@ -140,12 +140,14 @@ Unit::Unit() for (float & stat : m_createStats) stat = 0.0f; - for (auto& m_createResistance : m_createResistances) - m_createResistance = 0; + for (auto& resistance : m_createResistances) + resistance = 0; m_attacking = nullptr; m_modSpellHitChance = 0.0f; - m_baseSpellCritChance = 5; + + for (float & crit : m_modSpellCritChance) + crit = 0.0f; m_combatTimer = 0; m_lastManaUseTimer = 0; @@ -2799,6 +2801,80 @@ float Unit::GetUnitCriticalChance(WeaponAttackType attackType, Unit const* pVict return crit; } +float Unit::GetSpellCritFromIntellect() const +{ + // Chance to crit is computed from INT and LEVEL as follows: + // chance = base + INT / (rate0 + rate1 * LEVEL) + // The formula keeps the crit chance at %5 on every level unless the player + // increases his intelligence by other means (enchants, buffs, talents, ...) + + //[TZERO] from mangos 3462 for 1.12 MUST BE CHECKED + + static const struct + { + float base; + float rate0, rate1; + } + crit_data[MAX_CLASSES] = + { + { 0.0f, 0.0f, 10.0f }, // 0: unused + { 0.0f, 0.0f, 10.0f }, // 1: warrior + { 3.70f, 14.77f, 0.65f }, // 2: paladin + { 0.0f, 0.0f, 10.0f }, // 3: hunter + { 0.0f, 0.0f, 10.0f }, // 4: rogue + { 2.97f, 10.03f, 0.82f }, // 5: priest + { 0.0f, 0.0f, 10.0f }, // 6: unused + { 3.54f, 11.51f, 0.80f }, // 7: shaman + { 3.70f, 14.77f, 0.65f }, // 8: mage + { 3.18f, 11.30f, 0.82f }, // 9: warlock + { 0.0f, 0.0f, 10.0f }, // 10: unused + { 3.33f, 12.41f, 0.79f } // 11: druid + }; + float crit_chance; + + // only players use intelligence for critical chance computations + if (GetTypeId() == TYPEID_PLAYER) + { + int my_class = GetClass(); + float crit_ratio = crit_data[my_class].rate0 + crit_data[my_class].rate1 * GetLevel(); + crit_chance = crit_data[my_class].base + GetStat(STAT_INTELLECT) / crit_ratio; + } + else + crit_chance = 5.0f; + + crit_chance = crit_chance > 0.0 ? crit_chance : 0.0; + + return crit_chance; +} + +void Unit::UpdateSpellCritChance(uint32 school) +{ + // For normal school set zero crit chance + if (school == SPELL_SCHOOL_NORMAL) + { + m_modSpellCritChance[1] = 0.0f; + return; + } + // For others recalculate it from: + float crit = 0.0f; + // Crit from Intellect + crit += GetSpellCritFromIntellect(); + // Increase crit from SPELL_AURA_MOD_SPELL_CRIT_CHANCE + crit += GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_CRIT_CHANCE); + // Increase crit by school from SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL + crit += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL, 1 << school); + + // Store crit value + m_modSpellCritChance[school] = crit; +} + +void Unit::UpdateAllSpellCritChances() +{ + for (int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; ++i) + UpdateSpellCritChance(i); +} + + void Unit::_UpdateSpells(uint32 time) { if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL]) @@ -5350,13 +5426,9 @@ bool Unit::IsSpellCrit(Unit const* pVictim, SpellEntry const* spellProto, SpellS if (schoolMask & SPELL_SCHOOL_MASK_NORMAL) crit_chance = 0.0f; // For other schools - else if (IsPlayer()) - crit_chance = ((Player*)this)->GetSpellCritPercent(GetFirstSchoolInMask(schoolMask)); else - { - crit_chance = float(m_baseSpellCritChance); - crit_chance += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL, schoolMask); - } + crit_chance = GetSpellCritPercent(GetFirstSchoolInMask(schoolMask)); + // taken if (!spellProto->IsPositiveSpell()) { diff --git a/src/game/Objects/Unit.h b/src/game/Objects/Unit.h index 6cbd78cd3cd..5048a1712e1 100644 --- a/src/game/Objects/Unit.h +++ b/src/game/Objects/Unit.h @@ -402,7 +402,7 @@ class Unit : public SpellCaster public: // Data float m_modSpellHitChance; - int32 m_baseSpellCritChance; + float m_modSpellCritChance[MAX_SPELL_SCHOOL]; float m_threatModifier[MAX_SPELL_SCHOOL]; float m_modAttackSpeedPct[3]; float m_modRecalcDamagePct[3]; @@ -465,6 +465,11 @@ class Unit : public SpellCaster float GetUnitParryChance() const; float GetUnitBlockChance() const; float GetUnitCriticalChance(WeaponAttackType attackType, Unit const* pVictim) const; + float GetSpellCritFromIntellect() const; + float GetSpellCritPercent(SpellSchools school) const { return m_modSpellCritChance[school]; } + void SetSpellCritPercent(SpellSchools school, float percent) { m_modSpellCritChance[school] = percent; } + void UpdateAllSpellCritChances(); + void UpdateSpellCritChance(uint32 school); virtual uint32 GetShieldBlockValue() const = 0; float GetPPMProcChance(uint32 WeaponSpeed, float PPM) const; diff --git a/src/game/Spells/SpellAuras.cpp b/src/game/Spells/SpellAuras.cpp index 46bb2108e81..f003ea5dcd1 100644 --- a/src/game/Spells/SpellAuras.cpp +++ b/src/game/Spells/SpellAuras.cpp @@ -5267,10 +5267,7 @@ void Aura::HandleModSpellCritChance(bool apply, bool Real) if (!Real) return; - if (GetTarget()->GetTypeId() == TYPEID_PLAYER) - ((Player*)GetTarget())->UpdateAllSpellCritChances(); - else - GetTarget()->m_baseSpellCritChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount); + GetTarget()->UpdateAllSpellCritChances(); } void Aura::HandleModSpellCritChanceSchool(bool /*apply*/, bool Real) @@ -5279,12 +5276,9 @@ void Aura::HandleModSpellCritChanceSchool(bool /*apply*/, bool Real) if (!Real) return; - if (GetTarget()->GetTypeId() != TYPEID_PLAYER) - return; - for (int school = SPELL_SCHOOL_NORMAL; school < MAX_SPELL_SCHOOL; ++school) if (m_modifier.m_miscvalue & (1 << school)) - ((Player*)GetTarget())->UpdateSpellCritChance(school); + GetTarget()->UpdateSpellCritChance(school); } /********************************/ diff --git a/src/game/StatSystem.cpp b/src/game/StatSystem.cpp index d555085d1da..5d82f145ab7 100644 --- a/src/game/StatSystem.cpp +++ b/src/game/StatSystem.cpp @@ -630,33 +630,6 @@ void Player::UpdateDodgePercentage() SetStatFloatValue(PLAYER_DODGE_PERCENTAGE, value); } -void Player::UpdateSpellCritChance(uint32 school) -{ - // For normal school set zero crit chance - if (school == SPELL_SCHOOL_NORMAL) - { - m_SpellCritPercentage[1] = 0.0f; - return; - } - // For others recalculate it from: - float crit = 0.0f; - // Crit from Intellect - crit += GetSpellCritFromIntellect(); - // Increase crit from SPELL_AURA_MOD_SPELL_CRIT_CHANCE - crit += GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_CRIT_CHANCE); - // Increase crit by school from SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL - crit += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL, 1 << school); - - // Store crit value - m_SpellCritPercentage[school] = crit; -} - -void Player::UpdateAllSpellCritChances() -{ - for (int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; ++i) - UpdateSpellCritChance(i); -} - void Player::UpdateManaRegen() { // Mana regen from spirit @@ -754,6 +727,7 @@ bool Creature::UpdateAllStats() UpdateMaxHealth(); UpdateAttackPowerAndDamage(); UpdateAttackPowerAndDamage(true); + UpdateAllSpellCritChances(); for (int i = POWER_MANA; i < MAX_POWERS; ++i) UpdateMaxPower(Powers(i)); @@ -1005,6 +979,8 @@ bool Pet::UpdateAllStats() for (int i = STAT_STRENGTH; i < MAX_STATS; ++i) UpdateStats(Stats(i)); + UpdateAllSpellCritChances(); + for (int i = POWER_MANA; i < MAX_POWERS; ++i) UpdateMaxPower(Powers(i));