Skip to content

Commit

Permalink
feat(LuaEngine/Spell): Add RegisterSpellEvent
Browse files Browse the repository at this point in the history
  • Loading branch information
iThorgrim committed Jan 12, 2025
1 parent e72f139 commit 8bf7365
Show file tree
Hide file tree
Showing 8 changed files with 174 additions and 3 deletions.
17 changes: 16 additions & 1 deletion src/ElunaLuaEngine_SC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,7 @@ class Eluna_PlayerScript : public PlayerScript

void OnSpellCast(Player* player, Spell* spell, bool skipCheck) override
{
sEluna->OnSpellCast(player, spell, skipCheck);
sEluna->OnPlayerSpellCast(player, spell, skipCheck);
}

void OnLogin(Player* player) override
Expand Down Expand Up @@ -855,6 +855,21 @@ class Eluna_SpellSC : public SpellSC
{
sEluna->OnDummyEffect(caster, spellID, effIndex, itemTarget);
}

void OnSpellCastCancel(Spell* spell, Unit* caster, SpellInfo const* spellInfo, bool bySelf) override
{
sEluna->OnSpellCastCancel(caster, spell, spellInfo, bySelf);
}

void OnSpellCast(Spell* spell, Unit* caster, SpellInfo const* spellInfo, bool skipCheck) override
{
sEluna->OnSpellCast(caster, spell, spellInfo, skipCheck);
}

void OnSpellPrepare(Spell* spell, Unit* caster, SpellInfo const* spellInfo) override
{
sEluna->OnSpellPrepare(caster, spell, spellInfo);
}
};

class Eluna_UnitScript : public UnitScript
Expand Down
9 changes: 9 additions & 0 deletions src/LuaEngine/Hooks.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ namespace Hooks
REGTYPE_BG,
REGTYPE_MAP,
REGTYPE_INSTANCE,
REGTYPE_SPELL,
REGTYPE_COUNT
};

Expand Down Expand Up @@ -365,6 +366,14 @@ namespace Hooks
INSTANCE_EVENT_ON_CHECK_ENCOUNTER_IN_PROGRESS = 7, // (event, instance_data, map)
INSTANCE_EVENT_COUNT
};

enum SpellEvents
{
SPELL_EVENT_ON_PREPARE = 1, // (caster, spell, spellInfo)
SPELL_EVENT_ON_CAST = 2, // (caster, spell, spellInfo, skipCheck)
SPELL_EVENT_ON_CAST_CANCEL = 3, // (caster, spell, spellInfo, bySelf)
SPELL_EVENT_COUNT
};
};

#endif // _HOOKS_H
20 changes: 20 additions & 0 deletions src/LuaEngine/LuaEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ ItemGossipBindings(NULL),
PlayerGossipBindings(NULL),
MapEventBindings(NULL),
InstanceEventBindings(NULL),
SpellEventBindings(NULL),

CreatureUniqueBindings(NULL)
{
Expand Down Expand Up @@ -283,6 +284,7 @@ void Eluna::CreateBindStores()
PlayerGossipBindings = new BindingMap< EntryKey<Hooks::GossipEvents> >(L);
MapEventBindings = new BindingMap< EntryKey<Hooks::InstanceEvents> >(L);
InstanceEventBindings = new BindingMap< EntryKey<Hooks::InstanceEvents> >(L);
SpellEventBindings = new BindingMap< EntryKey<Hooks::SpellEvents> >(L);

CreatureUniqueBindings = new BindingMap< UniqueObjectKey<Hooks::CreatureEvents> >(L);
}
Expand All @@ -306,6 +308,7 @@ void Eluna::DestroyBindStores()
delete BGEventBindings;
delete MapEventBindings;
delete InstanceEventBindings;
delete SpellEventBindings;

delete CreatureUniqueBindings;

Expand All @@ -326,6 +329,7 @@ void Eluna::DestroyBindStores()
BGEventBindings = NULL;
MapEventBindings = NULL;
InstanceEventBindings = NULL;
SpellEventBindings = NULL;

