From 637955c439ddd8516e1170129a38d2b1348e24cd Mon Sep 17 00:00:00 2001 From: killerwife Date: Wed, 27 Dec 2023 15:23:44 +0100 Subject: [PATCH] Player: Properly encapsulate weapon hit chance recalculation on item operations --- src/game/Entities/Player.cpp | 26 +++++++-------- src/game/Entities/Player.h | 5 +-- src/game/Entities/StatSystem.cpp | 54 +++++++++++++++++--------------- src/game/Entities/Unit.cpp | 9 +++--- src/game/Entities/Unit.h | 3 +- src/game/Spells/SpellAuras.cpp | 10 +++--- 6 files changed, 55 insertions(+), 52 deletions(-) diff --git a/src/game/Entities/Player.cpp b/src/game/Entities/Player.cpp index 5fae00d339..e9ff538df8 100644 --- a/src/game/Entities/Player.cpp +++ b/src/game/Entities/Player.cpp @@ -5218,10 +5218,11 @@ void Player::UpdateRating(CombatRating cr) UpdateBlockPercentage(); break; case CR_HIT_MELEE: - UpdateMeleeHitChances(); + UpdateWeaponHitChances(BASE_ATTACK); + UpdateWeaponHitChances(OFF_ATTACK); break; case CR_HIT_RANGED: - UpdateRangedHitChances(); + UpdateWeaponHitChances(RANGED_ATTACK); break; case CR_HIT_SPELL: UpdateSpellHitChances(); @@ -10484,14 +10485,11 @@ Item* Player::EquipItem(uint16 pos, Item* pItem, bool update) ApplyEquipCooldown(pItem); if (slot == EQUIPMENT_SLOT_MAINHAND) - { - UpdateExpertise(BASE_ATTACK); - UpdateMeleeHitChances(); - } + UpdateWeaponDependantStats(BASE_ATTACK); else if (slot == EQUIPMENT_SLOT_OFFHAND) - UpdateExpertise(OFF_ATTACK); + UpdateWeaponDependantStats(OFF_ATTACK); else if (slot == EQUIPMENT_SLOT_RANGED) - UpdateRangedHitChances(); + UpdateWeaponDependantStats(RANGED_ATTACK); } else { @@ -10646,10 +10644,10 @@ void Player::RemoveItem(uint8 bag, uint8 slot, bool update) pItem->ClearEnchantment(PROP_ENCHANTMENT_SLOT_1); } - UpdateExpertise(BASE_ATTACK); + UpdateWeaponDependantStats(BASE_ATTACK); } else if (slot == EQUIPMENT_SLOT_OFFHAND) - UpdateExpertise(OFF_ATTACK); + UpdateWeaponDependantStats(OFF_ATTACK); } } @@ -10772,11 +10770,13 @@ void Player::DestroyItem(uint8 bag, uint8 slot, bool update) // remove item dependent auras and casts (only weapon and armor slots) RemoveItemDependentAurasAndCasts(pItem); - // update expertise + // update weapon dependant stats if (slot == EQUIPMENT_SLOT_MAINHAND) - UpdateExpertise(BASE_ATTACK); + UpdateWeaponDependantStats(BASE_ATTACK); else if (slot == EQUIPMENT_SLOT_OFFHAND) - UpdateExpertise(OFF_ATTACK); + UpdateWeaponDependantStats(OFF_ATTACK); + else if (slot == EQUIPMENT_SLOT_RANGED) + UpdateWeaponDependantStats(RANGED_ATTACK); // equipment visual show SetVisibleItemSlot(slot, nullptr); diff --git a/src/game/Entities/Player.h b/src/game/Entities/Player.h index b22715ab86..46d8a355ac 100644 --- a/src/game/Entities/Player.h +++ b/src/game/Entities/Player.h @@ -1716,8 +1716,7 @@ class Player : public Unit void UpdateAllCritPercentages(); void UpdateParryPercentage(); void UpdateDodgePercentage(); - void UpdateMeleeHitChances(); - void UpdateRangedHitChances(); + void UpdateWeaponHitChances(WeaponAttackType attType); void UpdateSpellHitChances(); void UpdateAllSpellCritChances(); @@ -1726,6 +1725,8 @@ class Player : public Unit void UpdateManaRegen(); void UpdateEnergyRegen(); + void UpdateWeaponDependantStats(WeaponAttackType attType); + ObjectGuid const& GetLootGuid() const { return m_lootGuid; } void SetLootGuid(ObjectGuid const& guid) { m_lootGuid = guid; } diff --git a/src/game/Entities/StatSystem.cpp b/src/game/Entities/StatSystem.cpp index 1892a33a68..025c733f5b 100644 --- a/src/game/Entities/StatSystem.cpp +++ b/src/game/Entities/StatSystem.cpp @@ -125,6 +125,9 @@ bool Player::UpdateAllStats() UpdateManaRegen(); UpdateExpertise(BASE_ATTACK); UpdateExpertise(OFF_ATTACK); + UpdateWeaponHitChances(BASE_ATTACK); + UpdateWeaponHitChances(OFF_ATTACK); + UpdateWeaponHitChances(RANGED_ATTACK); for (int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; ++i) UpdateResistances(i); @@ -570,42 +573,23 @@ void Player::UpdateSpellCritChance(uint32 school) SetFloatValue(PLAYER_SPELL_CRIT_PERCENTAGE1 + school, std::max(0.0f, std::min(crit, 100.0f))); } -void Player::UpdateMeleeHitChances() +void Player::UpdateWeaponHitChances(WeaponAttackType attType) { - int32 meleeHitChance = 0; - Item* weapon = GetWeaponForAttack(BASE_ATTACK); + int32 weaponHitChance = 0; + Item* weapon = GetWeaponForAttack(attType); AuraList const& hitAura = GetAurasByType(SPELL_AURA_MOD_HIT_CHANCE); for (auto hitAura : hitAura) { // item neutral spell if (hitAura->GetSpellProto()->EquippedItemClass == -1) - meleeHitChance += hitAura->GetModifier()->m_amount; + weaponHitChance += hitAura->GetModifier()->m_amount; // item dependent spell else if (weapon && weapon->IsFitToSpellRequirements(hitAura->GetSpellProto())) - meleeHitChance += hitAura->GetModifier()->m_amount; + weaponHitChance += hitAura->GetModifier()->m_amount; } - m_modMeleeHitChance = meleeHitChance; - m_modMeleeHitChance += GetRatingBonusValue(CR_HIT_MELEE); -} - -void Player::UpdateRangedHitChances() -{ - int32 rangedHitChance = 0; - Item* weapon = GetWeaponForAttack(RANGED_ATTACK); - - AuraList const& hitAura = GetAurasByType(SPELL_AURA_MOD_HIT_CHANCE); - for (auto hitAura : hitAura) - { - // item neutral spell - if (hitAura->GetSpellProto()->EquippedItemClass == -1) - rangedHitChance += hitAura->GetModifier()->m_amount; - // item dependent spell - else if (weapon && weapon->IsFitToSpellRequirements(hitAura->GetSpellProto())) - rangedHitChance += hitAura->GetModifier()->m_amount; - } - m_modMeleeHitChance = rangedHitChance; - m_modRangedHitChance += GetRatingBonusValue(CR_HIT_RANGED); + m_modWeaponHitChance[attType] = weaponHitChance; + m_modWeaponHitChance[attType] += attType == RANGED_ATTACK ? GetRatingBonusValue(CR_HIT_RANGED) : GetRatingBonusValue(CR_HIT_MELEE); } void Player::UpdateSpellHitChances() @@ -698,6 +682,24 @@ void Player::UpdateEnergyRegen() m_energyRegenRate = GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, POWER_ENERGY); } +void Player::UpdateWeaponDependantStats(WeaponAttackType attType) +{ + switch (attType) + { + case BASE_ATTACK: + UpdateWeaponHitChances(attType); + UpdateExpertise(attType); + break; + case OFF_ATTACK: + UpdateWeaponHitChances(attType); + UpdateExpertise(attType); + break; + case RANGED_ATTACK: + UpdateWeaponHitChances(attType); + break; + } +} + void Player::_ApplyAllStatBonuses() { SetCanModifyStats(false); diff --git a/src/game/Entities/Unit.cpp b/src/game/Entities/Unit.cpp index acb256ec23..2fc566072c 100644 --- a/src/game/Entities/Unit.cpp +++ b/src/game/Entities/Unit.cpp @@ -391,8 +391,9 @@ Unit::Unit() : m_createResistance = 0; m_attacking = nullptr; - m_modMeleeHitChance = 0.0f; - m_modRangedHitChance = 0.0f; + m_modWeaponHitChance[BASE_ATTACK] = 0.0f; + m_modWeaponHitChance[OFF_ATTACK] = 0.0f; + m_modWeaponHitChance[RANGED_ATTACK] = 0.0f; m_modSpellHitChance = 0.0f; for (float& i : m_modSpellCritChance) i = 0.0f; @@ -3776,9 +3777,7 @@ uint32 Unit::CalculateCritAmount(CalcDamageInfo* meleeInfo) const float Unit::GetHitChance(WeaponAttackType attackType) const { - if (attackType == RANGED_ATTACK) - return m_modRangedHitChance; - return m_modMeleeHitChance; + return m_modWeaponHitChance[attackType]; } float Unit::GetHitChance(SpellSchoolMask schoolMask) const diff --git a/src/game/Entities/Unit.h b/src/game/Entities/Unit.h index 37576af7f7..33b40628b7 100644 --- a/src/game/Entities/Unit.h +++ b/src/game/Entities/Unit.h @@ -2026,8 +2026,7 @@ class Unit : public WorldObject form != FORM_SHADOW && form != FORM_STEALTH; } - float m_modMeleeHitChance; - float m_modRangedHitChance; + float m_modWeaponHitChance[MAX_ATTACK]; float m_modSpellHitChance; float m_modSpellCritChance[MAX_SPELL_SCHOOL]; diff --git a/src/game/Spells/SpellAuras.cpp b/src/game/Spells/SpellAuras.cpp index 7e1ba93de5..87bc0b673e 100755 --- a/src/game/Spells/SpellAuras.cpp +++ b/src/game/Spells/SpellAuras.cpp @@ -5865,13 +5865,15 @@ void Aura::HandleModHitChance(bool apply, bool /*Real*/) if (target->IsPlayer()) { - static_cast(target)->UpdateMeleeHitChances(); - static_cast(target)->UpdateRangedHitChances(); + static_cast(target)->UpdateWeaponHitChances(BASE_ATTACK); + static_cast(target)->UpdateWeaponHitChances(OFF_ATTACK); + static_cast(target)->UpdateWeaponHitChances(RANGED_ATTACK); } else { - target->m_modMeleeHitChance += (apply ? m_modifier.m_amount : -m_modifier.m_amount); - target->m_modRangedHitChance += (apply ? m_modifier.m_amount : -m_modifier.m_amount); + target->m_modWeaponHitChance[BASE_ATTACK] += (apply ? m_modifier.m_amount : -m_modifier.m_amount); + target->m_modWeaponHitChance[OFF_ATTACK] += (apply ? m_modifier.m_amount : -m_modifier.m_amount); + target->m_modWeaponHitChance[RANGED_ATTACK] += (apply ? m_modifier.m_amount : -m_modifier.m_amount); } }