fix(Core/Player): smooth energy regeneration with SPELL_AURA_MOD_POWER_REGEN_PERCENT mods (#22041)

Co-authored-by: r4dish <ovitnez@gmail.com>
This commit is contained in:
Jelle Meeus
2025-05-04 14:20:59 +02:00
committed by GitHub
parent 3643d80ecf
commit 297f16820e
5 changed files with 32 additions and 35 deletions

View File

@@ -1882,9 +1882,9 @@ void Player::Regenerate(Powers power)
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) * ManaIncreaseRate * 0.001f * m_regenTimer;
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) * ManaIncreaseRate * 0.001f * m_regenTimer;
addvalue += GetFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER + AsUnderlyingType(POWER_MANA)) * ManaIncreaseRate * 0.001f * m_regenTimer;
}
break;
case POWER_RAGE: // Regenerate rage
@@ -1897,7 +1897,14 @@ void Player::Regenerate(Powers power)
}
break;
case POWER_ENERGY: // Regenerate energy (rogue)
addvalue += 0.01f * m_regenTimer * sWorld->getRate(RATE_POWER_ENERGY);
// 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:
{
@@ -1918,8 +1925,8 @@ void Player::Regenerate(Powers power)
break;
}
// Mana regen calculated in Player::UpdateManaRegen()
if (power != POWER_MANA)
// Mana regen calculated in Player::UpdateManaRegen(), energy regen calculated in Player::UpdateEnergyRegen()
if (power != POWER_MANA && power != POWER_ENERGY)
{
AuraEffectList const& ModPowerRegenPCTAuras = GetAuraEffectsByType(SPELL_AURA_MOD_POWER_REGEN_PERCENT);
for (AuraEffectList::const_iterator i = ModPowerRegenPCTAuras.begin(); i != ModPowerRegenPCTAuras.end(); ++i)
@@ -1947,7 +1954,6 @@ void Player::Regenerate(Powers power)
addvalue += m_powerFraction[power];
uint32 integerValue = uint32(std::fabs(addvalue));
bool forcedUpdate = false;
if (addvalue < 0.0f)
{
if (curValue > integerValue)
@@ -1959,7 +1965,6 @@ void Player::Regenerate(Powers power)
{
curValue = 0;
m_powerFraction[power] = 0;
forcedUpdate = true;
}
}
else
@@ -1970,22 +1975,15 @@ void Player::Regenerate(Powers power)
{
curValue = maxValue;
m_powerFraction[power] = 0;
forcedUpdate = true;
}
else
{
m_powerFraction[power] = addvalue - integerValue;
}
}
if (m_regenTimerCount >= 2000 || forcedUpdate)
{
if (m_regenTimerCount >= 2000 || curValue == 0 || curValue == maxValue)
SetPower(power, curValue, true, true);
}
else
{
UpdateUInt32Value(static_cast<uint16>(UNIT_FIELD_POWER1) + power, curValue);
}
UpdateUInt32Value(UNIT_FIELD_POWER1 + AsUnderlyingType(power), curValue);
}
void Player::RegenerateHealth()

View File

@@ -1996,6 +1996,7 @@ public:
void ApplyManaRegenBonus(int32 amount, bool apply);
void ApplyHealthRegenBonus(int32 amount, bool apply);
void UpdateManaRegen();
void UpdateEnergyRegen();
void UpdateRuneRegen(RuneType rune);
[[nodiscard]] ObjectGuid GetLootGUID() const { return m_lootGuid; }

View File

@@ -952,9 +952,19 @@ void Player::UpdateManaRegen()
int32 modManaRegenInterrupt = GetTotalAuraModifier(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT);
if (modManaRegenInterrupt > 100)
modManaRegenInterrupt = 100;
SetStatFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER, power_regen_mp5 + CalculatePct(power_regen, modManaRegenInterrupt));
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, power_regen_mp5 + power_regen);
SetStatFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER + AsUnderlyingType(POWER_MANA), power_regen_mp5 + power_regen);
}
void Player::UpdateEnergyRegen()
{
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));
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);
}
void Player::UpdateRuneRegen(RuneType rune)

View File

@@ -15618,29 +15618,23 @@ void Unit::SetMaxHealth(uint32 val)
void Unit::SetPower(Powers power, uint32 val, bool withPowerUpdate /*= true*/, bool fromRegenerate /* = false */)
{
if (!fromRegenerate && GetPower(power) == val)
{
return;
}
uint32 maxPower = GetMaxPower(power);
if (maxPower < val)
{
val = maxPower;
}
if (fromRegenerate)
{
UpdateUInt32Value(static_cast<uint16>(UNIT_FIELD_POWER1) + power, val);
UpdateUInt32Value(UNIT_FIELD_POWER1 + AsUnderlyingType(power), val);
AddToObjectUpdateIfNeeded();
}
else
{
SetStatInt32Value(static_cast<uint16>(UNIT_FIELD_POWER1) + power, val);
}
SetStatInt32Value(UNIT_FIELD_POWER1 + AsUnderlyingType(power), val);
if (withPowerUpdate)
{
WorldPacket data(SMSG_POWER_UPDATE);
WorldPacket data(SMSG_POWER_UPDATE, 8 + 1 + 4);
data << GetPackGUID();
data << uint8(power);
data << uint32(val);
@@ -15652,14 +15646,10 @@ void Unit::SetPower(Powers power, uint32 val, bool withPowerUpdate /*= true*/, b
{
Player* player = ToPlayer();
if (getPowerType() == power && player->NeedSendSpectatorData())
{
ArenaSpectator::SendCommand_UInt32Value(FindMap(), GetGUID(), "CPW", power == POWER_RAGE || power == POWER_RUNIC_POWER ? val / 10 : val);
}
if (player->GetGroup())
{
player->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_CUR_POWER);
}
}
else if (Pet* pet = ToCreature()->ToPet())
{
@@ -15667,16 +15657,12 @@ void Unit::SetPower(Powers power, uint32 val, bool withPowerUpdate /*= true*/, b
{
Unit* owner = GetOwner();
if (owner && (owner->IsPlayer()) && owner->ToPlayer()->GetGroup())
{
owner->ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_POWER);
}
}
// Update the pet's character sheet with happiness damage bonus
if (pet->getPetType() == HUNTER_PET && power == POWER_HAPPINESS)
{
pet->UpdateDamagePhysical(BASE_ATTACK);
}
}
}

View File

@@ -4664,6 +4664,8 @@ void AuraEffect::HandleModPowerRegen(AuraApplication const* aurApp, uint8 mode,
// Update manaregen value
if (GetMiscValue() == POWER_MANA)
target->ToPlayer()->UpdateManaRegen();
else if (GetMiscValue() == POWER_ENERGY)
target->ToPlayer()->UpdateEnergyRegen();
else if (GetMiscValue() == POWER_RUNE)
target->ToPlayer()->UpdateRuneRegen(RuneType(GetMiscValueB()));
// other powers are not immediate effects - implemented in Player::Regenerate, Creature::Regenerate