Core/Auras: Implemented OnHeartbeat AuraScript hook and refactored an aurascript to use it as example

Port From (https://github.com/TrinityCore/TrinityCore/commit/55ce5b150f716b6d470af80a9c31adf78e4cc198)
This commit is contained in:
Hondacrx
2024-08-19 12:24:24 -04:00
parent d7130c982d
commit cf42b5e591
5 changed files with 41 additions and 16 deletions
@@ -59,6 +59,7 @@ namespace Framework.Constants
CheckAreaTarget, CheckAreaTarget,
Dispel, Dispel,
AfterDispel, AfterDispel,
OnHeartbeat,
EnterLeaveCombat, EnterLeaveCombat,
// Spell Proc Hooks // Spell Proc Hooks
CheckProc, CheckProc,
+1 -1
View File
@@ -2562,7 +2562,7 @@ namespace Game.Entities
// SMSG_FLIGHT_SPLINE_SYNC for cyclic splines // SMSG_FLIGHT_SPLINE_SYNC for cyclic splines
SendFlightSplineSyncUpdate(); SendFlightSplineSyncUpdate();
// Trigger heartbeat procs and generic aura behavior such as food emotes // Trigger heartbeat procs and generic aura behavior such as food emotes and invoking aura script hooks
TriggerAuraHeartbeat(); TriggerAuraHeartbeat();
// Update Vignette position and visibility // Update Vignette position and visibility
+19 -1
View File
@@ -1094,6 +1094,7 @@ namespace Game.Scripting
// DO NOT OVERRIDE THESE IN SCRIPTS // DO NOT OVERRIDE THESE IN SCRIPTS
public delegate bool AuraCheckAreaTargetDelegate(Unit target); public delegate bool AuraCheckAreaTargetDelegate(Unit target);
public delegate void AuraDispelDelegate(DispelInfo dispelInfo); public delegate void AuraDispelDelegate(DispelInfo dispelInfo);
public delegate void AuraHeartbeatDelegate();
public delegate void AuraEffectDamageAndHealingCalcFnType(AuraEffect aurEff, Unit victim, ref int damageOrHealing, ref int flatMod, ref float pctMod); public delegate void AuraEffectDamageAndHealingCalcFnType(AuraEffect aurEff, Unit victim, ref int damageOrHealing, ref int flatMod, ref float pctMod);
public delegate void AuraEffectApplicationModeDelegate(AuraEffect aura, AuraEffectHandleModes auraMode); public delegate void AuraEffectApplicationModeDelegate(AuraEffect aura, AuraEffectHandleModes auraMode);
public delegate void AuraEffectPeriodicDelegate(AuraEffect aura); public delegate void AuraEffectPeriodicDelegate(AuraEffect aura);
@@ -1135,6 +1136,18 @@ namespace Game.Scripting
} }
} }
public class AuraHeartbeatHandler
{
AuraHeartbeatDelegate _callImpl;
public AuraHeartbeatHandler(AuraHeartbeatDelegate callImpl) { _callImpl = callImpl; }
public void Call(AuraScript auraScript)
{
_callImpl();
}
}
public class EffectBase : EffectHook public class EffectBase : EffectHook
{ {
AuraType _effAurName; AuraType _effAurName;
@@ -1264,7 +1277,7 @@ namespace Game.Scripting
_callImpl(aurEff, victim, ref damageOrHealing, ref flatMod, ref pctMod); _callImpl(aurEff, victim, ref damageOrHealing, ref flatMod, ref pctMod);
} }
} }
public class EffectApplyHandler : EffectBase public class EffectApplyHandler : EffectBase
{ {
AuraEffectApplicationModeDelegate _callImpl; AuraEffectApplicationModeDelegate _callImpl;
@@ -1601,6 +1614,11 @@ namespace Game.Scripting
// where function is: void function (DispelInfo dispelInfo); // where function is: void function (DispelInfo dispelInfo);
public List<AuraDispelHandler> AfterDispel = new(); public List<AuraDispelHandler> AfterDispel = new();
// executed on every heartbeat of a unit
// example: OnHeartbeat += AuraHeartbeatFn(class::function);
// where function is: void function ();
public List<AuraHeartbeatHandler> OnHeartbeat = new();
// executed when aura effect is applied with specified mode to target // executed when aura effect is applied with specified mode to target
// should be used when effect handler preventing/replacing is needed, do not use this hook for triggering spellcasts/removing auras etc - may be unsafe // should be used when effect handler preventing/replacing is needed, do not use this hook for triggering spellcasts/removing auras etc - may be unsafe
// example: OnEffectApply += AuraEffectApplyFn(class.function, EffectIndexSpecifier, EffectAuraNameSpecifier, AuraEffectHandleModes); // example: OnEffectApply += AuraEffectApplyFn(class.function, EffectIndexSpecifier, EffectAuraNameSpecifier, AuraEffectHandleModes);
+16 -1
View File
@@ -1986,6 +1986,18 @@ namespace Game.Spells
} }
} }
public void CallScriptOnHeartbeat()
{
foreach (var script in m_loadedScripts)
{
script._PrepareScriptCall(AuraScriptHookType.OnHeartbeat);
foreach (var onHeartbeat in script.OnHeartbeat)
onHeartbeat.Call(script);
script._FinishScriptCall();
}
}
public bool CallScriptEffectApplyHandlers(AuraEffect aurEff, AuraApplication aurApp, AuraEffectHandleModes mode) public bool CallScriptEffectApplyHandlers(AuraEffect aurEff, AuraApplication aurApp, AuraEffectHandleModes mode)
{ {
bool preventDefault = false; bool preventDefault = false;
@@ -2865,12 +2877,15 @@ namespace Game.Spells
_staticApplications[target.GetGUID()] |= effMask; _staticApplications[target.GetGUID()] |= effMask;
} }
void Heartbeat() public override void Heartbeat()
{ {
base.Heartbeat(); base.Heartbeat();
// Periodic food and drink emote animation // Periodic food and drink emote animation
HandlePeriodicFoodSpellVisualKit(); HandlePeriodicFoodSpellVisualKit();
// Invoke the OnHeartbeat AuraScript hook
CallScriptOnHeartbeat();
} }
void HandlePeriodicFoodSpellVisualKit() void HandlePeriodicFoodSpellVisualKit()
+4 -13
View File
@@ -3883,17 +3883,9 @@ namespace Scripts.Spells.Azerite
return ValidateSpellInfo(SpellFragileEchoesMonk, SpellFragileEchoesShaman, SpellFragileEchoesPriestDiscipline, SpellFragileEchoesPaladin, SpellFragileEchoesDruid, SpellFragileEchoesPriestHoly); return ValidateSpellInfo(SpellFragileEchoesMonk, SpellFragileEchoesShaman, SpellFragileEchoesPriestDiscipline, SpellFragileEchoesPaladin, SpellFragileEchoesDruid, SpellFragileEchoesPriestHoly);
} }
void ForcePeriodic(AuraEffect aurEff, ref bool isPeriodic, ref int amplitude) void UpdateSpecAura()
{ {
// simulate heartbeat timer Player target = GetUnitOwner().ToPlayer();
isPeriodic = true;
amplitude = 5000;
}
void UpdateSpecAura(AuraEffect aurEff)
{
PreventDefaultAction();
Player target = GetTarget().ToPlayer();
if (target == null) if (target == null)
return; return;
@@ -3902,7 +3894,7 @@ namespace Scripts.Spells.Azerite
if (target.GetPrimarySpecialization() != spec) if (target.GetPrimarySpecialization() != spec)
target.RemoveAurasDueToSpell(aura); target.RemoveAurasDueToSpell(aura);
else if (!target.HasAura(aura)) else if (!target.HasAura(aura))
target.CastSpell(target, aura, aurEff); target.CastSpell(target, aura, GetEffect(0));
} }
switch (target.GetClass()) switch (target.GetClass())
@@ -3930,8 +3922,7 @@ namespace Scripts.Spells.Azerite
public override void Register() public override void Register()
{ {
DoEffectCalcPeriodic.Add(new(ForcePeriodic, 0, AuraType.Dummy)); OnHeartbeat.Add(new(UpdateSpecAura));
OnEffectPeriodic.Add(new(UpdateSpecAura, 0, AuraType.Dummy));
} }
} }