diff options
| author | r4dish <ovitnez@gmail.com> | 2024-02-25 13:36:50 +0100 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2024-02-25 13:36:50 +0100 |
| commit | a7dab01c2dc7105f5feddcbd4bf5489b330d70b5 (patch) | |
| tree | 111c17f886bfa0070b06bb9932daaa3aeff54942 /src/server/game/Entities/Unit | |
| parent | 1a3006b20d8c41139b206f610bcb6c22508ec329 (diff) | |
Core/Players: Move power regeneration calculations to Player::UpdatePowerRegen
Diffstat (limited to 'src/server/game/Entities/Unit')
| -rw-r--r-- | src/server/game/Entities/Unit/StatSystem.cpp | 139 |
1 files changed, 108 insertions, 31 deletions
diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp index 44cfc2edf62..cb467b8de38 100644 --- a/src/server/game/Entities/Unit/StatSystem.cpp +++ b/src/server/game/Entities/Unit/StatSystem.cpp @@ -158,7 +158,7 @@ bool Player::UpdateStats(Stats stat) } UpdateSpellDamageAndHealingBonus(); - UpdateManaRegen(); + UpdatePowerRegen(POWER_MANA); // Update ratings in exist SPELL_AURA_MOD_RATING_FROM_STAT and only depends from stat uint32 mask = 0; @@ -227,7 +227,10 @@ bool Player::UpdateAllStats() UpdateDefenseBonusesMod(); UpdateShieldBlockValue(); UpdateSpellDamageAndHealingBonus(); - UpdateManaRegen(); + UpdatePowerRegen(POWER_MANA); + UpdatePowerRegen(POWER_RAGE); + UpdatePowerRegen(POWER_ENERGY); + UpdatePowerRegen(POWER_RUNIC_POWER); UpdateExpertise(BASE_ATTACK); UpdateExpertise(OFF_ATTACK); RecalculateRating(CR_ARMOR_PENETRATION); @@ -908,7 +911,7 @@ void Player::UpdateExpertise(WeaponAttackType attack) void Player::ApplyManaRegenBonus(int32 amount, bool apply) { _ModifyUInt32(apply, m_baseManaRegen, amount); - UpdateManaRegen(); + UpdatePowerRegen(POWER_MANA); } void Player::ApplyHealthRegenBonus(int32 amount, bool apply) @@ -916,39 +919,113 @@ void Player::ApplyHealthRegenBonus(int32 amount, bool apply) _ModifyUInt32(apply, m_baseHealthRegen, amount); } -void Player::UpdateManaRegen() +static std::pair<float, Optional<Rates>> const powerRegenInfo[MAX_POWERS] = { - float Intellect = GetStat(STAT_INTELLECT); - // Mana regen from spirit and intellect - float power_regen = std::sqrt(Intellect) * OCTRegenMPPerSpirit(); - // Apply PCT bonus from SPELL_AURA_MOD_POWER_REGEN_PERCENT aura on spirit base regen - power_regen *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, POWER_MANA); - - // Mana regen from SPELL_AURA_MOD_POWER_REGEN aura - float power_regen_mp5 = (GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA) + m_baseManaRegen) / 5.0f; - - // Get bonus from SPELL_AURA_MOD_MANA_REGEN_FROM_STAT aura - AuraEffectList const& regenAura = GetAuraEffectsByType(SPELL_AURA_MOD_MANA_REGEN_FROM_STAT); - for (AuraEffectList::const_iterator i = regenAura.begin(); i != regenAura.end(); ++i) - power_regen_mp5 += GetStat(Stats((*i)->GetMiscValue())) * (*i)->GetAmount() / 500.0f; - - // Set regen rate in cast state apply only on spirit based regen - int32 modManaRegenInterrupt = GetTotalAuraModifier(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT); - if (modManaRegenInterrupt > 100) - modManaRegenInterrupt = 100; - SetStatFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER + AsUnderlyingType(POWER_MANA), power_regen_mp5 + CalculatePct(power_regen, modManaRegenInterrupt)); - - SetStatFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER + AsUnderlyingType(POWER_MANA), power_regen_mp5 + power_regen); + { 0.f, RATE_POWER_MANA }, // POWER_MANA + { -12.5f, RATE_POWER_RAGE_LOSS }, // POWER_RAGE, -1.25 rage per second + { 0.f, std::nullopt }, // POWER_FOCUS + { 10.f, RATE_POWER_ENERGY }, // POWER_ENERGY, +10 energy per second + { 0.f, std::nullopt }, // POWER_HAPPINESS + { 0.f, std::nullopt }, // POWER_RUNE + { -12.5f, RATE_POWER_RUNICPOWER_LOSS } // POWER_RUNIC_POWER, -1.25 runic power per second +}; + +void Player::UpdatePowerRegen(Powers power) +{ + if (power == POWER_HEALTH || power >= MAX_POWERS) + return; + + float result_regen = 0.f; // Out-of-combat / without last mana use effect + float result_regen_interrupted = 0.f; // In combat / with last mana use effect + float modifier = 1.f; // Config rate or any other modifiers + + /// @todo possible use of miscvalueb instead of amount + if (HasAuraTypeWithValue(SPELL_AURA_PREVENT_REGENERATE_POWER, power)) + { + SetFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER + AsUnderlyingType(power), power == POWER_ENERGY ? -10.f : 0.f); + SetFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER + AsUnderlyingType(power), power == POWER_ENERGY ? -10.f : 0.f); + return; + } + + switch (power) + { + case POWER_MANA: + { + float Intellect = GetStat(STAT_INTELLECT); + // Mana regen from spirit and intellect + float power_regen = std::sqrt(Intellect) * OCTRegenMPPerSpirit(); + // Apply PCT bonus from SPELL_AURA_MOD_POWER_REGEN_PERCENT aura on spirit base regen + power_regen *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, POWER_MANA); + + // Mana regen from SPELL_AURA_MOD_POWER_REGEN aura + float power_regen_mp5 = (GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA) + m_baseManaRegen) / 5.0f; + + // Get bonus from SPELL_AURA_MOD_MANA_REGEN_FROM_STAT aura + AuraEffectList const& regenAura = GetAuraEffectsByType(SPELL_AURA_MOD_MANA_REGEN_FROM_STAT); + for (AuraEffectList::const_iterator i = regenAura.begin(); i != regenAura.end(); ++i) + power_regen_mp5 += GetStat(Stats((*i)->GetMiscValue())) * (*i)->GetAmount() / 500.0f; + + // Set regen rate in cast state apply only on spirit based regen + int32 modManaRegenInterrupt = GetTotalAuraModifier(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT); + if (modManaRegenInterrupt > 100) + modManaRegenInterrupt = 100; + + result_regen = power_regen_mp5 + power_regen; + result_regen_interrupted = power_regen_mp5 + CalculatePct(power_regen, modManaRegenInterrupt); + + if (GetLevel() < 15) + modifier *= 2.066f - (GetLevel() * 0.066f); + break; + } + case POWER_RAGE: + case POWER_ENERGY: + case POWER_RUNIC_POWER: + { + result_regen = powerRegenInfo[AsUnderlyingType(power)].first; + result_regen_interrupted = 0.f; + + result_regen *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, AsUnderlyingType(power)); + result_regen_interrupted += static_cast<float>(GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, AsUnderlyingType(power))) / 5.f; + + if (power != POWER_RUNIC_POWER) // Butchery requires combat + result_regen += result_regen_interrupted; + break; + } + default: + break; + } + + if (powerRegenInfo[AsUnderlyingType(power)].second.has_value()) + modifier *= sWorld->getRate(powerRegenInfo[AsUnderlyingType(power)].second.value()); // Config rate + + result_regen *= modifier; + result_regen_interrupted *= modifier; + + // Unit fields contain an offset relative to the base power regeneration. + if (power != POWER_MANA) + result_regen -= powerRegenInfo[AsUnderlyingType(power)].first; + + if (power == POWER_ENERGY) + result_regen_interrupted = result_regen; + + SetFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER + AsUnderlyingType(power), result_regen); + SetFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER + AsUnderlyingType(power), result_regen_interrupted); } -void Player::UpdateEnergyRegen() +float Player::GetPowerRegen(Powers power) const { - float regenPerSecond = 10.f; // +10 energy per second - regenPerSecond *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, POWER_ENERGY); - regenPerSecond += static_cast<float>(GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_ENERGY)) / static_cast<float>((5 * IN_MILLISECONDS)); + if (power == POWER_HEALTH || power >= MAX_POWERS) + return 0.f; + + bool interrupted = HasAuraType(SPELL_AURA_INTERRUPT_REGEN) || + (power == POWER_MANA && IsUnderLastManaUseEffect()) || + (power != POWER_MANA && IsInCombat()); + + float regen = GetFloatValue((interrupted ? UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER : UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER) + AsUnderlyingType(power)); + if (power != POWER_MANA) + regen += (power == POWER_ENERGY || !interrupted) ? powerRegenInfo[AsUnderlyingType(power)].first : 0.f; - SetStatFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER + AsUnderlyingType(POWER_ENERGY), regenPerSecond - 10.f); - SetStatFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER + AsUnderlyingType(POWER_ENERGY), regenPerSecond - 10.f); + return regen; } void Player::UpdateRuneRegen(RuneType rune) |
