diff --git a/ElunaIncludes.h b/ElunaIncludes.h index fec1f48d59..2e6cd85383 100644 --- a/ElunaIncludes.h +++ b/ElunaIncludes.h @@ -36,6 +36,7 @@ #include "ScriptMgr.h" #include "Spell.h" #include "SpellAuras.h" +#include "SpellAuraEffects.h" #include "SpellMgr.h" #include "TemporarySummon.h" #include "WorldPacket.h" diff --git a/ElunaTemplate.cpp b/ElunaTemplate.cpp index 462ea92d65..8baa2b1425 100644 --- a/ElunaTemplate.cpp +++ b/ElunaTemplate.cpp @@ -20,6 +20,13 @@ ElunaConstrainedObjectRef GetWeakPtrFor(Aura const* obj) #endif return { obj->GetWeakPtr(), map }; } + +ElunaConstrainedObjectRef GetWeakPtrFor(AuraEffect const* obj) +{ + Map* map = obj->GetBase()->GetOwner()->GetMap(); + return { obj->GetWeakPtr(), map }; +} + ElunaConstrainedObjectRef GetWeakPtrFor(BattleGround const* obj) { return { obj->GetWeakPtr(), obj->GetBgMap() }; } ElunaConstrainedObjectRef GetWeakPtrFor(Group const* obj) { return { obj->GetWeakPtr(), nullptr }; } ElunaConstrainedObjectRef GetWeakPtrFor(Guild const* obj) { return { obj->GetWeakPtr(), nullptr }; } diff --git a/ElunaTemplate.h b/ElunaTemplate.h index 74d98f3bf2..7fcf780104 100644 --- a/ElunaTemplate.h +++ b/ElunaTemplate.h @@ -62,6 +62,7 @@ struct ElunaConstrainedObjectRef }; ElunaConstrainedObjectRef GetWeakPtrFor(Aura const* obj); +ElunaConstrainedObjectRef GetWeakPtrFor(AuraEffect const* obj); ElunaConstrainedObjectRef GetWeakPtrFor(BattleGround const* obj); ElunaConstrainedObjectRef GetWeakPtrFor(Group const* obj); ElunaConstrainedObjectRef GetWeakPtrFor(Guild const* obj); diff --git a/LuaEngine.h b/LuaEngine.h index 408d340813..82fcdbfc25 100644 --- a/LuaEngine.h +++ b/LuaEngine.h @@ -611,6 +611,12 @@ class ELUNA_GAME_API Eluna /* Spell */ void OnSpellCast(Spell* pSpell, bool skipCheck); + bool OnAuraApplication(Aura* aura, AuraEffect const* auraEff, Unit* target, uint8 mode, bool apply); + void OnAuraDispel(Aura* aura, DispelInfo* dispelInfo); + bool OnPerodicTick(Aura* aura, AuraEffect const* auraEff, Unit* target); + void OnPerodicUpdate(Aura* aura, AuraEffect const* auraEff); + void OnAuraCalcAmount(Aura* aura, AuraEffect const* auraEff, int32& amount, bool& canBeRecalculated); + void OnCalcPerodic(Aura* aura, AuraEffect const* auraEff, bool& isPeriodic, int32& amplitude); }; template<> Unit* Eluna::CHECKOBJ(int narg, bool error); template<> Object* Eluna::CHECKOBJ(int narg, bool error); diff --git a/hooks/Hooks.h b/hooks/Hooks.h index 0197f37810..6f583c81c1 100644 --- a/hooks/Hooks.h +++ b/hooks/Hooks.h @@ -275,7 +275,13 @@ namespace Hooks enum SpellEvents { - SPELL_EVENT_ON_CAST = 1, // (event, spell, skipCheck) + SPELL_EVENT_ON_CAST = 1, // (event, spell, skipCheck) + SPELL_EVENT_ON_AURA_APPLICATION = 2, // (event, aura, auraEffect, target, mode, apply) - Can return true to stop normal action + SPELL_EVENT_ON_DISPEL = 3, // (event, aura, dispeler, dispelSpellId, removedCharges) + SPELL_EVENT_ON_PERODIC_TICK = 4, // (event, aura, auraEffect, target) Can return true to stop normal action + SPELL_EVENT_ON_PERODIC_UPDATE = 5, // (event, aura, auraEffect) + SPELL_EVENT_ON_AURA_CALC_AMOUNT = 6, // (event, aura, auraEffect, amount, canBeRecalculated) - can return new amount as first return value, can return new canBeRecalculated as second return value + SPELL_EVENT_ON_CALC_PERODIC = 7, // (event, aura, auraEffect, isPeriodic, amplitude) - can return new isPeriodic as first return value, can return new amplitude as second return value SPELL_EVENT_COUNT }; @@ -520,7 +526,13 @@ class HookToReadableString }; static constexpr EventEntry SpellEventsTable[] = { - {Hooks::SPELL_EVENT_ON_CAST, "on_cast"} + {Hooks::SPELL_EVENT_ON_CAST, "on_cast"}, + {Hooks::SPELL_EVENT_ON_AURA_APPLICATION, "on_aura_application" }, + {Hooks::SPELL_EVENT_ON_DISPEL, "on_aura_dispel" }, + {Hooks::SPELL_EVENT_ON_PERODIC_TICK, "on_perodic_tick" }, + {Hooks::SPELL_EVENT_ON_PERODIC_UPDATE, "on_perodic_update" }, + {Hooks::SPELL_EVENT_ON_AURA_CALC_AMOUNT, "on_aura_calc_amount" }, + {Hooks::SPELL_EVENT_ON_CALC_PERODIC, "on_calc_perodic" } }; static constexpr EventEntry ItemEventsTable[] = { diff --git a/hooks/SpellHooks.cpp b/hooks/SpellHooks.cpp index a5ef8a30a6..e3e76ec986 100644 --- a/hooks/SpellHooks.cpp +++ b/hooks/SpellHooks.cpp @@ -15,13 +15,13 @@ using namespace Hooks; #define START_HOOK(EVENT, SPELL) \ auto binding = GetBinding>(REGTYPE_SPELL);\ - auto key = EntryKey(EVENT, SPELL->m_spellInfo->Id);\ + auto key = EntryKey(EVENT, SPELL->GetSpellInfo()->Id);\ if (!binding->HasBindingsFor(key))\ return; #define START_HOOK_WITH_RETVAL(EVENT, SPELL, RETVAL) \ auto binding = GetBinding>(REGTYPE_SPELL);\ - auto key = EntryKey(EVENT, SPELL->m_spellInfo->Id);\ + auto key = EntryKey(EVENT, SPELL->GetSpellInfo()->Id);\ if (!binding->HasBindingsFor(key))\ return RETVAL; @@ -32,3 +32,112 @@ void Eluna::OnSpellCast(Spell* pSpell, bool skipCheck) HookPush(skipCheck); CallAllFunctions(binding, key); } + +bool Eluna::OnAuraApplication(Aura* aura, AuraEffect const* auraEff, Unit* target, uint8 mode, bool apply) +{ + START_HOOK_WITH_RETVAL(SPELL_EVENT_ON_AURA_APPLICATION, aura, false); + HookPush(aura); + HookPush(auraEff); + HookPush(target); + HookPush(mode); + HookPush(apply); + return CallAllFunctionsBool(binding, key, false); +} + +void Eluna::OnAuraDispel(Aura* aura, DispelInfo* dispelInfo) +{ + START_HOOK(SPELL_EVENT_ON_DISPEL, aura); + HookPush(aura); + HookPush(dispelInfo->GetDispeller()); + HookPush(dispelInfo->GetDispellerSpellId()); + HookPush(dispelInfo->GetRemovedCharges()); + CallAllFunctions(binding, key); +} + +bool Eluna::OnPerodicTick(Aura* aura, AuraEffect const* auraEff, Unit* target) +{ + START_HOOK_WITH_RETVAL(SPELL_EVENT_ON_PERODIC_TICK, aura, false); + HookPush(aura); + HookPush(auraEff); + HookPush(target); + return CallAllFunctionsBool(binding, key, false); +} + +void Eluna::OnPerodicUpdate(Aura* aura, AuraEffect const* auraEff) +{ + START_HOOK(SPELL_EVENT_ON_PERODIC_UPDATE, aura); + HookPush(aura); + HookPush(auraEff); + CallAllFunctions(binding, key); +} + +void Eluna::OnAuraCalcAmount(Aura* aura, AuraEffect const* auraEff, int32& amount, bool& canBeRecalculated) +{ + START_HOOK(SPELL_EVENT_ON_AURA_CALC_AMOUNT, aura); + HookPush(aura); + HookPush(auraEff); + HookPush(amount); + int amountIndex = lua_gettop(L); + HookPush(canBeRecalculated); + int canBeRecalculatedIndex = lua_gettop(L); + int n = SetupStack(binding, key, 4); + + while (n > 0) + { + int r = CallOneFunction(n--, 4, 2); + + if (lua_isnumber(L, r + 0)) + { + amount = CHECKVAL(r + 0); + // Update the stack for subsequent calls. + ReplaceArgument(amount, amountIndex); + } + + + if (lua_isboolean(L, r + 1)) + { + canBeRecalculated = lua_toboolean(L, r + 1); + // Update the stack for subsequent calls. + ReplaceArgument(amount, canBeRecalculatedIndex); + } + + lua_pop(L, 2); + } + + CleanUpStack(2); +} + +void Eluna::OnCalcPerodic(Aura* aura, AuraEffect const* auraEff, bool& isPeriodic, int32& amplitude) +{ + START_HOOK(SPELL_EVENT_ON_AURA_CALC_AMOUNT, aura); + HookPush(aura); + HookPush(auraEff); + HookPush(isPeriodic); + int isPeriodicIndex = lua_gettop(L); + HookPush(amplitude); + int amplitudeIndex = lua_gettop(L); + int n = SetupStack(binding, key, 4); + + while (n > 0) + { + int r = CallOneFunction(n--, 4, 2); + + if (lua_isboolean(L, r + 0)) + { + isPeriodic = lua_toboolean(L, r + 0); + // Update the stack for subsequent calls. + ReplaceArgument(isPeriodic, isPeriodicIndex); + } + + if (lua_isnumber(L, r + 1)) + { + amplitude = CHECKVAL(r + 1); + // Update the stack for subsequent calls. + ReplaceArgument(amplitude, amplitudeIndex); + } + + lua_pop(L, 2); + } + + CleanUpStack(2); +} diff --git a/methods/Methods.cpp b/methods/Methods.cpp index ae2bf4d229..0f53ef36c9 100644 --- a/methods/Methods.cpp +++ b/methods/Methods.cpp @@ -23,6 +23,7 @@ #include "GameObjectMethods.h" #include "ElunaQueryMethods.h" #include "AuraMethods.h" +#include "AuraEffectMethods.h" #include "ItemMethods.h" #include "WorldPacketMethods.h" #include "SpellMethods.h" @@ -90,6 +91,9 @@ void RegisterMethods(Eluna* E) ElunaTemplate::Register(E, "Aura"); ElunaTemplate::SetMethods(E, LuaAura::AuraMethods); + ElunaTemplate::Register(E, "AuraEffect"); + ElunaTemplate::SetMethods(E, LuaAuraEffects::AuraEffectMethods); + ElunaTemplate::Register(E, "Spell"); ElunaTemplate::SetMethods(E, LuaSpell::SpellMethods); diff --git a/methods/TrinityCore/AuraEffectMethods.h b/methods/TrinityCore/AuraEffectMethods.h new file mode 100644 index 0000000000..f2749c0296 --- /dev/null +++ b/methods/TrinityCore/AuraEffectMethods.h @@ -0,0 +1,159 @@ +/* +* Copyright (C) 2010 - 2024 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef AURAEFFECTMETHODS_H +#define AURAEFFECTMETHODS_H + + +namespace LuaAuraEffects +{ + int GetBase(Eluna* E, AuraEffect* aurEff) + { + E->Push(aurEff->GetBase()); + return 1; + } + + int GetBaseAmount(Eluna* E, AuraEffect* aurEff) + { + E->Push(aurEff->GetBaseAmount()); + return 1; + } + + int GetAmplitude(Eluna* E, AuraEffect* aurEff) + { + E->Push(aurEff->GetAmplitude()); + return 1; + } + + int GetAmount(Eluna* E, AuraEffect* aurEff) + { + E->Push(aurEff->GetAmount()); + return 1; + } + + int SetAmount(Eluna* E, AuraEffect* aurEff) + { + int32 amount = E->CHECKVAL(2); + aurEff->SetAmount(amount); + return 0; + } + + int GetPeriodicTimer(Eluna* E, AuraEffect* aurEff) + { + E->Push(aurEff->GetPeriodicTimer()); + return 1; + } + + int SetPeriodicTimer(Eluna* E, AuraEffect* aurEff) + { + int32 timer = E->CHECKVAL(2); + aurEff->SetPeriodicTimer(timer); + return 0; + } + + int CalculateAmount(Eluna* E, AuraEffect* aurEff) + { + Unit* caster = E->CHECKOBJ(2); + E->Push(aurEff->CalculateAmount(caster)); + return 1; + } + + int CalculatePeriodic(Eluna* E, AuraEffect* aurEff) + { + Unit* caster = E->CHECKOBJ(2); + bool resetPeriodicTimer = E->CHECKVAL(3, false); + bool load = E->CHECKVAL(4, false); + aurEff->CalculatePeriodic(caster, resetPeriodicTimer, load); + return 0; + } + + int ChangeAmount(Eluna* E, AuraEffect* aurEff) + { + int32 newAmount = E->CHECKVAL(2); + bool mark = E->CHECKVAL(3, true); + bool onStackOrReapply = E->CHECKVAL(4, false); + aurEff->ChangeAmount(newAmount, mark, onStackOrReapply); + return 0; + } + + int RecalculateAmount(Eluna* /*E*/, AuraEffect* aurEff) + { + aurEff->RecalculateAmount(); + return 0; + } + + int CanBeRecalculated(Eluna* E, AuraEffect* aurEff) + { + E->Push(aurEff->CanBeRecalculated()); + return 1; + } + + int SetCanBeRecalculated(Eluna* E, AuraEffect* aurEff) + { + bool val = E->CHECKVAL(2, true); + aurEff->SetCanBeRecalculated(val); + return 0; + } + + int GetTickNumber(Eluna* E, AuraEffect* aurEff) + { + E->Push(aurEff->GetTickNumber()); + return 1; + } + + int GetRemainingTicks(Eluna* E, AuraEffect* aurEff) + { + E->Push(aurEff->GetRemainingTicks()); + return 1; + } + + int GetTotalTicks(Eluna* E, AuraEffect* aurEff) + { + E->Push(aurEff->GetTotalTicks()); + return 1; + } + + int GetTargetList(Eluna* E, AuraEffect* aurEff) + { + std::list list; + aurEff->GetTargetList(list); + lua_createtable(E->L, list.size(), 0); + int tbl = lua_gettop(E->L); + uint32 i = 0; + + for (std::list::const_iterator it = list.begin(); it != list.end(); ++it) + { + E->Push(*it); + lua_rawseti(E->L, tbl, ++i); + } + + lua_settop(E->L, tbl); + return 1; + } + + ElunaRegister AuraEffectMethods[] = + { + {"GetBase", &LuaAuraEffects::GetBase}, + {"GetBaseAmount", &LuaAuraEffects::GetBaseAmount}, + {"GetAmplitude", &LuaAuraEffects::GetAmplitude}, + {"GetAmount", &LuaAuraEffects::GetAmount}, + {"SetAmount", &LuaAuraEffects::SetAmount}, + {"GetPeriodicTimer", &LuaAuraEffects::GetPeriodicTimer}, + {"SetPeriodicTimer", &LuaAuraEffects::SetPeriodicTimer}, + {"CalculateAmount", &LuaAuraEffects::CalculateAmount}, + {"CalculatePeriodic", &LuaAuraEffects::CalculatePeriodic}, + {"ChangeAmount", &LuaAuraEffects::ChangeAmount}, + {"RecalculateAmount", &LuaAuraEffects::RecalculateAmount}, + {"CanBeRecalculated", &LuaAuraEffects::CanBeRecalculated}, + {"SetCanBeRecalculated", &LuaAuraEffects::SetCanBeRecalculated}, + {"GetTickNumber", &LuaAuraEffects::GetTickNumber}, + {"GetRemainingTicks", &LuaAuraEffects::GetRemainingTicks}, + {"GetTotalTicks", &LuaAuraEffects::GetTotalTicks}, + {"GetTargetList", &LuaAuraEffects::GetTargetList} + }; +}; +#endif +