mirror of
https://github.com/araxiaonline/TrinityCore.git
synced 2026-06-17 05:29:43 -04:00
Core/Auras: Implemented OnHeartbeat AuraScript hook and refactored an aurascript to use it as example (#29945)
* Updated Amalgam's Seventh Spine dummy aura script to use the new AuraScript hook
(cherry picked from commit 55ce5b150f)
This commit is contained in:
@@ -502,7 +502,7 @@ void Unit::Heartbeat()
|
||||
// SMSG_FLIGHT_SPLINE_SYNC for cyclic splines
|
||||
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();
|
||||
|
||||
// Update Vignette position and visibility
|
||||
|
||||
@@ -2073,6 +2073,18 @@ void Aura::CallScriptAfterDispel(DispelInfo* dispelInfo)
|
||||
}
|
||||
}
|
||||
|
||||
void Aura::CallScriptOnHeartbeat()
|
||||
{
|
||||
for (AuraScript* script : m_loadedScripts)
|
||||
{
|
||||
script->_PrepareScriptCall(AURA_SCRIPT_HOOK_ON_HEARTBEAT);
|
||||
for (AuraScript::AuraHeartbeatHandler const& onHeartbeat : script->OnHeartbeat)
|
||||
onHeartbeat.Call(script);
|
||||
|
||||
script->_FinishScriptCall();
|
||||
}
|
||||
}
|
||||
|
||||
bool Aura::CallScriptEffectApplyHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, AuraEffectHandleModes mode)
|
||||
{
|
||||
bool preventDefault = false;
|
||||
@@ -2627,6 +2639,9 @@ void UnitAura::Heartbeat()
|
||||
|
||||
// Periodic food and drink emote animation
|
||||
HandlePeriodicFoodSpellVisualKit();
|
||||
|
||||
// Invoke the OnHeartbeat AuraScript hook
|
||||
CallScriptOnHeartbeat();
|
||||
}
|
||||
|
||||
void UnitAura::HandlePeriodicFoodSpellVisualKit()
|
||||
|
||||
@@ -264,6 +264,7 @@ class TC_GAME_API Aura
|
||||
bool CallScriptCheckAreaTargetHandlers(Unit* target);
|
||||
void CallScriptDispel(DispelInfo* dispelInfo);
|
||||
void CallScriptAfterDispel(DispelInfo* dispelInfo);
|
||||
void CallScriptOnHeartbeat();
|
||||
bool CallScriptEffectApplyHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, AuraEffectHandleModes mode);
|
||||
bool CallScriptEffectRemoveHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, AuraEffectHandleModes mode);
|
||||
void CallScriptAfterEffectApplyHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, AuraEffectHandleModes mode);
|
||||
|
||||
@@ -1048,6 +1048,7 @@ enum AuraScriptHookType
|
||||
AURA_SCRIPT_HOOK_CHECK_AREA_TARGET,
|
||||
AURA_SCRIPT_HOOK_DISPEL,
|
||||
AURA_SCRIPT_HOOK_AFTER_DISPEL,
|
||||
AURA_SCRIPT_HOOK_ON_HEARTBEAT,
|
||||
AURA_SCRIPT_HOOK_ENTER_LEAVE_COMBAT,
|
||||
// Spell Proc Hooks
|
||||
AURA_SCRIPT_HOOK_CHECK_PROC,
|
||||
@@ -1174,6 +1175,58 @@ public:
|
||||
SafeWrapperType _safeWrapper;
|
||||
};
|
||||
|
||||
class AuraHeartbeatHandler final
|
||||
{
|
||||
public:
|
||||
union AuraHeartbeatFnType
|
||||
{
|
||||
void(AuraScript::* Member)();
|
||||
void(*Static)();
|
||||
};
|
||||
|
||||
using SafeWrapperType = void(*)(AuraScript* auraScript, AuraHeartbeatFnType callImpl);
|
||||
|
||||
template<typename ScriptFunc>
|
||||
explicit AuraHeartbeatHandler(ScriptFunc handler)
|
||||
{
|
||||
using ScriptClass = GetScriptClass_t<ScriptFunc>;
|
||||
|
||||
static_assert(sizeof(AuraHeartbeatFnType) >= sizeof(ScriptFunc));
|
||||
static_assert(alignof(AuraHeartbeatFnType) >= alignof(ScriptFunc));
|
||||
|
||||
if constexpr (!std::is_void_v<ScriptClass>)
|
||||
{
|
||||
static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass>,
|
||||
"AuraHeartbeat signature must be \"void HandleHeartbeat()\"");
|
||||
|
||||
_callImpl = { .Member = reinterpret_cast<decltype(AuraHeartbeatFnType::Member)>(handler) };
|
||||
_safeWrapper = [](AuraScript* auraScript, AuraHeartbeatFnType callImpl) -> void
|
||||
{
|
||||
return (static_cast<ScriptClass*>(auraScript)->*reinterpret_cast<ScriptFunc>(callImpl.Member))();
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
static_assert(std::is_invocable_r_v<void, ScriptFunc>,
|
||||
"AuraHeartbeatHandler signature must be \"static void HandleHeartbeat()\"");
|
||||
|
||||
_callImpl = { .Static = reinterpret_cast<decltype(AuraHeartbeatFnType::Static)>(handler) };
|
||||
_safeWrapper = [](AuraScript* /*auraScript*/, AuraHeartbeatFnType callImpl) -> void
|
||||
{
|
||||
return reinterpret_cast<ScriptFunc>(callImpl.Static)();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void Call(AuraScript* auraScript) const
|
||||
{
|
||||
return _safeWrapper(auraScript, _callImpl);
|
||||
}
|
||||
private:
|
||||
AuraHeartbeatFnType _callImpl;
|
||||
SafeWrapperType _safeWrapper;
|
||||
};
|
||||
|
||||
class TC_GAME_API EffectBase : public EffectHook
|
||||
{
|
||||
public:
|
||||
@@ -2017,6 +2070,12 @@ public:
|
||||
HookList<AuraDispelHandler> AfterDispel;
|
||||
#define AuraDispelFn(F) AuraDispelHandler(&F)
|
||||
|
||||
// executed on every heartbeat of a unit
|
||||
// example: OnHeartbeat += AuraHeartbeatFn(class::function);
|
||||
// where function is: void function ();
|
||||
HookList<AuraHeartbeatHandler> OnHeartbeat;
|
||||
#define AuraHeartbeatFn(F) AuraHeartbeatHandler(&F)
|
||||
|
||||
// executed when aura effect is applied with specified mode to target
|
||||
// should be used when 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);
|
||||
|
||||
@@ -4326,17 +4326,9 @@ class spell_item_amalgams_seventh_spine : public AuraScript
|
||||
});
|
||||
}
|
||||
|
||||
void ForcePeriodic(AuraEffect const* /*aurEff*/, bool& isPeriodic, int32& amplitude)
|
||||
void UpdateSpecAura()
|
||||
{
|
||||
// simulate heartbeat timer
|
||||
isPeriodic = true;
|
||||
amplitude = 5000;
|
||||
}
|
||||
|
||||
void UpdateSpecAura(AuraEffect const* aurEff)
|
||||
{
|
||||
PreventDefaultAction();
|
||||
Player* target = GetTarget()->ToPlayer();
|
||||
Player* target = GetUnitOwner()->ToPlayer();
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
@@ -4345,7 +4337,7 @@ class spell_item_amalgams_seventh_spine : public AuraScript
|
||||
if (target->GetPrimarySpecialization() != spec)
|
||||
target->RemoveAurasDueToSpell(aura);
|
||||
else if (!target->HasAura(aura))
|
||||
target->CastSpell(target, aura, aurEff);
|
||||
target->CastSpell(target, aura, GetEffect(EFFECT_0));
|
||||
};
|
||||
|
||||
switch (target->GetClass())
|
||||
@@ -4373,8 +4365,7 @@ class spell_item_amalgams_seventh_spine : public AuraScript
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoEffectCalcPeriodic += AuraEffectCalcPeriodicFn(spell_item_amalgams_seventh_spine::ForcePeriodic, EFFECT_0, SPELL_AURA_DUMMY);
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_item_amalgams_seventh_spine::UpdateSpecAura, EFFECT_0, SPELL_AURA_DUMMY);
|
||||
OnHeartbeat += AuraHeartbeatFn(spell_item_amalgams_seventh_spine::UpdateSpecAura);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user