diff options
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 68 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 4 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/StatSystem.cpp | 139 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 34 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.h | 1 |
5 files changed, 134 insertions, 112 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 11d9c9ea1c8..6872705706f 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -2056,73 +2056,7 @@ void Player::Regenerate(Powers power) return; uint32 curValue = GetPower(power); - - /// @todo possible use of miscvalueb instead of amount - if (HasAuraTypeWithValue(SPELL_AURA_PREVENT_REGENERATE_POWER, power)) - return; - - float addvalue = 0.0f; - - switch (power) - { - case POWER_MANA: - { - bool recentCast = IsUnderLastManaUseEffect(); - float ManaIncreaseRate = sWorld->getRate(RATE_POWER_MANA); - - if (GetLevel() < 15) - ManaIncreaseRate = sWorld->getRate(RATE_POWER_MANA) * (2.066f - (GetLevel() * 0.066f)); - - if (recentCast) // Trinity Updates Mana in intervals of 2s, which is correct - addvalue += GetFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER + AsUnderlyingType(POWER_MANA)) * ManaIncreaseRate * 0.001f * m_regenTimer; - else - addvalue += GetFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER + AsUnderlyingType(POWER_MANA)) * ManaIncreaseRate * 0.001f * m_regenTimer; - } break; - case POWER_RAGE: // Regenerate rage - { - if (!IsInCombat() && !HasAuraType(SPELL_AURA_INTERRUPT_REGEN)) - { - float RageDecreaseRate = sWorld->getRate(RATE_POWER_RAGE_LOSS); - addvalue += -0.0125f * m_regenTimer * RageDecreaseRate; // -1.25 rage per second - } - } break; - case POWER_ENERGY: // Regenerate energy (rogue) - // Regen per second - addvalue += (GetFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER + AsUnderlyingType(POWER_ENERGY)) + 10.f); - // Regen per millisecond - addvalue *= 0.001f; - // Milliseconds passed - addvalue *= m_regenTimer; - // Rate - addvalue *= sWorld->getRate(RATE_POWER_ENERGY); - break; - case POWER_RUNIC_POWER: - { - if (!IsInCombat() && !HasAuraType(SPELL_AURA_INTERRUPT_REGEN)) - { - float RunicPowerDecreaseRate = sWorld->getRate(RATE_POWER_RUNICPOWER_LOSS); - addvalue += -0.0125f * m_regenTimer * RunicPowerDecreaseRate; // -1.25 runic power per second - } - } break; - case POWER_RUNE: - case POWER_FOCUS: - case POWER_HAPPINESS: - break; - case POWER_HEALTH: - return; - default: - break; - } - - // Mana regen calculated in Player::UpdateManaRegen(), energy regen calculated in Player::UpdateEnergyRegen() - if (power != POWER_MANA && power != POWER_ENERGY) - { - addvalue *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, power); - - // Butchery requires combat for this effect - if (power != POWER_RUNIC_POWER || IsInCombat()) - addvalue += static_cast<float>(GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, power)) * static_cast<float>(m_regenTimer) / static_cast<float>((5 * IN_MILLISECONDS)); - } + float addvalue = GetPowerRegen(power) * 0.001f * m_regenTimer; if (addvalue < 0.0f) { diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 80f90f4e09c..3d5f7fd4361 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1649,9 +1649,9 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> void UpdateExpertise(WeaponAttackType attType); void ApplyManaRegenBonus(int32 amount, bool apply); void ApplyHealthRegenBonus(int32 amount, bool apply); - void UpdateManaRegen(); - void UpdateEnergyRegen(); + void UpdatePowerRegen(Powers power); void UpdateRuneRegen(RuneType rune); + float GetPowerRegen(Powers power) const; uint32 GetRuneTimer(uint8 index) const { return m_runeGraceCooldown[index]; } void SetRuneTimer(uint8 index, uint32 timer) { m_runeGraceCooldown[index] = timer; } uint32 GetLastRuneGraceTimer(uint8 index) const { return m_lastRuneGraceTimers[index]; } 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) diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 018bff978e9..119f5c8f304 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -144,7 +144,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleWaterBreathing, // 82 SPELL_AURA_WATER_BREATHING &AuraEffect::HandleModBaseResistance, // 83 SPELL_AURA_MOD_BASE_RESISTANCE &AuraEffect::HandleNoImmediateEffect, // 84 SPELL_AURA_MOD_REGEN implemented in Player::RegenerateHealth - &AuraEffect::HandleModPowerRegen, // 85 SPELL_AURA_MOD_POWER_REGEN implemented in Player::Regenerate + &AuraEffect::HandleModPowerRegen, // 85 SPELL_AURA_MOD_POWER_REGEN &AuraEffect::HandleChannelDeathItem, // 86 SPELL_AURA_CHANNEL_DEATH_ITEM &AuraEffect::HandleNoImmediateEffect, // 87 SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus &AuraEffect::HandleNoImmediateEffect, // 88 SPELL_AURA_MOD_HEALTH_REGEN_PERCENT implemented in Player::RegenerateHealth @@ -153,7 +153,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleNoImmediateEffect, // 91 SPELL_AURA_MOD_DETECT_RANGE implemented in Creature::GetAttackDistance &AuraEffect::HandlePreventFleeing, // 92 SPELL_AURA_PREVENTS_FLEEING &AuraEffect::HandleModUnattackable, // 93 SPELL_AURA_MOD_UNATTACKABLE - &AuraEffect::HandleNoImmediateEffect, // 94 SPELL_AURA_INTERRUPT_REGEN implemented in Player::Regenerate + &AuraEffect::HandleNoImmediateEffect, // 94 SPELL_AURA_INTERRUPT_REGEN implemented in Player::GetPowerRegen &AuraEffect::HandleAuraGhost, // 95 SPELL_AURA_GHOST &AuraEffect::HandleNoImmediateEffect, // 96 SPELL_AURA_SPELL_MAGNET implemented in Unit::SelectMagnetTarget &AuraEffect::HandleNoImmediateEffect, // 97 SPELL_AURA_MANA_SHIELD implemented in Unit::CalcAbsorbResist @@ -169,7 +169,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleNoImmediateEffect, //107 SPELL_AURA_ADD_FLAT_MODIFIER implemented in AuraEffect::CalculateSpellMod() &AuraEffect::HandleNoImmediateEffect, //108 SPELL_AURA_ADD_PCT_MODIFIER implemented in AuraEffect::CalculateSpellMod() &AuraEffect::HandleNoImmediateEffect, //109 SPELL_AURA_ADD_TARGET_TRIGGER - &AuraEffect::HandleModPowerRegenPCT, //110 SPELL_AURA_MOD_POWER_REGEN_PERCENT implemented in Player::Regenerate, Creature::Regenerate + &AuraEffect::HandleModPowerRegenPCT, //110 SPELL_AURA_MOD_POWER_REGEN_PERCENT implemented in Player::UpdatePowerRegen, Creature::Regenerate &AuraEffect::HandleNoImmediateEffect, //111 SPELL_AURA_ADD_CASTER_HIT_TRIGGER implemented in Unit::SelectMagnetTarget &AuraEffect::HandleNoImmediateEffect, //112 SPELL_AURA_OVERRIDE_CLASS_SCRIPTS &AuraEffect::HandleNoImmediateEffect, //113 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus @@ -353,7 +353,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleNoImmediateEffect, //291 SPELL_AURA_MOD_XP_QUEST_PCT implemented in Player::RewardQuest &AuraEffect::HandleAuraOpenStable, //292 SPELL_AURA_OPEN_STABLE &AuraEffect::HandleAuraOverrideSpells, //293 SPELL_AURA_OVERRIDE_SPELLS auras which probably add set of abilities to their target based on it's miscvalue - &AuraEffect::HandleNoImmediateEffect, //294 SPELL_AURA_PREVENT_REGENERATE_POWER implemented in Player::Regenerate(Powers power) + &AuraEffect::HandleAuraPreventRegeneratePower, //294 SPELL_AURA_PREVENT_REGENERATE_POWER &AuraEffect::HandleUnused, //295 0 spells in 3.3.5 &AuraEffect::HandleAuraSetVehicle, //296 SPELL_AURA_SET_VEHICLE_ID sets vehicle on target &AuraEffect::HandleNULL, //297 Spirit Burst spells @@ -3643,14 +3643,11 @@ void AuraEffect::HandleModPowerRegen(AuraApplication const* aurApp, uint8 mode, if (target->GetTypeId() != TYPEID_PLAYER) return; - // Update manaregen value - if (GetMiscValue() == POWER_MANA) - target->ToPlayer()->UpdateManaRegen(); - else if (GetMiscValue() == POWER_ENERGY) - target->ToPlayer()->UpdateEnergyRegen(); - else if (GetMiscValue() == POWER_RUNE) + if (GetMiscValue() == POWER_RUNE) target->ToPlayer()->UpdateRuneRegen(RuneType(GetMiscValueB())); - // other powers are not immediate effects - implemented in Player::Regenerate, Creature::Regenerate + else + target->ToPlayer()->UpdatePowerRegen(static_cast<Powers>(GetMiscValue())); + } void AuraEffect::HandleModPowerRegenPCT(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -3669,7 +3666,7 @@ void AuraEffect::HandleModManaRegen(AuraApplication const* aurApp, uint8 mode, b return; //Note: an increase in regen does NOT cause threat. - target->ToPlayer()->UpdateManaRegen(); + target->ToPlayer()->UpdatePowerRegen(POWER_MANA); } void AuraEffect::HandleAuraModIncreaseHealth(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -4997,6 +4994,19 @@ void AuraEffect::HandleAuraOverrideSpells(AuraApplication const* aurApp, uint8 m } } +void AuraEffect::HandleAuraPreventRegeneratePower(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const +{ + if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit* target = aurApp->GetTarget(); + + if (target->GetTypeId() != TYPEID_PLAYER) + return; + + target->ToPlayer()->UpdatePowerRegen(static_cast<Powers>(GetAmount())); /// @todo possible use of miscvalueb instead of amount +} + void AuraEffect::HandleAuraSetVehicle(AuraApplication const* aurApp, uint8 mode, bool apply) const { if (!(mode & AURA_EFFECT_HANDLE_REAL)) diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h index 6a50956f81d..27c1ef275ef 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.h +++ b/src/server/game/Spells/Auras/SpellAuraEffects.h @@ -288,6 +288,7 @@ class TC_GAME_API AuraEffect void HandleAuraOpenStable(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleAuraModFakeInebriation(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleAuraOverrideSpells(AuraApplication const* aurApp, uint8 mode, bool apply) const; + void HandleAuraPreventRegeneratePower(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleAuraSetVehicle(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandlePreventResurrection(AuraApplication const* aurApp, uint8 mode, bool apply) const; |