mirror of
https://github.com/azerothcore/mod-ale
synced 2025-11-29 15:38:17 +08:00
Merge new_bindings, closes #151
Refer to 6194ddb43c for new C++11 required changes for mangos based cores
This commit is contained in:
@@ -4,64 +4,55 @@
|
||||
* Please see the included DOCS/LICENSE.md for more information
|
||||
*/
|
||||
|
||||
#ifndef _BATTLEGROUND_HOOKS_H
|
||||
#define _BATTLEGROUND_HOOKS_H
|
||||
|
||||
#include "Hooks.h"
|
||||
#include "HookHelpers.h"
|
||||
#include "LuaEngine.h"
|
||||
#include "ElunaBinding.h"
|
||||
#include "BindingMap.h"
|
||||
#include "ElunaTemplate.h"
|
||||
|
||||
using namespace Hooks;
|
||||
|
||||
#define START_HOOK(EVENT) \
|
||||
if (!IsEnabled())\
|
||||
return;\
|
||||
auto key = EventKey<BGEvents>(EVENT);\
|
||||
if (!BGEventBindings->HasBindingsFor(key))\
|
||||
return;\
|
||||
LOCK_ELUNA
|
||||
|
||||
void Eluna::OnBGStart(BattleGround* bg, BattleGroundTypeId bgId, uint32 instanceId)
|
||||
{
|
||||
if (!BGEventBindings->HasEvents(BG_EVENT_ON_START))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(BG_EVENT_ON_START);
|
||||
Push(bg);
|
||||
Push(bgId);
|
||||
Push(instanceId);
|
||||
CallAllFunctions(BGEventBindings, BG_EVENT_ON_START);
|
||||
CallAllFunctions(BGEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnBGEnd(BattleGround* bg, BattleGroundTypeId bgId, uint32 instanceId, Team winner)
|
||||
{
|
||||
if (!BGEventBindings->HasEvents(BG_EVENT_ON_END))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(BG_EVENT_ON_END);
|
||||
Push(bg);
|
||||
Push(bgId);
|
||||
Push(instanceId);
|
||||
Push(winner);
|
||||
CallAllFunctions(BGEventBindings, BG_EVENT_ON_END);
|
||||
CallAllFunctions(BGEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnBGCreate(BattleGround* bg, BattleGroundTypeId bgId, uint32 instanceId)
|
||||
{
|
||||
if (!BGEventBindings->HasEvents(BG_EVENT_ON_CREATE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(BG_EVENT_ON_CREATE);
|
||||
Push(bg);
|
||||
Push(bgId);
|
||||
Push(instanceId);
|
||||
CallAllFunctions(BGEventBindings, BG_EVENT_ON_CREATE);
|
||||
CallAllFunctions(BGEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnBGDestroy(BattleGround* bg, BattleGroundTypeId bgId, uint32 instanceId)
|
||||
{
|
||||
if (!BGEventBindings->HasEvents(BG_EVENT_ON_PRE_DESTROY))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(BG_EVENT_ON_PRE_DESTROY);
|
||||
Push(bg);
|
||||
Push(bgId);
|
||||
Push(instanceId);
|
||||
CallAllFunctions(BGEventBindings, BG_EVENT_ON_PRE_DESTROY);
|
||||
CallAllFunctions(BGEventBindings, key);
|
||||
}
|
||||
|
||||
#endif // _BATTLEGROUND_HOOKS_H
|
||||
|
||||
344
BindingMap.h
Normal file
344
BindingMap.h
Normal file
@@ -0,0 +1,344 @@
|
||||
/*
|
||||
* Copyright (C) 2010 - 2015 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
|
||||
*/
|
||||
|
||||
#ifndef _BINDING_MAP_H
|
||||
#define _BINDING_MAP_H
|
||||
|
||||
#include <memory>
|
||||
#include "Common.h"
|
||||
#include "ElunaUtility.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "lua.h"
|
||||
#include "lauxlib.h"
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* A set of bindings from keys of type `K` to Lua references.
|
||||
*/
|
||||
template<typename K>
|
||||
class BindingMap : public ElunaUtil::RWLockable
|
||||
{
|
||||
private:
|
||||
lua_State* L;
|
||||
uint64 maxBindingID;
|
||||
|
||||
struct Binding
|
||||
{
|
||||
uint64 id;
|
||||
int functionReference;
|
||||
uint32 remainingShots;
|
||||
lua_State* L;
|
||||
|
||||
Binding(lua_State* L, uint64 id, int functionReference, uint32 remainingShots) :
|
||||
L(L),
|
||||
id(id),
|
||||
functionReference(functionReference),
|
||||
remainingShots(remainingShots)
|
||||
{}
|
||||
|
||||
~Binding()
|
||||
{
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, functionReference);
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::vector< std::unique_ptr<Binding> > BindingList;
|
||||
|
||||
std::unordered_map<K, BindingList> bindings;
|
||||
/*
|
||||
* This table is for fast removal of bindings by ID.
|
||||
*
|
||||
* Instead of having to look through (potentially) every BindingList to find
|
||||
* the Binding with the right ID, this allows you to go directly to the
|
||||
* BindingList that might have the Binding with that ID.
|
||||
*
|
||||
* However, you must be careful not to store pointers to BindingLists
|
||||
* that no longer exist (see `void Clear(const K& key)` implementation).
|
||||
*/
|
||||
std::unordered_map<uint64, BindingList*> id_lookup_table;
|
||||
|
||||
public:
|
||||
BindingMap(lua_State* L) :
|
||||
L(L),
|
||||
maxBindingID(0)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert a new binding from `key` to `ref`, which lasts for `shots`-many pushes.
|
||||
*
|
||||
* If `shots` is 0, it will never automatically expire, but can still be
|
||||
* removed with `Clear` or `Remove`.
|
||||
*/
|
||||
uint64 Insert(const K& key, int ref, uint32 shots)
|
||||
{
|
||||
WriteGuard guard(GetLock());
|
||||
|
||||
uint64 id = (++maxBindingID);
|
||||
BindingList& list = bindings[key];
|
||||
list.push_back(std::unique_ptr<Binding>(new Binding(L, id, ref, shots)));
|
||||
id_lookup_table[id] = &list;
|
||||
return id;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear all bindings for `key`.
|
||||
*/
|
||||
void Clear(const K& key)
|
||||
{
|
||||
WriteGuard guard(GetLock());
|
||||
|
||||
if (bindings.empty())
|
||||
return;
|
||||
|
||||
auto iter = bindings.find(key);
|
||||
if (iter == bindings.end())
|
||||
return;
|
||||
|
||||
BindingList& list = iter->second;
|
||||
|
||||
// Remove all pointers to `list` from `id_lookup_table`.
|
||||
for (auto i = list.begin(); i != list.end(); ++i)
|
||||
{
|
||||
std::unique_ptr<Binding>& binding = *i;
|
||||
id_lookup_table.erase(binding->id);
|
||||
}
|
||||
|
||||
bindings.erase(key);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear all bindings for all keys.
|
||||
*/
|
||||
void Clear()
|
||||
{
|
||||
WriteGuard guard(GetLock());
|
||||
|
||||
if (bindings.empty())
|
||||
return;
|
||||
|
||||
id_lookup_table.clear();
|
||||
bindings.clear();
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove a specific binding identified by `id`.
|
||||
*
|
||||
* If `id` in invalid, nothing is removed.
|
||||
*/
|
||||
void Remove(uint64 id)
|
||||
{
|
||||
WriteGuard guard(GetLock());
|
||||
|
||||
auto iter = id_lookup_table.find(id);
|
||||
if (iter == id_lookup_table.end())
|
||||
return;
|
||||
|
||||
BindingList* list = iter->second;
|
||||
auto i = list->begin();
|
||||
|
||||
for (; i != list->end(); ++i)
|
||||
{
|
||||
std::unique_ptr<Binding>& binding = *i;
|
||||
if (binding->id == id)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i != list->end())
|
||||
list->erase(i);
|
||||
|
||||
// Unconditionally erase the ID in the lookup table because
|
||||
// it was either already invalid, or it's no longer valid.
|
||||
id_lookup_table.erase(id);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether `key` has any bindings.
|
||||
*/
|
||||
bool HasBindingsFor(const K& key)
|
||||
{
|
||||
ReadGuard guard(GetLock());
|
||||
|
||||
if (bindings.empty())
|
||||
return false;
|
||||
|
||||
auto result = bindings.find(key);
|
||||
if (result == bindings.end())
|
||||
return false;
|
||||
|
||||
BindingList& list = result->second;
|
||||
return !list.empty();
|
||||
}
|
||||
|
||||
/*
|
||||
* Push all Lua references for `key` onto the stack.
|
||||
*/
|
||||
void PushRefsFor(const K& key)
|
||||
{
|
||||
WriteGuard guard(GetLock());
|
||||
|
||||
if (bindings.empty())
|
||||
return;
|
||||
|
||||
auto result = bindings.find(key);
|
||||
if (result == bindings.end())
|
||||
return;
|
||||
|
||||
BindingList& list = result->second;
|
||||
for (auto i = list.begin(); i != list.end();)
|
||||
{
|
||||
std::unique_ptr<Binding>& binding = (*i);
|
||||
auto i_prev = (i++);
|
||||
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, binding->functionReference);
|
||||
|
||||
if (binding->remainingShots > 0)
|
||||
{
|
||||
binding->remainingShots -= 1;
|
||||
|
||||
if (binding->remainingShots == 0)
|
||||
{
|
||||
id_lookup_table.erase(binding->id);
|
||||
list.erase(i_prev);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* A `BindingMap` key type for simple event ID bindings
|
||||
* (ServerEvents, GuildEvents, etc.).
|
||||
*/
|
||||
template <typename T>
|
||||
struct EventKey
|
||||
{
|
||||
T event_id;
|
||||
|
||||
EventKey(T event_id) :
|
||||
event_id(event_id)
|
||||
{}
|
||||
};
|
||||
|
||||
/*
|
||||
* A `BindingMap` key type for event ID/Object entry ID bindings
|
||||
* (CreatureEvents, GameObjectEvents, etc.).
|
||||
*/
|
||||
template <typename T>
|
||||
struct EntryKey : public EventKey<T>
|
||||
{
|
||||
uint32 entry;
|
||||
|
||||
EntryKey(T event_type, uint32 entry) :
|
||||
EventKey<T>(event_type),
|
||||
entry(entry)
|
||||
{}
|
||||
};
|
||||
|
||||
/*
|
||||
* A `BindingMap` key type for event ID/unique Object bindings
|
||||
* (currently just CreatureEvents).
|
||||
*/
|
||||
template <typename T>
|
||||
struct UniqueObjectKey : public EventKey<T>
|
||||
{
|
||||
uint64 guid;
|
||||
uint32 instance_id;
|
||||
|
||||
UniqueObjectKey(T event_type, uint64 guid, uint32 instance_id) :
|
||||
EventKey<T>(event_type),
|
||||
guid(guid),
|
||||
instance_id(instance_id)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Implementations of various std functions on the above key types,
|
||||
* so that they can be used within an unordered_map.
|
||||
*/
|
||||
namespace std
|
||||
{
|
||||
template<typename T>
|
||||
struct equal_to < EventKey<T> >
|
||||
{
|
||||
bool operator()(EventKey<T> const& lhs, EventKey<T> const& rhs) const
|
||||
{
|
||||
return lhs.event_id == rhs.event_id;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct equal_to < EntryKey<T> >
|
||||
{
|
||||
bool operator()(EntryKey<T> const& lhs, EntryKey<T> const& rhs) const
|
||||
{
|
||||
return lhs.event_id == rhs.event_id
|
||||
&& lhs.entry == rhs.entry;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct equal_to < UniqueObjectKey<T> >
|
||||
{
|
||||
bool operator()(UniqueObjectKey<T> const& lhs, UniqueObjectKey<T> const& rhs) const
|
||||
{
|
||||
return lhs.event_id == rhs.event_id
|
||||
&& lhs.guid == rhs.guid
|
||||
&& lhs.instance_id == rhs.instance_id;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct hash < EventKey<T> >
|
||||
{
|
||||
typedef EventKey<T> argument_type;
|
||||
typedef std::size_t result_type;
|
||||
|
||||
result_type operator()(argument_type const& k) const
|
||||
{
|
||||
result_type const h1(std::hash<uint32>()(k.event_id));
|
||||
return h1;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct hash < EntryKey<T> >
|
||||
{
|
||||
typedef EntryKey<T> argument_type;
|
||||
typedef std::size_t result_type;
|
||||
|
||||
result_type operator()(argument_type const& k) const
|
||||
{
|
||||
result_type const h1(std::hash<uint32>()(k.event_id));
|
||||
result_type const h2(std::hash<uint32>()(k.entry));
|
||||
|
||||
return h1 ^ (h2 << 8); // `event_id` probably won't exceed 2^8.
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct hash < UniqueObjectKey<T> >
|
||||
{
|
||||
typedef UniqueObjectKey<T> argument_type;
|
||||
typedef std::size_t result_type;
|
||||
|
||||
result_type operator()(argument_type const& k) const
|
||||
{
|
||||
result_type const h1(std::hash<uint32>()(k.event_id));
|
||||
result_type const h2(std::hash<uint32>()(k.instance_id));
|
||||
result_type const h3(std::hash<uint64>()(k.guid));
|
||||
|
||||
return h1 ^ (h2 << 8) ^ (h3 << 24); // `instance_id` probably won't exceed 2^16.
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // _BINDING_MAP_H
|
||||
@@ -4,187 +4,123 @@
|
||||
* Please see the included DOCS/LICENSE.md for more information
|
||||
*/
|
||||
|
||||
#ifndef _CREATURE_HOOKS_H
|
||||
#define _CREATURE_HOOKS_H
|
||||
|
||||
#include "Hooks.h"
|
||||
#include "HookHelpers.h"
|
||||
#include "LuaEngine.h"
|
||||
#include "ElunaBinding.h"
|
||||
#include "BindingMap.h"
|
||||
#include "ElunaIncludes.h"
|
||||
#include "ElunaTemplate.h"
|
||||
|
||||
using namespace Hooks;
|
||||
|
||||
#define START_HOOK(EVENT, CREATURE) \
|
||||
if (!IsEnabled())\
|
||||
return;\
|
||||
auto entry_key = EntryKey<CreatureEvents>(EVENT, CREATURE->GetEntry());\
|
||||
auto unique_key = UniqueObjectKey<CreatureEvents>(EVENT, CREATURE->GET_GUID(), CREATURE->GetInstanceId());\
|
||||
if (!CreatureEventBindings->HasBindingsFor(entry_key))\
|
||||
if (!CreatureUniqueBindings->HasBindingsFor(unique_key))\
|
||||
return;\
|
||||
LOCK_ELUNA
|
||||
|
||||
#define START_HOOK_WITH_RETVAL(EVENT, CREATURE, RETVAL) \
|
||||
if (!IsEnabled())\
|
||||
return RETVAL;\
|
||||
auto entry_key = EntryKey<CreatureEvents>(EVENT, CREATURE->GetEntry());\
|
||||
auto unique_key = UniqueObjectKey<CreatureEvents>(EVENT, CREATURE->GET_GUID(), CREATURE->GetInstanceId());\
|
||||
if (!CreatureEventBindings->HasBindingsFor(entry_key))\
|
||||
if (!CreatureUniqueBindings->HasBindingsFor(unique_key))\
|
||||
return RETVAL;\
|
||||
LOCK_ELUNA
|
||||
|
||||
bool Eluna::OnDummyEffect(Unit* pCaster, uint32 spellId, SpellEffIndex effIndex, Creature* pTarget)
|
||||
{
|
||||
if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_DUMMY_EFFECT, pTarget->GetEntry()))
|
||||
if (!CreatureUniqueBindings->HasEvents(CREATURE_EVENT_ON_DUMMY_EFFECT, pTarget->GET_GUID(), pTarget->GetInstanceId()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_DUMMY_EFFECT, pTarget, false);
|
||||
Push(pCaster);
|
||||
Push(spellId);
|
||||
Push(effIndex);
|
||||
Push(pTarget);
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_DUMMY_EFFECT, pTarget->GetEntry(), pTarget->GET_GUID(), pTarget->GetInstanceId());
|
||||
}
|
||||
|
||||
bool Eluna::OnGossipHello(Player* pPlayer, Creature* pCreature)
|
||||
{
|
||||
if (!CreatureGossipBindings->HasEvents(GOSSIP_EVENT_ON_HELLO, pCreature->GetEntry()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
pPlayer->PlayerTalkClass->ClearMenus();
|
||||
Push(pPlayer);
|
||||
Push(pCreature);
|
||||
return CallAllFunctionsBool(CreatureGossipBindings, GOSSIP_EVENT_ON_HELLO, pCreature->GetEntry(), true);
|
||||
}
|
||||
|
||||
bool Eluna::OnGossipSelect(Player* pPlayer, Creature* pCreature, uint32 sender, uint32 action)
|
||||
{
|
||||
if (!CreatureGossipBindings->HasEvents(GOSSIP_EVENT_ON_SELECT, pCreature->GetEntry()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
pPlayer->PlayerTalkClass->ClearMenus();
|
||||
Push(pPlayer);
|
||||
Push(pCreature);
|
||||
Push(sender);
|
||||
Push(action);
|
||||
return CallAllFunctionsBool(CreatureGossipBindings, GOSSIP_EVENT_ON_SELECT, pCreature->GetEntry(), true);
|
||||
}
|
||||
|
||||
bool Eluna::OnGossipSelectCode(Player* pPlayer, Creature* pCreature, uint32 sender, uint32 action, const char* code)
|
||||
{
|
||||
if (!CreatureGossipBindings->HasEvents(GOSSIP_EVENT_ON_SELECT, pCreature->GetEntry()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
pPlayer->PlayerTalkClass->ClearMenus();
|
||||
Push(pPlayer);
|
||||
Push(pCreature);
|
||||
Push(sender);
|
||||
Push(action);
|
||||
Push(code);
|
||||
return CallAllFunctionsBool(CreatureGossipBindings, GOSSIP_EVENT_ON_SELECT, pCreature->GetEntry(), true);
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
|
||||
}
|
||||
|
||||
bool Eluna::OnQuestAccept(Player* pPlayer, Creature* pCreature, Quest const* pQuest)
|
||||
{
|
||||
if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_QUEST_ACCEPT, pCreature->GetEntry()))
|
||||
if (!CreatureUniqueBindings->HasEvents(CREATURE_EVENT_ON_QUEST_ACCEPT, pCreature->GET_GUID(), pCreature->GetInstanceId()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_QUEST_ACCEPT, pCreature, false);
|
||||
Push(pPlayer);
|
||||
Push(pCreature);
|
||||
Push(pQuest);
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_QUEST_ACCEPT, pCreature->GetEntry(), pCreature->GET_GUID(), pCreature->GetInstanceId());
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
|
||||
}
|
||||
|
||||
bool Eluna::OnQuestReward(Player* pPlayer, Creature* pCreature, Quest const* pQuest, uint32 opt)
|
||||
{
|
||||
if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_QUEST_REWARD, pCreature->GetEntry()))
|
||||
if (!CreatureUniqueBindings->HasEvents(CREATURE_EVENT_ON_QUEST_REWARD, pCreature->GET_GUID(), pCreature->GetInstanceId()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_QUEST_REWARD, pCreature, false);
|
||||
Push(pPlayer);
|
||||
Push(pCreature);
|
||||
Push(pQuest);
|
||||
Push(opt);
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_QUEST_REWARD, pCreature->GetEntry(), pCreature->GET_GUID(), pCreature->GetInstanceId());
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
|
||||
}
|
||||
|
||||
uint32 Eluna::GetDialogStatus(Player* pPlayer, Creature* pCreature)
|
||||
{
|
||||
if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_DIALOG_STATUS, pCreature->GetEntry()))
|
||||
if (!CreatureUniqueBindings->HasEvents(CREATURE_EVENT_ON_DIALOG_STATUS, pCreature->GET_GUID(), pCreature->GetInstanceId()))
|
||||
return DIALOG_STATUS_SCRIPTED_NO_STATUS;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_DIALOG_STATUS, pCreature, DIALOG_STATUS_SCRIPTED_NO_STATUS);
|
||||
Push(pPlayer);
|
||||
Push(pCreature);
|
||||
CallAllFunctions(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_DIALOG_STATUS, pCreature->GetEntry(), pCreature->GET_GUID(), pCreature->GetInstanceId());
|
||||
CallAllFunctions(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
|
||||
return DIALOG_STATUS_SCRIPTED_NO_STATUS;
|
||||
}
|
||||
|
||||
void Eluna::OnAddToWorld(Creature* creature)
|
||||
void Eluna::OnAddToWorld(Creature* pCreature)
|
||||
{
|
||||
if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_ADD, creature->GetEntry()))
|
||||
if (!CreatureUniqueBindings->HasEvents(CREATURE_EVENT_ON_ADD, creature->GET_GUID(), creature->GetInstanceId()))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
Push(creature);
|
||||
CallAllFunctions(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_ADD, creature->GetEntry(), creature->GET_GUID(), creature->GetInstanceId());
|
||||
START_HOOK(CREATURE_EVENT_ON_ADD, pCreature);
|
||||
Push(pCreature);
|
||||
CallAllFunctions(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
|
||||
}
|
||||
|
||||
void Eluna::OnRemoveFromWorld(Creature* creature)
|
||||
void Eluna::OnRemoveFromWorld(Creature* pCreature)
|
||||
{
|
||||
if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_REMOVE, creature->GetEntry()))
|
||||
if (!CreatureUniqueBindings->HasEvents(CREATURE_EVENT_ON_REMOVE, creature->GET_GUID(), creature->GetInstanceId()))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
Push(creature);
|
||||
CallAllFunctions(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_REMOVE, creature->GetEntry(), creature->GET_GUID(), creature->GetInstanceId());
|
||||
START_HOOK(CREATURE_EVENT_ON_REMOVE, pCreature);
|
||||
Push(pCreature);
|
||||
CallAllFunctions(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
|
||||
}
|
||||
|
||||
bool Eluna::OnSummoned(Creature* pCreature, Unit* pSummoner)
|
||||
{
|
||||
if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_SUMMONED, pCreature->GetEntry()))
|
||||
if (!CreatureUniqueBindings->HasEvents(CREATURE_EVENT_ON_SUMMONED, pCreature->GET_GUID(), pCreature->GetInstanceId()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_SUMMONED, pCreature, false);
|
||||
Push(pCreature);
|
||||
Push(pSummoner);
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_SUMMONED, pCreature->GetEntry(), pCreature->GET_GUID(), pCreature->GetInstanceId());
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
|
||||
}
|
||||
|
||||
bool Eluna::UpdateAI(Creature* me, const uint32 diff)
|
||||
{
|
||||
if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_AIUPDATE, me->GetEntry()))
|
||||
if (!CreatureUniqueBindings->HasEvents(CREATURE_EVENT_ON_AIUPDATE, me->GET_GUID(), me->GetInstanceId()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_AIUPDATE, me, false);
|
||||
Push(me);
|
||||
Push(diff);
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_AIUPDATE, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
|
||||
}
|
||||
|
||||
//Called for reaction at enter to combat if not in combat yet (enemy can be NULL)
|
||||
//Called at creature aggro either by MoveInLOS or Attack Start
|
||||
bool Eluna::EnterCombat(Creature* me, Unit* target)
|
||||
{
|
||||
if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_ENTER_COMBAT, me->GetEntry()))
|
||||
if (!CreatureUniqueBindings->HasEvents(CREATURE_EVENT_ON_ENTER_COMBAT, me->GET_GUID(), me->GetInstanceId()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_ENTER_COMBAT, me, false);
|
||||
Push(me);
|
||||
Push(target);
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_ENTER_COMBAT, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
|
||||
}
|
||||
|
||||
// Called at any Damage from any attacker (before damage apply)
|
||||
bool Eluna::DamageTaken(Creature* me, Unit* attacker, uint32& damage)
|
||||
{
|
||||
if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_DAMAGE_TAKEN, me->GetEntry()))
|
||||
if (!CreatureUniqueBindings->HasEvents(CREATURE_EVENT_ON_DAMAGE_TAKEN, me->GET_GUID(), me->GetInstanceId()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_DAMAGE_TAKEN, me, false);
|
||||
bool result = false;
|
||||
Push(me);
|
||||
Push(attacker);
|
||||
Push(damage);
|
||||
int damageIndex = lua_gettop(L);
|
||||
int n = SetupStack(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_DAMAGE_TAKEN, me->GetEntry(), me->GET_GUID(), me->GetInstanceId(), 3);
|
||||
int n = SetupStack(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key, 3);
|
||||
|
||||
while (n > 0)
|
||||
{
|
||||
@@ -211,163 +147,112 @@ bool Eluna::DamageTaken(Creature* me, Unit* attacker, uint32& damage)
|
||||
bool Eluna::JustDied(Creature* me, Unit* killer)
|
||||
{
|
||||
On_Reset(me);
|
||||
|
||||
if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_DIED, me->GetEntry()))
|
||||
if (!CreatureUniqueBindings->HasEvents(CREATURE_EVENT_ON_DIED, me->GET_GUID(), me->GetInstanceId()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_DIED, me, false);
|
||||
Push(me);
|
||||
Push(killer);
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_DIED, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
|
||||
}
|
||||
|
||||
//Called at creature killing another unit
|
||||
bool Eluna::KilledUnit(Creature* me, Unit* victim)
|
||||
{
|
||||
if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_TARGET_DIED, me->GetEntry()))
|
||||
if (!CreatureUniqueBindings->HasEvents(CREATURE_EVENT_ON_TARGET_DIED, me->GET_GUID(), me->GetInstanceId()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_TARGET_DIED, me, false);
|
||||
Push(me);
|
||||
Push(victim);
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_TARGET_DIED, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
|
||||
}
|
||||
|
||||
// Called when the creature summon successfully other creature
|
||||
bool Eluna::JustSummoned(Creature* me, Creature* summon)
|
||||
{
|
||||
if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_JUST_SUMMONED_CREATURE, me->GetEntry()))
|
||||
if (!CreatureUniqueBindings->HasEvents(CREATURE_EVENT_ON_JUST_SUMMONED_CREATURE, me->GET_GUID(), me->GetInstanceId()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_JUST_SUMMONED_CREATURE, me, false);
|
||||
Push(me);
|
||||
Push(summon);
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_JUST_SUMMONED_CREATURE, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
|
||||
}
|
||||
|
||||
// Called when a summoned creature is despawned
|
||||
bool Eluna::SummonedCreatureDespawn(Creature* me, Creature* summon)
|
||||
{
|
||||
if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_SUMMONED_CREATURE_DESPAWN, me->GetEntry()))
|
||||
if (!CreatureUniqueBindings->HasEvents(CREATURE_EVENT_ON_SUMMONED_CREATURE_DESPAWN, me->GET_GUID(), me->GetInstanceId()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_SUMMONED_CREATURE_DESPAWN, me, false);
|
||||
Push(me);
|
||||
Push(summon);
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_SUMMONED_CREATURE_DESPAWN, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
|
||||
}
|
||||
|
||||
//Called at waypoint reached or PointMovement end
|
||||
bool Eluna::MovementInform(Creature* me, uint32 type, uint32 id)
|
||||
{
|
||||
if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_REACH_WP, me->GetEntry()))
|
||||
if (!CreatureUniqueBindings->HasEvents(CREATURE_EVENT_ON_REACH_WP, me->GET_GUID(), me->GetInstanceId()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_REACH_WP, me, false);
|
||||
Push(me);
|
||||
Push(type);
|
||||
Push(id);
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_REACH_WP, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
|
||||
}
|
||||
|
||||
// Called before EnterCombat even before the creature is in combat.
|
||||
bool Eluna::AttackStart(Creature* me, Unit* target)
|
||||
{
|
||||
if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_PRE_COMBAT, me->GetEntry()))
|
||||
if (!CreatureUniqueBindings->HasEvents(CREATURE_EVENT_ON_PRE_COMBAT, me->GET_GUID(), me->GetInstanceId()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_PRE_COMBAT, me, false);
|
||||
Push(me);
|
||||
Push(target);
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_PRE_COMBAT, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
|
||||
}
|
||||
|
||||
// Called for reaction at stopping attack at no attackers or targets
|
||||
bool Eluna::EnterEvadeMode(Creature* me)
|
||||
{
|
||||
On_Reset(me);
|
||||
|
||||
if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_LEAVE_COMBAT, me->GetEntry()))
|
||||
if (!CreatureUniqueBindings->HasEvents(CREATURE_EVENT_ON_LEAVE_COMBAT, me->GET_GUID(), me->GetInstanceId()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_LEAVE_COMBAT, me, false);
|
||||
Push(me);
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_LEAVE_COMBAT, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
|
||||
}
|
||||
|
||||
// Called when the creature is target of hostile action: swing, hostile spell landed, fear/etc)
|
||||
bool Eluna::AttackedBy(Creature* me, Unit* attacker)
|
||||
{
|
||||
if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_ATTACKED_AT, me->GetEntry()))
|
||||
if (!CreatureUniqueBindings->HasEvents(CREATURE_EVENT_ON_ATTACKED_AT, me->GET_GUID(), me->GetInstanceId()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_ATTACKED_AT, me, false);
|
||||
Push(me);
|
||||
Push(attacker);
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_ATTACKED_AT, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
|
||||
}
|
||||
|
||||
// Called when creature is spawned or respawned (for reseting variables)
|
||||
bool Eluna::JustRespawned(Creature* me)
|
||||
{
|
||||
On_Reset(me);
|
||||
|
||||
if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_SPAWN, me->GetEntry()))
|
||||
if (!CreatureUniqueBindings->HasEvents(CREATURE_EVENT_ON_SPAWN, me->GET_GUID(), me->GetInstanceId()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_SPAWN, me, false);
|
||||
Push(me);
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_SPAWN, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
|
||||
}
|
||||
|
||||
// Called at reaching home after evade
|
||||
bool Eluna::JustReachedHome(Creature* me)
|
||||
{
|
||||
if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_REACH_HOME, me->GetEntry()))
|
||||
if (!CreatureUniqueBindings->HasEvents(CREATURE_EVENT_ON_REACH_HOME, me->GET_GUID(), me->GetInstanceId()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_REACH_HOME, me, false);
|
||||
Push(me);
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_REACH_HOME, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
|
||||
}
|
||||
|
||||
// Called at text emote receive from player
|
||||
bool Eluna::ReceiveEmote(Creature* me, Player* player, uint32 emoteId)
|
||||
{
|
||||
if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_RECEIVE_EMOTE, me->GetEntry()))
|
||||
if (!CreatureUniqueBindings->HasEvents(CREATURE_EVENT_ON_RECEIVE_EMOTE, me->GET_GUID(), me->GetInstanceId()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_RECEIVE_EMOTE, me, false);
|
||||
Push(me);
|
||||
Push(player);
|
||||
Push(emoteId);
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_RECEIVE_EMOTE, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
|
||||
}
|
||||
|
||||
// called when the corpse of this creature gets removed
|
||||
bool Eluna::CorpseRemoved(Creature* me, uint32& respawnDelay)
|
||||
{
|
||||
if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_CORPSE_REMOVED, me->GetEntry()))
|
||||
if (!CreatureUniqueBindings->HasEvents(CREATURE_EVENT_ON_CORPSE_REMOVED, me->GET_GUID(), me->GetInstanceId()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_CORPSE_REMOVED, me, false);
|
||||
bool result = false;
|
||||
Push(me);
|
||||
Push(respawnDelay);
|
||||
int respawnDelayIndex = lua_gettop(L);
|
||||
int n = SetupStack(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_CORPSE_REMOVED, me->GetEntry(), me->GET_GUID(), me->GetInstanceId(), 2);
|
||||
int n = SetupStack(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key, 2);
|
||||
|
||||
while (n > 0)
|
||||
{
|
||||
@@ -392,96 +277,67 @@ bool Eluna::CorpseRemoved(Creature* me, uint32& respawnDelay)
|
||||
|
||||
bool Eluna::MoveInLineOfSight(Creature* me, Unit* who)
|
||||
{
|
||||
if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_MOVE_IN_LOS, me->GetEntry()))
|
||||
if (!CreatureUniqueBindings->HasEvents(CREATURE_EVENT_ON_MOVE_IN_LOS, me->GET_GUID(), me->GetInstanceId()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_MOVE_IN_LOS, me, false);
|
||||
Push(me);
|
||||
Push(who);
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_MOVE_IN_LOS, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
|
||||
}
|
||||
|
||||
// Called on creature initial spawn, respawn, death, evade (leave combat)
|
||||
void Eluna::On_Reset(Creature* me) // Not an override, custom
|
||||
{
|
||||
if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_RESET, me->GetEntry()))
|
||||
if (!CreatureUniqueBindings->HasEvents(CREATURE_EVENT_ON_RESET, me->GET_GUID(), me->GetInstanceId()))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(CREATURE_EVENT_ON_RESET, me);
|
||||
Push(me);
|
||||
CallAllFunctions(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_RESET, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
|
||||
CallAllFunctions(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
|
||||
}
|
||||
|
||||
// Called when hit by a spell
|
||||
bool Eluna::SpellHit(Creature* me, Unit* caster, SpellInfo const* spell)
|
||||
{
|
||||
if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_HIT_BY_SPELL, me->GetEntry()))
|
||||
if (!CreatureUniqueBindings->HasEvents(CREATURE_EVENT_ON_HIT_BY_SPELL, me->GET_GUID(), me->GetInstanceId()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_HIT_BY_SPELL, me, false);
|
||||
Push(me);
|
||||
Push(caster);
|
||||
Push(spell->Id); // Pass spell object?
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_HIT_BY_SPELL, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
|
||||
}
|
||||
|
||||
// Called when spell hits a target
|
||||
bool Eluna::SpellHitTarget(Creature* me, Unit* target, SpellInfo const* spell)
|
||||
{
|
||||
if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_SPELL_HIT_TARGET, me->GetEntry()))
|
||||
if (!CreatureUniqueBindings->HasEvents(CREATURE_EVENT_ON_SPELL_HIT_TARGET, me->GET_GUID(), me->GetInstanceId()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_SPELL_HIT_TARGET, me, false);
|
||||
Push(me);
|
||||
Push(target);
|
||||
Push(spell->Id); // Pass spell object?
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_SPELL_HIT_TARGET, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
|
||||
}
|
||||
|
||||
#ifdef TRINITY
|
||||
|
||||
bool Eluna::SummonedCreatureDies(Creature* me, Creature* summon, Unit* killer)
|
||||
{
|
||||
if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_SUMMONED_CREATURE_DIED, me->GetEntry()))
|
||||
if (!CreatureUniqueBindings->HasEvents(CREATURE_EVENT_ON_SUMMONED_CREATURE_DIED, me->GET_GUID(), me->GetInstanceId()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_SUMMONED_CREATURE_DIED, me, false);
|
||||
Push(me);
|
||||
Push(summon);
|
||||
Push(killer);
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_SUMMONED_CREATURE_DIED, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
|
||||
}
|
||||
|
||||
// Called when owner takes damage
|
||||
bool Eluna::OwnerAttackedBy(Creature* me, Unit* attacker)
|
||||
{
|
||||
if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_OWNER_ATTACKED_AT, me->GetEntry()))
|
||||
if (!CreatureUniqueBindings->HasEvents(CREATURE_EVENT_ON_OWNER_ATTACKED_AT, me->GET_GUID(), me->GetInstanceId()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_OWNER_ATTACKED_AT, me, false);
|
||||
Push(me);
|
||||
Push(attacker);
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_OWNER_ATTACKED_AT, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
|
||||
}
|
||||
|
||||
// Called when owner attacks something
|
||||
bool Eluna::OwnerAttacked(Creature* me, Unit* target)
|
||||
{
|
||||
if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_OWNER_ATTACKED, me->GetEntry()))
|
||||
if (!CreatureUniqueBindings->HasEvents(CREATURE_EVENT_ON_OWNER_ATTACKED, me->GET_GUID(), me->GetInstanceId()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_OWNER_ATTACKED, me, false);
|
||||
Push(me);
|
||||
Push(target);
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_OWNER_ATTACKED, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
|
||||
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
|
||||
}
|
||||
|
||||
#endif // TRINITY
|
||||
#endif // _CREATURE_HOOKS_H
|
||||
|
||||
573
ElunaBinding.h
573
ElunaBinding.h
@@ -1,573 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 - 2015 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
|
||||
*/
|
||||
|
||||
#ifndef _ELUNA_BINDING_H
|
||||
#define _ELUNA_BINDING_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "LuaEngine.h"
|
||||
#include "ElunaUtility.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "lua.h"
|
||||
#include "lauxlib.h"
|
||||
};
|
||||
|
||||
#ifdef WIN32
|
||||
// VC++ complains about UniqueBind because one of its template types is really long.
|
||||
#pragma warning(disable:4503)
|
||||
#endif
|
||||
|
||||
class ElunaBind : public ElunaUtil::RWLockable
|
||||
{
|
||||
public:
|
||||
struct Binding
|
||||
{
|
||||
int functionReference;
|
||||
bool isTemporary;
|
||||
uint32 remainingShots;
|
||||
int cancelCallbackRef; // Reference to a callback that will cancel this binding, or 0.
|
||||
Eluna& E;
|
||||
|
||||
Binding(Eluna& _E, int funcRef, uint32 shots, int cancelCallbackRef) :
|
||||
functionReference(funcRef),
|
||||
isTemporary(shots != 0 && cancelCallbackRef == 0),
|
||||
remainingShots(shots),
|
||||
cancelCallbackRef(cancelCallbackRef),
|
||||
E(_E)
|
||||
{
|
||||
}
|
||||
|
||||
~Binding()
|
||||
{
|
||||
// Remove our function and cancel callback from the registry when the Binding is deleted.
|
||||
if (cancelCallbackRef > 0)
|
||||
luaL_unref(E.L, LUA_REGISTRYINDEX, cancelCallbackRef);
|
||||
|
||||
luaL_unref(E.L, LUA_REGISTRYINDEX, functionReference);
|
||||
}
|
||||
};
|
||||
typedef std::vector<Binding*> FunctionRefVector;
|
||||
typedef UNORDERED_MAP<int, FunctionRefVector> EventToFunctionsMap;
|
||||
|
||||
Eluna& E;
|
||||
const char* groupName;
|
||||
|
||||
ElunaBind(const char* bindGroupName, Eluna& _E) : E(_E), groupName(bindGroupName)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~ElunaBind()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
// unregisters all registered functions and clears all registered events from the bindings
|
||||
virtual void Clear() { };
|
||||
|
||||
virtual void ClearOne(int ref, uint32 event_id, uint32 entry, uint64 guid) = 0;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class EventBind : public ElunaBind
|
||||
{
|
||||
public:
|
||||
EventBind(const char* bindGroupName, Eluna& _E) : ElunaBind(bindGroupName, _E)
|
||||
{
|
||||
}
|
||||
|
||||
// unregisters all registered functions and clears all registered events from the bind std::maps (reset)
|
||||
void Clear() override
|
||||
{
|
||||
WriteGuard guard(GetLock());
|
||||
|
||||
for (EventToFunctionsMap::iterator itr = Bindings.begin(); itr != Bindings.end(); ++itr)
|
||||
{
|
||||
FunctionRefVector& funcrefvec = itr->second;
|
||||
std::vector<int> cancelRefVector;
|
||||
|
||||
for (FunctionRefVector::iterator it = funcrefvec.begin(); it != funcrefvec.end(); ++it)
|
||||
{
|
||||
Binding* binding = (*it);
|
||||
|
||||
// Can't call the callback now, since it might modify `v` and crash the server.
|
||||
// Just add the ref to a list and call them all after this loop.
|
||||
if (binding->cancelCallbackRef)
|
||||
cancelRefVector.push_back(binding->cancelCallbackRef);
|
||||
else
|
||||
delete binding; // Don't bother removing from list, clear is called at end anyway.
|
||||
}
|
||||
|
||||
// Call all of the cancel callbacks for bindings with cancel callbacks.
|
||||
for (std::vector<int>::iterator i = cancelRefVector.begin(); i != cancelRefVector.end(); ++i)
|
||||
{
|
||||
lua_rawgeti(E.L, LUA_REGISTRYINDEX, (*i));
|
||||
lua_call(E.L, 0, 0);
|
||||
}
|
||||
|
||||
funcrefvec.clear();
|
||||
}
|
||||
Bindings.clear();
|
||||
}
|
||||
|
||||
void Clear(uint32 event_id)
|
||||
{
|
||||
WriteGuard guard(GetLock());
|
||||
FunctionRefVector& v = Bindings[event_id];
|
||||
std::vector<int> cancelRefVector;
|
||||
|
||||
for (FunctionRefVector::iterator itr = v.begin(); itr != v.end(); ++itr)
|
||||
{
|
||||
Binding* binding = (*itr);
|
||||
|
||||
// Can't call the callback now, since it might modify `v` and crash the server.
|
||||
// Just add the ref to a list and call them all after this loop.
|
||||
if (binding->cancelCallbackRef)
|
||||
cancelRefVector.push_back(binding->cancelCallbackRef);
|
||||
else
|
||||
delete binding; // Don't bother removing from list, clear is called at end anyway.
|
||||
}
|
||||
|
||||
// Call all of the cancel callbacks for bindings with cancel callbacks.
|
||||
for (std::vector<int>::iterator i = cancelRefVector.begin(); i != cancelRefVector.end(); ++i)
|
||||
{
|
||||
lua_rawgeti(E.L, LUA_REGISTRYINDEX, (*i));
|
||||
lua_call(E.L, 0, 0);
|
||||
}
|
||||
|
||||
v.clear();
|
||||
}
|
||||
|
||||
void ClearOne(int ref, uint32 event_id, uint32 entry, uint64 guid) override
|
||||
{
|
||||
ASSERT(entry == 0 && guid == 0);
|
||||
WriteGuard guard(GetLock());
|
||||
|
||||
FunctionRefVector& funcrefvec = Bindings[event_id];
|
||||
|
||||
for (FunctionRefVector::iterator i = funcrefvec.begin(); i != funcrefvec.end(); ++i)
|
||||
{
|
||||
Binding* binding = (*i);
|
||||
|
||||
if (binding->functionReference == ref)
|
||||
{
|
||||
i = funcrefvec.erase(i);
|
||||
delete binding;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(false && "tried to clear function ref that doesn't exist");
|
||||
}
|
||||
|
||||
// Pushes the function references and updates the counters on the binds and erases them if the counter would reach 0
|
||||
void PushFuncRefs(lua_State* L, int event_id)
|
||||
{
|
||||
WriteGuard guard(GetLock());
|
||||
|
||||
for (FunctionRefVector::iterator it = Bindings[event_id].begin(); it != Bindings[event_id].end();)
|
||||
{
|
||||
FunctionRefVector::iterator it_old = it++;
|
||||
Binding* binding = (*it_old);
|
||||
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, binding->functionReference);
|
||||
|
||||
if (binding->isTemporary)
|
||||
{
|
||||
// Bad things will happen if there's a cancel callback (due to ref reuse).
|
||||
ASSERT(binding->cancelCallbackRef == 0);
|
||||
|
||||
binding->remainingShots--;
|
||||
if (binding->remainingShots == 0)
|
||||
{
|
||||
delete binding;
|
||||
Bindings[event_id].erase(it_old);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Bindings[event_id].empty())
|
||||
Bindings.erase(event_id);
|
||||
};
|
||||
|
||||
void Insert(int eventId, int funcRef, uint32 shots, int callbackRef = 0) // Inserts a new registered event
|
||||
{
|
||||
WriteGuard guard(GetLock());
|
||||
Bindings[eventId].push_back(new Binding(E, funcRef, shots, callbackRef));
|
||||
}
|
||||
|
||||
// Checks if there are events for ID
|
||||
bool HasEvents(T eventId)
|
||||
{
|
||||
ReadGuard guard(GetLock());
|
||||
|
||||
if (!E.IsEnabled())
|
||||
return false;
|
||||
|
||||
if (Bindings.empty())
|
||||
return false;
|
||||
if (Bindings.find(eventId) == Bindings.end())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
EventToFunctionsMap Bindings; // Binding store Bindings[eventId] = {(funcRef, counter)};
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class EntryBind : public ElunaBind
|
||||
{
|
||||
public:
|
||||
typedef UNORDERED_MAP<uint32, EventToFunctionsMap> EntryToEventsMap;
|
||||
|
||||
EntryBind(const char* bindGroupName, Eluna& _E) : ElunaBind(bindGroupName, _E)
|
||||
{
|
||||
}
|
||||
|
||||
// unregisters all registered functions and clears all registered events from the bindmap
|
||||
void Clear() override
|
||||
{
|
||||
WriteGuard guard(GetLock());
|
||||
|
||||
for (EntryToEventsMap::iterator itr = Bindings.begin(); itr != Bindings.end(); ++itr)
|
||||
{
|
||||
EventToFunctionsMap& funcmap = itr->second;
|
||||
for (EventToFunctionsMap::iterator it = funcmap.begin(); it != funcmap.end(); ++it)
|
||||
{
|
||||
FunctionRefVector& funcrefvec = it->second;
|
||||
std::vector<int> cancelRefVector;
|
||||
|
||||
for (FunctionRefVector::iterator i = funcrefvec.begin(); i != funcrefvec.end(); ++i)
|
||||
{
|
||||
Binding* binding = (*i);
|
||||
|
||||
// Can't call the callback now, since it might modify `v` and crash the server.
|
||||
// Just add the ref to a list and call them all after this loop.
|
||||
if (binding->cancelCallbackRef)
|
||||
cancelRefVector.push_back(binding->cancelCallbackRef);
|
||||
else
|
||||
delete binding; // Don't bother removing from list, clear is called at end anyway.
|
||||
}
|
||||
|
||||
// Call all of the cancel callbacks for bindings with cancel callbacks.
|
||||
for (std::vector<int>::iterator i = cancelRefVector.begin(); i != cancelRefVector.end(); ++i)
|
||||
{
|
||||
lua_rawgeti(E.L, LUA_REGISTRYINDEX, (*i));
|
||||
lua_call(E.L, 0, 0);
|
||||
}
|
||||
|
||||
funcrefvec.clear();
|
||||
}
|
||||
funcmap.clear();
|
||||
}
|
||||
Bindings.clear();
|
||||
}
|
||||
|
||||
void Clear(uint32 entry, uint32 event_id)
|
||||
{
|
||||
WriteGuard guard(GetLock());
|
||||
FunctionRefVector& v = Bindings[entry][event_id];
|
||||
std::vector<int> cancelRefVector;
|
||||
|
||||
for (FunctionRefVector::iterator itr = v.begin(); itr != v.end(); ++itr)
|
||||
{
|
||||
Binding* binding = (*itr);
|
||||
|
||||
// Can't call the callback now, since it might modify `v` and crash the server.
|
||||
// Just add the ref to a list and call them all after this loop.
|
||||
if (binding->cancelCallbackRef)
|
||||
cancelRefVector.push_back(binding->cancelCallbackRef);
|
||||
else
|
||||
delete binding; // Don't bother removing from list, clear is called at end anyway.
|
||||
}
|
||||
|
||||
// Call all of the cancel callbacks for bindings with cancel callbacks.
|
||||
for (std::vector<int>::iterator i = cancelRefVector.begin(); i != cancelRefVector.end(); ++i)
|
||||
{
|
||||
lua_rawgeti(E.L, LUA_REGISTRYINDEX, (*i));
|
||||
lua_call(E.L, 0, 0);
|
||||
}
|
||||
|
||||
v.clear();
|
||||
}
|
||||
|
||||
void ClearOne(int ref, uint32 event_id, uint32 entry, uint64 guid) override
|
||||
{
|
||||
ASSERT(entry != 0 && guid == 0);
|
||||
WriteGuard guard(GetLock());
|
||||
|
||||
FunctionRefVector& funcrefvec = Bindings[entry][event_id];
|
||||
|
||||
for (FunctionRefVector::iterator i = funcrefvec.begin(); i != funcrefvec.end(); ++i)
|
||||
{
|
||||
Binding* binding = (*i);
|
||||
|
||||
if (binding->functionReference == ref)
|
||||
{
|
||||
i = funcrefvec.erase(i);
|
||||
delete binding;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(false && "tried to clear function ref that doesn't exist");
|
||||
}
|
||||
|
||||
// Pushes the function references and updates the counters on the binds and erases them if the counter would reach 0
|
||||
void PushFuncRefs(lua_State* L, int event_id, uint32 entry)
|
||||
{
|
||||
WriteGuard guard(GetLock());
|
||||
|
||||
for (FunctionRefVector::iterator it = Bindings[entry][event_id].begin(); it != Bindings[entry][event_id].end();)
|
||||
{
|
||||
FunctionRefVector::iterator it_old = it++;
|
||||
Binding* binding = (*it_old);
|
||||
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, binding->functionReference);
|
||||
|
||||
if (binding->isTemporary)
|
||||
{
|
||||
// Bad things will happen if there's a cancel callback (due to ref reuse).
|
||||
ASSERT(binding->cancelCallbackRef == 0);
|
||||
|
||||
binding->remainingShots--;
|
||||
if (binding->remainingShots == 0)
|
||||
{
|
||||
delete binding;
|
||||
Bindings[entry][event_id].erase(it_old);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Bindings[entry][event_id].empty())
|
||||
Bindings[entry].erase(event_id);
|
||||
|
||||
if (Bindings[entry].empty())
|
||||
Bindings.erase(entry);
|
||||
};
|
||||
|
||||
void Insert(uint32 entryId, int eventId, int funcRef, uint32 shots, int callbackRef = 0) // Inserts a new registered event
|
||||
{
|
||||
WriteGuard guard(GetLock());
|
||||
Bindings[entryId][eventId].push_back(new Binding(E, funcRef, shots, callbackRef));
|
||||
}
|
||||
|
||||
// Returns true if the entry has registered binds
|
||||
bool HasEvents(T eventId, uint32 entryId)
|
||||
{
|
||||
ReadGuard guard(GetLock());
|
||||
|
||||
if (Bindings.empty())
|
||||
return false;
|
||||
|
||||
EntryToEventsMap::const_iterator itr = Bindings.find(entryId);
|
||||
if (itr == Bindings.end())
|
||||
return false;
|
||||
|
||||
return itr->second.find(eventId) != itr->second.end();
|
||||
}
|
||||
|
||||
bool HasEvents(uint32 entryId)
|
||||
{
|
||||
ReadGuard guard(GetLock());
|
||||
|
||||
if (!E.IsEnabled())
|
||||
return false;
|
||||
|
||||
if (Bindings.empty())
|
||||
return false;
|
||||
|
||||
return Bindings.find(entryId) != Bindings.end();
|
||||
}
|
||||
|
||||
EntryToEventsMap Bindings; // Binding store Bindings[entryId][eventId] = {(funcRef, counter)};
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class UniqueBind : public ElunaBind
|
||||
{
|
||||
public:
|
||||
typedef UNORDERED_MAP<uint32, EventToFunctionsMap> InstanceToEventsMap;
|
||||
typedef UNORDERED_MAP<uint64, InstanceToEventsMap> GUIDToInstancesMap;
|
||||
|
||||
UniqueBind(const char* bindGroupName, Eluna& _E) : ElunaBind(bindGroupName, _E)
|
||||
{
|
||||
}
|
||||
|
||||
// unregisters all registered functions and clears all registered events from the bindmap
|
||||
void Clear() override
|
||||
{
|
||||
WriteGuard guard(GetLock());
|
||||
|
||||
for (GUIDToInstancesMap::iterator iter = Bindings.begin(); iter != Bindings.end(); ++iter)
|
||||
{
|
||||
InstanceToEventsMap& eventsMap = iter->second;
|
||||
for (InstanceToEventsMap::iterator itr = eventsMap.begin(); itr != eventsMap.end(); ++itr)
|
||||
{
|
||||
EventToFunctionsMap& funcmap = itr->second;
|
||||
for (EventToFunctionsMap::iterator it = funcmap.begin(); it != funcmap.end(); ++it)
|
||||
{
|
||||
FunctionRefVector& funcrefvec = it->second;
|
||||
std::vector<int> cancelRefVector;
|
||||
|
||||
for (FunctionRefVector::iterator i = funcrefvec.begin(); i != funcrefvec.end(); ++i)
|
||||
{
|
||||
Binding* binding = (*i);
|
||||
|
||||
// Can't call the callback now, since it might modify `v` and crash the server.
|
||||
// Just add the ref to a list and call them all after this loop.
|
||||
if (binding->cancelCallbackRef)
|
||||
cancelRefVector.push_back(binding->cancelCallbackRef);
|
||||
else
|
||||
delete binding; // Don't bother removing from list, clear is called at end anyway.
|
||||
}
|
||||
|
||||
// Call all of the cancel callbacks for bindings with cancel callbacks.
|
||||
for (std::vector<int>::iterator i = cancelRefVector.begin(); i != cancelRefVector.end(); ++i)
|
||||
{
|
||||
lua_rawgeti(E.L, LUA_REGISTRYINDEX, (*i));
|
||||
lua_call(E.L, 0, 0);
|
||||
}
|
||||
funcrefvec.clear();
|
||||
}
|
||||
funcmap.clear();
|
||||
}
|
||||
eventsMap.clear();
|
||||
}
|
||||
Bindings.clear();
|
||||
}
|
||||
|
||||
void Clear(uint64 guid, uint32 instanceId, uint32 event_id)
|
||||
{
|
||||
WriteGuard guard(GetLock());
|
||||
FunctionRefVector& v = Bindings[guid][instanceId][event_id];
|
||||
std::vector<int> cancelRefVector;
|
||||
|
||||
for (FunctionRefVector::iterator itr = v.begin(); itr != v.end(); ++itr)
|
||||
{
|
||||
Binding* binding = (*itr);
|
||||
|
||||
// Can't call the callback now, since it might modify `v` and crash the server.
|
||||
// Just add the ref to a list and call them all after this loop.
|
||||
if (binding->cancelCallbackRef)
|
||||
cancelRefVector.push_back(binding->cancelCallbackRef);
|
||||
else
|
||||
delete binding; // Don't bother removing from list, clear is called at end anyway.
|
||||
}
|
||||
|
||||
// Call all of the cancel callbacks for bindings with cancel callbacks.
|
||||
for (std::vector<int>::iterator i = cancelRefVector.begin(); i != cancelRefVector.end(); ++i)
|
||||
{
|
||||
lua_rawgeti(E.L, LUA_REGISTRYINDEX, (*i));
|
||||
lua_call(E.L, 0, 0);
|
||||
}
|
||||
|
||||
v.clear();
|
||||
}
|
||||
|
||||
void ClearOne(int ref, uint32 event_id, uint32 instance_id, uint64 guid) override
|
||||
{
|
||||
ASSERT(guid != 0);
|
||||
WriteGuard guard(GetLock());
|
||||
|
||||
FunctionRefVector& funcrefvec = Bindings[guid][instance_id][event_id];
|
||||
|
||||
for (FunctionRefVector::iterator i = funcrefvec.begin(); i != funcrefvec.end(); ++i)
|
||||
{
|
||||
Binding* binding = (*i);
|
||||
|
||||
if (binding->functionReference == ref)
|
||||
{
|
||||
i = funcrefvec.erase(i);
|
||||
delete binding;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(false && "tried to clear function ref that doesn't exist");
|
||||
}
|
||||
|
||||
// Pushes the function references and updates the counters on the binds and erases them if the counter would reach 0
|
||||
void PushFuncRefs(lua_State* L, int event_id, uint64 guid, uint32 instanceId)
|
||||
{
|
||||
WriteGuard guard(GetLock());
|
||||
FunctionRefVector& v = Bindings[guid][instanceId][event_id];
|
||||
|
||||
for (FunctionRefVector::iterator it = v.begin(); it != v.end();)
|
||||
{
|
||||
FunctionRefVector::iterator it_old = it++;
|
||||
Binding* binding = (*it_old);
|
||||
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, binding->functionReference);
|
||||
|
||||
if (binding->isTemporary)
|
||||
{
|
||||
// Bad things will happen if there's a cancel callback (due to ref reuse).
|
||||
ASSERT(binding->cancelCallbackRef == 0);
|
||||
|
||||
binding->remainingShots--;
|
||||
if (binding->remainingShots == 0)
|
||||
{
|
||||
delete binding;
|
||||
v.erase(it_old);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Bindings[guid][instanceId][event_id].empty())
|
||||
Bindings[guid][instanceId].erase(event_id);
|
||||
|
||||
if (Bindings[guid][instanceId].empty())
|
||||
Bindings[guid].erase(instanceId);
|
||||
|
||||
if (Bindings[guid].empty())
|
||||
Bindings.erase(guid);
|
||||
};
|
||||
|
||||
void Insert(uint64 guid, uint32 instanceId, int eventId, int funcRef, uint32 shots, int callbackRef = 0) // Inserts a new registered event
|
||||
{
|
||||
WriteGuard guard(GetLock());
|
||||
Bindings[guid][instanceId][eventId].push_back(new Binding(E, funcRef, shots, callbackRef));
|
||||
}
|
||||
|
||||
// Returns true if the entry has registered binds
|
||||
bool HasEvents(T eventId, uint64 guid, uint32 instanceId)
|
||||
{
|
||||
ReadGuard guard(GetLock());
|
||||
|
||||
if (Bindings.empty())
|
||||
return false;
|
||||
|
||||
GUIDToInstancesMap::const_iterator itr = Bindings.find(guid);
|
||||
if (itr == Bindings.end())
|
||||
return false;
|
||||
|
||||
InstanceToEventsMap::const_iterator it = itr->second.find(instanceId);
|
||||
if (it == itr->second.end())
|
||||
return false;
|
||||
|
||||
return it->second.find(eventId) != it->second.end();
|
||||
}
|
||||
|
||||
bool HasEvents(uint64 guid, uint32 instanceId)
|
||||
{
|
||||
ReadGuard guard(GetLock());
|
||||
|
||||
if (Bindings.empty())
|
||||
return false;
|
||||
|
||||
GUIDToInstancesMap::const_iterator itr = Bindings.find(guid);
|
||||
if (itr == Bindings.end())
|
||||
return false;
|
||||
|
||||
return itr->second.find(instanceId) != itr->second.end();
|
||||
}
|
||||
|
||||
GUIDToInstancesMap Bindings; // Binding store Bindings[guid][instanceId][eventId] = {(funcRef, counter)};
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -54,7 +54,7 @@ class ElunaEventProcessor
|
||||
|
||||
public:
|
||||
typedef std::multimap<uint64, LuaEvent*> EventList;
|
||||
typedef UNORDERED_MAP<int, LuaEvent*> EventMap;
|
||||
typedef std::unordered_map<int, LuaEvent*> EventMap;
|
||||
|
||||
ElunaEventProcessor(Eluna** _E, WorldObject* _obj);
|
||||
~ElunaEventProcessor();
|
||||
@@ -80,7 +80,7 @@ private:
|
||||
class EventMgr : public ElunaUtil::RWLockable
|
||||
{
|
||||
public:
|
||||
typedef UNORDERED_SET<ElunaEventProcessor*> ProcessorSet;
|
||||
typedef std::unordered_set<ElunaEventProcessor*> ProcessorSet;
|
||||
ProcessorSet processors;
|
||||
ElunaEventProcessor* globalProcessor;
|
||||
Eluna** E;
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#ifndef _ELUNA_UTIL_H
|
||||
#define _ELUNA_UTIL_H
|
||||
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include "Common.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "ObjectGuid.h"
|
||||
@@ -28,8 +30,6 @@
|
||||
#ifdef USING_BOOST
|
||||
#include <boost/thread/locks.hpp>
|
||||
#include <boost/thread/shared_mutex.hpp>
|
||||
#else
|
||||
#include <ace/Recursive_Thread_Mutex.h>
|
||||
#endif
|
||||
|
||||
#ifdef TRINITY
|
||||
@@ -50,15 +50,6 @@ typedef QueryNamedResult ElunaQuery;
|
||||
#define GetTemplate GetProto
|
||||
#endif
|
||||
|
||||
#ifndef UNORDERED_MAP
|
||||
#include <unordered_map>
|
||||
#define UNORDERED_MAP std::unordered_map
|
||||
#endif
|
||||
#ifndef UNORDERED_SET
|
||||
#include <unordered_set>
|
||||
#define UNORDERED_SET std::unordered_set
|
||||
#endif
|
||||
|
||||
#ifndef MAKE_NEW_GUID
|
||||
#define MAKE_NEW_GUID(l, e, h) ObjectGuid(h, e, l)
|
||||
#endif
|
||||
@@ -132,11 +123,11 @@ namespace ElunaUtil
|
||||
public:
|
||||
|
||||
#ifdef USING_BOOST
|
||||
typedef boost::recursive_mutex LockType;
|
||||
typedef boost::shared_lock<boost::shared_mutex> ReadGuard;
|
||||
typedef boost::unique_lock<boost::shared_mutex> WriteGuard;
|
||||
typedef boost::shared_mutex LockType;
|
||||
typedef boost::shared_lock<LockType> ReadGuard;
|
||||
typedef boost::unique_lock<LockType> WriteGuard;
|
||||
#else
|
||||
typedef ACE_Recursive_Thread_Mutex LockType;
|
||||
typedef ACE_RW_Thread_Mutex LockType;
|
||||
typedef ACE_Read_Guard<LockType> ReadGuard;
|
||||
typedef ACE_Write_Guard<LockType> WriteGuard;
|
||||
#endif
|
||||
|
||||
@@ -4,119 +4,76 @@
|
||||
* Please see the included DOCS/LICENSE.md for more information
|
||||
*/
|
||||
|
||||
#ifndef _GAMEOBJECT_HOOKS_H
|
||||
#define _GAMEOBJECT_HOOKS_H
|
||||
|
||||
#include "Hooks.h"
|
||||
#include "HookHelpers.h"
|
||||
#include "LuaEngine.h"
|
||||
#include "ElunaBinding.h"
|
||||
#include "BindingMap.h"
|
||||
#include "ElunaIncludes.h"
|
||||
#include "ElunaEventMgr.h"
|
||||
#include "ElunaTemplate.h"
|
||||
|
||||
using namespace Hooks;
|
||||
|
||||
#define START_HOOK(EVENT, ENTRY) \
|
||||
if (!IsEnabled())\
|
||||
return;\
|
||||
auto key = EntryKey<GameObjectEvents>(EVENT, ENTRY);\
|
||||
if (!GameObjectEventBindings->HasBindingsFor(key))\
|
||||
return;\
|
||||
LOCK_ELUNA
|
||||
|
||||
#define START_HOOK_WITH_RETVAL(EVENT, ENTRY, RETVAL) \
|
||||
if (!IsEnabled())\
|
||||
return RETVAL;\
|
||||
auto key = EntryKey<GameObjectEvents>(EVENT, ENTRY);\
|
||||
if (!GameObjectEventBindings->HasBindingsFor(key))\
|
||||
return RETVAL;\
|
||||
LOCK_ELUNA
|
||||
|
||||
bool Eluna::OnDummyEffect(Unit* pCaster, uint32 spellId, SpellEffIndex effIndex, GameObject* pTarget)
|
||||
{
|
||||
if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_DUMMY_EFFECT, pTarget->GetEntry()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(GAMEOBJECT_EVENT_ON_DUMMY_EFFECT, pTarget->GetEntry(), false);
|
||||
Push(pCaster);
|
||||
Push(spellId);
|
||||
Push(effIndex);
|
||||
Push(pTarget);
|
||||
return CallAllFunctionsBool(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_DUMMY_EFFECT, pTarget->GetEntry());
|
||||
}
|
||||
|
||||
bool Eluna::OnGossipHello(Player* pPlayer, GameObject* pGameObject)
|
||||
{
|
||||
if (!GameObjectGossipBindings->HasEvents(GOSSIP_EVENT_ON_HELLO, pGameObject->GetEntry()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
pPlayer->PlayerTalkClass->ClearMenus();
|
||||
Push(pPlayer);
|
||||
Push(pGameObject);
|
||||
return CallAllFunctionsBool(GameObjectGossipBindings, GOSSIP_EVENT_ON_HELLO, pGameObject->GetEntry(), true);
|
||||
}
|
||||
|
||||
bool Eluna::OnGossipSelect(Player* pPlayer, GameObject* pGameObject, uint32 sender, uint32 action)
|
||||
{
|
||||
if (!GameObjectGossipBindings->HasEvents(GOSSIP_EVENT_ON_SELECT, pGameObject->GetEntry()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
pPlayer->PlayerTalkClass->ClearMenus();
|
||||
Push(pPlayer);
|
||||
Push(pGameObject);
|
||||
Push(sender);
|
||||
Push(action);
|
||||
return CallAllFunctionsBool(GameObjectGossipBindings, GOSSIP_EVENT_ON_SELECT, pGameObject->GetEntry(), true);
|
||||
}
|
||||
|
||||
bool Eluna::OnGossipSelectCode(Player* pPlayer, GameObject* pGameObject, uint32 sender, uint32 action, const char* code)
|
||||
{
|
||||
if (!GameObjectGossipBindings->HasEvents(GOSSIP_EVENT_ON_SELECT, pGameObject->GetEntry()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
pPlayer->PlayerTalkClass->ClearMenus();
|
||||
Push(pPlayer);
|
||||
Push(pGameObject);
|
||||
Push(sender);
|
||||
Push(action);
|
||||
Push(code);
|
||||
return CallAllFunctionsBool(GameObjectGossipBindings, GOSSIP_EVENT_ON_SELECT, pGameObject->GetEntry(), true);
|
||||
}
|
||||
|
||||
bool Eluna::OnQuestAccept(Player* pPlayer, GameObject* pGameObject, Quest const* pQuest)
|
||||
{
|
||||
if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_QUEST_ACCEPT, pGameObject->GetEntry()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
Push(pPlayer);
|
||||
Push(pGameObject);
|
||||
Push(pQuest);
|
||||
return CallAllFunctionsBool(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_QUEST_ACCEPT, pGameObject->GetEntry());
|
||||
return CallAllFunctionsBool(GameObjectEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::UpdateAI(GameObject* pGameObject, uint32 diff)
|
||||
{
|
||||
if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_AIUPDATE, pGameObject->GetEntry()))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(GAMEOBJECT_EVENT_ON_AIUPDATE, pGameObject->GetEntry());
|
||||
pGameObject->elunaEvents->Update(diff);
|
||||
Push(pGameObject);
|
||||
Push(diff);
|
||||
CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_AIUPDATE, pGameObject->GetEntry());
|
||||
CallAllFunctions(GameObjectEventBindings, key);
|
||||
}
|
||||
|
||||
bool Eluna::OnQuestAccept(Player* pPlayer, GameObject* pGameObject, Quest const* pQuest)
|
||||
{
|
||||
START_HOOK_WITH_RETVAL(GAMEOBJECT_EVENT_ON_QUEST_ACCEPT, pGameObject->GetEntry(), false);
|
||||
Push(pPlayer);
|
||||
Push(pGameObject);
|
||||
Push(pQuest);
|
||||
return CallAllFunctionsBool(GameObjectEventBindings, key);
|
||||
}
|
||||
|
||||
bool Eluna::OnQuestReward(Player* pPlayer, GameObject* pGameObject, Quest const* pQuest, uint32 opt)
|
||||
{
|
||||
if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_QUEST_REWARD, pGameObject->GetEntry()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(GAMEOBJECT_EVENT_ON_QUEST_REWARD, pGameObject->GetEntry(), false);
|
||||
Push(pPlayer);
|
||||
Push(pGameObject);
|
||||
Push(pQuest);
|
||||
Push(opt);
|
||||
return CallAllFunctionsBool(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_QUEST_REWARD, pGameObject->GetEntry());
|
||||
return CallAllFunctionsBool(GameObjectEventBindings, key);
|
||||
}
|
||||
|
||||
uint32 Eluna::GetDialogStatus(Player* pPlayer, GameObject* pGameObject)
|
||||
{
|
||||
if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_DIALOG_STATUS, pGameObject->GetEntry()))
|
||||
return DIALOG_STATUS_SCRIPTED_NO_STATUS;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(GAMEOBJECT_EVENT_ON_DIALOG_STATUS, pGameObject->GetEntry(), false);
|
||||
Push(pPlayer);
|
||||
Push(pGameObject);
|
||||
CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_DIALOG_STATUS, pGameObject->GetEntry());
|
||||
CallAllFunctions(GameObjectEventBindings, key);
|
||||
return DIALOG_STATUS_SCRIPTED_NO_STATUS; // DIALOG_STATUS_UNDEFINED
|
||||
}
|
||||
|
||||
@@ -124,89 +81,63 @@ uint32 Eluna::GetDialogStatus(Player* pPlayer, GameObject* pGameObject)
|
||||
#ifndef TBC
|
||||
void Eluna::OnDestroyed(GameObject* pGameObject, Player* pPlayer)
|
||||
{
|
||||
if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_DESTROYED, pGameObject->GetEntry()))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(GAMEOBJECT_EVENT_ON_DESTROYED, pGameObject->GetEntry());
|
||||
Push(pGameObject);
|
||||
Push(pPlayer);
|
||||
CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_DESTROYED, pGameObject->GetEntry());
|
||||
CallAllFunctions(GameObjectEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnDamaged(GameObject* pGameObject, Player* pPlayer)
|
||||
{
|
||||
if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_DAMAGED, pGameObject->GetEntry()))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(GAMEOBJECT_EVENT_ON_DAMAGED, pGameObject->GetEntry());
|
||||
Push(pGameObject);
|
||||
Push(pPlayer);
|
||||
CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_DAMAGED, pGameObject->GetEntry());
|
||||
CallAllFunctions(GameObjectEventBindings, key);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void Eluna::OnLootStateChanged(GameObject* pGameObject, uint32 state)
|
||||
{
|
||||
if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_LOOT_STATE_CHANGE, pGameObject->GetEntry()))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(GAMEOBJECT_EVENT_ON_LOOT_STATE_CHANGE, pGameObject->GetEntry());
|
||||
Push(pGameObject);
|
||||
Push(state);
|
||||
CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_LOOT_STATE_CHANGE, pGameObject->GetEntry());
|
||||
CallAllFunctions(GameObjectEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnGameObjectStateChanged(GameObject* pGameObject, uint32 state)
|
||||
{
|
||||
if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_GO_STATE_CHANGED, pGameObject->GetEntry()))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(GAMEOBJECT_EVENT_ON_GO_STATE_CHANGED, pGameObject->GetEntry());
|
||||
Push(pGameObject);
|
||||
Push(state);
|
||||
CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_GO_STATE_CHANGED, pGameObject->GetEntry());
|
||||
CallAllFunctions(GameObjectEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnSpawn(GameObject* gameobject)
|
||||
void Eluna::OnSpawn(GameObject* pGameObject)
|
||||
{
|
||||
if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_SPAWN, gameobject->GetEntry()))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
Push(gameobject);
|
||||
CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_SPAWN, gameobject->GetEntry());
|
||||
START_HOOK(GAMEOBJECT_EVENT_ON_SPAWN, pGameObject->GetEntry());
|
||||
Push(pGameObject);
|
||||
CallAllFunctions(GameObjectEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnAddToWorld(GameObject* gameobject)
|
||||
void Eluna::OnAddToWorld(GameObject* pGameObject)
|
||||
{
|
||||
if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_ADD, gameobject->GetEntry()))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
Push(gameobject);
|
||||
CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_ADD, gameobject->GetEntry());
|
||||
START_HOOK(GAMEOBJECT_EVENT_ON_ADD, pGameObject->GetEntry());
|
||||
Push(pGameObject);
|
||||
CallAllFunctions(GameObjectEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnRemoveFromWorld(GameObject* gameobject)
|
||||
void Eluna::OnRemoveFromWorld(GameObject* pGameObject)
|
||||
{
|
||||
if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_REMOVE, gameobject->GetEntry()))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
Push(gameobject);
|
||||
CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_REMOVE, gameobject->GetEntry());
|
||||
START_HOOK(GAMEOBJECT_EVENT_ON_REMOVE, pGameObject->GetEntry());
|
||||
Push(pGameObject);
|
||||
CallAllFunctions(GameObjectEventBindings, key);
|
||||
}
|
||||
|
||||
bool Eluna::OnGameObjectUse(Player* pPlayer, GameObject* pGameObject)
|
||||
{
|
||||
if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_USE, pGameObject->GetEntry()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(GAMEOBJECT_EVENT_ON_USE, pGameObject->GetEntry(), false);
|
||||
Push(pGameObject);
|
||||
Push(pPlayer);
|
||||
return CallAllFunctionsBool(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_USE, pGameObject->GetEntry());
|
||||
return CallAllFunctionsBool(GameObjectEventBindings, key);
|
||||
}
|
||||
|
||||
#endif // _GAMEOBJECT_HOOKS_H
|
||||
|
||||
360
GlobalMethods.h
360
GlobalMethods.h
@@ -7,7 +7,7 @@
|
||||
#ifndef GLOBALMETHODS_H
|
||||
#define GLOBALMETHODS_H
|
||||
|
||||
#include "ElunaBinding.h"
|
||||
#include "BindingMap.h"
|
||||
|
||||
/***
|
||||
* These functions can be used anywhere at any time, including at start-up.
|
||||
@@ -503,18 +503,11 @@ namespace LuaGlobalFunctions
|
||||
uint32 ev = Eluna::CHECKVAL<uint32>(L, 2);
|
||||
luaL_checktype(L, 3, LUA_TFUNCTION);
|
||||
uint32 shots = Eluna::CHECKVAL<uint32>(L, 4, 0);
|
||||
bool returnCallback = Eluna::CHECKVAL<bool>(L, 5, false);
|
||||
|
||||
if (shots > 0 && returnCallback)
|
||||
{
|
||||
luaL_argerror(L, 5, "cannot return a callback if shots is > 0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
lua_pushvalue(L, 3);
|
||||
int functionRef = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
if (functionRef >= 0)
|
||||
return E->Register(L, regtype, entry, 0, 0, ev, functionRef, shots, returnCallback);
|
||||
return E->Register(L, regtype, entry, 0, 0, ev, functionRef, shots);
|
||||
else
|
||||
luaL_argerror(L, 3, "unable to make a ref to function");
|
||||
return 0;
|
||||
@@ -525,18 +518,11 @@ namespace LuaGlobalFunctions
|
||||
uint32 ev = Eluna::CHECKVAL<uint32>(L, 1);
|
||||
luaL_checktype(L, 2, LUA_TFUNCTION);
|
||||
uint32 shots = Eluna::CHECKVAL<uint32>(L, 3, 0);
|
||||
bool returnCallback = Eluna::CHECKVAL<bool>(L, 4, false);
|
||||
|
||||
if (shots > 0 && returnCallback)
|
||||
{
|
||||
luaL_argerror(L, 5, "cannot return a callback if shots is > 0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
lua_pushvalue(L, 2);
|
||||
int functionRef = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
if (functionRef >= 0)
|
||||
return E->Register(L, regtype, 0, 0, 0, ev, functionRef, shots, returnCallback);
|
||||
return E->Register(L, regtype, 0, 0, 0, ev, functionRef, shots);
|
||||
else
|
||||
luaL_argerror(L, 2, "unable to make a ref to function");
|
||||
return 0;
|
||||
@@ -549,18 +535,11 @@ namespace LuaGlobalFunctions
|
||||
uint32 ev = Eluna::CHECKVAL<uint32>(L, 3);
|
||||
luaL_checktype(L, 4, LUA_TFUNCTION);
|
||||
uint32 shots = Eluna::CHECKVAL<uint32>(L, 5, 0);
|
||||
bool returnCallback = Eluna::CHECKVAL<bool>(L, 6, false);
|
||||
|
||||
if (shots > 0 && returnCallback)
|
||||
{
|
||||
luaL_argerror(L, 5, "cannot return a callback if shots is > 0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
lua_pushvalue(L, 4);
|
||||
int functionRef = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
if (functionRef >= 0)
|
||||
return E->Register(L, regtype, 0, guid, instanceId, ev, functionRef, shots, returnCallback);
|
||||
return E->Register(L, regtype, 0, guid, instanceId, ev, functionRef, shots);
|
||||
else
|
||||
luaL_argerror(L, 4, "unable to make a ref to function");
|
||||
return 0;
|
||||
@@ -569,16 +548,6 @@ namespace LuaGlobalFunctions
|
||||
/**
|
||||
* Registers a server event handler.
|
||||
*
|
||||
* If `return_callback` is `true`, a function will be returned which
|
||||
* cancels this event binding.
|
||||
*
|
||||
* (The returned function is the **only** way to cancel the bindings;
|
||||
* `shots` must be `0` (e.g. the binding will never expire), and
|
||||
* [Global:ClearServerEvents] will skip this binding.)
|
||||
*
|
||||
* If `return_callback` is `false`, nothing is returned, and `shots` and
|
||||
* [Global:ClearServerEvents] work as normal.
|
||||
*
|
||||
* enum ServerEvents
|
||||
* {
|
||||
* // Server
|
||||
@@ -634,14 +603,12 @@ namespace LuaGlobalFunctions
|
||||
* SERVER_EVENT_COUNT
|
||||
* };
|
||||
*
|
||||
* @proto (event, function)
|
||||
* @proto (event, function, shots)
|
||||
* @proto cancel = (event, function, 0, true)
|
||||
* @proto cancel = (event, function)
|
||||
* @proto cancel = (event, function, shots)
|
||||
*
|
||||
* @param uint32 event : server event ID, refer to ServerEvents above
|
||||
* @param function function : function that will be called when the event occurs
|
||||
* @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function"
|
||||
* @param bool return_callback = false
|
||||
*
|
||||
* @return function cancel : a function that cancels the binding when called
|
||||
*/
|
||||
@@ -653,16 +620,6 @@ namespace LuaGlobalFunctions
|
||||
/**
|
||||
* Registers a [Player] event handler.
|
||||
*
|
||||
* If `return_callback` is `true`, a function will be returned which
|
||||
* cancels this event binding.
|
||||
*
|
||||
* (The returned function is the **only** way to cancel the bindings;
|
||||
* `shots` must be `0` (e.g. the binding will never expire), and
|
||||
* [Global:ClearPlayerEvents] will skip this binding.)
|
||||
*
|
||||
* If `return_callback` is `false`, nothing is returned, and `shots` and
|
||||
* [Global:ClearPlayerEvents] work as normal.
|
||||
*
|
||||
* <pre>
|
||||
* enum PlayerEvents
|
||||
* {
|
||||
@@ -715,14 +672,12 @@ namespace LuaGlobalFunctions
|
||||
* };
|
||||
* </pre>
|
||||
*
|
||||
* @proto (event, function)
|
||||
* @proto (event, function, shots)
|
||||
* @proto cancel = (event, function, 0, true)
|
||||
* @proto cancel = (event, function)
|
||||
* @proto cancel = (event, function, shots)
|
||||
*
|
||||
* @param uint32 event : [Player] event Id, refer to PlayerEvents 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"
|
||||
* @param bool return_callback = false
|
||||
*
|
||||
* @return function cancel : a function that cancels the binding when called
|
||||
*/
|
||||
@@ -734,16 +689,6 @@ namespace LuaGlobalFunctions
|
||||
/**
|
||||
* Registers a [Guild] event handler.
|
||||
*
|
||||
* If `return_callback` is `true`, a function will be returned which
|
||||
* cancels this event binding.
|
||||
*
|
||||
* (The returned function is the **only** way to cancel the bindings;
|
||||
* `shots` must be `0` (e.g. the binding will never expire), and
|
||||
* [Global:ClearGuildEvents] will skip this binding.)
|
||||
*
|
||||
* If `return_callback` is `false`, nothing is returned, and `shots` and
|
||||
* [Global:ClearGuildEvents] work as normal.
|
||||
*
|
||||
* <pre>
|
||||
* enum GuildEvents
|
||||
* {
|
||||
@@ -764,14 +709,12 @@ namespace LuaGlobalFunctions
|
||||
* };
|
||||
* </pre>
|
||||
*
|
||||
* @proto (event, function)
|
||||
* @proto (event, function, shots)
|
||||
* @proto cancel = (event, function, 0, true)
|
||||
* @proto cancel = (event, function)
|
||||
* @proto cancel = (event, function, shots)
|
||||
*
|
||||
* @param uint32 event : [Guild] event Id, refer to GuildEvents 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"
|
||||
* @param bool return_callback = false
|
||||
*
|
||||
* @return function cancel : a function that cancels the binding when called
|
||||
*/
|
||||
@@ -783,16 +726,6 @@ namespace LuaGlobalFunctions
|
||||
/**
|
||||
* Registers a [Group] event handler.
|
||||
*
|
||||
* If `return_callback` is `true`, a function will be returned which
|
||||
* cancels this event binding.
|
||||
*
|
||||
* (The returned function is the **only** way to cancel the bindings;
|
||||
* `shots` must be `0` (e.g. the binding will never expire), and
|
||||
* [Global:ClearGroupEvents] will skip this binding.)
|
||||
*
|
||||
* If `return_callback` is `false`, nothing is returned, and `shots` and
|
||||
* [Global:ClearGroupEvents] work as normal.
|
||||
*
|
||||
* <pre>
|
||||
* enum GroupEvents
|
||||
* {
|
||||
@@ -808,14 +741,12 @@ namespace LuaGlobalFunctions
|
||||
* };
|
||||
* </pre>
|
||||
*
|
||||
* @proto (event, function)
|
||||
* @proto (event, function, shots)
|
||||
* @proto cancel = (event, function, 0, true)
|
||||
* @proto cancel = (event, function)
|
||||
* @proto cancel = (event, function, shots)
|
||||
*
|
||||
* @param uint32 event : [Group] event Id, refer to GroupEvents 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"
|
||||
* @param bool return_callback = false
|
||||
*
|
||||
* @return function cancel : a function that cancels the binding when called
|
||||
*/
|
||||
@@ -828,16 +759,6 @@ namespace LuaGlobalFunctions
|
||||
/**
|
||||
* Registers a [BattleGround] event handler.
|
||||
*
|
||||
* If `return_callback` is `true`, a function will be returned which
|
||||
* cancels this event binding.
|
||||
*
|
||||
* (The returned function is the **only** way to cancel the bindings;
|
||||
* `shots` must be `0` (e.g. the binding will never expire), and
|
||||
* [Global:ClearBattleGroundEvents] will skip this binding.)
|
||||
*
|
||||
* If `return_callback` is `false`, nothing is returned, and `shots` and
|
||||
* [Global:ClearBattleGroundEvents] work as normal.
|
||||
*
|
||||
* <pre>
|
||||
* enum BGEvents
|
||||
* {
|
||||
@@ -849,14 +770,12 @@ namespace LuaGlobalFunctions
|
||||
* };
|
||||
* </pre>
|
||||
*
|
||||
* @proto (event, function)
|
||||
* @proto (event, function, shots)
|
||||
* @proto cancel = (event, function, 0, true)
|
||||
* @proto cancel = (event, function)
|
||||
* @proto cancel = (event, function, shots)
|
||||
*
|
||||
* @param uint32 event : [BattleGround] event Id, refer to BGEvents 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"
|
||||
* @param bool return_callback = false
|
||||
*
|
||||
* @return function cancel : a function that cancels the binding when called
|
||||
*/
|
||||
@@ -868,16 +787,6 @@ namespace LuaGlobalFunctions
|
||||
/**
|
||||
* Registers a [WorldPacket] event handler.
|
||||
*
|
||||
* If `return_callback` is `true`, a function will be returned which
|
||||
* cancels this event binding.
|
||||
*
|
||||
* (The returned function is the **only** way to cancel the bindings;
|
||||
* `shots` must be `0` (e.g. the binding will never expire), and
|
||||
* [Global:ClearPacketEvents] will skip this binding.)
|
||||
*
|
||||
* If `return_callback` is `false`, nothing is returned, and `shots` and
|
||||
* [Global:ClearPacketEvents] work as normal.
|
||||
*
|
||||
* <pre>
|
||||
* enum PacketEvents
|
||||
* {
|
||||
@@ -889,15 +798,13 @@ namespace LuaGlobalFunctions
|
||||
* };
|
||||
* </pre>
|
||||
*
|
||||
* @proto (entry, event, function)
|
||||
* @proto (entry, event, function, shots)
|
||||
* @proto cancel = (entry, event, function, 0, true)
|
||||
* @proto cancel = (entry, event, function)
|
||||
* @proto cancel = (entry, event, function, shots)
|
||||
*
|
||||
* @param uint32 entry : opcode
|
||||
* @param uint32 event : packet event Id, refer to PacketEvents 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"
|
||||
* @param bool return_callback = false
|
||||
*
|
||||
* @return function cancel : a function that cancels the binding when called
|
||||
*/
|
||||
@@ -909,16 +816,6 @@ namespace LuaGlobalFunctions
|
||||
/**
|
||||
* Registers a [Creature] gossip event handler.
|
||||
*
|
||||
* If `return_callback` is `true`, a function will be returned which
|
||||
* cancels this event binding.
|
||||
*
|
||||
* (The returned function is the **only** way to cancel the bindings;
|
||||
* `shots` must be `0` (e.g. the binding will never expire), and
|
||||
* [Global:ClearCreatureGossipEvents] will skip this binding.)
|
||||
*
|
||||
* If `return_callback` is `false`, nothing is returned, and `shots` and
|
||||
* [Global:ClearCreatureGossipEvents] work as normal.
|
||||
*
|
||||
* <pre>
|
||||
* enum GossipEvents
|
||||
* {
|
||||
@@ -928,15 +825,13 @@ namespace LuaGlobalFunctions
|
||||
* };
|
||||
* </pre>
|
||||
*
|
||||
* @proto (menu_id, event, function)
|
||||
* @proto (menu_id, event, function, shots)
|
||||
* @proto cancel = (menu_id, event, function, 0, true)
|
||||
* @proto cancel = (menu_id, event, function)
|
||||
* @proto cancel = (menu_id, event, function, shots)
|
||||
*
|
||||
* @param uint32 menu_id : [Creature] entry Id
|
||||
* @param uint32 event : [Creature] gossip event Id, refer to GossipEvents 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"
|
||||
* @param bool return_callback = false
|
||||
*
|
||||
* @return function cancel : a function that cancels the binding when called
|
||||
*/
|
||||
@@ -948,16 +843,6 @@ namespace LuaGlobalFunctions
|
||||
/**
|
||||
* Registers a [GameObject] gossip event handler.
|
||||
*
|
||||
* If `return_callback` is `true`, a function will be returned which
|
||||
* cancels this event binding.
|
||||
*
|
||||
* (The returned function is the **only** way to cancel the bindings;
|
||||
* `shots` must be `0` (e.g. the binding will never expire), and
|
||||
* [Global:ClearGameObjectGossipEvents] will skip this binding.)
|
||||
*
|
||||
* If `return_callback` is `false`, nothing is returned, and `shots` and
|
||||
* [Global:ClearGameObjectGossipEvents] work as normal.
|
||||
*
|
||||
* <pre>
|
||||
* enum GossipEvents
|
||||
* {
|
||||
@@ -967,15 +852,13 @@ namespace LuaGlobalFunctions
|
||||
* };
|
||||
* </pre>
|
||||
*
|
||||
* @proto (menu_id, event, function)
|
||||
* @proto (menu_id, event, function, shots)
|
||||
* @proto cancel = (menu_id, event, function, 0, true)
|
||||
* @proto cancel = (menu_id, event, function)
|
||||
* @proto cancel = (menu_id, event, function, shots)
|
||||
*
|
||||
* @param uint32 menu_id : [GameObject] entry Id
|
||||
* @param uint32 event : [GameObject] gossip event Id, refer to GossipEvents 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"
|
||||
* @param bool return_callback = false
|
||||
*
|
||||
* @return function cancel : a function that cancels the binding when called
|
||||
*/
|
||||
@@ -987,16 +870,6 @@ namespace LuaGlobalFunctions
|
||||
/**
|
||||
* Registers an [Item] event handler.
|
||||
*
|
||||
* If `return_callback` is `true`, a function will be returned which
|
||||
* cancels this event binding.
|
||||
*
|
||||
* (The returned function is the **only** way to cancel the bindings;
|
||||
* `shots` must be `0` (e.g. the binding will never expire), and
|
||||
* [Global:ClearItemEvents] will skip this binding.)
|
||||
*
|
||||
* If `return_callback` is `false`, nothing is returned, and `shots` and
|
||||
* [Global:ClearItemEvents] work as normal.
|
||||
*
|
||||
* <pre>
|
||||
* enum ItemEvents
|
||||
* {
|
||||
@@ -1009,15 +882,13 @@ namespace LuaGlobalFunctions
|
||||
* };
|
||||
* </pre>
|
||||
*
|
||||
* @proto (entry, event, function)
|
||||
* @proto (entry, event, function, shots)
|
||||
* @proto cancel = (entry, event, function, 0, true)
|
||||
* @proto cancel = (entry, event, function)
|
||||
* @proto cancel = (entry, event, function, shots)
|
||||
*
|
||||
* @param uint32 entry : [Item] entry Id
|
||||
* @param uint32 event : [Item] event Id, refer to ItemEvents 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"
|
||||
* @param bool return_callback = false
|
||||
*
|
||||
* @return function cancel : a function that cancels the binding when called
|
||||
*/
|
||||
@@ -1029,16 +900,6 @@ namespace LuaGlobalFunctions
|
||||
/**
|
||||
* Registers an [Item] gossip event handler.
|
||||
*
|
||||
* If `return_callback` is `true`, a function will be returned which
|
||||
* cancels this event binding.
|
||||
*
|
||||
* (The returned function is the **only** way to cancel the bindings;
|
||||
* `shots` must be `0` (e.g. the binding will never expire), and
|
||||
* [Global:ClearItemGossipEvents] will skip this binding.)
|
||||
*
|
||||
* If `return_callback` is `false`, nothing is returned, and `shots` and
|
||||
* [Global:ClearItemGossipEvents] work as normal.
|
||||
*
|
||||
* <pre>
|
||||
* enum GossipEvents
|
||||
* {
|
||||
@@ -1048,15 +909,13 @@ namespace LuaGlobalFunctions
|
||||
* };
|
||||
* </pre>
|
||||
*
|
||||
* @proto (entry, event, function)
|
||||
* @proto (entry, event, function, shots)
|
||||
* @proto cancel = (entry, event, function, 0, true)
|
||||
* @proto cancel = (entry, event, function)
|
||||
* @proto cancel = (entry, event, function, shots)
|
||||
*
|
||||
* @param uint32 entry : [Item] entry Id
|
||||
* @param uint32 event : [Item] gossip event Id, refer to GossipEvents 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"
|
||||
* @param bool return_callback = false
|
||||
*
|
||||
* @return function cancel : a function that cancels the binding when called
|
||||
*/
|
||||
@@ -1068,16 +927,6 @@ namespace LuaGlobalFunctions
|
||||
/**
|
||||
* Registers a [Player] gossip event handler.
|
||||
*
|
||||
* If `return_callback` is `true`, a function will be returned which
|
||||
* cancels this event binding.
|
||||
*
|
||||
* (The returned function is the **only** way to cancel the bindings;
|
||||
* `shots` must be `0` (e.g. the binding will never expire), and
|
||||
* [Global:ClearPlayerGossipEvents] will skip this binding.)
|
||||
*
|
||||
* If `return_callback` is `false`, nothing is returned, and `shots` and
|
||||
* [Global:ClearPlayerGossipEvents] work as normal.
|
||||
*
|
||||
* <pre>
|
||||
* enum GossipEvents
|
||||
* {
|
||||
@@ -1087,15 +936,13 @@ namespace LuaGlobalFunctions
|
||||
* };
|
||||
* </pre>
|
||||
*
|
||||
* @proto (menu_id, event, function)
|
||||
* @proto (menu_id, event, function, shots)
|
||||
* @proto cancel = (menu_id, event, function, 0, true)
|
||||
* @proto cancel = (menu_id, event, function)
|
||||
* @proto cancel = (menu_id, event, function, shots)
|
||||
*
|
||||
* @param uint32 menu_id : [Player] gossip menu Id
|
||||
* @param uint32 event : [Player] gossip event Id, refer to GossipEvents 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"
|
||||
* @param bool return_callback = false
|
||||
*
|
||||
* @return function cancel : a function that cancels the binding when called
|
||||
*/
|
||||
@@ -1107,16 +954,6 @@ namespace LuaGlobalFunctions
|
||||
/**
|
||||
* Registers a [Creature] event handler.
|
||||
*
|
||||
* If `return_callback` is `true`, a function will be returned which
|
||||
* cancels this event binding.
|
||||
*
|
||||
* (The returned function is the **only** way to cancel the bindings;
|
||||
* `shots` must be `0` (e.g. the binding will never expire), and
|
||||
* [Global:ClearCreatureEvents] will skip this binding.)
|
||||
*
|
||||
* If `return_callback` is `false`, nothing is returned, and `shots` and
|
||||
* [Global:ClearCreatureEvents] work as normal.
|
||||
*
|
||||
* <pre>
|
||||
* enum CreatureEvents
|
||||
* {
|
||||
@@ -1161,15 +998,13 @@ namespace LuaGlobalFunctions
|
||||
* };
|
||||
* </pre>
|
||||
*
|
||||
* @proto (entry, event, function)
|
||||
* @proto (entry, event, function, shots)
|
||||
* @proto cancel = (entry, event, function, 0, true)
|
||||
* @proto cancel = (entry, event, function)
|
||||
* @proto cancel = (entry, event, function, shots)
|
||||
*
|
||||
* @param uint32 entry : the ID of one or more [Creature]s
|
||||
* @param uint32 event : refer to CreatureEvents above
|
||||
* @param function function : function that will be called when the event occurs
|
||||
* @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function"
|
||||
* @param bool return_callback = false
|
||||
*
|
||||
* @return function cancel : a function that cancels the binding when called
|
||||
*/
|
||||
@@ -1181,16 +1016,6 @@ namespace LuaGlobalFunctions
|
||||
/**
|
||||
* Registers a [Creature] event handler for a *single* [Creature].
|
||||
*
|
||||
* If `return_callback` is `true`, a function will be returned which
|
||||
* cancels this event binding.
|
||||
*
|
||||
* (The returned function is the **only** way to cancel the bindings;
|
||||
* `shots` must be `0` (e.g. the binding will never expire), and
|
||||
* [Global:ClearUniqueCreatureEvents] will skip this binding.)
|
||||
*
|
||||
* If `return_callback` is `false`, nothing is returned, and `shots` and
|
||||
* [Global:ClearUniqueCreatureEvents] work as normal.
|
||||
*
|
||||
* <pre>
|
||||
* enum CreatureEvents
|
||||
* {
|
||||
@@ -1235,16 +1060,14 @@ namespace LuaGlobalFunctions
|
||||
* };
|
||||
* </pre>
|
||||
*
|
||||
* @proto (guid, instance_id, event, function)
|
||||
* @proto (guid, instance_id, event, function, shots)
|
||||
* @proto cancel = (guid, instance_id, event, function, 0, true)
|
||||
* @proto cancel = (guid, instance_id, event, function)
|
||||
* @proto cancel = (guid, instance_id, event, function, shots)
|
||||
*
|
||||
* @param uint64 guid : the GUID of a single [Creature]
|
||||
* @param uint32 instance_id : the instance ID of a single [Creature]
|
||||
* @param uint32 event : refer to CreatureEvents above
|
||||
* @param function function : function that will be called when the event occurs
|
||||
* @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function"
|
||||
* @param bool return_callback = false
|
||||
*
|
||||
* @return function cancel : a function that cancels the binding when called
|
||||
*/
|
||||
@@ -1256,16 +1079,6 @@ namespace LuaGlobalFunctions
|
||||
/**
|
||||
* Registers a [GameObject] event handler.
|
||||
*
|
||||
* If `return_callback` is `true`, a function will be returned which
|
||||
* cancels this event binding.
|
||||
*
|
||||
* (The returned function is the **only** way to cancel the bindings;
|
||||
* `shots` must be `0` (e.g. the binding will never expire), and
|
||||
* [Global:ClearGameObjectEvents] will skip this binding.)
|
||||
*
|
||||
* If `return_callback` is `false`, nothing is returned, and `shots` and
|
||||
* [Global:ClearGameObjectEvents] work as normal.
|
||||
*
|
||||
* <pre>
|
||||
* enum GameObjectEvents
|
||||
* {
|
||||
@@ -1286,15 +1099,13 @@ namespace LuaGlobalFunctions
|
||||
* };
|
||||
* </pre>
|
||||
*
|
||||
* @proto (entry, event, function)
|
||||
* @proto (entry, event, function, shots)
|
||||
* @proto cancel = (entry, event, function, 0, true)
|
||||
* @proto cancel = (entry, event, function)
|
||||
* @proto cancel = (entry, event, function, shots)
|
||||
*
|
||||
* @param uint32 entry : [GameObject] entry Id
|
||||
* @param uint32 event : [GameObject] event Id, refer to GameObjectEvents 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"
|
||||
* @param bool return_callback = false
|
||||
*
|
||||
* @return function cancel : a function that cancels the binding when called
|
||||
*/
|
||||
@@ -2632,15 +2443,16 @@ namespace LuaGlobalFunctions
|
||||
*/
|
||||
int ClearBattleGroundEvents(Eluna* E, lua_State* L)
|
||||
{
|
||||
typedef EventKey<Hooks::BGEvents> Key;
|
||||
|
||||
if (lua_isnoneornil(L, 1))
|
||||
{
|
||||
for (uint32 i = Hooks::BG_EVENT_ON_START; i < Hooks::BG_EVENT_COUNT; ++i)
|
||||
E->BGEventBindings->Clear(i);
|
||||
E->BGEventBindings->Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 event_type = Eluna::CHECKVAL<uint32>(L, 1);
|
||||
E->BGEventBindings->Clear(event_type);
|
||||
E->BGEventBindings->Clear(Key((Hooks::BGEvents)event_type));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -2662,18 +2474,20 @@ namespace LuaGlobalFunctions
|
||||
*/
|
||||
int ClearCreatureEvents(Eluna* E, lua_State* L)
|
||||
{
|
||||
typedef EntryKey<Hooks::CreatureEvents> Key;
|
||||
|
||||
if (lua_isnoneornil(L, 2))
|
||||
{
|
||||
uint32 entry = Eluna::CHECKVAL<uint32>(L, 1);
|
||||
|
||||
for (uint32 i = Hooks::CREATURE_EVENT_ON_ENTER_COMBAT; i < Hooks::CREATURE_EVENT_COUNT; ++i)
|
||||
E->CreatureEventBindings->Clear(entry, i);
|
||||
for (uint32 i = 1; i < Hooks::CREATURE_EVENT_COUNT; ++i)
|
||||
E->CreatureEventBindings->Clear(Key((Hooks::CreatureEvents)i, entry));
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 entry = Eluna::CHECKVAL<uint32>(L, 1);
|
||||
uint32 event_type = Eluna::CHECKVAL<uint32>(L, 2);
|
||||
E->CreatureEventBindings->Clear(entry, event_type);
|
||||
E->CreatureEventBindings->Clear(Key((Hooks::CreatureEvents)event_type, entry));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -2696,20 +2510,22 @@ namespace LuaGlobalFunctions
|
||||
*/
|
||||
int ClearUniqueCreatureEvents(Eluna* E, lua_State* L)
|
||||
{
|
||||
typedef UniqueObjectKey<Hooks::CreatureEvents> Key;
|
||||
|
||||
if (lua_isnoneornil(L, 3))
|
||||
{
|
||||
uint64 guid = Eluna::CHECKVAL<uint64>(L, 1);
|
||||
uint32 instanceId = Eluna::CHECKVAL<uint32>(L, 2);
|
||||
|
||||
for (uint32 i = Hooks::CREATURE_EVENT_ON_ENTER_COMBAT; i < Hooks::CREATURE_EVENT_COUNT; ++i)
|
||||
E->CreatureUniqueBindings->Clear(guid, instanceId, i);
|
||||
for (uint32 i = 1; i < Hooks::CREATURE_EVENT_COUNT; ++i)
|
||||
E->CreatureUniqueBindings->Clear(Key((Hooks::CreatureEvents)i, guid, instanceId));
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64 guid = Eluna::CHECKVAL<uint64>(L, 1);
|
||||
uint32 instanceId = Eluna::CHECKVAL<uint32>(L, 2);
|
||||
uint32 event_type = Eluna::CHECKVAL<uint32>(L, 3);
|
||||
E->CreatureUniqueBindings->Clear(guid, instanceId, event_type);
|
||||
E->CreatureUniqueBindings->Clear(Key((Hooks::CreatureEvents)event_type, guid, instanceId));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -2731,18 +2547,20 @@ namespace LuaGlobalFunctions
|
||||
*/
|
||||
int ClearCreatureGossipEvents(Eluna* E, lua_State* L)
|
||||
{
|
||||
typedef EntryKey<Hooks::GossipEvents> Key;
|
||||
|
||||
if (lua_isnoneornil(L, 2))
|
||||
{
|
||||
uint32 entry = Eluna::CHECKVAL<uint32>(L, 1);
|
||||
|
||||
for (uint32 i = Hooks::GOSSIP_EVENT_ON_HELLO; i < Hooks::GOSSIP_EVENT_COUNT; ++i)
|
||||
E->CreatureGossipBindings->Clear(entry, i);
|
||||
for (uint32 i = 1; i < Hooks::GOSSIP_EVENT_COUNT; ++i)
|
||||
E->CreatureGossipBindings->Clear(Key((Hooks::GossipEvents)i, entry));
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 entry = Eluna::CHECKVAL<uint32>(L, 1);
|
||||
uint32 event_type = Eluna::CHECKVAL<uint32>(L, 2);
|
||||
E->CreatureGossipBindings->Clear(entry, event_type);
|
||||
E->CreatureGossipBindings->Clear(Key((Hooks::GossipEvents)event_type, entry));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -2764,18 +2582,20 @@ namespace LuaGlobalFunctions
|
||||
*/
|
||||
int ClearGameObjectEvents(Eluna* E, lua_State* L)
|
||||
{
|
||||
typedef EntryKey<Hooks::GameObjectEvents> Key;
|
||||
|
||||
if (lua_isnoneornil(L, 2))
|
||||
{
|
||||
uint32 entry = Eluna::CHECKVAL<uint32>(L, 1);
|
||||
|
||||
for (uint32 i = Hooks::GAMEOBJECT_EVENT_ON_AIUPDATE; i < Hooks::GAMEOBJECT_EVENT_COUNT; ++i)
|
||||
E->GameObjectEventBindings->Clear(entry, i);
|
||||
for (uint32 i = 1; i < Hooks::GAMEOBJECT_EVENT_COUNT; ++i)
|
||||
E->GameObjectEventBindings->Clear(Key((Hooks::GameObjectEvents)i, entry));
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 entry = Eluna::CHECKVAL<uint32>(L, 1);
|
||||
uint32 event_type = Eluna::CHECKVAL<uint32>(L, 2);
|
||||
E->GameObjectEventBindings->Clear(entry, event_type);
|
||||
E->GameObjectEventBindings->Clear(Key((Hooks::GameObjectEvents)event_type, entry));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -2797,18 +2617,20 @@ namespace LuaGlobalFunctions
|
||||
*/
|
||||
int ClearGameObjectGossipEvents(Eluna* E, lua_State* L)
|
||||
{
|
||||
typedef EntryKey<Hooks::GossipEvents> Key;
|
||||
|
||||
if (lua_isnoneornil(L, 2))
|
||||
{
|
||||
uint32 entry = Eluna::CHECKVAL<uint32>(L, 1);
|
||||
|
||||
for (uint32 i = Hooks::GOSSIP_EVENT_ON_HELLO; i < Hooks::GOSSIP_EVENT_COUNT; ++i)
|
||||
E->GameObjectGossipBindings->Clear(entry, i);
|
||||
for (uint32 i = 1; i < Hooks::GOSSIP_EVENT_COUNT; ++i)
|
||||
E->GameObjectGossipBindings->Clear(Key((Hooks::GossipEvents)i, entry));
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 entry = Eluna::CHECKVAL<uint32>(L, 1);
|
||||
uint32 event_type = Eluna::CHECKVAL<uint32>(L, 2);
|
||||
E->GameObjectGossipBindings->Clear(entry, event_type);
|
||||
E->GameObjectGossipBindings->Clear(Key((Hooks::GossipEvents)event_type, entry));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -2826,15 +2648,16 @@ namespace LuaGlobalFunctions
|
||||
*/
|
||||
int ClearGroupEvents(Eluna* E, lua_State* L)
|
||||
{
|
||||
typedef EventKey<Hooks::GroupEvents> Key;
|
||||
|
||||
if (lua_isnoneornil(L, 1))
|
||||
{
|
||||
for (uint32 i = Hooks::GROUP_EVENT_ON_MEMBER_ADD; i < Hooks::GROUP_EVENT_COUNT; ++i)
|
||||
E->GroupEventBindings->Clear(i);
|
||||
E->GroupEventBindings->Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 event_type = Eluna::CHECKVAL<uint32>(L, 1);
|
||||
E->GroupEventBindings->Clear(event_type);
|
||||
E->GroupEventBindings->Clear(Key((Hooks::GroupEvents)event_type));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -2852,15 +2675,16 @@ namespace LuaGlobalFunctions
|
||||
*/
|
||||
int ClearGuildEvents(Eluna* E, lua_State* L)
|
||||
{
|
||||
typedef EventKey<Hooks::GuildEvents> Key;
|
||||
|
||||
if (lua_isnoneornil(L, 1))
|
||||
{
|
||||
for (uint32 i = Hooks::GUILD_EVENT_ON_ADD_MEMBER; i < Hooks::GUILD_EVENT_COUNT; ++i)
|
||||
E->GuildEventBindings->Clear(i);
|
||||
E->GuildEventBindings->Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 event_type = Eluna::CHECKVAL<uint32>(L, 1);
|
||||
E->GuildEventBindings->Clear(event_type);
|
||||
E->GuildEventBindings->Clear(Key((Hooks::GuildEvents)event_type));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -2882,18 +2706,20 @@ namespace LuaGlobalFunctions
|
||||
*/
|
||||
int ClearItemEvents(Eluna* E, lua_State* L)
|
||||
{
|
||||
typedef EntryKey<Hooks::ItemEvents> Key;
|
||||
|
||||
if (lua_isnoneornil(L, 2))
|
||||
{
|
||||
uint32 entry = Eluna::CHECKVAL<uint32>(L, 1);
|
||||
|
||||
for (uint32 i = Hooks::ITEM_EVENT_ON_DUMMY_EFFECT; i < Hooks::ITEM_EVENT_COUNT; ++i)
|
||||
E->ItemEventBindings->Clear(entry, i);
|
||||
for (uint32 i = 1; i < Hooks::ITEM_EVENT_COUNT; ++i)
|
||||
E->ItemEventBindings->Clear(Key((Hooks::ItemEvents)i, entry));
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 entry = Eluna::CHECKVAL<uint32>(L, 1);
|
||||
uint32 event_type = Eluna::CHECKVAL<uint32>(L, 2);
|
||||
E->ItemEventBindings->Clear(entry, event_type);
|
||||
E->ItemEventBindings->Clear(Key((Hooks::ItemEvents)event_type, entry));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -2915,18 +2741,20 @@ namespace LuaGlobalFunctions
|
||||
*/
|
||||
int ClearItemGossipEvents(Eluna* E, lua_State* L)
|
||||
{
|
||||
typedef EntryKey<Hooks::GossipEvents> Key;
|
||||
|
||||
if (lua_isnoneornil(L, 2))
|
||||
{
|
||||
uint32 entry = Eluna::CHECKVAL<uint32>(L, 1);
|
||||
|
||||
for (uint32 i = Hooks::GOSSIP_EVENT_ON_HELLO; i < Hooks::GOSSIP_EVENT_COUNT; ++i)
|
||||
E->ItemGossipBindings->Clear(entry, i);
|
||||
for (uint32 i = 1; i < Hooks::GOSSIP_EVENT_COUNT; ++i)
|
||||
E->ItemGossipBindings->Clear(Key((Hooks::GossipEvents)i, entry));
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 entry = Eluna::CHECKVAL<uint32>(L, 1);
|
||||
uint32 event_type = Eluna::CHECKVAL<uint32>(L, 2);
|
||||
E->ItemGossipBindings->Clear(entry, event_type);
|
||||
E->ItemGossipBindings->Clear(Key((Hooks::GossipEvents)event_type, entry));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -2945,18 +2773,20 @@ namespace LuaGlobalFunctions
|
||||
*/
|
||||
int ClearPacketEvents(Eluna* E, lua_State* L)
|
||||
{
|
||||
typedef EntryKey<Hooks::PacketEvents> Key;
|
||||
|
||||
if (lua_isnoneornil(L, 2))
|
||||
{
|
||||
uint32 entry = Eluna::CHECKVAL<uint32>(L, 1);
|
||||
|
||||
for (uint32 i = Hooks::PACKET_EVENT_ON_PACKET_RECEIVE; i < Hooks::PACKET_EVENT_COUNT; ++i)
|
||||
E->PacketEventBindings->Clear(entry, i);
|
||||
for (uint32 i = 1; i < Hooks::PACKET_EVENT_COUNT; ++i)
|
||||
E->PacketEventBindings->Clear(Key((Hooks::PacketEvents)i, entry));
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 entry = Eluna::CHECKVAL<uint32>(L, 1);
|
||||
uint32 event_type = Eluna::CHECKVAL<uint32>(L, 2);
|
||||
E->PacketEventBindings->Clear(entry, event_type);
|
||||
E->PacketEventBindings->Clear(Key((Hooks::PacketEvents)event_type, entry));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -2974,15 +2804,16 @@ namespace LuaGlobalFunctions
|
||||
*/
|
||||
int ClearPlayerEvents(Eluna* E, lua_State* L)
|
||||
{
|
||||
typedef EventKey<Hooks::PlayerEvents> Key;
|
||||
|
||||
if (lua_isnoneornil(L, 1))
|
||||
{
|
||||
for (uint32 i = Hooks::PLAYER_EVENT_ON_CHARACTER_CREATE; i < Hooks::PLAYER_EVENT_COUNT; ++i)
|
||||
E->PlayerEventBindings->Clear(i);
|
||||
E->PlayerEventBindings->Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 event_type = Eluna::CHECKVAL<uint32>(L, 1);
|
||||
E->PlayerEventBindings->Clear(event_type);
|
||||
E->PlayerEventBindings->Clear(Key((Hooks::PlayerEvents)event_type));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -3001,18 +2832,20 @@ namespace LuaGlobalFunctions
|
||||
*/
|
||||
int ClearPlayerGossipEvents(Eluna* E, lua_State* L)
|
||||
{
|
||||
typedef EntryKey<Hooks::GossipEvents> Key;
|
||||
|
||||
if (lua_isnoneornil(L, 2))
|
||||
{
|
||||
uint32 entry = Eluna::CHECKVAL<uint32>(L, 1);
|
||||
|
||||
for (uint32 i = Hooks::GOSSIP_EVENT_ON_HELLO; i < Hooks::GOSSIP_EVENT_COUNT; ++i)
|
||||
E->playerGossipBindings->Clear(entry, i);
|
||||
for (uint32 i = 1; i < Hooks::GOSSIP_EVENT_COUNT; ++i)
|
||||
E->PlayerGossipBindings->Clear(Key((Hooks::GossipEvents)i, entry));
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 entry = Eluna::CHECKVAL<uint32>(L, 1);
|
||||
uint32 event_type = Eluna::CHECKVAL<uint32>(L, 2);
|
||||
E->playerGossipBindings->Clear(entry, event_type);
|
||||
E->PlayerGossipBindings->Clear(Key((Hooks::GossipEvents)event_type, entry));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -3030,15 +2863,16 @@ namespace LuaGlobalFunctions
|
||||
*/
|
||||
int ClearServerEvents(Eluna* E, lua_State* L)
|
||||
{
|
||||
typedef EventKey<Hooks::ServerEvents> Key;
|
||||
|
||||
if (lua_isnoneornil(L, 1))
|
||||
{
|
||||
for (uint32 i = Hooks::SERVER_EVENT_ON_NETWORK_START; i < Hooks::SERVER_EVENT_COUNT; ++i)
|
||||
E->ServerEventBindings->Clear(i);
|
||||
E->ServerEventBindings->Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 event_type = Eluna::CHECKVAL<uint32>(L, 1);
|
||||
E->ServerEventBindings->Clear(event_type);
|
||||
E->ServerEventBindings->Clear(Key((Hooks::ServerEvents)event_type));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
137
GossipHooks.cpp
Normal file
137
GossipHooks.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (C) 2010 - 2015 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(BINDINGS, EVENT, ENTRY) \
|
||||
if (!IsEnabled())\
|
||||
return;\
|
||||
auto key = EntryKey<GossipEvents>(EVENT, ENTRY);\
|
||||
if (!BINDINGS->HasBindingsFor(key))\
|
||||
return;\
|
||||
LOCK_ELUNA
|
||||
|
||||
#define START_HOOK_WITH_RETVAL(BINDINGS, EVENT, ENTRY, RETVAL) \
|
||||
if (!IsEnabled())\
|
||||
return RETVAL;\
|
||||
auto key = EntryKey<GossipEvents>(EVENT, ENTRY);\
|
||||
if (!BINDINGS->HasBindingsFor(key))\
|
||||
return RETVAL;\
|
||||
LOCK_ELUNA
|
||||
|
||||
bool Eluna::OnGossipHello(Player* pPlayer, GameObject* pGameObject)
|
||||
{
|
||||
START_HOOK_WITH_RETVAL(GameObjectGossipBindings, GOSSIP_EVENT_ON_HELLO, pGameObject->GetEntry(), false);
|
||||
pPlayer->PlayerTalkClass->ClearMenus();
|
||||
Push(pPlayer);
|
||||
Push(pGameObject);
|
||||
return CallAllFunctionsBool(GameObjectGossipBindings, key, true);
|
||||
}
|
||||
|
||||
bool Eluna::OnGossipSelect(Player* pPlayer, GameObject* pGameObject, uint32 sender, uint32 action)
|
||||
{
|
||||
START_HOOK_WITH_RETVAL(GameObjectGossipBindings, GOSSIP_EVENT_ON_SELECT, pGameObject->GetEntry(), false);
|
||||
pPlayer->PlayerTalkClass->ClearMenus();
|
||||
Push(pPlayer);
|
||||
Push(pGameObject);
|
||||
Push(sender);
|
||||
Push(action);
|
||||
return CallAllFunctionsBool(GameObjectGossipBindings, key, true);
|
||||
}
|
||||
|
||||
bool Eluna::OnGossipSelectCode(Player* pPlayer, GameObject* pGameObject, uint32 sender, uint32 action, const char* code)
|
||||
{
|
||||
START_HOOK_WITH_RETVAL(GameObjectGossipBindings, GOSSIP_EVENT_ON_SELECT, pGameObject->GetEntry(), false);
|
||||
pPlayer->PlayerTalkClass->ClearMenus();
|
||||
Push(pPlayer);
|
||||
Push(pGameObject);
|
||||
Push(sender);
|
||||
Push(action);
|
||||
Push(code);
|
||||
return CallAllFunctionsBool(GameObjectGossipBindings, key, true);
|
||||
}
|
||||
|
||||
void Eluna::HandleGossipSelectOption(Player* pPlayer, uint32 menuId, uint32 sender, uint32 action, const std::string& code)
|
||||
{
|
||||
START_HOOK(PlayerGossipBindings, GOSSIP_EVENT_ON_SELECT, menuId);
|
||||
pPlayer->PlayerTalkClass->ClearMenus();
|
||||
|
||||
Push(pPlayer); // receiver
|
||||
Push(pPlayer); // sender, just not to mess up the amount of args.
|
||||
Push(sender);
|
||||
Push(action);
|
||||
if (code.empty())
|
||||
Push();
|
||||
else
|
||||
Push(code);
|
||||
|
||||
CallAllFunctions(PlayerGossipBindings, key);
|
||||
}
|
||||
|
||||
bool Eluna::OnItemGossip(Player* pPlayer, Item* pItem, SpellCastTargets const& /*targets*/)
|
||||
{
|
||||
START_HOOK_WITH_RETVAL(ItemGossipBindings, GOSSIP_EVENT_ON_HELLO, pItem->GetEntry(), true);
|
||||
pPlayer->PlayerTalkClass->ClearMenus();
|
||||
Push(pPlayer);
|
||||
Push(pItem);
|
||||
return CallAllFunctionsBool(ItemGossipBindings, key, true);
|
||||
}
|
||||
|
||||
void Eluna::HandleGossipSelectOption(Player* pPlayer, Item* pItem, uint32 sender, uint32 action, const std::string& code)
|
||||
{
|
||||
START_HOOK(ItemGossipBindings, GOSSIP_EVENT_ON_SELECT, pItem->GetEntry());
|
||||
pPlayer->PlayerTalkClass->ClearMenus();
|
||||
|
||||
Push(pPlayer);
|
||||
Push(pItem);
|
||||
Push(sender);
|
||||
Push(action);
|
||||
if (code.empty())
|
||||
Push();
|
||||
else
|
||||
Push(code);
|
||||
|
||||
CallAllFunctions(ItemGossipBindings, key);
|
||||
}
|
||||
|
||||
bool Eluna::OnGossipHello(Player* pPlayer, Creature* pCreature)
|
||||
{
|
||||
START_HOOK_WITH_RETVAL(CreatureGossipBindings, GOSSIP_EVENT_ON_HELLO, pCreature->GetEntry(), false);
|
||||
pPlayer->PlayerTalkClass->ClearMenus();
|
||||
Push(pPlayer);
|
||||
Push(pCreature);
|
||||
return CallAllFunctionsBool(CreatureGossipBindings, key, true);
|
||||
}
|
||||
|
||||
bool Eluna::OnGossipSelect(Player* pPlayer, Creature* pCreature, uint32 sender, uint32 action)
|
||||
{
|
||||
START_HOOK_WITH_RETVAL(CreatureGossipBindings, GOSSIP_EVENT_ON_SELECT, pCreature->GetEntry(), false);
|
||||
pPlayer->PlayerTalkClass->ClearMenus();
|
||||
Push(pPlayer);
|
||||
Push(pCreature);
|
||||
Push(sender);
|
||||
Push(action);
|
||||
return CallAllFunctionsBool(CreatureGossipBindings, key, true);
|
||||
}
|
||||
|
||||
bool Eluna::OnGossipSelectCode(Player* pPlayer, Creature* pCreature, uint32 sender, uint32 action, const char* code)
|
||||
{
|
||||
START_HOOK_WITH_RETVAL(CreatureGossipBindings, GOSSIP_EVENT_ON_SELECT, pCreature->GetEntry(), false);
|
||||
pPlayer->PlayerTalkClass->ClearMenus();
|
||||
Push(pPlayer);
|
||||
Push(pCreature);
|
||||
Push(sender);
|
||||
Push(action);
|
||||
Push(code);
|
||||
return CallAllFunctionsBool(CreatureGossipBindings, key, true);
|
||||
}
|
||||
@@ -4,83 +4,68 @@
|
||||
* Please see the included DOCS/LICENSE.md for more information
|
||||
*/
|
||||
|
||||
#ifndef _GROUP_HOOKS_H
|
||||
#define _GROUP_HOOKS_H
|
||||
|
||||
#include "Hooks.h"
|
||||
#include "HookHelpers.h"
|
||||
#include "LuaEngine.h"
|
||||
#include "ElunaBinding.h"
|
||||
#include "BindingMap.h"
|
||||
#include "ElunaTemplate.h"
|
||||
|
||||
using namespace Hooks;
|
||||
|
||||
#define START_HOOK(EVENT) \
|
||||
if (!IsEnabled())\
|
||||
return;\
|
||||
auto key = EventKey<GroupEvents>(EVENT);\
|
||||
if (!GroupEventBindings->HasBindingsFor(key))\
|
||||
return;\
|
||||
LOCK_ELUNA
|
||||
|
||||
void Eluna::OnAddMember(Group* group, uint64 guid)
|
||||
{
|
||||
if (!GroupEventBindings->HasEvents(GROUP_EVENT_ON_MEMBER_ADD))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(GROUP_EVENT_ON_MEMBER_ADD);
|
||||
Push(group);
|
||||
Push(guid);
|
||||
CallAllFunctions(GroupEventBindings, GROUP_EVENT_ON_MEMBER_ADD);
|
||||
CallAllFunctions(GroupEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnInviteMember(Group* group, uint64 guid)
|
||||
{
|
||||
if (!GroupEventBindings->HasEvents(GROUP_EVENT_ON_MEMBER_INVITE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(GROUP_EVENT_ON_MEMBER_INVITE);
|
||||
Push(group);
|
||||
Push(guid);
|
||||
CallAllFunctions(GroupEventBindings, GROUP_EVENT_ON_MEMBER_INVITE);
|
||||
CallAllFunctions(GroupEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnRemoveMember(Group* group, uint64 guid, uint8 method)
|
||||
{
|
||||
if (!GroupEventBindings->HasEvents(GROUP_EVENT_ON_MEMBER_REMOVE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(GROUP_EVENT_ON_MEMBER_REMOVE);
|
||||
Push(group);
|
||||
Push(guid);
|
||||
Push(method);
|
||||
CallAllFunctions(GroupEventBindings, GROUP_EVENT_ON_MEMBER_REMOVE);
|
||||
CallAllFunctions(GroupEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnChangeLeader(Group* group, uint64 newLeaderGuid, uint64 oldLeaderGuid)
|
||||
{
|
||||
if (!GroupEventBindings->HasEvents(GROUP_EVENT_ON_LEADER_CHANGE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(GROUP_EVENT_ON_LEADER_CHANGE);
|
||||
Push(group);
|
||||
Push(newLeaderGuid);
|
||||
Push(oldLeaderGuid);
|
||||
CallAllFunctions(GroupEventBindings, GROUP_EVENT_ON_LEADER_CHANGE);
|
||||
CallAllFunctions(GroupEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnDisband(Group* group)
|
||||
{
|
||||
if (!GroupEventBindings->HasEvents(GROUP_EVENT_ON_DISBAND))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(GROUP_EVENT_ON_DISBAND);
|
||||
Push(group);
|
||||
CallAllFunctions(GroupEventBindings, GROUP_EVENT_ON_DISBAND);
|
||||
CallAllFunctions(GroupEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnCreate(Group* group, uint64 leaderGuid, GroupType groupType)
|
||||
{
|
||||
if (!GroupEventBindings->HasEvents(GROUP_EVENT_ON_CREATE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(GROUP_EVENT_ON_CREATE);
|
||||
Push(group);
|
||||
Push(leaderGuid);
|
||||
Push(groupType);
|
||||
CallAllFunctions(GroupEventBindings, GROUP_EVENT_ON_CREATE);
|
||||
CallAllFunctions(GroupEventBindings, key);
|
||||
}
|
||||
|
||||
#endif // _GROUP_HOOKS_H
|
||||
|
||||
@@ -4,97 +4,81 @@
|
||||
* Please see the included DOCS/LICENSE.md for more information
|
||||
*/
|
||||
|
||||
#ifndef _GUILD_HOOKS_H
|
||||
#define _GUILD_HOOKS_H
|
||||
|
||||
#include "Hooks.h"
|
||||
#include "HookHelpers.h"
|
||||
#include "LuaEngine.h"
|
||||
#include "ElunaBinding.h"
|
||||
#include "BindingMap.h"
|
||||
#include "ElunaTemplate.h"
|
||||
|
||||
using namespace Hooks;
|
||||
|
||||
#define START_HOOK(EVENT) \
|
||||
if (!IsEnabled())\
|
||||
return;\
|
||||
auto key = EventKey<GuildEvents>(EVENT);\
|
||||
if (!GuildEventBindings->HasBindingsFor(key))\
|
||||
return;\
|
||||
LOCK_ELUNA
|
||||
|
||||
void Eluna::OnAddMember(Guild* guild, Player* player, uint32 plRank)
|
||||
{
|
||||
if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_ADD_MEMBER))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(GUILD_EVENT_ON_ADD_MEMBER);
|
||||
Push(guild);
|
||||
Push(player);
|
||||
Push(plRank);
|
||||
CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_ADD_MEMBER);
|
||||
CallAllFunctions(GuildEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnRemoveMember(Guild* guild, Player* player, bool isDisbanding)
|
||||
{
|
||||
if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_REMOVE_MEMBER))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(GUILD_EVENT_ON_REMOVE_MEMBER);
|
||||
Push(guild);
|
||||
Push(player);
|
||||
Push(isDisbanding);
|
||||
CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_REMOVE_MEMBER);
|
||||
CallAllFunctions(GuildEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnMOTDChanged(Guild* guild, const std::string& newMotd)
|
||||
{
|
||||
if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_MOTD_CHANGE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(GUILD_EVENT_ON_MOTD_CHANGE);
|
||||
Push(guild);
|
||||
Push(newMotd);
|
||||
CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_MOTD_CHANGE);
|
||||
CallAllFunctions(GuildEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnInfoChanged(Guild* guild, const std::string& newInfo)
|
||||
{
|
||||
if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_INFO_CHANGE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(GUILD_EVENT_ON_INFO_CHANGE);
|
||||
Push(guild);
|
||||
Push(newInfo);
|
||||
CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_INFO_CHANGE);
|
||||
CallAllFunctions(GuildEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnCreate(Guild* guild, Player* leader, const std::string& name)
|
||||
{
|
||||
if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_CREATE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(GUILD_EVENT_ON_CREATE);
|
||||
Push(guild);
|
||||
Push(leader);
|
||||
Push(name);
|
||||
CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_CREATE);
|
||||
CallAllFunctions(GuildEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnDisband(Guild* guild)
|
||||
{
|
||||
if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_DISBAND))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(GUILD_EVENT_ON_DISBAND);
|
||||
Push(guild);
|
||||
CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_DISBAND);
|
||||
CallAllFunctions(GuildEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnMemberWitdrawMoney(Guild* guild, Player* player, uint32& amount, bool isRepair) // isRepair not a part of Mangos, implement?
|
||||
{
|
||||
if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_MONEY_WITHDRAW))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(GUILD_EVENT_ON_MONEY_WITHDRAW);
|
||||
Push(guild);
|
||||
Push(player);
|
||||
Push(amount);
|
||||
Push(isRepair); // isRepair not a part of Mangos, implement?
|
||||
int amountIndex = lua_gettop(L) - 1;
|
||||
int n = SetupStack(GuildEventBindings, GUILD_EVENT_ON_MONEY_WITHDRAW, 4);
|
||||
int n = SetupStack(GuildEventBindings, key, 4);
|
||||
|
||||
while (n > 0)
|
||||
{
|
||||
@@ -115,15 +99,12 @@ void Eluna::OnMemberWitdrawMoney(Guild* guild, Player* player, uint32& amount, b
|
||||
|
||||
void Eluna::OnMemberDepositMoney(Guild* guild, Player* player, uint32& amount)
|
||||
{
|
||||
if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_MONEY_DEPOSIT))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(GUILD_EVENT_ON_MONEY_DEPOSIT);
|
||||
Push(guild);
|
||||
Push(player);
|
||||
Push(amount);
|
||||
int amountIndex = lua_gettop(L);
|
||||
int n = SetupStack(GuildEventBindings, GUILD_EVENT_ON_MONEY_DEPOSIT, 3);
|
||||
int n = SetupStack(GuildEventBindings, key, 3);
|
||||
|
||||
while (n > 0)
|
||||
{
|
||||
@@ -145,10 +126,7 @@ void Eluna::OnMemberDepositMoney(Guild* guild, Player* player, uint32& amount)
|
||||
void Eluna::OnItemMove(Guild* guild, Player* player, Item* pItem, bool isSrcBank, uint8 srcContainer, uint8 srcSlotId,
|
||||
bool isDestBank, uint8 destContainer, uint8 destSlotId)
|
||||
{
|
||||
if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_ITEM_MOVE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(GUILD_EVENT_ON_ITEM_MOVE);
|
||||
Push(guild);
|
||||
Push(player);
|
||||
Push(pItem);
|
||||
@@ -158,29 +136,23 @@ void Eluna::OnItemMove(Guild* guild, Player* player, Item* pItem, bool isSrcBank
|
||||
Push(isDestBank);
|
||||
Push(destContainer);
|
||||
Push(destSlotId);
|
||||
CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_ITEM_MOVE);
|
||||
CallAllFunctions(GuildEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnEvent(Guild* guild, uint8 eventType, uint32 playerGuid1, uint32 playerGuid2, uint8 newRank)
|
||||
{
|
||||
if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_EVENT))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(GUILD_EVENT_ON_EVENT);
|
||||
Push(guild);
|
||||
Push(eventType);
|
||||
Push(playerGuid1);
|
||||
Push(playerGuid2);
|
||||
Push(newRank);
|
||||
CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_EVENT);
|
||||
CallAllFunctions(GuildEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnBankEvent(Guild* guild, uint8 eventType, uint8 tabId, uint32 playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId)
|
||||
{
|
||||
if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_BANK_EVENT))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(GUILD_EVENT_ON_BANK_EVENT);
|
||||
Push(guild);
|
||||
Push(eventType);
|
||||
Push(tabId);
|
||||
@@ -188,7 +160,5 @@ void Eluna::OnBankEvent(Guild* guild, uint8 eventType, uint8 tabId, uint32 playe
|
||||
Push(itemOrMoney);
|
||||
Push(itemStackCount);
|
||||
Push(destTabId);
|
||||
CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_BANK_EVENT);
|
||||
CallAllFunctions(GuildEventBindings, key);
|
||||
}
|
||||
|
||||
#endif // _GUILD_HOOKS_H
|
||||
|
||||
@@ -14,18 +14,15 @@
|
||||
* Sets up the stack so that event handlers can be called.
|
||||
*
|
||||
* Returns the number of functions that were pushed onto the stack.
|
||||
*
|
||||
* Use the simpler overloads for just EventBind or EntryBind instead of this overload in hooks.
|
||||
*/
|
||||
template<typename T>
|
||||
int Eluna::SetupStack(EventBind<T>* event_bindings, EntryBind<T>* entry_bindings, UniqueBind<T>* guid_bindings, T event_id, uint32 entry, uint64 guid, uint32 instanceId, int number_of_arguments)
|
||||
template<typename K1, typename K2>
|
||||
int Eluna::SetupStack(BindingMap<K1>* bindings1, BindingMap<K2>* bindings2, const K1& key1, const K2& key2, int number_of_arguments)
|
||||
{
|
||||
// Ensure that if `entry_bindings` is not NULL, a valid entry is supplied.
|
||||
ASSERT(!entry_bindings || (entry_bindings && entry > 0));
|
||||
ASSERT(number_of_arguments == this->push_counter);
|
||||
ASSERT(key1.event_id == key2.event_id);
|
||||
// Stack: [arguments]
|
||||
|
||||
Push(event_id);
|
||||
Push(key1.event_id);
|
||||
this->push_counter = 0;
|
||||
++number_of_arguments;
|
||||
// Stack: [arguments], event_id
|
||||
@@ -37,14 +34,9 @@ int Eluna::SetupStack(EventBind<T>* event_bindings, EntryBind<T>* entry_bindings
|
||||
lua_insert(L, first_argument_index);
|
||||
// Stack: event_id, [arguments]
|
||||
|
||||
if (event_bindings)
|
||||
event_bindings->PushFuncRefs(L, (int)event_id);
|
||||
|
||||
if (entry_bindings)
|
||||
entry_bindings->PushFuncRefs(L, (int)event_id, entry);
|
||||
|
||||
if (guid_bindings)
|
||||
guid_bindings->PushFuncRefs(L, (int)event_id, guid, instanceId);
|
||||
bindings1->PushRefsFor(key1);
|
||||
if (bindings2)
|
||||
bindings2->PushRefsFor(key2);
|
||||
// Stack: event_id, [arguments], [functions]
|
||||
|
||||
int number_of_functions = lua_gettop(L) - arguments_top;
|
||||
@@ -70,13 +62,13 @@ void Eluna::ReplaceArgument(T value, uint8 index)
|
||||
/*
|
||||
* Call all event handlers registered to the event ID/entry combination and ignore any results.
|
||||
*/
|
||||
template<typename T>
|
||||
void Eluna::CallAllFunctions(EventBind<T>* event_bindings, EntryBind<T>* entry_bindings, UniqueBind<T>* guid_bindings, T event_id, uint32 entry, uint64 guid, uint32 instanceId)
|
||||
template<typename K1, typename K2>
|
||||
void Eluna::CallAllFunctions(BindingMap<K1>* bindings1, BindingMap<K2>* bindings2, const K1& key1, const K2& key2)
|
||||
{
|
||||
int number_of_arguments = this->push_counter;
|
||||
// Stack: [arguments]
|
||||
|
||||
int number_of_functions = SetupStack(event_bindings, entry_bindings, guid_bindings, event_id, entry, guid, instanceId, number_of_arguments);
|
||||
int number_of_functions = SetupStack(bindings1, bindings2, key1, key2, number_of_arguments);
|
||||
// Stack: event_id, [arguments], [functions]
|
||||
|
||||
while (number_of_functions > 0)
|
||||
@@ -96,15 +88,15 @@ void Eluna::CallAllFunctions(EventBind<T>* event_bindings, EntryBind<T>* entry_b
|
||||
* and returns `default_value` if ALL event handlers returned `default_value`,
|
||||
* otherwise returns the opposite of `default_value`.
|
||||
*/
|
||||
template<typename T>
|
||||
bool Eluna::CallAllFunctionsBool(EventBind<T>* event_bindings, EntryBind<T>* entry_bindings, UniqueBind<T>* guid_bindings, T event_id, uint32 entry, uint64 guid, uint32 instanceId, bool default_value)
|
||||
template<typename K1, typename K2>
|
||||
bool Eluna::CallAllFunctionsBool(BindingMap<K1>* bindings1, BindingMap<K2>* bindings2, const K1& key1, const K2& key2, bool default_value/* = false*/)
|
||||
{
|
||||
bool result = default_value;
|
||||
// Note: number_of_arguments here does not count in eventID, which is pushed in SetupStack
|
||||
int number_of_arguments = this->push_counter;
|
||||
// Stack: [arguments]
|
||||
|
||||
int number_of_functions = SetupStack(event_bindings, entry_bindings, guid_bindings, event_id, entry, guid, instanceId, number_of_arguments);
|
||||
int number_of_functions = SetupStack(bindings1, bindings2, key1, key2, number_of_arguments);
|
||||
// Stack: event_id, [arguments], [functions]
|
||||
|
||||
while (number_of_functions > 0)
|
||||
|
||||
4
Hooks.h
4
Hooks.h
@@ -13,7 +13,7 @@
|
||||
* A. If results will be IGNORED:
|
||||
*
|
||||
* // Return early if there are no bindings.
|
||||
* if (!WhateverBindings->HasEvents(SOME_EVENT_TYPE))
|
||||
* if (!WhateverBindings->HasBindingsFor(SOME_EVENT_TYPE))
|
||||
* return;
|
||||
*
|
||||
* // Lock out any other threads.
|
||||
@@ -31,7 +31,7 @@
|
||||
* B. If results will be USED:
|
||||
*
|
||||
* // Return early if there are no bindings.
|
||||
* if (!WhateverBindings->HasEvents(SOME_EVENT_TYPE))
|
||||
* if (!WhateverBindings->HasBindingsFor(SOME_EVENT_TYPE))
|
||||
* return;
|
||||
*
|
||||
* // Lock out any other threads.
|
||||
|
||||
@@ -4,41 +4,40 @@
|
||||
* Please see the included DOCS/LICENSE.md for more information
|
||||
*/
|
||||
|
||||
#ifndef _ITEM_HOOKS_H
|
||||
#define _ITEM_HOOKS_H
|
||||
|
||||
#include "Hooks.h"
|
||||
#include "HookHelpers.h"
|
||||
#include "LuaEngine.h"
|
||||
#include "ElunaBinding.h"
|
||||
#include "BindingMap.h"
|
||||
#include "ElunaIncludes.h"
|
||||
#include "ElunaTemplate.h"
|
||||
|
||||
using namespace Hooks;
|
||||
|
||||
#define START_HOOK_WITH_RETVAL(EVENT, ENTRY, RETVAL) \
|
||||
if (!IsEnabled())\
|
||||
return RETVAL;\
|
||||
auto key = EntryKey<ItemEvents>(EVENT, ENTRY);\
|
||||
if (!ItemEventBindings->HasBindingsFor(key))\
|
||||
return RETVAL;\
|
||||
LOCK_ELUNA
|
||||
|
||||
bool Eluna::OnDummyEffect(Unit* pCaster, uint32 spellId, SpellEffIndex effIndex, Item* pTarget)
|
||||
{
|
||||
if (!ItemEventBindings->HasEvents(ITEM_EVENT_ON_DUMMY_EFFECT, pTarget->GetEntry()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(ITEM_EVENT_ON_DUMMY_EFFECT, pTarget->GetEntry(), false);
|
||||
Push(pCaster);
|
||||
Push(spellId);
|
||||
Push(effIndex);
|
||||
Push(pTarget);
|
||||
return CallAllFunctionsBool(ItemEventBindings, ITEM_EVENT_ON_DUMMY_EFFECT, pTarget->GetEntry());
|
||||
return CallAllFunctionsBool(ItemEventBindings, key);
|
||||
}
|
||||
|
||||
bool Eluna::OnQuestAccept(Player* pPlayer, Item* pItem, Quest const* pQuest)
|
||||
{
|
||||
if (!ItemEventBindings->HasEvents(ITEM_EVENT_ON_QUEST_ACCEPT, pItem->GetEntry()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(ITEM_EVENT_ON_QUEST_ACCEPT, pItem->GetEntry(), false);
|
||||
Push(pPlayer);
|
||||
Push(pItem);
|
||||
Push(pQuest);
|
||||
return CallAllFunctionsBool(ItemEventBindings, ITEM_EVENT_ON_QUEST_ACCEPT, pItem->GetEntry());
|
||||
return CallAllFunctionsBool(ItemEventBindings, key);
|
||||
}
|
||||
|
||||
bool Eluna::OnUse(Player* pPlayer, Item* pItem, SpellCastTargets const& targets)
|
||||
@@ -73,10 +72,7 @@ bool Eluna::OnUse(Player* pPlayer, Item* pItem, SpellCastTargets const& targets)
|
||||
|
||||
bool Eluna::OnItemUse(Player* pPlayer, Item* pItem, SpellCastTargets const& targets)
|
||||
{
|
||||
if (!ItemEventBindings->HasEvents(ITEM_EVENT_ON_USE, pItem->GetEntry()))
|
||||
return true;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(ITEM_EVENT_ON_USE, pItem->GetEntry(), true);
|
||||
Push(pPlayer);
|
||||
Push(pItem);
|
||||
#ifndef TRINITY
|
||||
@@ -105,41 +101,21 @@ bool Eluna::OnItemUse(Player* pPlayer, Item* pItem, SpellCastTargets const& targ
|
||||
Push();
|
||||
#endif
|
||||
|
||||
return CallAllFunctionsBool(ItemEventBindings, ITEM_EVENT_ON_USE, pItem->GetEntry(), true);
|
||||
}
|
||||
|
||||
bool Eluna::OnItemGossip(Player* pPlayer, Item* pItem, SpellCastTargets const& /*targets*/)
|
||||
{
|
||||
if (!ItemGossipBindings->HasEvents(GOSSIP_EVENT_ON_HELLO, pItem->GetEntry()))
|
||||
return true;
|
||||
|
||||
LOCK_ELUNA;
|
||||
pPlayer->PlayerTalkClass->ClearMenus();
|
||||
Push(pPlayer);
|
||||
Push(pItem);
|
||||
return CallAllFunctionsBool(ItemGossipBindings, GOSSIP_EVENT_ON_HELLO, pItem->GetEntry(), true);
|
||||
return CallAllFunctionsBool(ItemEventBindings, key, true);
|
||||
}
|
||||
|
||||
bool Eluna::OnExpire(Player* pPlayer, ItemTemplate const* pProto)
|
||||
{
|
||||
if (!ItemEventBindings->HasEvents(ITEM_EVENT_ON_EXPIRE, pProto->ItemId))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(ITEM_EVENT_ON_EXPIRE, pProto->ItemId, false);
|
||||
Push(pPlayer);
|
||||
Push(pProto->ItemId);
|
||||
return CallAllFunctionsBool(ItemEventBindings, ITEM_EVENT_ON_EXPIRE, pProto->ItemId);
|
||||
return CallAllFunctionsBool(ItemEventBindings, key);
|
||||
}
|
||||
|
||||
bool Eluna::OnRemove(Player* pPlayer, Item* item)
|
||||
bool Eluna::OnRemove(Player* pPlayer, Item* pItem)
|
||||
{
|
||||
if (!ItemEventBindings->HasEvents(ITEM_EVENT_ON_REMOVE, item->GetEntry()))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(ITEM_EVENT_ON_REMOVE, pItem->GetEntry(), false);
|
||||
Push(pPlayer);
|
||||
Push(item);
|
||||
return CallAllFunctionsBool(ItemEventBindings, ITEM_EVENT_ON_REMOVE, item->GetEntry());
|
||||
Push(pItem);
|
||||
return CallAllFunctionsBool(ItemEventBindings, key);
|
||||
}
|
||||
|
||||
#endif // _ITEM_HOOKS_H
|
||||
|
||||
360
LuaEngine.cpp
360
LuaEngine.cpp
@@ -6,7 +6,7 @@
|
||||
|
||||
#include "Hooks.h"
|
||||
#include "LuaEngine.h"
|
||||
#include "ElunaBinding.h"
|
||||
#include "BindingMap.h"
|
||||
#include "ElunaEventMgr.h"
|
||||
#include "ElunaIncludes.h"
|
||||
#include "ElunaTemplate.h"
|
||||
@@ -151,7 +151,7 @@ GameObjectEventBindings(NULL),
|
||||
GameObjectGossipBindings(NULL),
|
||||
ItemEventBindings(NULL),
|
||||
ItemGossipBindings(NULL),
|
||||
playerGossipBindings(NULL),
|
||||
PlayerGossipBindings(NULL),
|
||||
|
||||
CreatureUniqueBindings(NULL)
|
||||
{
|
||||
@@ -189,8 +189,6 @@ void Eluna::CloseLua()
|
||||
|
||||
void Eluna::OpenLua()
|
||||
{
|
||||
CreateBindStores();
|
||||
|
||||
enabled = eConfigMgr->GetBoolDefault("Eluna.Enabled", true);
|
||||
if (!IsEnabled())
|
||||
{
|
||||
@@ -199,6 +197,7 @@ void Eluna::OpenLua()
|
||||
}
|
||||
|
||||
L = luaL_newstate();
|
||||
CreateBindStores();
|
||||
|
||||
// open base lua libraries
|
||||
luaL_openlibs(L);
|
||||
@@ -229,23 +228,23 @@ void Eluna::CreateBindStores()
|
||||
{
|
||||
DestroyBindStores();
|
||||
|
||||
ServerEventBindings = new EventBind<Hooks::ServerEvents>("ServerEvents", *this);
|
||||
PlayerEventBindings = new EventBind<Hooks::PlayerEvents>("PlayerEvents", *this);
|
||||
GuildEventBindings = new EventBind<Hooks::GuildEvents>("GuildEvents", *this);
|
||||
GroupEventBindings = new EventBind<Hooks::GroupEvents>("GroupEvents", *this);
|
||||
VehicleEventBindings = new EventBind<Hooks::VehicleEvents>("VehicleEvents", *this);
|
||||
BGEventBindings = new EventBind<Hooks::BGEvents>("BGEvents", *this);
|
||||
ServerEventBindings = new BindingMap< EventKey<Hooks::ServerEvents> >(L);
|
||||
PlayerEventBindings = new BindingMap< EventKey<Hooks::PlayerEvents> >(L);
|
||||
GuildEventBindings = new BindingMap< EventKey<Hooks::GuildEvents> >(L);
|
||||
GroupEventBindings = new BindingMap< EventKey<Hooks::GroupEvents> >(L);
|
||||
VehicleEventBindings = new BindingMap< EventKey<Hooks::VehicleEvents> >(L);
|
||||
BGEventBindings = new BindingMap< EventKey<Hooks::BGEvents> >(L);
|
||||
|
||||
PacketEventBindings = new EntryBind<Hooks::PacketEvents>("PacketEvents", *this);
|
||||
CreatureEventBindings = new EntryBind<Hooks::CreatureEvents>("CreatureEvents", *this);
|
||||
CreatureGossipBindings = new EntryBind<Hooks::GossipEvents>("GossipEvents (creature)", *this);
|
||||
GameObjectEventBindings = new EntryBind<Hooks::GameObjectEvents>("GameObjectEvents", *this);
|
||||
GameObjectGossipBindings = new EntryBind<Hooks::GossipEvents>("GossipEvents (gameobject)", *this);
|
||||
ItemEventBindings = new EntryBind<Hooks::ItemEvents>("ItemEvents", *this);
|
||||
ItemGossipBindings = new EntryBind<Hooks::GossipEvents>("GossipEvents (item)", *this);
|
||||
playerGossipBindings = new EntryBind<Hooks::GossipEvents>("GossipEvents (player)", *this);
|
||||
PacketEventBindings = new BindingMap< EntryKey<Hooks::PacketEvents> >(L);
|
||||
CreatureEventBindings = new BindingMap< EntryKey<Hooks::CreatureEvents> >(L);
|
||||
CreatureGossipBindings = new BindingMap< EntryKey<Hooks::GossipEvents> >(L);
|
||||
GameObjectEventBindings = new BindingMap< EntryKey<Hooks::GameObjectEvents> >(L);
|
||||
GameObjectGossipBindings = new BindingMap< EntryKey<Hooks::GossipEvents> >(L);
|
||||
ItemEventBindings = new BindingMap< EntryKey<Hooks::ItemEvents> >(L);
|
||||
ItemGossipBindings = new BindingMap< EntryKey<Hooks::GossipEvents> >(L);
|
||||
PlayerGossipBindings = new BindingMap< EntryKey<Hooks::GossipEvents> >(L);
|
||||
|
||||
CreatureUniqueBindings = new UniqueBind<Hooks::CreatureEvents>("CreatureEvents (unique)", *this);
|
||||
CreatureUniqueBindings = new BindingMap< UniqueObjectKey<Hooks::CreatureEvents> >(L);
|
||||
}
|
||||
|
||||
void Eluna::DestroyBindStores()
|
||||
@@ -263,7 +262,7 @@ void Eluna::DestroyBindStores()
|
||||
delete GameObjectGossipBindings;
|
||||
delete ItemEventBindings;
|
||||
delete ItemGossipBindings;
|
||||
delete playerGossipBindings;
|
||||
delete PlayerGossipBindings;
|
||||
delete BGEventBindings;
|
||||
|
||||
delete CreatureUniqueBindings;
|
||||
@@ -281,7 +280,7 @@ void Eluna::DestroyBindStores()
|
||||
GameObjectGossipBindings = NULL;
|
||||
ItemEventBindings = NULL;
|
||||
ItemGossipBindings = NULL;
|
||||
playerGossipBindings = NULL;
|
||||
PlayerGossipBindings = NULL;
|
||||
BGEventBindings = NULL;
|
||||
|
||||
CreatureUniqueBindings = NULL;
|
||||
@@ -435,7 +434,7 @@ void Eluna::RunScripts()
|
||||
scripts.insert(scripts.end(), lua_extensions.begin(), lua_extensions.end());
|
||||
scripts.insert(scripts.end(), lua_scripts.begin(), lua_scripts.end());
|
||||
|
||||
UNORDERED_MAP<std::string, std::string> loaded; // filename, path
|
||||
std::unordered_map<std::string, std::string> loaded; // filename, path
|
||||
|
||||
lua_getglobal(L, "package");
|
||||
// Stack: package
|
||||
@@ -907,333 +906,239 @@ ElunaObject* Eluna::CHECKTYPE(lua_State* luastate, int narg, const char* tname,
|
||||
return *ptrHold;
|
||||
}
|
||||
|
||||
template<typename K>
|
||||
static int cancelBinding(lua_State *L)
|
||||
{
|
||||
int ref = lua_tointeger(L, lua_upvalueindex(1));
|
||||
uint32 event_id = lua_tounsigned(L, lua_upvalueindex(2));
|
||||
uint32 entry_id = lua_tounsigned(L, lua_upvalueindex(3));
|
||||
uint64 guid = Eluna::CHECKVAL<uint64>(L, lua_upvalueindex(4));
|
||||
uint64 bindingID = Eluna::CHECKVAL<uint64>(L, lua_upvalueindex(1));
|
||||
|
||||
// This marker (initially `false`) is used to protect against calling this callback twice.
|
||||
// After the first call, `alreadyCalled` will be `true`, so we know not to proceed.
|
||||
bool alreadyCalled = lua_toboolean(L, lua_upvalueindex(5));
|
||||
BindingMap<K>* bindings = (BindingMap<K>*)lua_touserdata(L, lua_upvalueindex(2));
|
||||
ASSERT(bindings != NULL);
|
||||
|
||||
if (alreadyCalled)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
lua_pushboolean(L, true);
|
||||
lua_replace(L, lua_upvalueindex(5));
|
||||
}
|
||||
|
||||
ElunaBind* bindings1 = (ElunaBind*)lua_touserdata(L, lua_upvalueindex(6));
|
||||
ASSERT(bindings1 != NULL);
|
||||
bindings1->ClearOne(ref, event_id, entry_id, guid);
|
||||
bindings->Remove(bindingID);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int createCancelCallback(lua_State* L, int ref, ElunaBind* bindings1, uint32 event_id, uint32 entry_id = 0, uint64 guid = 0)
|
||||
template<typename K>
|
||||
static void createCancelCallback(lua_State* L, uint64 bindingID, BindingMap<K>* bindings)
|
||||
{
|
||||
lua_pushinteger(L, ref);
|
||||
lua_pushunsigned(L, event_id);
|
||||
lua_pushunsigned(L, entry_id);
|
||||
Eluna::Push(L, guid);
|
||||
lua_pushboolean(L, false);
|
||||
lua_pushlightuserdata(L, bindings1);
|
||||
// Stack: ref, event_id, entry_id, guid, false, bindings1
|
||||
Eluna::Push(L, bindingID);
|
||||
lua_pushlightuserdata(L, bindings);
|
||||
// Stack: bindingID, bindings
|
||||
|
||||
lua_pushcclosure(L, &cancelBinding, 6);
|
||||
// Stack: cancel_callback
|
||||
|
||||
lua_pushvalue(L, -1);
|
||||
return luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
lua_pushcclosure(L, &cancelBinding<K>, 2);
|
||||
// Stack: cancel_callback
|
||||
}
|
||||
|
||||
// Saves the function reference ID given to the register type's store for given entry under the given event
|
||||
int Eluna::Register(lua_State* L, uint8 regtype, uint32 id, uint64 guid, uint32 instanceId, uint32 evt, int functionRef, uint32 shots, bool returnCallback)
|
||||
int Eluna::Register(lua_State* L, uint8 regtype, uint32 entry, uint64 guid, uint32 instanceId, uint32 event_id, int functionRef, uint32 shots)
|
||||
{
|
||||
uint64 bindingID;
|
||||
|
||||
switch (regtype)
|
||||
{
|
||||
case Hooks::REGTYPE_SERVER:
|
||||
if (evt < Hooks::SERVER_EVENT_COUNT)
|
||||
if (event_id < Hooks::SERVER_EVENT_COUNT)
|
||||
{
|
||||
if (returnCallback)
|
||||
{
|
||||
int callbackRef = createCancelCallback(L, functionRef, ServerEventBindings, evt);
|
||||
ServerEventBindings->Insert(evt, functionRef, shots, callbackRef);
|
||||
return 1; // Stack: callback
|
||||
}
|
||||
|
||||
ServerEventBindings->Insert(evt, functionRef, shots);
|
||||
return 0; // Stack: (empty)
|
||||
auto key = EventKey<Hooks::ServerEvents>((Hooks::ServerEvents)event_id);
|
||||
bindingID = ServerEventBindings->Insert(key, functionRef, shots);
|
||||
createCancelCallback(L, bindingID, ServerEventBindings);
|
||||
return 1; // Stack: callback
|
||||
}
|
||||
break;
|
||||
|
||||
case Hooks::REGTYPE_PLAYER:
|
||||
if (evt < Hooks::PLAYER_EVENT_COUNT)
|
||||
if (event_id < Hooks::PLAYER_EVENT_COUNT)
|
||||
{
|
||||
if (returnCallback)
|
||||
{
|
||||
int callbackRef = createCancelCallback(L, functionRef, PlayerEventBindings, evt);
|
||||
PlayerEventBindings->Insert(evt, functionRef, shots, callbackRef);
|
||||
return 1; // Stack: callback
|
||||
}
|
||||
|
||||
PlayerEventBindings->Insert(evt, functionRef, shots);
|
||||
return 0; // Stack: (empty)
|
||||
auto key = EventKey<Hooks::PlayerEvents>((Hooks::PlayerEvents)event_id);
|
||||
bindingID = PlayerEventBindings->Insert(key, functionRef, shots);
|
||||
createCancelCallback(L, bindingID, PlayerEventBindings);
|
||||
return 1; // Stack: callback
|
||||
}
|
||||
break;
|
||||
|
||||
case Hooks::REGTYPE_GUILD:
|
||||
if (evt < Hooks::GUILD_EVENT_COUNT)
|
||||
if (event_id < Hooks::GUILD_EVENT_COUNT)
|
||||
{
|
||||
if (returnCallback)
|
||||
{
|
||||
int callbackRef = createCancelCallback(L, functionRef, GuildEventBindings, evt);
|
||||
GuildEventBindings->Insert(evt, functionRef, shots, callbackRef);
|
||||
return 1; // Stack: callback
|
||||
}
|
||||
|
||||
GuildEventBindings->Insert(evt, functionRef, shots);
|
||||
return 0; // Stack: (empty)
|
||||
auto key = EventKey<Hooks::GuildEvents>((Hooks::GuildEvents)event_id);
|
||||
bindingID = GuildEventBindings->Insert(key, functionRef, shots);
|
||||
createCancelCallback(L, bindingID, GuildEventBindings);
|
||||
return 1; // Stack: callback
|
||||
}
|
||||
break;
|
||||
|
||||
case Hooks::REGTYPE_GROUP:
|
||||
if (evt < Hooks::GROUP_EVENT_COUNT)
|
||||
if (event_id < Hooks::GROUP_EVENT_COUNT)
|
||||
{
|
||||
if (returnCallback)
|
||||
{
|
||||
int callbackRef = createCancelCallback(L, functionRef, GroupEventBindings, evt);
|
||||
GroupEventBindings->Insert(evt, functionRef, shots, callbackRef);
|
||||
return 1; // Stack: callback
|
||||
}
|
||||
|
||||
GroupEventBindings->Insert(evt, functionRef, shots);
|
||||
return 0; // Stack: (empty)
|
||||
auto key = EventKey<Hooks::GroupEvents>((Hooks::GroupEvents)event_id);
|
||||
bindingID = GroupEventBindings->Insert(key, functionRef, shots);
|
||||
createCancelCallback(L, bindingID, GroupEventBindings);
|
||||
return 1; // Stack: callback
|
||||
}
|
||||
break;
|
||||
|
||||
case Hooks::REGTYPE_VEHICLE:
|
||||
if (evt < Hooks::VEHICLE_EVENT_COUNT)
|
||||
if (event_id < Hooks::VEHICLE_EVENT_COUNT)
|
||||
{
|
||||
if (returnCallback)
|
||||
{
|
||||
int callbackRef = createCancelCallback(L, functionRef, VehicleEventBindings, evt);
|
||||
VehicleEventBindings->Insert(evt, functionRef, shots, callbackRef);
|
||||
return 1; // Stack: callback
|
||||
}
|
||||
|
||||
VehicleEventBindings->Insert(evt, functionRef, shots);
|
||||
return 0; // Stack: (empty)
|
||||
auto key = EventKey<Hooks::VehicleEvents>((Hooks::VehicleEvents)event_id);
|
||||
bindingID = VehicleEventBindings->Insert(key, functionRef, shots);
|
||||
createCancelCallback(L, bindingID, VehicleEventBindings);
|
||||
return 1; // Stack: callback
|
||||
}
|
||||
break;
|
||||
|
||||
case Hooks::REGTYPE_BG:
|
||||
if (evt < Hooks::BG_EVENT_COUNT)
|
||||
if (event_id < Hooks::BG_EVENT_COUNT)
|
||||
{
|
||||
if (returnCallback)
|
||||
{
|
||||
int callbackRef = createCancelCallback(L, functionRef, BGEventBindings, evt);
|
||||
BGEventBindings->Insert(evt, functionRef, shots, callbackRef);
|
||||
return 1; // Stack: callback
|
||||
}
|
||||
|
||||
BGEventBindings->Insert(evt, functionRef, shots);
|
||||
return 0; // Stack: (empty)
|
||||
auto key = EventKey<Hooks::BGEvents>((Hooks::BGEvents)event_id);
|
||||
bindingID = BGEventBindings->Insert(key, functionRef, shots);
|
||||
createCancelCallback(L, bindingID, BGEventBindings);
|
||||
return 1; // Stack: callback
|
||||
}
|
||||
break;
|
||||
|
||||
case Hooks::REGTYPE_PACKET:
|
||||
if (evt < Hooks::PACKET_EVENT_COUNT)
|
||||
if (event_id < Hooks::PACKET_EVENT_COUNT)
|
||||
{
|
||||
if (id >= NUM_MSG_TYPES)
|
||||
if (entry >= NUM_MSG_TYPES)
|
||||
{
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, functionRef);
|
||||
luaL_error(L, "Couldn't find a creature with (ID: %d)!", id);
|
||||
luaL_error(L, "Couldn't find a creature with (ID: %d)!", entry);
|
||||
return 0; // Stack: (empty)
|
||||
}
|
||||
|
||||
if (returnCallback)
|
||||
{
|
||||
int callbackRef = createCancelCallback(L, functionRef, PacketEventBindings, evt, id);
|
||||
PacketEventBindings->Insert(id, evt, functionRef, shots, callbackRef);
|
||||
return 1; // Stack: callback
|
||||
}
|
||||
|
||||
PacketEventBindings->Insert(id, evt, functionRef, shots);
|
||||
return 0; // Stack: (empty)
|
||||
auto key = EntryKey<Hooks::PacketEvents>((Hooks::PacketEvents)event_id, entry);
|
||||
bindingID = PacketEventBindings->Insert(key, functionRef, shots);
|
||||
createCancelCallback(L, bindingID, PacketEventBindings);
|
||||
return 1; // Stack: callback
|
||||
}
|
||||
break;
|
||||
|
||||
case Hooks::REGTYPE_CREATURE:
|
||||
if (evt < Hooks::CREATURE_EVENT_COUNT)
|
||||
if (event_id < Hooks::CREATURE_EVENT_COUNT)
|
||||
{
|
||||
if (id != 0)
|
||||
if (entry != 0)
|
||||
{
|
||||
if (!eObjectMgr->GetCreatureTemplate(id))
|
||||
if (!eObjectMgr->GetCreatureTemplate(entry))
|
||||
{
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, functionRef);
|
||||
luaL_error(L, "Couldn't find a creature with (ID: %d)!", id);
|
||||
luaL_error(L, "Couldn't find a creature with (ID: %d)!", entry);
|
||||
return 0; // Stack: (empty)
|
||||
}
|
||||
|
||||
if (returnCallback)
|
||||
{
|
||||
int callbackRef = createCancelCallback(L, functionRef, CreatureEventBindings, evt, id);
|
||||
CreatureEventBindings->Insert(id, evt, functionRef, shots, callbackRef);
|
||||
return 1; // Stack: callback
|
||||
}
|
||||
|
||||
CreatureEventBindings->Insert(id, evt, functionRef, shots);
|
||||
auto key = EntryKey<Hooks::CreatureEvents>((Hooks::CreatureEvents)event_id, entry);
|
||||
bindingID = CreatureEventBindings->Insert(key, functionRef, shots);
|
||||
createCancelCallback(L, bindingID, CreatureEventBindings);
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(guid != 0);
|
||||
|
||||
if (returnCallback)
|
||||
{
|
||||
int callbackRef = createCancelCallback(L, functionRef, CreatureUniqueBindings, evt, instanceId, guid);
|
||||
CreatureUniqueBindings->Insert(guid, instanceId, evt, functionRef, shots, callbackRef);
|
||||
return 1; // Stack: callback
|
||||
}
|
||||
|
||||
CreatureUniqueBindings->Insert(guid, instanceId, evt, functionRef, shots);
|
||||
auto key = UniqueObjectKey<Hooks::CreatureEvents>((Hooks::CreatureEvents)event_id, guid, instanceId);
|
||||
bindingID = CreatureUniqueBindings->Insert(key, functionRef, shots);
|
||||
createCancelCallback(L, bindingID, CreatureUniqueBindings);
|
||||
}
|
||||
|
||||
return 0; // Stack: (empty)
|
||||
return 1; // Stack: callback
|
||||
}
|
||||
break;
|
||||
|
||||
case Hooks::REGTYPE_CREATURE_GOSSIP:
|
||||
if (evt < Hooks::GOSSIP_EVENT_COUNT)
|
||||
if (event_id < Hooks::GOSSIP_EVENT_COUNT)
|
||||
{
|
||||
if (!eObjectMgr->GetCreatureTemplate(id))
|
||||
if (!eObjectMgr->GetCreatureTemplate(entry))
|
||||
{
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, functionRef);
|
||||
luaL_error(L, "Couldn't find a creature with (ID: %d)!", id);
|
||||
luaL_error(L, "Couldn't find a creature with (ID: %d)!", entry);
|
||||
return 0; // Stack: (empty)
|
||||
}
|
||||
|
||||
if (returnCallback)
|
||||
{
|
||||
int callbackRef = createCancelCallback(L, functionRef, CreatureGossipBindings, evt, id);
|
||||
CreatureGossipBindings->Insert(id, evt, functionRef, shots, callbackRef);
|
||||
return 1; // Stack: callback
|
||||
}
|
||||
|
||||
CreatureGossipBindings->Insert(id, evt, functionRef, shots);
|
||||
return 0; // Stack: (empty)
|
||||
auto key = EntryKey<Hooks::GossipEvents>((Hooks::GossipEvents)event_id, entry);
|
||||
bindingID = CreatureGossipBindings->Insert(key, functionRef, shots);
|
||||
createCancelCallback(L, bindingID, CreatureGossipBindings);
|
||||
return 1; // Stack: callback
|
||||
}
|
||||
break;
|
||||
|
||||
case Hooks::REGTYPE_GAMEOBJECT:
|
||||
if (evt < Hooks::GAMEOBJECT_EVENT_COUNT)
|
||||
if (event_id < Hooks::GAMEOBJECT_EVENT_COUNT)
|
||||
{
|
||||
if (!eObjectMgr->GetGameObjectTemplate(id))
|
||||
if (!eObjectMgr->GetGameObjectTemplate(entry))
|
||||
{
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, functionRef);
|
||||
luaL_error(L, "Couldn't find a gameobject with (ID: %d)!", id);
|
||||
luaL_error(L, "Couldn't find a gameobject with (ID: %d)!", entry);
|
||||
return 0; // Stack: (empty)
|
||||
}
|
||||
|
||||
if (returnCallback)
|
||||
{
|
||||
int callbackRef = createCancelCallback(L, functionRef, GameObjectEventBindings, evt, id);
|
||||
GameObjectEventBindings->Insert(id, evt, functionRef, shots, callbackRef);
|
||||
return 1; // Stack: callback
|
||||
}
|
||||
|
||||
GameObjectEventBindings->Insert(id, evt, functionRef, shots);
|
||||
return 0; // Stack: (empty)
|
||||
auto key = EntryKey<Hooks::GameObjectEvents>((Hooks::GameObjectEvents)event_id, entry);
|
||||
bindingID = GameObjectEventBindings->Insert(key, functionRef, shots);
|
||||
createCancelCallback(L, bindingID, GameObjectEventBindings);
|
||||
return 1; // Stack: callback
|
||||
}
|
||||
break;
|
||||
|
||||
case Hooks::REGTYPE_GAMEOBJECT_GOSSIP:
|
||||
if (evt < Hooks::GOSSIP_EVENT_COUNT)
|
||||
if (event_id < Hooks::GOSSIP_EVENT_COUNT)
|
||||
{
|
||||
if (!eObjectMgr->GetGameObjectTemplate(id))
|
||||
if (!eObjectMgr->GetGameObjectTemplate(entry))
|
||||
{
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, functionRef);
|
||||
luaL_error(L, "Couldn't find a gameobject with (ID: %d)!", id);
|
||||
luaL_error(L, "Couldn't find a gameobject with (ID: %d)!", entry);
|
||||
return 0; // Stack: (empty)
|
||||
}
|
||||
|
||||
if (returnCallback)
|
||||
{
|
||||
int callbackRef = createCancelCallback(L, functionRef, GameObjectGossipBindings, evt, id);
|
||||
GameObjectGossipBindings->Insert(id, evt, functionRef, shots, callbackRef);
|
||||
return 1; // Stack: callback
|
||||
}
|
||||
|
||||
GameObjectGossipBindings->Insert(id, evt, functionRef, shots);
|
||||
return 0; // Stack: (empty)
|
||||
auto key = EntryKey<Hooks::GossipEvents>((Hooks::GossipEvents)event_id, entry);
|
||||
bindingID = GameObjectGossipBindings->Insert(key, functionRef, shots);
|
||||
createCancelCallback(L, bindingID, GameObjectGossipBindings);
|
||||
return 1; // Stack: callback
|
||||
}
|
||||
break;
|
||||
|
||||
case Hooks::REGTYPE_ITEM:
|
||||
if (evt < Hooks::ITEM_EVENT_COUNT)
|
||||
if (event_id < Hooks::ITEM_EVENT_COUNT)
|
||||
{
|
||||
if (!eObjectMgr->GetItemTemplate(id))
|
||||
if (!eObjectMgr->GetItemTemplate(entry))
|
||||
{
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, functionRef);
|
||||
luaL_error(L, "Couldn't find a item with (ID: %d)!", id);
|
||||
luaL_error(L, "Couldn't find a item with (ID: %d)!", entry);
|
||||
return 0; // Stack: (empty)
|
||||
}
|
||||
|
||||
if (returnCallback)
|
||||
{
|
||||
int callbackRef = createCancelCallback(L, functionRef, ItemEventBindings, evt, id);
|
||||
ItemEventBindings->Insert(id, evt, functionRef, shots, callbackRef);
|
||||
return 1; // Stack: callback
|
||||
}
|
||||
|
||||
ItemEventBindings->Insert(id, evt, functionRef, shots);
|
||||
return 0; // Stack: (empty)
|
||||
auto key = EntryKey<Hooks::ItemEvents>((Hooks::ItemEvents)event_id, entry);
|
||||
bindingID = ItemEventBindings->Insert(key, functionRef, shots);
|
||||
createCancelCallback(L, bindingID, ItemEventBindings);
|
||||
return 1; // Stack: callback
|
||||
}
|
||||
break;
|
||||
|
||||
case Hooks::REGTYPE_ITEM_GOSSIP:
|
||||
if (evt < Hooks::GOSSIP_EVENT_COUNT)
|
||||
if (event_id < Hooks::GOSSIP_EVENT_COUNT)
|
||||
{
|
||||
if (!eObjectMgr->GetItemTemplate(id))
|
||||
if (!eObjectMgr->GetItemTemplate(entry))
|
||||
{
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, functionRef);
|
||||
luaL_error(L, "Couldn't find a item with (ID: %d)!", id);
|
||||
luaL_error(L, "Couldn't find a item with (ID: %d)!", entry);
|
||||
return 0; // Stack: (empty)
|
||||
}
|
||||
|
||||
if (returnCallback)
|
||||
{
|
||||
int callbackRef = createCancelCallback(L, functionRef, ItemGossipBindings, evt, id);
|
||||
ItemGossipBindings->Insert(id, evt, functionRef, shots, callbackRef);
|
||||
return 1; // Stack: callback
|
||||
}
|
||||
|
||||
ItemGossipBindings->Insert(id, evt, functionRef, shots);
|
||||
return 0; // Stack: (empty)
|
||||
auto key = EntryKey<Hooks::GossipEvents>((Hooks::GossipEvents)event_id, entry);
|
||||
bindingID = ItemGossipBindings->Insert(key, functionRef, shots);
|
||||
createCancelCallback(L, bindingID, ItemGossipBindings);
|
||||
return 1; // Stack: callback
|
||||
}
|
||||
break;
|
||||
|
||||
case Hooks::REGTYPE_PLAYER_GOSSIP:
|
||||
if (evt < Hooks::GOSSIP_EVENT_COUNT)
|
||||
if (event_id < Hooks::GOSSIP_EVENT_COUNT)
|
||||
{
|
||||
if (returnCallback)
|
||||
{
|
||||
int callbackRef = createCancelCallback(L, functionRef, playerGossipBindings, evt, id);
|
||||
playerGossipBindings->Insert(id, evt, functionRef, shots, callbackRef);
|
||||
return 1; // Stack: callback
|
||||
}
|
||||
|
||||
playerGossipBindings->Insert(id, evt, functionRef, shots);
|
||||
return 0; // Stack: (empty)
|
||||
auto key = EntryKey<Hooks::GossipEvents>((Hooks::GossipEvents)event_id, entry);
|
||||
bindingID = PlayerGossipBindings->Insert(key, functionRef, shots);
|
||||
createCancelCallback(L, bindingID, PlayerGossipBindings);
|
||||
return 1; // Stack: callback
|
||||
}
|
||||
break;
|
||||
}
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, functionRef);
|
||||
luaL_error(L, "Unknown event type (regtype %d, id %d, event %d)", regtype, id, evt);
|
||||
luaL_error(L, "Unknown event type (regtype %hhu, event %u, entry %u, guid " UI64FMTD ", instance %u)", regtype, event_id, entry, guid, instanceId);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1283,9 +1188,20 @@ int Eluna::CallOneFunction(int number_of_functions, int number_of_arguments, int
|
||||
|
||||
CreatureAI* Eluna::GetAI(Creature* creature)
|
||||
{
|
||||
if (CreatureEventBindings->HasEvents(creature->GetEntry()) ||
|
||||
CreatureUniqueBindings->HasEvents(creature->GET_GUID(), creature->GetInstanceId()))
|
||||
return new ElunaCreatureAI(creature);
|
||||
if (!IsEnabled())
|
||||
return NULL;
|
||||
|
||||
for (int i = 1; i < Hooks::CREATURE_EVENT_COUNT; ++i)
|
||||
{
|
||||
Hooks::CreatureEvents event_id = (Hooks::CreatureEvents)i;
|
||||
|
||||
auto entryKey = EntryKey<Hooks::CreatureEvents>(event_id, creature->GetEntry());
|
||||
auto uniqueKey = UniqueObjectKey<Hooks::CreatureEvents>(event_id, creature->GET_GUID(), creature->GetInstanceId());
|
||||
|
||||
if (CreatureEventBindings->HasBindingsFor(entryKey) ||
|
||||
CreatureUniqueBindings->HasBindingsFor(uniqueKey))
|
||||
return new ElunaCreatureAI(creature);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
101
LuaEngine.h
101
LuaEngine.h
@@ -86,14 +86,12 @@ typedef VehicleInfo Vehicle;
|
||||
struct lua_State;
|
||||
class EventMgr;
|
||||
class ElunaObject;
|
||||
template<typename T>
|
||||
class ElunaTemplate;
|
||||
template<typename T>
|
||||
class EventBind;
|
||||
template<typename T>
|
||||
class EntryBind;
|
||||
template<typename T>
|
||||
class UniqueBind;
|
||||
template<typename T> class ElunaTemplate;
|
||||
|
||||
template<typename K> class BindingMap;
|
||||
template<typename T> struct EventKey;
|
||||
template<typename T> struct EntryKey;
|
||||
template<typename T> struct UniqueObjectKey;
|
||||
|
||||
struct LuaScript
|
||||
{
|
||||
@@ -164,53 +162,26 @@ private:
|
||||
|
||||
// Some helpers for hooks to call event handlers.
|
||||
// The bodies of the templates are in HookHelpers.h, so if you want to use them you need to #include "HookHelpers.h".
|
||||
template<typename T> int SetupStack(EventBind<T>* event_bindings, EntryBind<T>* entry_bindings, UniqueBind<T>* guid_bindings, T event_id, uint32 entry, uint64 guid, uint32 instanceId, int number_of_arguments);
|
||||
int CallOneFunction(int number_of_functions, int number_of_arguments, int number_of_results);
|
||||
void CleanUpStack(int number_of_arguments);
|
||||
template<typename T> void ReplaceArgument(T value, uint8 index);
|
||||
template<typename T> void CallAllFunctions(EventBind<T>* event_bindings, EntryBind<T>* entry_bindings, UniqueBind<T>* guid_bindings, T event_id, uint32 entry, uint64 guid, uint32 instanceId);
|
||||
template<typename T> bool CallAllFunctionsBool(EventBind<T>* event_bindings, EntryBind<T>* entry_bindings, UniqueBind<T>* guid_bindings, T event_id, uint32 entry, uint64 guid, uint32 instanceId, bool default_value);
|
||||
template<typename K1, typename K2> int SetupStack(BindingMap<K1>* bindings1, BindingMap<K2>* bindings2, const K1& key1, const K2& key2, int number_of_arguments);
|
||||
int CallOneFunction(int number_of_functions, int number_of_arguments, int number_of_results);
|
||||
void CleanUpStack(int number_of_arguments);
|
||||
template<typename T> void ReplaceArgument(T value, uint8 index);
|
||||
template<typename K1, typename K2> void CallAllFunctions(BindingMap<K1>* bindings1, BindingMap<K2>* bindings2, const K1& key1, const K2& key2);
|
||||
template<typename K1, typename K2> bool CallAllFunctionsBool(BindingMap<K1>* bindings1, BindingMap<K2>* bindings2, const K1& key1, const K2& key2, bool default_value = false);
|
||||
|
||||
// Convenient overloads for Setup. Use these in hooks instead of original.
|
||||
template<typename T> int SetupStack(EventBind<T>* event_bindings, T event_id, int number_of_arguments)
|
||||
// Same as above but for only one binding instead of two.
|
||||
// `key` is passed twice because there's no NULL for references, but it's not actually used if `bindings2` is NULL.
|
||||
template<typename K> int SetupStack(BindingMap<K>* bindings, const K& key, int number_of_arguments)
|
||||
{
|
||||
return SetupStack(event_bindings, (EntryBind<T>*)NULL, (UniqueBind<T>*)NULL, event_id, 0, 0, 0, number_of_arguments);
|
||||
return SetupStack<K, K>(bindings, NULL, key, key, number_of_arguments);
|
||||
}
|
||||
template<typename T> int SetupStack(EntryBind<T>* entry_bindings, T event_id, uint32 entry, int number_of_arguments)
|
||||
template<typename K> void CallAllFunctions(BindingMap<K>* bindings, const K& key)
|
||||
{
|
||||
return SetupStack((EventBind<T>*)NULL, entry_bindings, (UniqueBind<T>*)NULL, event_id, entry, 0, 0, number_of_arguments);
|
||||
CallAllFunctions<K, K>(bindings, NULL, key, key);
|
||||
}
|
||||
template<typename T> int SetupStack(EntryBind<T>* entry_bindings, UniqueBind<T>* guid_bindings, T event_id, uint32 entry, uint64 guid, uint32 instanceId, int number_of_arguments)
|
||||
template<typename K> bool CallAllFunctionsBool(BindingMap<K>* bindings, const K& key, bool default_value = false)
|
||||
{
|
||||
return SetupStack((EventBind<T>*)NULL, entry_bindings, guid_bindings, event_id, entry, guid, instanceId, number_of_arguments);
|
||||
}
|
||||
|
||||
// Convenient overloads for CallAllFunctions. Use these in hooks instead of original.
|
||||
template<typename T> void CallAllFunctions(EventBind<T>* event_bindings, T event_id)
|
||||
{
|
||||
CallAllFunctions(event_bindings, (EntryBind<T>*)NULL, (UniqueBind<T>*)NULL, event_id, 0, 0, 0);
|
||||
}
|
||||
template<typename T> void CallAllFunctions(EntryBind<T>* entry_bindings, T event_id, uint32 entry)
|
||||
{
|
||||
CallAllFunctions((EventBind<T>*)NULL, entry_bindings, (UniqueBind<T>*)NULL, event_id, entry, 0, 0);
|
||||
}
|
||||
template<typename T> void CallAllFunctions(EntryBind<T>* entry_bindings, UniqueBind<T>* guid_bindings, T event_id, uint32 entry, uint64 guid, uint32 instanceId)
|
||||
{
|
||||
CallAllFunctions((EventBind<T>*)NULL, entry_bindings, guid_bindings, event_id, entry, guid, instanceId);
|
||||
}
|
||||
|
||||
// Convenient overloads for CallAllFunctionsBool. Use these in hooks instead of original.
|
||||
template<typename T> bool CallAllFunctionsBool(EventBind<T>* event_bindings, T event_id, bool default_value = false)
|
||||
{
|
||||
return CallAllFunctionsBool(event_bindings, (EntryBind<T>*)NULL, (UniqueBind<T>*)NULL, event_id, 0, 0, 0, default_value);
|
||||
}
|
||||
template<typename T> bool CallAllFunctionsBool(EntryBind<T>* entry_bindings, T event_id, uint32 entry, bool default_value = false)
|
||||
{
|
||||
return CallAllFunctionsBool((EventBind<T>*)NULL, entry_bindings, (UniqueBind<T>*)NULL, event_id, entry, 0, 0, default_value);
|
||||
}
|
||||
template<typename T> bool CallAllFunctionsBool(EntryBind<T>* entry_bindings, UniqueBind<T>* guid_bindings, T event_id, uint32 entry, uint64 guid, uint32 instanceId, bool default_value = false)
|
||||
{
|
||||
return CallAllFunctionsBool((EventBind<T>*)NULL, entry_bindings, guid_bindings, event_id, entry, guid, instanceId, default_value);
|
||||
return CallAllFunctionsBool<K, K>(bindings, NULL, key, key, default_value);
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -219,23 +190,23 @@ public:
|
||||
lua_State* L;
|
||||
EventMgr* eventMgr;
|
||||
|
||||
EventBind<Hooks::ServerEvents>* ServerEventBindings;
|
||||
EventBind<Hooks::PlayerEvents>* PlayerEventBindings;
|
||||
EventBind<Hooks::GuildEvents>* GuildEventBindings;
|
||||
EventBind<Hooks::GroupEvents>* GroupEventBindings;
|
||||
EventBind<Hooks::VehicleEvents>* VehicleEventBindings;
|
||||
EventBind<Hooks::BGEvents>* BGEventBindings;
|
||||
BindingMap< EventKey<Hooks::ServerEvents> >* ServerEventBindings;
|
||||
BindingMap< EventKey<Hooks::PlayerEvents> >* PlayerEventBindings;
|
||||
BindingMap< EventKey<Hooks::GuildEvents> >* GuildEventBindings;
|
||||
BindingMap< EventKey<Hooks::GroupEvents> >* GroupEventBindings;
|
||||
BindingMap< EventKey<Hooks::VehicleEvents> >* VehicleEventBindings;
|
||||
BindingMap< EventKey<Hooks::BGEvents> >* BGEventBindings;
|
||||
|
||||
EntryBind<Hooks::PacketEvents>* PacketEventBindings;
|
||||
EntryBind<Hooks::CreatureEvents>* CreatureEventBindings;
|
||||
EntryBind<Hooks::GossipEvents>* CreatureGossipBindings;
|
||||
EntryBind<Hooks::GameObjectEvents>* GameObjectEventBindings;
|
||||
EntryBind<Hooks::GossipEvents>* GameObjectGossipBindings;
|
||||
EntryBind<Hooks::ItemEvents>* ItemEventBindings;
|
||||
EntryBind<Hooks::GossipEvents>* ItemGossipBindings;
|
||||
EntryBind<Hooks::GossipEvents>* playerGossipBindings;
|
||||
BindingMap< EntryKey<Hooks::PacketEvents> >* PacketEventBindings;
|
||||
BindingMap< EntryKey<Hooks::CreatureEvents> >* CreatureEventBindings;
|
||||
BindingMap< EntryKey<Hooks::GossipEvents> >* CreatureGossipBindings;
|
||||
BindingMap< EntryKey<Hooks::GameObjectEvents> >* GameObjectEventBindings;
|
||||
BindingMap< EntryKey<Hooks::GossipEvents> >* GameObjectGossipBindings;
|
||||
BindingMap< EntryKey<Hooks::ItemEvents> >* ItemEventBindings;
|
||||
BindingMap< EntryKey<Hooks::GossipEvents> >* ItemGossipBindings;
|
||||
BindingMap< EntryKey<Hooks::GossipEvents> >* PlayerGossipBindings;
|
||||
|
||||
UniqueBind<Hooks::CreatureEvents>* CreatureUniqueBindings;
|
||||
BindingMap< UniqueObjectKey<Hooks::CreatureEvents> >* CreatureUniqueBindings;
|
||||
|
||||
static void Initialize();
|
||||
static void Uninitialize();
|
||||
@@ -272,7 +243,7 @@ public:
|
||||
bool ShouldReload() const { return reload; }
|
||||
bool IsEnabled() const { return enabled && IsInitialized(); }
|
||||
bool HasLuaState() const { return L != NULL; }
|
||||
int Register(lua_State* L, uint8 reg, uint32 id, uint64 guid, uint32 instanceId, uint32 evt, int func, uint32 shots, bool returnCallback);
|
||||
int Register(lua_State* L, uint8 reg, uint32 entry, uint64 guid, uint32 instanceId, uint32 event_id, int functionRef, uint32 shots);
|
||||
|
||||
// Non-static pushes, to be used in hooks.
|
||||
// These just call the correct static version with the main thread's Lua state.
|
||||
|
||||
147
PacketHooks.cpp
Normal file
147
PacketHooks.cpp
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (C) 2010 - 2015 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_SERVER(EVENT) \
|
||||
if (!IsEnabled())\
|
||||
return;\
|
||||
auto key = EventKey<ServerEvents>(EVENT);\
|
||||
if (!ServerEventBindings->HasBindingsFor(key))\
|
||||
return;\
|
||||
LOCK_ELUNA
|
||||
|
||||
#define START_HOOK_PACKET(EVENT, OPCODE) \
|
||||
if (!IsEnabled())\
|
||||
return;\
|
||||
auto key = EntryKey<PacketEvents>(EVENT, OPCODE);\
|
||||
if (!PacketEventBindings->HasBindingsFor(key))\
|
||||
return;\
|
||||
LOCK_ELUNA
|
||||
|
||||
bool Eluna::OnPacketSend(WorldSession* session, WorldPacket& packet)
|
||||
{
|
||||
bool result = true;
|
||||
Player* player = NULL;
|
||||
if (session)
|
||||
player = session->GetPlayer();
|
||||
OnPacketSendAny(player, packet, result);
|
||||
OnPacketSendOne(player, packet, result);
|
||||
return result;
|
||||
}
|
||||
void Eluna::OnPacketSendAny(Player* player, WorldPacket& packet, bool& result)
|
||||
{
|
||||
START_HOOK_SERVER(SERVER_EVENT_ON_PACKET_SEND);
|
||||
Push(new WorldPacket(packet));
|
||||
Push(player);
|
||||
int n = SetupStack(ServerEventBindings, key, 2);
|
||||
|
||||
while (n > 0)
|
||||
{
|
||||
int r = CallOneFunction(n--, 2, 2);
|
||||
|
||||
if (lua_isboolean(L, r + 0) && !lua_toboolean(L, r + 0))
|
||||
result = false;
|
||||
|
||||
if (lua_isuserdata(L, r + 1))
|
||||
if (WorldPacket* data = CHECKOBJ<WorldPacket>(L, r + 1, false))
|
||||
packet = *data;
|
||||
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
|
||||
CleanUpStack(2);
|
||||
}
|
||||
|
||||
void Eluna::OnPacketSendOne(Player* player, WorldPacket& packet, bool& result)
|
||||
{
|
||||
START_HOOK_PACKET(PACKET_EVENT_ON_PACKET_SEND, packet.GetOpcode());
|
||||
Push(new WorldPacket(packet));
|
||||
Push(player);
|
||||
int n = SetupStack(PacketEventBindings, key, 2);
|
||||
|
||||
while (n > 0)
|
||||
{
|
||||
int r = CallOneFunction(n--, 2, 2);
|
||||
|
||||
if (lua_isboolean(L, r + 0) && !lua_toboolean(L, r + 0))
|
||||
result = false;
|
||||
|
||||
if (lua_isuserdata(L, r + 1))
|
||||
if (WorldPacket* data = CHECKOBJ<WorldPacket>(L, r + 1, false))
|
||||
packet = *data;
|
||||
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
|
||||
CleanUpStack(2);
|
||||
}
|
||||
|
||||
bool Eluna::OnPacketReceive(WorldSession* session, WorldPacket& packet)
|
||||
{
|
||||
bool result = true;
|
||||
Player* player = NULL;
|
||||
if (session)
|
||||
player = session->GetPlayer();
|
||||
OnPacketReceiveAny(player, packet, result);
|
||||
OnPacketReceiveOne(player, packet, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Eluna::OnPacketReceiveAny(Player* player, WorldPacket& packet, bool& result)
|
||||
{
|
||||
START_HOOK_SERVER(SERVER_EVENT_ON_PACKET_RECEIVE);
|
||||
Push(new WorldPacket(packet));
|
||||
Push(player);
|
||||
int n = SetupStack(ServerEventBindings, key, 2);
|
||||
|
||||
while (n > 0)
|
||||
{
|
||||
int r = CallOneFunction(n--, 2, 2);
|
||||
|
||||
if (lua_isboolean(L, r + 0) && !lua_toboolean(L, r + 0))
|
||||
result = false;
|
||||
|
||||
if (lua_isuserdata(L, r + 1))
|
||||
if (WorldPacket* data = CHECKOBJ<WorldPacket>(L, r + 1, false))
|
||||
packet = *data;
|
||||
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
|
||||
CleanUpStack(2);
|
||||
}
|
||||
|
||||
void Eluna::OnPacketReceiveOne(Player* player, WorldPacket& packet, bool& result)
|
||||
{
|
||||
START_HOOK_PACKET(PACKET_EVENT_ON_PACKET_SEND, packet.GetOpcode());
|
||||
Push(new WorldPacket(packet));
|
||||
Push(player);
|
||||
int n = SetupStack(PacketEventBindings, key, 2);
|
||||
|
||||
while (n > 0)
|
||||
{
|
||||
int r = CallOneFunction(n--, 2, 2);
|
||||
|
||||
if (lua_isboolean(L, r + 0) && !lua_toboolean(L, r + 0))
|
||||
result = false;
|
||||
|
||||
if (lua_isuserdata(L, r + 1))
|
||||
if (WorldPacket* data = CHECKOBJ<WorldPacket>(L, r + 1, false))
|
||||
packet = *data;
|
||||
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
|
||||
CleanUpStack(2);
|
||||
}
|
||||
369
PlayerHooks.cpp
369
PlayerHooks.cpp
@@ -4,69 +4,39 @@
|
||||
* Please see the included DOCS/LICENSE.md for more information
|
||||
*/
|
||||
|
||||
#ifndef _PLAYER_HOOKS_H
|
||||
#define _PLAYER_HOOKS_H
|
||||
|
||||
#include "Hooks.h"
|
||||
#include "HookHelpers.h"
|
||||
#include "LuaEngine.h"
|
||||
#include "ElunaBinding.h"
|
||||
#include "BindingMap.h"
|
||||
#include "ElunaIncludes.h"
|
||||
#include "ElunaTemplate.h"
|
||||
|
||||
using namespace Hooks;
|
||||
|
||||
#define START_HOOK(EVENT) \
|
||||
if (!IsEnabled())\
|
||||
return;\
|
||||
auto key = EventKey<PlayerEvents>(EVENT);\
|
||||
if (!PlayerEventBindings->HasBindingsFor(key))\
|
||||
return;\
|
||||
LOCK_ELUNA
|
||||
|
||||
#define START_HOOK_WITH_RETVAL(EVENT, RETVAL) \
|
||||
if (!IsEnabled())\
|
||||
return RETVAL;\
|
||||
auto key = EventKey<PlayerEvents>(EVENT);\
|
||||
if (!PlayerEventBindings->HasBindingsFor(key))\
|
||||
return RETVAL;\
|
||||
LOCK_ELUNA
|
||||
|
||||
void Eluna::OnLearnTalents(Player* pPlayer, uint32 talentId, uint32 talentRank, uint32 spellid)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_LEARN_TALENTS))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_LEARN_TALENTS);
|
||||
Push(pPlayer);
|
||||
Push(talentId);
|
||||
Push(talentRank);
|
||||
Push(spellid);
|
||||
CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_LEARN_TALENTS);
|
||||
}
|
||||
|
||||
void Eluna::HandleGossipSelectOption(Player* pPlayer, Item* item, uint32 sender, uint32 action, const std::string& code)
|
||||
{
|
||||
if (!ItemGossipBindings->HasEvents(GOSSIP_EVENT_ON_SELECT, item->GetEntry()))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
pPlayer->PlayerTalkClass->ClearMenus();
|
||||
|
||||
Push(pPlayer);
|
||||
Push(item);
|
||||
Push(sender);
|
||||
Push(action);
|
||||
if (code.empty())
|
||||
Push();
|
||||
else
|
||||
Push(code);
|
||||
|
||||
CallAllFunctions(ItemGossipBindings, GOSSIP_EVENT_ON_SELECT, item->GetEntry());
|
||||
}
|
||||
|
||||
void Eluna::HandleGossipSelectOption(Player* pPlayer, uint32 menuId, uint32 sender, uint32 action, const std::string& code)
|
||||
{
|
||||
if (!playerGossipBindings->HasEvents(GOSSIP_EVENT_ON_SELECT, menuId))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
pPlayer->PlayerTalkClass->ClearMenus();
|
||||
|
||||
Push(pPlayer); // receiver
|
||||
Push(pPlayer); // sender, just not to mess up the amount of args.
|
||||
Push(sender);
|
||||
Push(action);
|
||||
if (code.empty())
|
||||
Push();
|
||||
else
|
||||
Push(code);
|
||||
|
||||
CallAllFunctions(playerGossipBindings, GOSSIP_EVENT_ON_SELECT, menuId);
|
||||
CallAllFunctions(PlayerEventBindings, key);
|
||||
}
|
||||
|
||||
// Player
|
||||
@@ -95,103 +65,76 @@ bool Eluna::OnCommand(Player* player, const char* text)
|
||||
}
|
||||
}
|
||||
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_COMMAND))
|
||||
return true;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_COMMAND, true);
|
||||
Push(player);
|
||||
Push(fullcmd);
|
||||
return CallAllFunctionsBool(PlayerEventBindings, PLAYER_EVENT_ON_COMMAND, true);
|
||||
return CallAllFunctionsBool(PlayerEventBindings, key, true);
|
||||
}
|
||||
|
||||
void Eluna::OnLootItem(Player* pPlayer, Item* pItem, uint32 count, uint64 guid)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_LOOT_ITEM))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_LOOT_ITEM);
|
||||
Push(pPlayer);
|
||||
Push(pItem);
|
||||
Push(count);
|
||||
Push(guid);
|
||||
CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_LOOT_ITEM);
|
||||
CallAllFunctions(PlayerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnLootMoney(Player* pPlayer, uint32 amount)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_LOOT_MONEY))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_LOOT_MONEY);
|
||||
Push(pPlayer);
|
||||
Push(amount);
|
||||
CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_LOOT_MONEY);
|
||||
CallAllFunctions(PlayerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnFirstLogin(Player* pPlayer)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_FIRST_LOGIN))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_FIRST_LOGIN);
|
||||
Push(pPlayer);
|
||||
CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_FIRST_LOGIN);
|
||||
CallAllFunctions(PlayerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnRepop(Player* pPlayer)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_REPOP))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_REPOP);
|
||||
Push(pPlayer);
|
||||
CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_REPOP);
|
||||
CallAllFunctions(PlayerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnResurrect(Player* pPlayer)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_RESURRECT))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_RESURRECT);
|
||||
Push(pPlayer);
|
||||
CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_RESURRECT);
|
||||
CallAllFunctions(PlayerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnQuestAbandon(Player* pPlayer, uint32 questId)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_QUEST_ABANDON))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_QUEST_ABANDON);
|
||||
Push(pPlayer);
|
||||
Push(questId);
|
||||
CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_QUEST_ABANDON);
|
||||
CallAllFunctions(PlayerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnEquip(Player* pPlayer, Item* pItem, uint8 bag, uint8 slot)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_EQUIP))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_EQUIP);
|
||||
Push(pPlayer);
|
||||
Push(pItem);
|
||||
Push(bag);
|
||||
Push(slot);
|
||||
CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_EQUIP);
|
||||
CallAllFunctions(PlayerEventBindings, key);
|
||||
}
|
||||
|
||||
InventoryResult Eluna::OnCanUseItem(const Player* pPlayer, uint32 itemEntry)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_CAN_USE_ITEM))
|
||||
return EQUIP_ERR_OK;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_CAN_USE_ITEM, EQUIP_ERR_OK);
|
||||
InventoryResult result = EQUIP_ERR_OK;
|
||||
Push(pPlayer);
|
||||
Push(itemEntry);
|
||||
int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_CAN_USE_ITEM, 2);
|
||||
int n = SetupStack(PlayerEventBindings, key, 2);
|
||||
|
||||
while (n > 0)
|
||||
{
|
||||
@@ -208,101 +151,74 @@ InventoryResult Eluna::OnCanUseItem(const Player* pPlayer, uint32 itemEntry)
|
||||
}
|
||||
void Eluna::OnPlayerEnterCombat(Player* pPlayer, Unit* pEnemy)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_ENTER_COMBAT))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_ENTER_COMBAT);
|
||||
Push(pPlayer);
|
||||
Push(pEnemy);
|
||||
CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_ENTER_COMBAT);
|
||||
CallAllFunctions(PlayerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnPlayerLeaveCombat(Player* pPlayer)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_LEAVE_COMBAT))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_LEAVE_COMBAT);
|
||||
Push(pPlayer);
|
||||
CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_LEAVE_COMBAT);
|
||||
CallAllFunctions(PlayerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnPVPKill(Player* pKiller, Player* pKilled)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_KILL_PLAYER))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_KILL_PLAYER);
|
||||
Push(pKiller);
|
||||
Push(pKilled);
|
||||
CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_KILL_PLAYER);
|
||||
CallAllFunctions(PlayerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnCreatureKill(Player* pKiller, Creature* pKilled)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_KILL_CREATURE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_KILL_CREATURE);
|
||||
Push(pKiller);
|
||||
Push(pKilled);
|
||||
CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_KILL_CREATURE);
|
||||
CallAllFunctions(PlayerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnPlayerKilledByCreature(Creature* pKiller, Player* pKilled)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_KILLED_BY_CREATURE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_KILLED_BY_CREATURE);
|
||||
Push(pKiller);
|
||||
Push(pKilled);
|
||||
CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_KILLED_BY_CREATURE);
|
||||
CallAllFunctions(PlayerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnLevelChanged(Player* pPlayer, uint8 oldLevel)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_LEVEL_CHANGE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_LEVEL_CHANGE);
|
||||
Push(pPlayer);
|
||||
Push(oldLevel);
|
||||
CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_LEVEL_CHANGE);
|
||||
CallAllFunctions(PlayerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnFreeTalentPointsChanged(Player* pPlayer, uint32 newPoints)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_TALENTS_CHANGE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_TALENTS_CHANGE);
|
||||
Push(pPlayer);
|
||||
Push(newPoints);
|
||||
CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_TALENTS_CHANGE);
|
||||
CallAllFunctions(PlayerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnTalentsReset(Player* pPlayer, bool noCost)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_TALENTS_RESET))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_TALENTS_RESET);
|
||||
Push(pPlayer);
|
||||
Push(noCost);
|
||||
CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_TALENTS_RESET);
|
||||
CallAllFunctions(PlayerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnMoneyChanged(Player* pPlayer, int32& amount)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_MONEY_CHANGE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_MONEY_CHANGE);
|
||||
Push(pPlayer);
|
||||
Push(amount);
|
||||
int amountIndex = lua_gettop(L);
|
||||
int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_MONEY_CHANGE, 2);
|
||||
int n = SetupStack(PlayerEventBindings, key, 2);
|
||||
|
||||
while (n > 0)
|
||||
{
|
||||
@@ -323,15 +239,12 @@ void Eluna::OnMoneyChanged(Player* pPlayer, int32& amount)
|
||||
|
||||
void Eluna::OnGiveXP(Player* pPlayer, uint32& amount, Unit* pVictim)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_GIVE_XP))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_GIVE_XP);
|
||||
Push(pPlayer);
|
||||
Push(amount);
|
||||
Push(pVictim);
|
||||
int amountIndex = lua_gettop(L) - 1;
|
||||
int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_GIVE_XP, 3);
|
||||
int n = SetupStack(PlayerEventBindings, key, 3);
|
||||
|
||||
while (n > 0)
|
||||
{
|
||||
@@ -352,16 +265,13 @@ void Eluna::OnGiveXP(Player* pPlayer, uint32& amount, Unit* pVictim)
|
||||
|
||||
void Eluna::OnReputationChange(Player* pPlayer, uint32 factionID, int32& standing, bool incremental)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_REPUTATION_CHANGE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_REPUTATION_CHANGE);
|
||||
Push(pPlayer);
|
||||
Push(factionID);
|
||||
Push(standing);
|
||||
Push(incremental);
|
||||
int standingIndex = lua_gettop(L) - 1;
|
||||
int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_REPUTATION_CHANGE, 4);
|
||||
int n = SetupStack(PlayerEventBindings, key, 4);
|
||||
|
||||
while (n > 0)
|
||||
{
|
||||
@@ -382,183 +292,115 @@ void Eluna::OnReputationChange(Player* pPlayer, uint32 factionID, int32& standin
|
||||
|
||||
void Eluna::OnDuelRequest(Player* pTarget, Player* pChallenger)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_DUEL_REQUEST))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_DUEL_REQUEST);
|
||||
Push(pTarget);
|
||||
Push(pChallenger);
|
||||
CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_DUEL_REQUEST);
|
||||
CallAllFunctions(PlayerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnDuelStart(Player* pStarter, Player* pChallenger)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_DUEL_START))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_DUEL_START);
|
||||
Push(pStarter);
|
||||
Push(pChallenger);
|
||||
CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_DUEL_START);
|
||||
CallAllFunctions(PlayerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnDuelEnd(Player* pWinner, Player* pLoser, DuelCompleteType type)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_DUEL_END))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_DUEL_END);
|
||||
Push(pWinner);
|
||||
Push(pLoser);
|
||||
Push(type);
|
||||
CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_DUEL_END);
|
||||
CallAllFunctions(PlayerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnEmote(Player* pPlayer, uint32 emote)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_EMOTE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_EMOTE);
|
||||
Push(pPlayer);
|
||||
Push(emote);
|
||||
CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_EMOTE);
|
||||
CallAllFunctions(PlayerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnTextEmote(Player* pPlayer, uint32 textEmote, uint32 emoteNum, uint64 guid)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_TEXT_EMOTE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_TEXT_EMOTE);
|
||||
Push(pPlayer);
|
||||
Push(textEmote);
|
||||
Push(emoteNum);
|
||||
Push(guid);
|
||||
CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_TEXT_EMOTE);
|
||||
CallAllFunctions(PlayerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnSpellCast(Player* pPlayer, Spell* pSpell, bool skipCheck)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_SPELL_CAST))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_SPELL_CAST);
|
||||
Push(pPlayer);
|
||||
Push(pSpell);
|
||||
Push(skipCheck);
|
||||
CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_SPELL_CAST);
|
||||
CallAllFunctions(PlayerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnLogin(Player* pPlayer)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_LOGIN))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_LOGIN);
|
||||
Push(pPlayer);
|
||||
CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_LOGIN);
|
||||
CallAllFunctions(PlayerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnLogout(Player* pPlayer)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_LOGOUT))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_LOGOUT);
|
||||
Push(pPlayer);
|
||||
CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_LOGOUT);
|
||||
CallAllFunctions(PlayerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnCreate(Player* pPlayer)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_CHARACTER_CREATE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_CHARACTER_CREATE);
|
||||
Push(pPlayer);
|
||||
CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_CHARACTER_CREATE);
|
||||
CallAllFunctions(PlayerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnDelete(uint32 guidlow)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_CHARACTER_DELETE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_CHARACTER_DELETE);
|
||||
Push(guidlow);
|
||||
CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_CHARACTER_DELETE);
|
||||
CallAllFunctions(PlayerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnSave(Player* pPlayer)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_SAVE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_SAVE);
|
||||
Push(pPlayer);
|
||||
CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_SAVE);
|
||||
CallAllFunctions(PlayerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnBindToInstance(Player* pPlayer, Difficulty difficulty, uint32 mapid, bool permanent)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_BIND_TO_INSTANCE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_BIND_TO_INSTANCE);
|
||||
Push(pPlayer);
|
||||
Push(difficulty);
|
||||
Push(mapid);
|
||||
Push(permanent);
|
||||
CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_BIND_TO_INSTANCE);
|
||||
CallAllFunctions(PlayerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnUpdateZone(Player* pPlayer, uint32 newZone, uint32 newArea)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_UPDATE_ZONE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_UPDATE_ZONE);
|
||||
Push(pPlayer);
|
||||
Push(newZone);
|
||||
Push(newArea);
|
||||
CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_UPDATE_ZONE);
|
||||
CallAllFunctions(PlayerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnMapChanged(Player* player)
|
||||
{
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_MAP_CHANGE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(PLAYER_EVENT_ON_MAP_CHANGE);
|
||||
Push(player);
|
||||
CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_MAP_CHANGE);
|
||||
}
|
||||
|
||||
// AddOns
|
||||
bool Eluna::OnAddonMessage(Player* sender, uint32 type, std::string& msg, Player* receiver, Guild* guild, Group* group, Channel* channel)
|
||||
{
|
||||
if (!ServerEventBindings->HasEvents(ADDON_EVENT_ON_MESSAGE))
|
||||
return true;
|
||||
|
||||
LOCK_ELUNA;
|
||||
Push(sender);
|
||||
Push(type);
|
||||
const char* c_msg = msg.c_str();
|
||||
Push(strtok((char*)c_msg, "\t")); // prefix
|
||||
Push(strtok(NULL, "")); // msg
|
||||
if (receiver)
|
||||
Push(receiver);
|
||||
else if (guild)
|
||||
Push(guild);
|
||||
else if (group)
|
||||
Push(group);
|
||||
else if (channel)
|
||||
Push(channel->GetChannelId());
|
||||
else
|
||||
Push();
|
||||
|
||||
return CallAllFunctionsBool(ServerEventBindings, ADDON_EVENT_ON_MESSAGE, true);
|
||||
CallAllFunctions(PlayerEventBindings, key);
|
||||
}
|
||||
|
||||
bool Eluna::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg)
|
||||
@@ -566,16 +408,13 @@ bool Eluna::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg)
|
||||
if (lang == LANG_ADDON)
|
||||
return OnAddonMessage(pPlayer, type, msg, NULL, NULL, NULL, NULL);
|
||||
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_CHAT))
|
||||
return true;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_CHAT, true);
|
||||
bool result = true;
|
||||
Push(pPlayer);
|
||||
Push(msg);
|
||||
Push(type);
|
||||
Push(lang);
|
||||
int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_CHAT, 4);
|
||||
int n = SetupStack(PlayerEventBindings, key, 4);
|
||||
|
||||
while (n > 0)
|
||||
{
|
||||
@@ -599,17 +438,14 @@ bool Eluna::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg,
|
||||
if (lang == LANG_ADDON)
|
||||
return OnAddonMessage(pPlayer, type, msg, NULL, NULL, pGroup, NULL);
|
||||
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_GROUP_CHAT))
|
||||
return true;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_GROUP_CHAT, true);
|
||||
bool result = true;
|
||||
Push(pPlayer);
|
||||
Push(msg);
|
||||
Push(type);
|
||||
Push(lang);
|
||||
Push(pGroup);
|
||||
int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_GROUP_CHAT, 5);
|
||||
int n = SetupStack(PlayerEventBindings, key, 5);
|
||||
|
||||
while (n > 0)
|
||||
{
|
||||
@@ -633,17 +469,14 @@ bool Eluna::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg,
|
||||
if (lang == LANG_ADDON)
|
||||
return OnAddonMessage(pPlayer, type, msg, NULL, pGuild, NULL, NULL);
|
||||
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_GUILD_CHAT))
|
||||
return true;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_GUILD_CHAT, true);
|
||||
bool result = true;
|
||||
Push(pPlayer);
|
||||
Push(msg);
|
||||
Push(type);
|
||||
Push(lang);
|
||||
Push(pGuild);
|
||||
int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_GUILD_CHAT, 5);
|
||||
int n = SetupStack(PlayerEventBindings, key, 5);
|
||||
|
||||
while (n > 0)
|
||||
{
|
||||
@@ -667,17 +500,14 @@ bool Eluna::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg,
|
||||
if (lang == LANG_ADDON)
|
||||
return OnAddonMessage(pPlayer, type, msg, NULL, NULL, NULL, pChannel);
|
||||
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_CHANNEL_CHAT))
|
||||
return true;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_CHANNEL_CHAT, true);
|
||||
bool result = true;
|
||||
Push(pPlayer);
|
||||
Push(msg);
|
||||
Push(type);
|
||||
Push(lang);
|
||||
Push(pChannel->GetChannelId());
|
||||
int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_CHANNEL_CHAT, 5);
|
||||
int n = SetupStack(PlayerEventBindings, key, 5);
|
||||
|
||||
while (n > 0)
|
||||
{
|
||||
@@ -701,17 +531,14 @@ bool Eluna::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg,
|
||||
if (lang == LANG_ADDON)
|
||||
return OnAddonMessage(pPlayer, type, msg, pReceiver, NULL, NULL, NULL);
|
||||
|
||||
if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_WHISPER))
|
||||
return true;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_WHISPER, true);
|
||||
bool result = true;
|
||||
Push(pPlayer);
|
||||
Push(msg);
|
||||
Push(type);
|
||||
Push(lang);
|
||||
Push(pReceiver);
|
||||
int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_WHISPER, 5);
|
||||
int n = SetupStack(PlayerEventBindings, key, 5);
|
||||
|
||||
while (n > 0)
|
||||
{
|
||||
@@ -729,5 +556,3 @@ bool Eluna::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg,
|
||||
CleanUpStack(5);
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // _PLAYER_HOOKS_H
|
||||
|
||||
329
ServerHooks.cpp
329
ServerHooks.cpp
@@ -4,19 +4,54 @@
|
||||
* Please see the included DOCS/LICENSE.md for more information
|
||||
*/
|
||||
|
||||
#ifndef _SERVER_HOOKS_H
|
||||
#define _SERVER_HOOKS_H
|
||||
|
||||
#include "Hooks.h"
|
||||
#include "HookHelpers.h"
|
||||
#include "LuaEngine.h"
|
||||
#include "ElunaBinding.h"
|
||||
#include "BindingMap.h"
|
||||
#include "ElunaEventMgr.h"
|
||||
#include "ElunaIncludes.h"
|
||||
#include "ElunaTemplate.h"
|
||||
|
||||
using namespace Hooks;
|
||||
|
||||
#define START_HOOK(EVENT) \
|
||||
if (!IsEnabled())\
|
||||
return;\
|
||||
auto key = EventKey<ServerEvents>(EVENT);\
|
||||
if (!ServerEventBindings->HasBindingsFor(key))\
|
||||
return;\
|
||||
LOCK_ELUNA
|
||||
|
||||
#define START_HOOK_WITH_RETVAL(EVENT, RETVAL) \
|
||||
if (!IsEnabled())\
|
||||
return RETVAL;\
|
||||
auto key = EventKey<ServerEvents>(EVENT);\
|
||||
if (!ServerEventBindings->HasBindingsFor(key))\
|
||||
return RETVAL;\
|
||||
LOCK_ELUNA
|
||||
|
||||
bool Eluna::OnAddonMessage(Player* sender, uint32 type, std::string& msg, Player* receiver, Guild* guild, Group* group, Channel* channel)
|
||||
{
|
||||
START_HOOK_WITH_RETVAL(ADDON_EVENT_ON_MESSAGE, true);
|
||||
Push(sender);
|
||||
Push(type);
|
||||
const char* c_msg = msg.c_str();
|
||||
Push(strtok((char*)c_msg, "\t")); // prefix
|
||||
Push(strtok(NULL, "")); // msg
|
||||
if (receiver)
|
||||
Push(receiver);
|
||||
else if (guild)
|
||||
Push(guild);
|
||||
else if (group)
|
||||
Push(group);
|
||||
else if (channel)
|
||||
Push(channel->GetChannelId());
|
||||
else
|
||||
Push();
|
||||
|
||||
return CallAllFunctionsBool(ServerEventBindings, key, true);
|
||||
}
|
||||
|
||||
void Eluna::OnTimedEvent(int funcRef, uint32 delay, uint32 calls, WorldObject* obj)
|
||||
{
|
||||
LOCK_ELUNA;
|
||||
@@ -40,53 +75,38 @@ void Eluna::OnTimedEvent(int funcRef, uint32 delay, uint32 calls, WorldObject* o
|
||||
|
||||
void Eluna::OnLuaStateClose()
|
||||
{
|
||||
if (!ServerEventBindings->HasEvents(ELUNA_EVENT_ON_LUA_STATE_CLOSE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
CallAllFunctions(ServerEventBindings, ELUNA_EVENT_ON_LUA_STATE_CLOSE);
|
||||
START_HOOK(ELUNA_EVENT_ON_LUA_STATE_CLOSE);
|
||||
CallAllFunctions(ServerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnLuaStateOpen()
|
||||
{
|
||||
if (!ServerEventBindings->HasEvents(ELUNA_EVENT_ON_LUA_STATE_OPEN))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
CallAllFunctions(ServerEventBindings, ELUNA_EVENT_ON_LUA_STATE_OPEN);
|
||||
START_HOOK(ELUNA_EVENT_ON_LUA_STATE_OPEN);
|
||||
CallAllFunctions(ServerEventBindings, key);
|
||||
}
|
||||
|
||||
// areatrigger
|
||||
bool Eluna::OnAreaTrigger(Player* pPlayer, AreaTriggerEntry const* pTrigger)
|
||||
{
|
||||
if (!ServerEventBindings->HasEvents(TRIGGER_EVENT_ON_TRIGGER))
|
||||
return false;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK_WITH_RETVAL(TRIGGER_EVENT_ON_TRIGGER, false);
|
||||
Push(pPlayer);
|
||||
Push(pTrigger->id);
|
||||
return CallAllFunctionsBool(ServerEventBindings, TRIGGER_EVENT_ON_TRIGGER);
|
||||
return CallAllFunctionsBool(ServerEventBindings, key);
|
||||
}
|
||||
|
||||
// weather
|
||||
void Eluna::OnChange(Weather* weather, uint32 zone, WeatherState state, float grade)
|
||||
{
|
||||
if (!ServerEventBindings->HasEvents(WEATHER_EVENT_ON_CHANGE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(WEATHER_EVENT_ON_CHANGE);
|
||||
Push(zone);
|
||||
Push(state);
|
||||
Push(grade);
|
||||
CallAllFunctions(ServerEventBindings, WEATHER_EVENT_ON_CHANGE);
|
||||
CallAllFunctions(ServerEventBindings, key);
|
||||
}
|
||||
|
||||
// Auction House
|
||||
void Eluna::OnAdd(AuctionHouseObject* /*ah*/, AuctionEntry* entry)
|
||||
{
|
||||
if (!ServerEventBindings->HasEvents(AUCTION_EVENT_ON_ADD))
|
||||
return;
|
||||
|
||||
Player* owner = eObjectAccessor->FindPlayer(MAKE_NEW_GUID(entry->owner, 0, HIGHGUID_PLAYER));
|
||||
#ifdef TRINITY
|
||||
Item* item = eAuctionMgr->GetAItem(entry->itemGUIDLow);
|
||||
@@ -100,7 +120,7 @@ void Eluna::OnAdd(AuctionHouseObject* /*ah*/, AuctionEntry* entry)
|
||||
if (!owner || !item)
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(AUCTION_EVENT_ON_ADD);
|
||||
Push(entry->Id);
|
||||
Push(owner);
|
||||
Push(item);
|
||||
@@ -109,14 +129,11 @@ void Eluna::OnAdd(AuctionHouseObject* /*ah*/, AuctionEntry* entry)
|
||||
Push(entry->startbid);
|
||||
Push(entry->bid);
|
||||
Push(entry->bidder);
|
||||
CallAllFunctions(ServerEventBindings, AUCTION_EVENT_ON_ADD);
|
||||
CallAllFunctions(ServerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnRemove(AuctionHouseObject* /*ah*/, AuctionEntry* entry)
|
||||
{
|
||||
if (!ServerEventBindings->HasEvents(AUCTION_EVENT_ON_REMOVE))
|
||||
return;
|
||||
|
||||
Player* owner = eObjectAccessor->FindPlayer(MAKE_NEW_GUID(entry->owner, 0, HIGHGUID_PLAYER));
|
||||
#ifdef TRINITY
|
||||
Item* item = eAuctionMgr->GetAItem(entry->itemGUIDLow);
|
||||
@@ -130,7 +147,7 @@ void Eluna::OnRemove(AuctionHouseObject* /*ah*/, AuctionEntry* entry)
|
||||
if (!owner || !item)
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(AUCTION_EVENT_ON_REMOVE);
|
||||
Push(entry->Id);
|
||||
Push(owner);
|
||||
Push(item);
|
||||
@@ -139,14 +156,11 @@ void Eluna::OnRemove(AuctionHouseObject* /*ah*/, AuctionEntry* entry)
|
||||
Push(entry->startbid);
|
||||
Push(entry->bid);
|
||||
Push(entry->bidder);
|
||||
CallAllFunctions(ServerEventBindings, AUCTION_EVENT_ON_REMOVE);
|
||||
CallAllFunctions(ServerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnSuccessful(AuctionHouseObject* /*ah*/, AuctionEntry* entry)
|
||||
{
|
||||
if (!ServerEventBindings->HasEvents(AUCTION_EVENT_ON_SUCCESSFUL))
|
||||
return;
|
||||
|
||||
Player* owner = eObjectAccessor->FindPlayer(MAKE_NEW_GUID(entry->owner, 0, HIGHGUID_PLAYER));
|
||||
#ifdef TRINITY
|
||||
Item* item = eAuctionMgr->GetAItem(entry->itemGUIDLow);
|
||||
@@ -160,7 +174,7 @@ void Eluna::OnSuccessful(AuctionHouseObject* /*ah*/, AuctionEntry* entry)
|
||||
if (!owner || !item)
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(AUCTION_EVENT_ON_SUCCESSFUL);
|
||||
Push(entry->Id);
|
||||
Push(owner);
|
||||
Push(item);
|
||||
@@ -169,14 +183,11 @@ void Eluna::OnSuccessful(AuctionHouseObject* /*ah*/, AuctionEntry* entry)
|
||||
Push(entry->startbid);
|
||||
Push(entry->bid);
|
||||
Push(entry->bidder);
|
||||
CallAllFunctions(ServerEventBindings, AUCTION_EVENT_ON_SUCCESSFUL);
|
||||
CallAllFunctions(ServerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnExpire(AuctionHouseObject* /*ah*/, AuctionEntry* entry)
|
||||
{
|
||||
if (!ServerEventBindings->HasEvents(AUCTION_EVENT_ON_EXPIRE))
|
||||
return;
|
||||
|
||||
Player* owner = eObjectAccessor->FindPlayer(MAKE_NEW_GUID(entry->owner, 0, HIGHGUID_PLAYER));
|
||||
#ifdef TRINITY
|
||||
Item* item = eAuctionMgr->GetAItem(entry->itemGUIDLow);
|
||||
@@ -190,7 +201,7 @@ void Eluna::OnExpire(AuctionHouseObject* /*ah*/, AuctionEntry* entry)
|
||||
if (!owner || !item)
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(AUCTION_EVENT_ON_EXPIRE);
|
||||
Push(entry->Id);
|
||||
Push(owner);
|
||||
Push(item);
|
||||
@@ -199,177 +210,35 @@ void Eluna::OnExpire(AuctionHouseObject* /*ah*/, AuctionEntry* entry)
|
||||
Push(entry->startbid);
|
||||
Push(entry->bid);
|
||||
Push(entry->bidder);
|
||||
CallAllFunctions(ServerEventBindings, AUCTION_EVENT_ON_EXPIRE);
|
||||
}
|
||||
|
||||
// Packet
|
||||
bool Eluna::OnPacketSend(WorldSession* session, WorldPacket& packet)
|
||||
{
|
||||
bool result = true;
|
||||
Player* player = NULL;
|
||||
if (session)
|
||||
player = session->GetPlayer();
|
||||
OnPacketSendAny(player, packet, result);
|
||||
OnPacketSendOne(player, packet, result);
|
||||
return result;
|
||||
}
|
||||
void Eluna::OnPacketSendAny(Player* player, WorldPacket& packet, bool& result)
|
||||
{
|
||||
if (!ServerEventBindings->HasEvents(SERVER_EVENT_ON_PACKET_SEND))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
Push(new WorldPacket(packet));
|
||||
Push(player);
|
||||
int n = SetupStack(ServerEventBindings, SERVER_EVENT_ON_PACKET_SEND, 2);
|
||||
|
||||
while (n > 0)
|
||||
{
|
||||
int r = CallOneFunction(n--, 2, 2);
|
||||
|
||||
if (lua_isboolean(L, r + 0) && !lua_toboolean(L, r + 0))
|
||||
result = false;
|
||||
|
||||
if (lua_isuserdata(L, r + 1))
|
||||
if (WorldPacket* data = CHECKOBJ<WorldPacket>(L, r + 1, false))
|
||||
packet = *data;
|
||||
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
|
||||
CleanUpStack(2);
|
||||
}
|
||||
|
||||
void Eluna::OnPacketSendOne(Player* player, WorldPacket& packet, bool& result)
|
||||
{
|
||||
if (!PacketEventBindings->HasEvents(PACKET_EVENT_ON_PACKET_SEND, packet.GetOpcode()))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
Push(new WorldPacket(packet));
|
||||
Push(player);
|
||||
int n = SetupStack(PacketEventBindings, PACKET_EVENT_ON_PACKET_SEND, OpcodesList(packet.GetOpcode()), 2);
|
||||
|
||||
while (n > 0)
|
||||
{
|
||||
int r = CallOneFunction(n--, 2, 2);
|
||||
|
||||
if (lua_isboolean(L, r + 0) && !lua_toboolean(L, r + 0))
|
||||
result = false;
|
||||
|
||||
if (lua_isuserdata(L, r + 1))
|
||||
if (WorldPacket* data = CHECKOBJ<WorldPacket>(L, r + 1, false))
|
||||
packet = *data;
|
||||
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
|
||||
CleanUpStack(2);
|
||||
}
|
||||
|
||||
bool Eluna::OnPacketReceive(WorldSession* session, WorldPacket& packet)
|
||||
{
|
||||
bool result = true;
|
||||
Player* player = NULL;
|
||||
if (session)
|
||||
player = session->GetPlayer();
|
||||
OnPacketReceiveAny(player, packet, result);
|
||||
OnPacketReceiveOne(player, packet, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Eluna::OnPacketReceiveAny(Player* player, WorldPacket& packet, bool& result)
|
||||
{
|
||||
if (!ServerEventBindings->HasEvents(SERVER_EVENT_ON_PACKET_RECEIVE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
Push(new WorldPacket(packet));
|
||||
Push(player);
|
||||
int n = SetupStack(ServerEventBindings, SERVER_EVENT_ON_PACKET_RECEIVE, 2);
|
||||
|
||||
while (n > 0)
|
||||
{
|
||||
int r = CallOneFunction(n--, 2, 2);
|
||||
|
||||
if (lua_isboolean(L, r + 0) && !lua_toboolean(L, r + 0))
|
||||
result = false;
|
||||
|
||||
if (lua_isuserdata(L, r + 1))
|
||||
if (WorldPacket* data = CHECKOBJ<WorldPacket>(L, r + 1, false))
|
||||
packet = *data;
|
||||
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
|
||||
CleanUpStack(2);
|
||||
}
|
||||
|
||||
void Eluna::OnPacketReceiveOne(Player* player, WorldPacket& packet, bool& result)
|
||||
{
|
||||
if (!PacketEventBindings->HasEvents(PACKET_EVENT_ON_PACKET_RECEIVE, packet.GetOpcode()))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
Push(new WorldPacket(packet));
|
||||
Push(player);
|
||||
int n = SetupStack(PacketEventBindings, PACKET_EVENT_ON_PACKET_RECEIVE, OpcodesList(), 2);
|
||||
|
||||
while (n > 0)
|
||||
{
|
||||
int r = CallOneFunction(n--, 2, 2);
|
||||
|
||||
if (lua_isboolean(L, r + 0) && !lua_toboolean(L, r + 0))
|
||||
result = false;
|
||||
|
||||
if (lua_isuserdata(L, r + 1))
|
||||
if (WorldPacket* data = CHECKOBJ<WorldPacket>(L, r + 1, false))
|
||||
packet = *data;
|
||||
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
|
||||
CleanUpStack(2);
|
||||
CallAllFunctions(ServerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnOpenStateChange(bool open)
|
||||
{
|
||||
if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_OPEN_STATE_CHANGE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(WORLD_EVENT_ON_OPEN_STATE_CHANGE);
|
||||
Push(open);
|
||||
CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_OPEN_STATE_CHANGE);
|
||||
CallAllFunctions(ServerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnConfigLoad(bool reload)
|
||||
{
|
||||
if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_CONFIG_LOAD))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(WORLD_EVENT_ON_CONFIG_LOAD);
|
||||
Push(reload);
|
||||
CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_CONFIG_LOAD);
|
||||
CallAllFunctions(ServerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnShutdownInitiate(ShutdownExitCode code, ShutdownMask mask)
|
||||
{
|
||||
if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_SHUTDOWN_INIT))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(WORLD_EVENT_ON_SHUTDOWN_INIT);
|
||||
Push(code);
|
||||
Push(mask);
|
||||
CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_SHUTDOWN_INIT);
|
||||
CallAllFunctions(ServerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnShutdownCancel()
|
||||
{
|
||||
if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_SHUTDOWN_CANCEL))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_SHUTDOWN_CANCEL);
|
||||
START_HOOK(WORLD_EVENT_ON_SHUTDOWN_CANCEL);
|
||||
CallAllFunctions(ServerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnWorldUpdate(uint32 diff)
|
||||
@@ -382,106 +251,74 @@ void Eluna::OnWorldUpdate(uint32 diff)
|
||||
|
||||
eventMgr->globalProcessor->Update(diff);
|
||||
|
||||
if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_UPDATE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(WORLD_EVENT_ON_UPDATE);
|
||||
Push(diff);
|
||||
CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_UPDATE);
|
||||
CallAllFunctions(ServerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnStartup()
|
||||
{
|
||||
if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_STARTUP))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_STARTUP);
|
||||
START_HOOK(WORLD_EVENT_ON_STARTUP);
|
||||
CallAllFunctions(ServerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnShutdown()
|
||||
{
|
||||
if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_SHUTDOWN))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_SHUTDOWN);
|
||||
START_HOOK(WORLD_EVENT_ON_SHUTDOWN);
|
||||
CallAllFunctions(ServerEventBindings, key);
|
||||
}
|
||||
|
||||
/* Map */
|
||||
void Eluna::OnCreate(Map* map)
|
||||
{
|
||||
if (!ServerEventBindings->HasEvents(MAP_EVENT_ON_CREATE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(MAP_EVENT_ON_CREATE);
|
||||
Push(map);
|
||||
CallAllFunctions(ServerEventBindings, MAP_EVENT_ON_CREATE);
|
||||
CallAllFunctions(ServerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnDestroy(Map* map)
|
||||
{
|
||||
if (!ServerEventBindings->HasEvents(MAP_EVENT_ON_DESTROY))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(MAP_EVENT_ON_DESTROY);
|
||||
Push(map);
|
||||
CallAllFunctions(ServerEventBindings, MAP_EVENT_ON_DESTROY);
|
||||
CallAllFunctions(ServerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnPlayerEnter(Map* map, Player* player)
|
||||
{
|
||||
if (!ServerEventBindings->HasEvents(MAP_EVENT_ON_PLAYER_ENTER))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(MAP_EVENT_ON_PLAYER_ENTER);
|
||||
Push(map);
|
||||
Push(player);
|
||||
CallAllFunctions(ServerEventBindings, MAP_EVENT_ON_PLAYER_ENTER);
|
||||
CallAllFunctions(ServerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnPlayerLeave(Map* map, Player* player)
|
||||
{
|
||||
if (!ServerEventBindings->HasEvents(MAP_EVENT_ON_PLAYER_LEAVE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(MAP_EVENT_ON_PLAYER_LEAVE);
|
||||
Push(map);
|
||||
Push(player);
|
||||
CallAllFunctions(ServerEventBindings, MAP_EVENT_ON_PLAYER_LEAVE);
|
||||
CallAllFunctions(ServerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnUpdate(Map* map, uint32 diff)
|
||||
{
|
||||
if (!ServerEventBindings->HasEvents(MAP_EVENT_ON_UPDATE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(MAP_EVENT_ON_UPDATE);
|
||||
// enable this for multithread
|
||||
// eventMgr->globalProcessor->Update(diff);
|
||||
Push(map);
|
||||
Push(diff);
|
||||
CallAllFunctions(ServerEventBindings, MAP_EVENT_ON_UPDATE);
|
||||
CallAllFunctions(ServerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnRemove(GameObject* gameobject)
|
||||
{
|
||||
if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_DELETE_GAMEOBJECT))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(WORLD_EVENT_ON_DELETE_GAMEOBJECT);
|
||||
Push(gameobject);
|
||||
CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_DELETE_GAMEOBJECT);
|
||||
CallAllFunctions(ServerEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnRemove(Creature* creature)
|
||||
{
|
||||
if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_DELETE_CREATURE))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(WORLD_EVENT_ON_DELETE_CREATURE);
|
||||
Push(creature);
|
||||
CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_DELETE_CREATURE);
|
||||
CallAllFunctions(ServerEventBindings, key);
|
||||
}
|
||||
|
||||
#endif // _SERVER_HOOKS_H
|
||||
|
||||
@@ -4,13 +4,10 @@
|
||||
* Please see the included DOCS/LICENSE.md for more information
|
||||
*/
|
||||
|
||||
#ifndef _VEHICLE_HOOKS_H
|
||||
#define _VEHICLE_HOOKS_H
|
||||
|
||||
#include "Hooks.h"
|
||||
#include "HookHelpers.h"
|
||||
#include "LuaEngine.h"
|
||||
#include "ElunaBinding.h"
|
||||
#include "BindingMap.h"
|
||||
#include "ElunaTemplate.h"
|
||||
|
||||
#ifndef CLASSIC
|
||||
@@ -18,61 +15,53 @@
|
||||
|
||||
using namespace Hooks;
|
||||
|
||||
#define START_HOOK(EVENT) \
|
||||
if (!IsEnabled())\
|
||||
return;\
|
||||
auto key = EventKey<VehicleEvents>(EVENT);\
|
||||
if (!VehicleEventBindings->HasBindingsFor(key))\
|
||||
return;\
|
||||
LOCK_ELUNA
|
||||
|
||||
// Vehicle
|
||||
void Eluna::OnInstall(Vehicle* vehicle)
|
||||
{
|
||||
if (!VehicleEventBindings->HasEvents(VEHICLE_EVENT_ON_INSTALL))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(VEHICLE_EVENT_ON_INSTALL);
|
||||
Push(vehicle);
|
||||
CallAllFunctions(VehicleEventBindings, VEHICLE_EVENT_ON_INSTALL);
|
||||
CallAllFunctions(VehicleEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnUninstall(Vehicle* vehicle)
|
||||
{
|
||||
if (!VehicleEventBindings->HasEvents(VEHICLE_EVENT_ON_UNINSTALL))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(VEHICLE_EVENT_ON_UNINSTALL);
|
||||
Push(vehicle);
|
||||
CallAllFunctions(VehicleEventBindings, VEHICLE_EVENT_ON_UNINSTALL);
|
||||
CallAllFunctions(VehicleEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnInstallAccessory(Vehicle* vehicle, Creature* accessory)
|
||||
{
|
||||
if (!VehicleEventBindings->HasEvents(VEHICLE_EVENT_ON_INSTALL_ACCESSORY))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(VEHICLE_EVENT_ON_INSTALL_ACCESSORY);
|
||||
Push(vehicle);
|
||||
Push(accessory);
|
||||
CallAllFunctions(VehicleEventBindings, VEHICLE_EVENT_ON_INSTALL_ACCESSORY);
|
||||
CallAllFunctions(VehicleEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnAddPassenger(Vehicle* vehicle, Unit* passenger, int8 seatId)
|
||||
{
|
||||
if (!VehicleEventBindings->HasEvents(VEHICLE_EVENT_ON_ADD_PASSENGER))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(VEHICLE_EVENT_ON_ADD_PASSENGER);
|
||||
Push(vehicle);
|
||||
Push(passenger);
|
||||
Push(seatId);
|
||||
CallAllFunctions(VehicleEventBindings, VEHICLE_EVENT_ON_ADD_PASSENGER);
|
||||
CallAllFunctions(VehicleEventBindings, key);
|
||||
}
|
||||
|
||||
void Eluna::OnRemovePassenger(Vehicle* vehicle, Unit* passenger)
|
||||
{
|
||||
if (!VehicleEventBindings->HasEvents(VEHICLE_EVENT_ON_REMOVE_PASSENGER))
|
||||
return;
|
||||
|
||||
LOCK_ELUNA;
|
||||
START_HOOK(VEHICLE_EVENT_ON_REMOVE_PASSENGER);
|
||||
Push(vehicle);
|
||||
Push(passenger);
|
||||
CallAllFunctions(VehicleEventBindings, VEHICLE_EVENT_ON_REMOVE_PASSENGER);
|
||||
CallAllFunctions(VehicleEventBindings, key);
|
||||
}
|
||||
|
||||
#endif // CLASSIC
|
||||
#endif // TBC
|
||||
#endif // _VEHICLE_HOOKS_H
|
||||
|
||||
Reference in New Issue
Block a user