CreatureUniqueBindings = NULL;
}
Expand Down Expand Up @@ -1195,6 +1199,22 @@ int Eluna::Register(lua_State* L, uint8 regtype, uint32 entry, ObjectGuid guid,
return 1; // Stack: callback
}
break;
case Hooks::REGTYPE_SPELL:
if (event_id < Hooks::SPELL_EVENT_COUNT)
{
if (!sSpellMgr->GetSpellInfo(entry))
{
luaL_unref(L, LUA_REGISTRYINDEX, functionRef);
luaL_error(L, "Couldn't find a spell with (ID: %d)!", entry);
return 0; // Stack: (empty)
}

auto key = EntryKey<Hooks::SpellEvents>((Hooks::SpellEvents)event_id, entry);
bindingID = SpellEventBindings->Insert(key, functionRef, shots);
createCancelCallback(L, bindingID, SpellEventBindings);
return 1; // Stack: callback
}
break;
}
luaL_unref(L, LUA_REGISTRYINDEX, functionRef);
std::ostringstream oss;
Expand Down
8 changes: 7 additions & 1 deletion src/LuaEngine/LuaEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ class ELUNA_GAME_API Eluna
BindingMap< EntryKey<Hooks::GossipEvents> >* PlayerGossipBindings;
BindingMap< EntryKey<Hooks::InstanceEvents> >* MapEventBindings;
BindingMap< EntryKey<Hooks::InstanceEvents> >* InstanceEventBindings;
BindingMap< EntryKey<Hooks::SpellEvents> >* SpellEventBindings;

BindingMap< UniqueObjectKey<Hooks::CreatureEvents> >* CreatureUniqueBindings;

Expand Down Expand Up @@ -470,7 +471,7 @@ class ELUNA_GAME_API Eluna
bool OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg, Player* pReceiver);
void OnEmote(Player* pPlayer, uint32 emote);
void OnTextEmote(Player* pPlayer, uint32 textEmote, uint32 emoteNum, ObjectGuid guid);
void OnSpellCast(Player* pPlayer, Spell* pSpell, bool skipCheck);
void OnPlayerSpellCast(Player* pPlayer, Spell* pSpell, bool skipCheck);
void OnLogin(Player* pPlayer);
void OnLogout(Player* pPlayer);
void OnCreate(Player* pPlayer);
Expand Down Expand Up @@ -581,6 +582,11 @@ class ELUNA_GAME_API Eluna
#endif
void OnBGCreate(BattleGround* bg, BattleGroundTypeId bgId, uint32 instanceId);
void OnBGDestroy(BattleGround* bg, BattleGroundTypeId bgId, uint32 instanceId);

/* Spell */
void OnSpellPrepare(Unit* caster, Spell* spell, SpellInfo const* spellInfo);
void OnSpellCast(Unit* caster, Spell* spell, SpellInfo const* spellInfo, bool skipCheck);
void OnSpellCastCancel(Unit* caster, Spell* spell, SpellInfo const* spellInfo, bool bySelf);
};
template<> Unit* Eluna::CHECKOBJ<Unit>(lua_State* L, int narg, bool error);
template<> Object* Eluna::CHECKOBJ<Object>(lua_State* L, int narg, bool error);
Expand Down
2 changes: 2 additions & 0 deletions src/LuaEngine/LuaFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ luaL_Reg GlobalMethods[] =
{ "RegisterBGEvent", &LuaGlobalFunctions::RegisterBGEvent },
{ "RegisterMapEvent", &LuaGlobalFunctions::RegisterMapEvent },
{ "RegisterInstanceEvent", &LuaGlobalFunctions::RegisterInstanceEvent },
{ "RegisterSpellEvent", &LuaGlobalFunctions::RegisterSpellEvent },

{ "ClearBattleGroundEvents", &LuaGlobalFunctions::ClearBattleGroundEvents },
{ "ClearCreatureEvents", &LuaGlobalFunctions::ClearCreatureEvents },
Expand All @@ -77,6 +78,7 @@ luaL_Reg GlobalMethods[] =
{ "ClearServerEvents", &LuaGlobalFunctions::ClearServerEvents },
{ "ClearMapEvents", &LuaGlobalFunctions::ClearMapEvents },
{ "ClearInstanceEvents", &LuaGlobalFunctions::ClearInstanceEvents },
{ "ClearSpellEvents", &LuaGlobalFunctions::ClearSpellEvents },

// Getters
{ "GetLuaEngine", &LuaGlobalFunctions::GetLuaEngine },
Expand Down
2 changes: 1 addition & 1 deletion src/LuaEngine/hooks/PlayerHooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ void Eluna::OnTextEmote(Player* pPlayer, uint32 textEmote, uint32 emoteNum, Obje
CallAllFunctions(PlayerEventBindings, key);
}

