Skip to content

Commit

Permalink
Unify crit chance storage for players and creatures.
Browse files Browse the repository at this point in the history
  • Loading branch information
ratkosrb committed Dec 19, 2024
1 parent 48f8410 commit 2da82e5
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 101 deletions.
50 changes: 1 addition & 49 deletions src/game/Objects/Player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand Down
7 changes: 0 additions & 7 deletions src/game/Objects/Player.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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 ***/
/*********************************************************/
Expand Down
90 changes: 81 additions & 9 deletions src/game/Objects/Unit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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])
Expand Down Expand Up @@ -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())
{
Expand Down
7 changes: 6 additions & 1 deletion src/game/Objects/Unit.h
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -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;
Expand Down
10 changes: 2 additions & 8 deletions src/game/Spells/SpellAuras.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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);
}

/********************************/
Expand Down
30 changes: 3 additions & 27 deletions src/game/StatSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -754,6 +727,7 @@ bool Creature::UpdateAllStats()
UpdateMaxHealth();
UpdateAttackPowerAndDamage();
UpdateAttackPowerAndDamage(true);
UpdateAllSpellCritChances();

for (int i = POWER_MANA; i < MAX_POWERS; ++i)
UpdateMaxPower(Powers(i));
Expand Down Expand Up @@ -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));

Expand Down

0 comments on commit 2da82e5

Please sign in to comment.