diff --git a/Source/Framework/Constants/Spells/SpellAuraConst.cs b/Source/Framework/Constants/Spells/SpellAuraConst.cs index 83c4fca50..a6ef5e5a1 100644 --- a/Source/Framework/Constants/Spells/SpellAuraConst.cs +++ b/Source/Framework/Constants/Spells/SpellAuraConst.cs @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - */ + */ namespace Framework.Constants { @@ -576,4 +576,10 @@ namespace Framework.Constants Level4 = 3, TauntImmune = 4 } + + public enum AuraTriggerOnPowerChangeDirection + { + Gain = 0, + Loss = 1 + } } diff --git a/Source/Framework/Util/MathFunctions.cs b/Source/Framework/Util/MathFunctions.cs index 3e81a1ff8..3a6ca98fe 100644 --- a/Source/Framework/Util/MathFunctions.cs +++ b/Source/Framework/Util/MathFunctions.cs @@ -171,6 +171,11 @@ public static class MathFunctions return (ulong)(value * pct / 100.0f); } + public static float GetPctOf(float value, float max) + { + return value / max * 100.0f; + } + public static int RoundToInterval(ref int num, dynamic floor, dynamic ceil) { return num = (int)Math.Min(Math.Max(num, floor), ceil); diff --git a/Source/Game/Entities/StatSystem.cs b/Source/Game/Entities/StatSystem.cs index ec024382c..d7464d5bd 100644 --- a/Source/Game/Entities/StatSystem.cs +++ b/Source/Game/Entities/StatSystem.cs @@ -603,6 +603,7 @@ namespace Game.Entities if (maxPower < val) val = maxPower; + int oldPower = m_unitData.Power[(int)powerIndex]; SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Power, (int)powerIndex), val); if (IsInWorld) @@ -613,6 +614,8 @@ namespace Game.Entities SendMessageToSet(packet, IsTypeId(TypeId.Player)); } + TriggerOnPowerChangeAuras(powerType, oldPower, val); + // group update if (IsTypeId(TypeId.Player)) { @@ -658,6 +661,48 @@ namespace Game.Entities public virtual uint GetPowerIndex(PowerType powerType) { return 0; } public float GetPowerPct(PowerType powerType) { return GetMaxPower(powerType) != 0 ? 100.0f* GetPower(powerType) / GetMaxPower(powerType) : 0.0f; } + void TriggerOnPowerChangeAuras(PowerType power, int oldVal, int newVal) + { + var effects = GetAuraEffectsByType(AuraType.TriggerSpellOnPowerPct); + var effectsAmount = GetAuraEffectsByType(AuraType.TriggerSpellOnPowerAmount); + effects.AddRange(effectsAmount); + + foreach (AuraEffect effect in effects) + { + if (effect.GetMiscValue() == (int)power) + { + uint effectAmount = (uint)effect.GetAmount(); + uint triggerSpell = effect.GetSpellEffectInfo().TriggerSpell; + + float oldValueCheck = oldVal; + float newValueCheck = newVal; + + if (effect.GetAuraType() == AuraType.TriggerSpellOnPowerPct) + { + int maxPower = GetMaxPower(power); + oldValueCheck = MathFunctions.GetPctOf(oldVal, maxPower); + newValueCheck = MathFunctions.GetPctOf(newVal, maxPower); + } + + switch ((AuraTriggerOnPowerChangeDirection)effect.GetMiscValueB()) + { + case AuraTriggerOnPowerChangeDirection.Gain: + if (oldValueCheck >= effect.GetAmount() || newValueCheck < effectAmount) + continue; + break; + case AuraTriggerOnPowerChangeDirection.Loss: + if (oldValueCheck <= effect.GetAmount() || newValueCheck > effectAmount) + continue; + break; + default: + break; + } + + CastSpell(this, triggerSpell, true, null, effect); + } + } + } + public void ApplyResilience(Unit victim, ref uint damage) { // player mounted on multi-passenger mount is also classified as vehicle diff --git a/Source/Game/Spells/Auras/AuraEffect.cs b/Source/Game/Spells/Auras/AuraEffect.cs index 6c0b07ec0..c0201ef9a 100644 --- a/Source/Game/Spells/Auras/AuraEffect.cs +++ b/Source/Game/Spells/Auras/AuraEffect.cs @@ -4698,6 +4698,64 @@ namespace Game.Spells } } + [AuraEffectHandler(AuraType.TriggerSpellOnPowerPct)] + void HandleTriggerSpellOnPowerPercent(AuraApplication aurApp, AuraEffectHandleModes mode, bool apply) + { + if (!mode.HasAnyFlag(AuraEffectHandleModes.Real) || !apply) + return; + + Unit target = aurApp.GetTarget(); + + int effectAmount = GetAmount(); + uint triggerSpell = GetSpellEffectInfo().TriggerSpell; + float powerAmountPct = MathFunctions.GetPctOf(target.GetPower((PowerType)GetMiscValue()), target.GetMaxPower((PowerType)GetMiscValue())); + + switch ((AuraTriggerOnPowerChangeDirection)GetMiscValueB()) + { + case AuraTriggerOnPowerChangeDirection.Gain: + if (powerAmountPct < effectAmount) + return; + break; + case AuraTriggerOnPowerChangeDirection.Loss: + if (powerAmountPct > effectAmount) + return; + break; + default: + break; + } + + target.CastSpell(target, triggerSpell, true); + } + + [AuraEffectHandler(AuraType.TriggerSpellOnPowerAmount)] + void HandleTriggerSpellOnPowerAmount(AuraApplication aurApp, AuraEffectHandleModes mode, bool apply) + { + if (!mode.HasAnyFlag(AuraEffectHandleModes.Real) || !apply) + return; + + Unit target = aurApp.GetTarget(); + + int effectAmount = GetAmount(); + uint triggerSpell = GetSpellEffectInfo().TriggerSpell; + float powerAmount = target.GetPower((PowerType)GetMiscValue()); + + switch ((AuraTriggerOnPowerChangeDirection)GetMiscValueB()) + { + case AuraTriggerOnPowerChangeDirection.Gain: + if (powerAmount < effectAmount) + return; + break; + case AuraTriggerOnPowerChangeDirection.Loss: + if (powerAmount > effectAmount) + return; + break; + default: + break; + } + + target.CastSpell(target, triggerSpell, true); + } + [AuraEffectHandler(AuraType.OpenStable)] void HandleAuraOpenStable(AuraApplication aurApp, AuraEffectHandleModes mode, bool apply) {