void Eluna::OnSpellCast(Player* pPlayer, Spell* pSpell, bool skipCheck)
void Eluna::OnPlayerSpellCast(Player* pPlayer, Spell* pSpell, bool skipCheck)
{
START_HOOK(PLAYER_EVENT_ON_SPELL_CAST);
Push(pPlayer);
Expand Down
62 changes: 62 additions & 0 deletions src/LuaEngine/hooks/SpellHooks.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright (C) 2010 - 2016 Eluna Lua Engine <http://emudevs.com/>
* This program is free software licensed under GPL version 3
* Please see the included DOCS/LICENSE.md for more information
*/

#include "Hooks.h"
#include "HookHelpers.h"
#include "LuaEngine.h"
#include "BindingMap.h"
#include "ElunaIncludes.h"
#include "ElunaTemplate.h"

using namespace Hooks;

#define START_HOOK(EVENT, ENTRY) \
if (!IsEnabled())\
return;\
auto key = EntryKey<SpellEvents>(EVENT, ENTRY);\
if (!SpellEventBindings->HasBindingsFor(key))\
return;\
LOCK_ELUNA

#define START_HOOK_WITH_RETVAL(EVENT, ENTRY, RETVAL) \
if (!IsEnabled())\
return RETVAL;\
auto key = EntryKey<SpellEvents>(EVENT, ENTRY);\
if (!SpellEventBindings->HasBindingsFor(key))\
return RETVAL;\
LOCK_ELUNA

void Eluna::OnSpellCastCancel(Unit* caster, Spell* spell, SpellInfo const* spellInfo, bool bySelf)
{
START_HOOK(SPELL_EVENT_ON_CAST_CANCEL, spellInfo->Id);
Push(caster);
Push(spell);
Push(spellInfo);
Push(bySelf);

CallAllFunctions(SpellEventBindings, key);
}

void Eluna::OnSpellCast(Unit* caster, Spell* spell, SpellInfo const* spellInfo, bool skipCheck)
{
START_HOOK(SPELL_EVENT_ON_CAST, spellInfo->Id);
Push(caster);
Push(spell);
Push(spellInfo);
Push(skipCheck);

CallAllFunctions(SpellEventBindings, key);
}

void Eluna::OnSpellPrepare(Unit* caster, Spell* spell, SpellInfo const* spellInfo)
{
START_HOOK(SPELL_EVENT_ON_PREPARE, spellInfo->Id);
Push(caster);
Push(spell);
Push(spellInfo);

CallAllFunctions(SpellEventBindings, key);
}
57 changes: 57 additions & 0 deletions src/LuaEngine/methods/GlobalMethods.h
Original file line number Diff line number Diff line change
Expand Up @@ -1267,6 +1267,29 @@ namespace LuaGlobalFunctions
return RegisterEntryHelper(L, Hooks::REGTYPE_GAMEOBJECT);
}

/**
* Registers a [Spell] event handler.
*
* <pre>
* enum SpellEvents
* {
* SPELL_EVENT_ON_PREPARE = 1, // (caster, spell, spellInfo)
* SPELL_EVENT_ON_CAST = 2, // (caster, spell, spellInfo, skipCheck)
* SPELL_EVENT_ON_CAST_CANCEL = 3, // (caster, spell, spellInfo, bySelf)
* SPELL_EVENT_COUNT
* };
* </pre>
*
* @param uint32 entry : [Spell] entry Id
* @param uint32 event : event ID, refer to SpellEvents above
* @param function function : function to register
* @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function"
*/
int RegisterSpellEvent(lua_State* L)
{
return RegisterEntryHelper(L, Hooks::REGTYPE_SPELL);
}

/**
* Reloads the Lua engine.
*/
Expand Down Expand Up @@ -3479,6 +3502,40 @@ namespace LuaGlobalFunctions
return 0;
}

/**
* Unbinds event handlers for either all of a [Spell]'s events, or one type of event.
*
* If `event_type` is `nil`, all the [Spell]'s event handlers are cleared.
*
* Otherwise, only event handlers for `event_type` are cleared.
*
*
* @proto (entry)
* @proto (entry, event_type)
* @param uint32 entry : the ID of a [Spell]s
* @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterSpellEvent]
*/
int ClearSpellEvents(lua_State* L)
{
typedef EntryKey<Hooks::SpellEvents> Key;

if (lua_isnoneornil(L, 2))
{
uint32 entry = Eluna::CHECKVAL<uint32>(L, 1);

Eluna* E = Eluna::GetEluna(L);
for (uint32 i = 1; i < Hooks::SPELL_EVENT_COUNT; ++i)
E->SpellEventBindings->Clear(Key((Hooks::SpellEvents)i, entry));
}
else
{
uint32 entry = Eluna::CHECKVAL<uint32>(L, 1);
uint32 event_type = Eluna::CHECKVAL<uint32>(L, 2);
Eluna::GetEluna(L)->SpellEventBindings->Clear(Key((Hooks::SpellEvents)event_type, entry));
}
return 0;
}

#ifdef AZEROTHCORE
/**
* Gets the faction which is the current owner of Halaa in Nagrand
Expand Down

0 comments on commit 8bf7365

Please sign in to comment.