mirror of
https://github.com/azerothcore/mod-ale
synced 2025-12-01 21:15:19 +08:00
Feat(LuaEngine/SpellHooks): Add support for RegisterSpellEvent with initial events (#224)
This commit is contained in:
@@ -695,7 +695,7 @@ public:
|
|||||||
|
|
||||||
void OnSpellCast(Player* player, Spell* spell, bool skipCheck) override
|
void OnSpellCast(Player* player, Spell* spell, bool skipCheck) override
|
||||||
{
|
{
|
||||||
sEluna->OnSpellCast(player, spell, skipCheck);
|
sEluna->OnPlayerSpellCast(player, spell, skipCheck);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnLogin(Player* player) override
|
void OnLogin(Player* player) override
|
||||||
@@ -855,6 +855,21 @@ public:
|
|||||||
{
|
{
|
||||||
sEluna->OnDummyEffect(caster, spellID, effIndex, itemTarget);
|
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
|
class Eluna_UnitScript : public UnitScript
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ namespace Hooks
|
|||||||
REGTYPE_BG,
|
REGTYPE_BG,
|
||||||
REGTYPE_MAP,
|
REGTYPE_MAP,
|
||||||
REGTYPE_INSTANCE,
|
REGTYPE_INSTANCE,
|
||||||
|
REGTYPE_SPELL,
|
||||||
REGTYPE_COUNT
|
REGTYPE_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -365,6 +366,14 @@ namespace Hooks
|
|||||||
INSTANCE_EVENT_ON_CHECK_ENCOUNTER_IN_PROGRESS = 7, // (event, instance_data, map)
|
INSTANCE_EVENT_ON_CHECK_ENCOUNTER_IN_PROGRESS = 7, // (event, instance_data, map)
|
||||||
INSTANCE_EVENT_COUNT
|
INSTANCE_EVENT_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum SpellEvents
|
||||||
|
{
|
||||||
|
SPELL_EVENT_ON_PREPARE = 1, // (event, caster, spell)
|
||||||
|
SPELL_EVENT_ON_CAST = 2, // (event, caster, spell, skipCheck)
|
||||||
|
SPELL_EVENT_ON_CAST_CANCEL = 3, // (event, caster, spell, bySelf)
|
||||||
|
SPELL_EVENT_COUNT
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _HOOKS_H
|
#endif // _HOOKS_H
|
||||||
|
|||||||
@@ -159,6 +159,7 @@ ItemGossipBindings(NULL),
|
|||||||
PlayerGossipBindings(NULL),
|
PlayerGossipBindings(NULL),
|
||||||
MapEventBindings(NULL),
|
MapEventBindings(NULL),
|
||||||
InstanceEventBindings(NULL),
|
InstanceEventBindings(NULL),
|
||||||
|
SpellEventBindings(NULL),
|
||||||
|
|
||||||
CreatureUniqueBindings(NULL)
|
CreatureUniqueBindings(NULL)
|
||||||
{
|
{
|
||||||
@@ -253,6 +254,7 @@ void Eluna::CreateBindStores()
|
|||||||
PlayerGossipBindings = new BindingMap< EntryKey<Hooks::GossipEvents> >(L);
|
PlayerGossipBindings = new BindingMap< EntryKey<Hooks::GossipEvents> >(L);
|
||||||
MapEventBindings = new BindingMap< EntryKey<Hooks::InstanceEvents> >(L);
|
MapEventBindings = new BindingMap< EntryKey<Hooks::InstanceEvents> >(L);
|
||||||
InstanceEventBindings = 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);
|
CreatureUniqueBindings = new BindingMap< UniqueObjectKey<Hooks::CreatureEvents> >(L);
|
||||||
}
|
}
|
||||||
@@ -276,6 +278,7 @@ void Eluna::DestroyBindStores()
|
|||||||
delete BGEventBindings;
|
delete BGEventBindings;
|
||||||
delete MapEventBindings;
|
delete MapEventBindings;
|
||||||
delete InstanceEventBindings;
|
delete InstanceEventBindings;
|
||||||
|
delete SpellEventBindings;
|
||||||
|
|
||||||
delete CreatureUniqueBindings;
|
delete CreatureUniqueBindings;
|
||||||
|
|
||||||
@@ -296,6 +299,7 @@ void Eluna::DestroyBindStores()
|
|||||||
BGEventBindings = NULL;
|
BGEventBindings = NULL;
|
||||||
MapEventBindings = NULL;
|
MapEventBindings = NULL;
|
||||||
InstanceEventBindings = NULL;
|
InstanceEventBindings = NULL;
|
||||||
|
SpellEventBindings = NULL;
|
||||||
|
|
||||||
CreatureUniqueBindings = NULL;
|
CreatureUniqueBindings = NULL;
|
||||||
}
|
}
|
||||||
@@ -1108,6 +1112,22 @@ int Eluna::Register(lua_State* L, uint8 regtype, uint32 entry, ObjectGuid guid,
|
|||||||
return 1; // Stack: callback
|
return 1; // Stack: callback
|
||||||
}
|
}
|
||||||
break;
|
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);
|
luaL_unref(L, LUA_REGISTRYINDEX, functionRef);
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
|
|||||||
@@ -216,6 +216,7 @@ public:
|
|||||||
BindingMap< EntryKey<Hooks::GossipEvents> >* PlayerGossipBindings;
|
BindingMap< EntryKey<Hooks::GossipEvents> >* PlayerGossipBindings;
|
||||||
BindingMap< EntryKey<Hooks::InstanceEvents> >* MapEventBindings;
|
BindingMap< EntryKey<Hooks::InstanceEvents> >* MapEventBindings;
|
||||||
BindingMap< EntryKey<Hooks::InstanceEvents> >* InstanceEventBindings;
|
BindingMap< EntryKey<Hooks::InstanceEvents> >* InstanceEventBindings;
|
||||||
|
BindingMap< EntryKey<Hooks::SpellEvents> >* SpellEventBindings;
|
||||||
|
|
||||||
BindingMap< UniqueObjectKey<Hooks::CreatureEvents> >* CreatureUniqueBindings;
|
BindingMap< UniqueObjectKey<Hooks::CreatureEvents> >* CreatureUniqueBindings;
|
||||||
|
|
||||||
@@ -421,7 +422,7 @@ public:
|
|||||||
bool OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg, Player* pReceiver);
|
bool OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg, Player* pReceiver);
|
||||||
void OnEmote(Player* pPlayer, uint32 emote);
|
void OnEmote(Player* pPlayer, uint32 emote);
|
||||||
void OnTextEmote(Player* pPlayer, uint32 textEmote, uint32 emoteNum, ObjectGuid guid);
|
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 OnLogin(Player* pPlayer);
|
||||||
void OnLogout(Player* pPlayer);
|
void OnLogout(Player* pPlayer);
|
||||||
void OnCreate(Player* pPlayer);
|
void OnCreate(Player* pPlayer);
|
||||||
@@ -520,6 +521,11 @@ public:
|
|||||||
void OnBGEnd(BattleGround* bg, BattleGroundTypeId bgId, uint32 instanceId, TeamId winner);
|
void OnBGEnd(BattleGround* bg, BattleGroundTypeId bgId, uint32 instanceId, TeamId winner);
|
||||||
void OnBGCreate(BattleGround* bg, BattleGroundTypeId bgId, uint32 instanceId);
|
void OnBGCreate(BattleGround* bg, BattleGroundTypeId bgId, uint32 instanceId);
|
||||||
void OnBGDestroy(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<> Unit* Eluna::CHECKOBJ<Unit>(lua_State* L, int narg, bool error);
|
||||||
template<> Object* Eluna::CHECKOBJ<Object>(lua_State* L, int narg, bool error);
|
template<> Object* Eluna::CHECKOBJ<Object>(lua_State* L, int narg, bool error);
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ luaL_Reg GlobalMethods[] =
|
|||||||
{ "RegisterBGEvent", &LuaGlobalFunctions::RegisterBGEvent },
|
{ "RegisterBGEvent", &LuaGlobalFunctions::RegisterBGEvent },
|
||||||
{ "RegisterMapEvent", &LuaGlobalFunctions::RegisterMapEvent },
|
{ "RegisterMapEvent", &LuaGlobalFunctions::RegisterMapEvent },
|
||||||
{ "RegisterInstanceEvent", &LuaGlobalFunctions::RegisterInstanceEvent },
|
{ "RegisterInstanceEvent", &LuaGlobalFunctions::RegisterInstanceEvent },
|
||||||
|
{ "RegisterSpellEvent", &LuaGlobalFunctions::RegisterSpellEvent },
|
||||||
|
|
||||||
{ "ClearBattleGroundEvents", &LuaGlobalFunctions::ClearBattleGroundEvents },
|
{ "ClearBattleGroundEvents", &LuaGlobalFunctions::ClearBattleGroundEvents },
|
||||||
{ "ClearCreatureEvents", &LuaGlobalFunctions::ClearCreatureEvents },
|
{ "ClearCreatureEvents", &LuaGlobalFunctions::ClearCreatureEvents },
|
||||||
@@ -77,6 +78,7 @@ luaL_Reg GlobalMethods[] =
|
|||||||
{ "ClearServerEvents", &LuaGlobalFunctions::ClearServerEvents },
|
{ "ClearServerEvents", &LuaGlobalFunctions::ClearServerEvents },
|
||||||
{ "ClearMapEvents", &LuaGlobalFunctions::ClearMapEvents },
|
{ "ClearMapEvents", &LuaGlobalFunctions::ClearMapEvents },
|
||||||
{ "ClearInstanceEvents", &LuaGlobalFunctions::ClearInstanceEvents },
|
{ "ClearInstanceEvents", &LuaGlobalFunctions::ClearInstanceEvents },
|
||||||
|
{ "ClearSpellEvents", &LuaGlobalFunctions::ClearSpellEvents },
|
||||||
|
|
||||||
// Getters
|
// Getters
|
||||||
{ "GetLuaEngine", &LuaGlobalFunctions::GetLuaEngine },
|
{ "GetLuaEngine", &LuaGlobalFunctions::GetLuaEngine },
|
||||||
|
|||||||
@@ -328,7 +328,7 @@ void Eluna::OnTextEmote(Player* pPlayer, uint32 textEmote, uint32 emoteNum, Obje
|
|||||||
CallAllFunctions(PlayerEventBindings, key);
|
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);
|
START_HOOK(PLAYER_EVENT_ON_SPELL_CAST);
|
||||||
Push(pPlayer);
|
Push(pPlayer);
|
||||||
|
|||||||
60
src/LuaEngine/hooks/SpellHooks.cpp
Normal file
60
src/LuaEngine/hooks/SpellHooks.cpp
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* 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(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(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);
|
||||||
|
|
||||||
|
CallAllFunctions(SpellEventBindings, key);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1215,6 +1215,29 @@ namespace LuaGlobalFunctions
|
|||||||
return RegisterEntryHelper(L, Hooks::REGTYPE_GAMEOBJECT);
|
return RegisterEntryHelper(L, Hooks::REGTYPE_GAMEOBJECT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a [Spell] event handler.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* enum SpellEvents
|
||||||
|
* {
|
||||||
|
* SPELL_EVENT_ON_PREPARE = 1, // (event, caster, spell)
|
||||||
|
* SPELL_EVENT_ON_CAST = 2, // (event, caster, spell, skipCheck)
|
||||||
|
* SPELL_EVENT_ON_CAST_CANCEL = 3, // (event, caster, spell, 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.
|
* Reloads the Lua engine.
|
||||||
*/
|
*/
|
||||||
@@ -3093,6 +3116,40 @@ namespace LuaGlobalFunctions
|
|||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the faction which is the current owner of Halaa in Nagrand
|
* Gets the faction which is the current owner of Halaa in Nagrand
|
||||||
* 0 = Alliance
|
* 0 = Alliance
|
||||||
|
|||||||
Reference in New Issue
Block a user