Core/Auras: Implemented SPELL_AURA_MOD_RECOVERY_RATE and SPELL_AURA_MOD_RECOVERY_RATE_BY_SPELL_LABEL

Port From (https://github.com/TrinityCore/TrinityCore/commit/0c198938005bb22f20a0d150a6505324a2d941de)
This commit is contained in:
Hondacrx
2025-06-16 17:21:48 -04:00
parent 3d043f984d
commit 7d46284519
3 changed files with 113 additions and 3 deletions
+18 -2
View File
@@ -501,16 +501,32 @@ namespace Game.Networking.Packets
_worldPacket.WriteUInt32(SpellID);
_worldPacket.WriteInt32(DeltaTime);
_worldPacket.WriteBit(IsPet);
_worldPacket.WriteBit(WithoutCategoryCooldown);
_worldPacket.WriteBit(SkipCategory);
_worldPacket.FlushBits();
}
public bool IsPet;
public bool WithoutCategoryCooldown;
public bool SkipCategory;
public int DeltaTime;
public uint SpellID;
}
class UpdateCooldown : ServerPacket
{
public uint SpellID;
public float ModChange = 1.0f;
public float ModRate = 1.0f;
public UpdateCooldown() : base(ServerOpcodes.UpdateCooldown, ConnectionType.Instance) { }
public override void Write()
{
_worldPacket.WriteUInt32(SpellID);
_worldPacket.WriteFloat(ModChange);
_worldPacket.WriteFloat(ModRate);
}
}
public class SpellCooldownPkt : ServerPacket
{
public SpellCooldownPkt() : base(ServerOpcodes.SpellCooldown, ConnectionType.Instance) { }
+29
View File
@@ -5813,6 +5813,35 @@ namespace Game.Spells
target.RemoveSpellCategoryCooldownMod(GetMiscValue(), GetAmount());
}
[AuraEffectHandler(AuraType.ModRecoveryRate)]
void HandleModRecoveryRate(AuraApplication aurApp, AuraEffectHandleModes mode, bool apply)
{
if (!mode.HasAnyFlag(AuraEffectHandleModes.ChangeAmountMask))
return;
float rate = 100.0f / (Math.Max(GetAmount(), -99.0f) + 100.0f);
aurApp.GetTarget().GetSpellHistory().UpdateCooldownRecoveryRate(cooldown =>
{
return IsAffectingSpell(Global.SpellMgr.GetSpellInfo(cooldown.SpellId, Difficulty.None));
}, rate, apply);
}
[AuraEffectHandler(AuraType.ModRecoveryRateBySpellLabel)]
void HandleModRecoveryRateBySpellLabel(AuraApplication aurApp, AuraEffectHandleModes mode, bool apply)
{
if (!mode.HasAnyFlag(AuraEffectHandleModes.ChangeAmountMask))
return;
float rate = 100.0f / (Math.Max(GetAmount(), -99.0f) + 100.0f);
aurApp.GetTarget().GetSpellHistory().UpdateCooldownRecoveryRate(cooldown =>
{
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(cooldown.SpellId, Difficulty.None);
return spellInfo.HasLabel((uint)GetMiscValue()) || (GetMiscValueB() != 0 && spellInfo.HasLabel((uint)GetMiscValueB()));
}, rate, apply);
}
[AuraEffectHandler(AuraType.ShowConfirmationPrompt)]
[AuraEffectHandler(AuraType.ShowConfirmationPromptWithDifficulty)]
void HandleShowConfirmationPrompt(AuraApplication aurApp, AuraEffectHandleModes mode, bool apply)
+66 -1
View File
@@ -354,6 +354,8 @@ namespace Game.Spells
{
if (!forcedCooldown.HasValue)
{
TimeSpan baseCooldown = cooldown;
// Now we have cooldown data (if found any), time to apply mods
Player modOwner = _owner.GetSpellModOwner();
if (modOwner != null)
@@ -384,6 +386,35 @@ namespace Game.Spells
categoryCooldown = TimeSpan.FromMilliseconds(categoryCooldown.TotalMilliseconds * _owner.m_unitData.ModHasteRegen);
}
{
float calcRecoveryRate(AuraEffect modRecoveryRate)
{
float rate = 100.0f / (Math.Max(modRecoveryRate.GetAmount(), -99.0f) + 100.0f);
if (baseCooldown <= TimeSpan.FromHours(1)
&& !spellInfo.HasAttribute(SpellAttr6.IgnoreForModTimeRate)
&& !modRecoveryRate.GetSpellEffectInfo().EffectAttributes.HasFlag(SpellEffectAttributes.IgnoreDuringCooldownTimeRateCalculation))
rate *= _owner.m_unitData.ModTimeRate;
return rate;
}
float recoveryRate = 1.0f;
foreach (AuraEffect modRecoveryRate in _owner.GetAuraEffectsByType(AuraType.ModRecoveryRate))
if (modRecoveryRate.IsAffectingSpell(spellInfo))
recoveryRate *= calcRecoveryRate(modRecoveryRate);
foreach (AuraEffect modRecoveryRate in _owner.GetAuraEffectsByType(AuraType.ModRecoveryRateBySpellLabel))
if (spellInfo.HasLabel((uint)modRecoveryRate.GetMiscValue()) || (modRecoveryRate.GetMiscValueB() != 0 && spellInfo.HasLabel((uint)modRecoveryRate.GetMiscValueB())))
recoveryRate *= calcRecoveryRate(modRecoveryRate);
if (recoveryRate > 0.0f)
{
cooldown = TimeSpan.FromMilliseconds((long)(cooldown.TotalMilliseconds * recoveryRate));
categoryCooldown = TimeSpan.FromMilliseconds((long)(categoryCooldown.TotalMilliseconds * recoveryRate));
}
}
int cooldownMod = _owner.GetTotalAuraModifier(AuraType.ModCooldown);
if (cooldownMod != 0)
{
@@ -535,7 +566,7 @@ namespace Game.Spells
modifyCooldown.IsPet = _owner != playerOwner;
modifyCooldown.SpellID = cooldownEntry.SpellId;
modifyCooldown.DeltaTime = (int)cooldownMod.TotalMilliseconds;
modifyCooldown.WithoutCategoryCooldown = withoutCategoryCooldown;
modifyCooldown.SkipCategory = withoutCategoryCooldown;
playerOwner.SendPacket(modifyCooldown);
}
@@ -546,6 +577,40 @@ namespace Game.Spells
}
}
public void UpdateCooldownRecoveryRate(Func<CooldownEntry, bool> predicate, float modChange, bool apply)
{
foreach (var cooldownEntry in _spellCooldowns.Values)
{
if (predicate(cooldownEntry))
UpdateCooldownRecoveryRate(cooldownEntry, modChange, apply);
}
}
public void UpdateCooldownRecoveryRate(CooldownEntry cooldownEntry, float modChange, bool apply)
{
if (modChange <= 0.0f)
return;
if (!apply)
modChange = 1.0f / modChange;
DateTime now = GameTime.GetDateAndTime();
cooldownEntry.CooldownEnd = now + TimeSpan.FromMilliseconds((cooldownEntry.CooldownEnd - now).TotalMilliseconds * modChange);
if (cooldownEntry.CategoryId != 0)
cooldownEntry.CategoryEnd = now + TimeSpan.FromMilliseconds((cooldownEntry.CategoryEnd - now).TotalMilliseconds * modChange);
Player playerOwner = GetPlayerOwner();
if (playerOwner != null)
{
UpdateCooldown updateCooldown = new();
updateCooldown.SpellID = cooldownEntry.SpellId;
updateCooldown.ModChange = modChange;
playerOwner.SendPacket(updateCooldown);
}
}
public void ModifyCooldown(uint spellId, TimeSpan cooldownMod, bool withoutCategoryCooldown = false)
{
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(spellId, _owner.GetMap().GetDifficultyID());