diff --git a/BattleGroundHooks.cpp b/BattleGroundHooks.cpp
new file mode 100644
index 0000000..17baa02
--- /dev/null
+++ b/BattleGroundHooks.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2010 - 2015 Eluna Lua Engine
+ * This program is free software licensed under GPL version 3
+ * 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 "ElunaTemplate.h" // Needed to be able to push BattleGround objects.
+#include "ElunaBinding.h"
+
+using namespace Hooks;
+
+void Eluna::OnBGStart(BattleGround* bg, BattleGroundTypeId bgId, uint32 instanceId)
+{
+ if (!BGEventBindings->HasEvents(BG_EVENT_ON_START))
+ return;
+
+ LOCK_ELUNA;
+ Push(bg);
+ Push(bgId);
+ Push(instanceId);
+ CallAllFunctions(BGEventBindings, BG_EVENT_ON_START);
+}
+
+void Eluna::OnBGEnd(BattleGround* bg, BattleGroundTypeId bgId, uint32 instanceId, Team winner)
+{
+ if (!BGEventBindings->HasEvents(BG_EVENT_ON_END))
+ return;
+
+ LOCK_ELUNA;
+ Push(bg);
+ Push(bgId);
+ Push(instanceId);
+ Push(winner);
+ CallAllFunctions(BGEventBindings, BG_EVENT_ON_END);
+}
+
+void Eluna::OnBGCreate(BattleGround* bg, BattleGroundTypeId bgId, uint32 instanceId)
+{
+ if (!BGEventBindings->HasEvents(BG_EVENT_ON_CREATE))
+ return;
+
+ LOCK_ELUNA;
+ Push(bg);
+ Push(bgId);
+ Push(instanceId);
+ CallAllFunctions(BGEventBindings, BG_EVENT_ON_CREATE);
+}
+
+void Eluna::OnBGDestroy(BattleGround* bg, BattleGroundTypeId bgId, uint32 instanceId)
+{
+ if (!BGEventBindings->HasEvents(BG_EVENT_ON_PRE_DESTROY))
+ return;
+
+ LOCK_ELUNA;
+ Push(bg);
+ Push(bgId);
+ Push(instanceId);
+ CallAllFunctions(BGEventBindings, BG_EVENT_ON_PRE_DESTROY);
+}
+
+#endif // _BATTLEGROUND_HOOKS_H
\ No newline at end of file
diff --git a/CreatureHooks.cpp b/CreatureHooks.cpp
new file mode 100644
index 0000000..5431e96
--- /dev/null
+++ b/CreatureHooks.cpp
@@ -0,0 +1,486 @@
+/*
+ * Copyright (C) 2010 - 2015 Eluna Lua Engine
+ * This program is free software licensed under GPL version 3
+ * 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 "ElunaIncludes.h"
+
+using namespace Hooks;
+
+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;
+ 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);
+}
+
+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;
+ Push(pPlayer);
+ Push(pCreature);
+ Push(pQuest);
+ return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_QUEST_ACCEPT, pCreature->GetEntry(), pCreature->GET_GUID(), pCreature->GetInstanceId());
+}
+
+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;
+ Push(pPlayer);
+ Push(pCreature);
+ Push(pQuest);
+ Push(opt);
+ return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_QUEST_REWARD, pCreature->GetEntry(), pCreature->GET_GUID(), pCreature->GetInstanceId());
+}
+
+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;
+ Push(pPlayer);
+ Push(pCreature);
+ CallAllFunctions(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_DIALOG_STATUS, pCreature->GetEntry(), pCreature->GET_GUID(), pCreature->GetInstanceId());
+ return DIALOG_STATUS_SCRIPTED_NO_STATUS;
+}
+
+void Eluna::OnAddToWorld(Creature* creature)
+{
+ 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());
+}
+
+void Eluna::OnRemoveFromWorld(Creature* creature)
+{
+ 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());
+}
+
+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;
+ Push(pCreature);
+ Push(pSummoner);
+ return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_SUMMONED, pCreature->GetEntry(), pCreature->GET_GUID(), pCreature->GetInstanceId());
+}
+
+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;
+ Push(me);
+ Push(diff);
+ return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_AIUPDATE, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
+}
+
+//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;
+ Push(me);
+ Push(target);
+ return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_ENTER_COMBAT, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
+}
+
+// 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;
+ 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);
+
+ while (n > 0)
+ {
+ int r = CallOneFunction(n--, 3, 2);
+
+ if (lua_isboolean(L, r + 0) && lua_toboolean(L, r + 0))
+ result = true;
+
+ if (lua_isnumber(L, r + 1))
+ {
+ damage = Eluna::CHECKVAL(L, r + 1);
+ // Update the stack for subsequent calls.
+ ReplaceArgument(damage, damageIndex);
+ }
+
+ lua_pop(L, 2);
+ }
+
+ CleanUpStack(3);
+ return result;
+}
+
+//Called at creature death
+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;
+ Push(me);
+ Push(killer);
+ return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_DIED, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
+}
+
+//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;
+ Push(me);
+ Push(victim);
+ return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_TARGET_DIED, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
+}
+
+// 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;
+ Push(me);
+ Push(summon);
+ return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_JUST_SUMMONED_CREATURE, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
+}
+
+// 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;
+ Push(me);
+ Push(summon);
+ return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_SUMMONED_CREATURE_DESPAWN, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
+}
+
+//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;
+ Push(me);
+ Push(type);
+ Push(id);
+ return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_REACH_WP, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
+}
+
+// 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;
+ Push(me);
+ Push(target);
+ return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_PRE_COMBAT, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
+}
+
+// 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;
+ Push(me);
+ return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_LEAVE_COMBAT, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
+}
+
+// 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;
+ Push(me);
+ Push(attacker);
+ return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_ATTACKED_AT, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
+}
+
+// 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;
+ Push(me);
+ return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_SPAWN, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
+}
+
+// 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;
+ Push(me);
+ return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_REACH_HOME, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
+}
+
+// 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;
+ Push(me);
+ Push(player);
+ Push(emoteId);
+ return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_RECEIVE_EMOTE, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
+}
+
+// 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;
+ 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);
+
+ while (n > 0)
+ {
+ int r = CallOneFunction(n--, 2, 2);
+
+ if (lua_isboolean(L, r + 0) && lua_toboolean(L, r + 0))
+ result = true;
+
+ if (lua_isnumber(L, r + 1))
+ {
+ respawnDelay = Eluna::CHECKVAL(L, r + 1);
+ // Update the stack for subsequent calls.
+ ReplaceArgument(respawnDelay, respawnDelayIndex);
+ }
+
+ lua_pop(L, 2);
+ }
+
+ CleanUpStack(2);
+ return result;
+}
+
+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;
+ Push(me);
+ Push(who);
+ return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_MOVE_IN_LOS, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
+}
+
+// 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;
+ Push(me);
+ CallAllFunctions(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_RESET, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
+}
+
+// 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;
+ 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());
+}
+
+// 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;
+ 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());
+}
+
+#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;
+ Push(me);
+ Push(summon);
+ Push(killer);
+ return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_SUMMONED_CREATURE_DIED, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
+}
+
+// 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;
+ Push(me);
+ Push(attacker);
+ return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_OWNER_ATTACKED_AT, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
+}
+
+// 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;
+ Push(me);
+ Push(target);
+ return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_OWNER_ATTACKED, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
+}
+
+#endif // TRINITY
+#endif // _CREATURE_HOOKS_H
\ No newline at end of file
diff --git a/GameObjectHooks.cpp b/GameObjectHooks.cpp
new file mode 100644
index 0000000..b62f6ab
--- /dev/null
+++ b/GameObjectHooks.cpp
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2010 - 2015 Eluna Lua Engine
+ * This program is free software licensed under GPL version 3
+ * 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 "ElunaIncludes.h"
+#include "ElunaEventMgr.h"
+
+using namespace Hooks;
+
+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;
+ 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());
+}
+
+void Eluna::UpdateAI(GameObject* pGameObject, uint32 diff)
+{
+ if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_AIUPDATE, pGameObject->GetEntry()))
+ return;
+
+ LOCK_ELUNA;
+ pGameObject->elunaEvents->Update(diff);
+ Push(pGameObject);
+ Push(diff);
+ CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_AIUPDATE, pGameObject->GetEntry());
+}
+
+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;
+ Push(pPlayer);
+ Push(pGameObject);
+ Push(pQuest);
+ Push(opt);
+ return CallAllFunctionsBool(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_QUEST_REWARD, pGameObject->GetEntry());
+}
+
+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;
+ Push(pPlayer);
+ Push(pGameObject);
+ CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_DIALOG_STATUS, pGameObject->GetEntry());
+ return DIALOG_STATUS_SCRIPTED_NO_STATUS; // DIALOG_STATUS_UNDEFINED
+}
+
+#ifndef CLASSIC
+#ifndef TBC
+void Eluna::OnDestroyed(GameObject* pGameObject, Player* pPlayer)
+{
+ if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_DESTROYED, pGameObject->GetEntry()))
+ return;
+
+ LOCK_ELUNA;
+ Push(pGameObject);
+ Push(pPlayer);
+ CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_DESTROYED, pGameObject->GetEntry());
+}
+
+void Eluna::OnDamaged(GameObject* pGameObject, Player* pPlayer)
+{
+ if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_DAMAGED, pGameObject->GetEntry()))
+ return;
+
+ LOCK_ELUNA;
+ Push(pGameObject);
+ Push(pPlayer);
+ CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_DAMAGED, pGameObject->GetEntry());
+}
+#endif
+#endif
+
+void Eluna::OnLootStateChanged(GameObject* pGameObject, uint32 state)
+{
+ if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_LOOT_STATE_CHANGE, pGameObject->GetEntry()))
+ return;
+
+ LOCK_ELUNA;
+ Push(pGameObject);
+ Push(state);
+ CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_LOOT_STATE_CHANGE, pGameObject->GetEntry());
+}
+
+void Eluna::OnGameObjectStateChanged(GameObject* pGameObject, uint32 state)
+{
+ if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_GO_STATE_CHANGED, pGameObject->GetEntry()))
+ return;
+
+ LOCK_ELUNA;
+ Push(pGameObject);
+ Push(state);
+ CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_GO_STATE_CHANGED, pGameObject->GetEntry());
+}
+
+void Eluna::OnSpawn(GameObject* gameobject)
+{
+ if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_SPAWN, gameobject->GetEntry()))
+ return;
+
+ LOCK_ELUNA;
+ Push(gameobject);
+ CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_SPAWN, gameobject->GetEntry());
+}
+
+void Eluna::OnAddToWorld(GameObject* gameobject)
+{
+ if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_ADD, gameobject->GetEntry()))
+ return;
+
+ LOCK_ELUNA;
+ Push(gameobject);
+ CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_ADD, gameobject->GetEntry());
+}
+
+void Eluna::OnRemoveFromWorld(GameObject* gameobject)
+{
+ if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_REMOVE, gameobject->GetEntry()))
+ return;
+
+ LOCK_ELUNA;
+ Push(gameobject);
+ CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_REMOVE, gameobject->GetEntry());
+}
+
+bool Eluna::OnGameObjectUse(Player* pPlayer, GameObject* pGameObject)
+{
+ if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_USE, pGameObject->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
+ Push(pGameObject);
+ Push(pPlayer);
+ return CallAllFunctionsBool(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_USE, pGameObject->GetEntry());
+}
+
+#endif // _GAMEOBJECT_HOOKS_H
\ No newline at end of file
diff --git a/GlobalMethods.h b/GlobalMethods.h
index 8f30903..f6b940e 100644
--- a/GlobalMethods.h
+++ b/GlobalMethods.h
@@ -593,7 +593,7 @@ namespace LuaGlobalFunctions
*/
int RegisterServerEvent(Eluna* E, lua_State* L)
{
- RegisterEventHelper(E, L, HookMgr::REGTYPE_SERVER);
+ RegisterEventHelper(E, L, Hooks::REGTYPE_SERVER);
return 0;
}
@@ -658,7 +658,7 @@ namespace LuaGlobalFunctions
*/
int RegisterPlayerEvent(Eluna* E, lua_State* L)
{
- RegisterEventHelper(E, L, HookMgr::REGTYPE_PLAYER);
+ RegisterEventHelper(E, L, Hooks::REGTYPE_PLAYER);
return 0;
}
@@ -691,7 +691,7 @@ namespace LuaGlobalFunctions
*/
int RegisterGuildEvent(Eluna* E, lua_State* L)
{
- RegisterEventHelper(E, L, HookMgr::REGTYPE_GUILD);
+ RegisterEventHelper(E, L, Hooks::REGTYPE_GUILD);
return 0;
}
@@ -719,7 +719,7 @@ namespace LuaGlobalFunctions
*/
int RegisterGroupEvent(Eluna* E, lua_State* L)
{
- RegisterEventHelper(E, L, HookMgr::REGTYPE_GROUP);
+ RegisterEventHelper(E, L, Hooks::REGTYPE_GROUP);
return 0;
}
@@ -743,7 +743,7 @@ namespace LuaGlobalFunctions
*/
int RegisterBGEvent(Eluna* E, lua_State* L)
{
- RegisterEventHelper(E, L, HookMgr::REGTYPE_BG);
+ RegisterEventHelper(E, L, Hooks::REGTYPE_BG);
return 0;
}
@@ -768,7 +768,7 @@ namespace LuaGlobalFunctions
*/
int RegisterPacketEvent(Eluna* E, lua_State* L)
{
- RegisterEntryHelper(E, L, HookMgr::REGTYPE_PACKET);
+ RegisterEntryHelper(E, L, Hooks::REGTYPE_PACKET);
return 0;
}
@@ -791,7 +791,7 @@ namespace LuaGlobalFunctions
*/
int RegisterCreatureGossipEvent(Eluna* E, lua_State* L)
{
- RegisterEntryHelper(E, L, HookMgr::REGTYPE_CREATURE_GOSSIP);
+ RegisterEntryHelper(E, L, Hooks::REGTYPE_CREATURE_GOSSIP);
return 0;
}
@@ -814,7 +814,7 @@ namespace LuaGlobalFunctions
*/
int RegisterGameObjectGossipEvent(Eluna* E, lua_State* L)
{
- RegisterEntryHelper(E, L, HookMgr::REGTYPE_GAMEOBJECT_GOSSIP);
+ RegisterEntryHelper(E, L, Hooks::REGTYPE_GAMEOBJECT_GOSSIP);
return 0;
}
@@ -840,7 +840,7 @@ namespace LuaGlobalFunctions
*/
int RegisterItemEvent(Eluna* E, lua_State* L)
{
- RegisterEntryHelper(E, L, HookMgr::REGTYPE_ITEM);
+ RegisterEntryHelper(E, L, Hooks::REGTYPE_ITEM);
return 0;
}
@@ -863,7 +863,7 @@ namespace LuaGlobalFunctions
*/
int RegisterItemGossipEvent(Eluna* E, lua_State* L)
{
- RegisterEntryHelper(E, L, HookMgr::REGTYPE_ITEM_GOSSIP);
+ RegisterEntryHelper(E, L, Hooks::REGTYPE_ITEM_GOSSIP);
return 0;
}
@@ -886,7 +886,7 @@ namespace LuaGlobalFunctions
*/
int RegisterPlayerGossipEvent(Eluna* E, lua_State* L)
{
- RegisterEntryHelper(E, L, HookMgr::REGTYPE_PLAYER_GOSSIP);
+ RegisterEntryHelper(E, L, Hooks::REGTYPE_PLAYER_GOSSIP);
return 0;
}
@@ -944,7 +944,7 @@ namespace LuaGlobalFunctions
*/
int RegisterCreatureEvent(Eluna* E, lua_State* L)
{
- RegisterEntryHelper(E, L, HookMgr::REGTYPE_CREATURE);
+ RegisterEntryHelper(E, L, Hooks::REGTYPE_CREATURE);
return 0;
}
@@ -1003,7 +1003,7 @@ namespace LuaGlobalFunctions
*/
int RegisterUniqueCreatureEvent(Eluna* E, lua_State* L)
{
- RegisterUniqueHelper(E, L, HookMgr::REGTYPE_CREATURE);
+ RegisterUniqueHelper(E, L, Hooks::REGTYPE_CREATURE);
return 0;
}
@@ -1037,7 +1037,7 @@ namespace LuaGlobalFunctions
*/
int RegisterGameObjectEvent(Eluna* E, lua_State* L)
{
- RegisterEntryHelper(E, L, HookMgr::REGTYPE_GAMEOBJECT);
+ RegisterEntryHelper(E, L, Hooks::REGTYPE_GAMEOBJECT);
return 0;
}
diff --git a/GroupHooks.cpp b/GroupHooks.cpp
new file mode 100644
index 0000000..6d26f9c
--- /dev/null
+++ b/GroupHooks.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2010 - 2015 Eluna Lua Engine
+ * This program is free software licensed under GPL version 3
+ * 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"
+
+using namespace Hooks;
+
+void Eluna::OnAddMember(Group* group, uint64 guid)
+{
+ if (!GroupEventBindings->HasEvents(GROUP_EVENT_ON_MEMBER_ADD))
+ return;
+
+ LOCK_ELUNA;
+ Push(group);
+ Push(guid);
+ CallAllFunctions(GroupEventBindings, GROUP_EVENT_ON_MEMBER_ADD);
+}
+
+void Eluna::OnInviteMember(Group* group, uint64 guid)
+{
+ if (!GroupEventBindings->HasEvents(GROUP_EVENT_ON_MEMBER_INVITE))
+ return;
+
+ LOCK_ELUNA;
+ Push(group);
+ Push(guid);
+ CallAllFunctions(GroupEventBindings, GROUP_EVENT_ON_MEMBER_INVITE);
+}
+
+void Eluna::OnRemoveMember(Group* group, uint64 guid, uint8 method)
+{
+ if (!GroupEventBindings->HasEvents(GROUP_EVENT_ON_MEMBER_REMOVE))
+ return;
+
+ LOCK_ELUNA;
+ Push(group);
+ Push(guid);
+ Push(method);
+ CallAllFunctions(GroupEventBindings, GROUP_EVENT_ON_MEMBER_REMOVE);
+}
+
+void Eluna::OnChangeLeader(Group* group, uint64 newLeaderGuid, uint64 oldLeaderGuid)
+{
+ if (!GroupEventBindings->HasEvents(GROUP_EVENT_ON_LEADER_CHANGE))
+ return;
+
+ LOCK_ELUNA;
+ Push(group);
+ Push(newLeaderGuid);
+ Push(oldLeaderGuid);
+ CallAllFunctions(GroupEventBindings, GROUP_EVENT_ON_LEADER_CHANGE);
+}
+
+void Eluna::OnDisband(Group* group)
+{
+ if (!GroupEventBindings->HasEvents(GROUP_EVENT_ON_DISBAND))
+ return;
+
+ LOCK_ELUNA;
+ Push(group);
+ CallAllFunctions(GroupEventBindings, GROUP_EVENT_ON_DISBAND);
+}
+
+void Eluna::OnCreate(Group* group, uint64 leaderGuid, GroupType groupType)
+{
+ if (!GroupEventBindings->HasEvents(GROUP_EVENT_ON_CREATE))
+ return;
+
+ LOCK_ELUNA;
+ Push(group);
+ Push(leaderGuid);
+ Push(groupType);
+ CallAllFunctions(GroupEventBindings, GROUP_EVENT_ON_CREATE);
+}
+
+#endif // _GROUP_HOOKS_H
\ No newline at end of file
diff --git a/GuildHooks.cpp b/GuildHooks.cpp
new file mode 100644
index 0000000..b34f78c
--- /dev/null
+++ b/GuildHooks.cpp
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2010 - 2015 Eluna Lua Engine
+ * This program is free software licensed under GPL version 3
+ * 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"
+
+using namespace Hooks;
+
+void Eluna::OnAddMember(Guild* guild, Player* player, uint32 plRank)
+{
+ if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_ADD_MEMBER))
+ return;
+
+ LOCK_ELUNA;
+ Push(guild);
+ Push(player);
+ Push(plRank);
+ CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_ADD_MEMBER);
+}
+
+void Eluna::OnRemoveMember(Guild* guild, Player* player, bool isDisbanding)
+{
+ if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_REMOVE_MEMBER))
+ return;
+
+ LOCK_ELUNA;
+ Push(guild);
+ Push(player);
+ Push(isDisbanding);
+ CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_REMOVE_MEMBER);
+}
+
+void Eluna::OnMOTDChanged(Guild* guild, const std::string& newMotd)
+{
+ if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_MOTD_CHANGE))
+ return;
+
+ LOCK_ELUNA;
+ Push(guild);
+ Push(newMotd);
+ CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_MOTD_CHANGE);
+}
+
+void Eluna::OnInfoChanged(Guild* guild, const std::string& newInfo)
+{
+ if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_INFO_CHANGE))
+ return;
+
+ LOCK_ELUNA;
+ Push(guild);
+ Push(newInfo);
+ CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_INFO_CHANGE);
+}
+
+void Eluna::OnCreate(Guild* guild, Player* leader, const std::string& name)
+{
+ if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_CREATE))
+ return;
+
+ LOCK_ELUNA;
+ Push(guild);
+ Push(leader);
+ Push(name);
+ CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_CREATE);
+}
+
+void Eluna::OnDisband(Guild* guild)
+{
+ if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_DISBAND))
+ return;
+
+ LOCK_ELUNA;
+ Push(guild);
+ CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_DISBAND);
+}
+
+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;
+ 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);
+
+ while (n > 0)
+ {
+ int r = CallOneFunction(n--, 4, 1);
+
+ if (lua_isnumber(L, r))
+ {
+ amount = CHECKVAL(L, r);
+ // Update the stack for subsequent calls.
+ ReplaceArgument(amount, amountIndex);
+ }
+
+ lua_pop(L, 1);
+ }
+
+ CleanUpStack(4);
+}
+
+void Eluna::OnMemberDepositMoney(Guild* guild, Player* player, uint32& amount)
+{
+ if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_MONEY_DEPOSIT))
+ return;
+
+ LOCK_ELUNA;
+ Push(guild);
+ Push(player);
+ Push(amount);
+ int amountIndex = lua_gettop(L);
+ int n = SetupStack(GuildEventBindings, GUILD_EVENT_ON_MONEY_DEPOSIT, 3);
+
+ while (n > 0)
+ {
+ int r = CallOneFunction(n--, 3, 1);
+
+ if (lua_isnumber(L, r))
+ {
+ amount = CHECKVAL(L, r);
+ // Update the stack for subsequent calls.
+ ReplaceArgument(amount, amountIndex);
+ }
+
+ lua_pop(L, 1);
+ }
+
+ CleanUpStack(3);
+}
+
+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;
+ Push(guild);
+ Push(player);
+ Push(pItem);
+ Push(isSrcBank);
+ Push(srcContainer);
+ Push(srcSlotId);
+ Push(isDestBank);
+ Push(destContainer);
+ Push(destSlotId);
+ CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_ITEM_MOVE);
+}
+
+void Eluna::OnEvent(Guild* guild, uint8 eventType, uint32 playerGuid1, uint32 playerGuid2, uint8 newRank)
+{
+ if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_EVENT))
+ return;
+
+ LOCK_ELUNA;
+ Push(guild);
+ Push(eventType);
+ Push(playerGuid1);
+ Push(playerGuid2);
+ Push(newRank);
+ CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_EVENT);
+}
+
+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;
+ Push(guild);
+ Push(eventType);
+ Push(tabId);
+ Push(playerGuid);
+ Push(itemOrMoney);
+ Push(itemStackCount);
+ Push(destTabId);
+ CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_BANK_EVENT);
+}
+
+#endif // _GUILD_HOOKS_H
\ No newline at end of file
diff --git a/HookHelpers.h b/HookHelpers.h
new file mode 100644
index 0000000..6ff54a9
--- /dev/null
+++ b/HookHelpers.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2010 - 2015 Eluna Lua Engine
+ * This program is free software licensed under GPL version 3
+ * Please see the included DOCS/LICENSE.md for more information
+ */
+
+#ifndef _HOOK_HELPERS_H
+#define _HOOK_HELPERS_H
+
+#include "LuaEngine.h"
+#include "ElunaUtility.h"
+
+/*
+ * 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
+int Eluna::SetupStack(EventBind* event_bindings, EntryBind* entry_bindings, UniqueBind* guid_bindings, T event_id, uint32 entry, uint64 guid, uint32 instanceId, 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);
+ // Stack: [arguments]
+
+ Push(event_id);
+ this->push_counter = 0;
+ ++number_of_arguments;
+ // Stack: [arguments], event_id
+
+ int arguments_top = lua_gettop(L);
+ int first_argument_index = arguments_top - number_of_arguments + 1;
+ ASSERT(arguments_top >= number_of_arguments);
+
+ 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);
+ // Stack: event_id, [arguments], [functions]
+
+ int number_of_functions = lua_gettop(L) - arguments_top;
+ return number_of_functions;
+}
+
+/*
+ * Replace one of the arguments pushed before `SetupStack` with a new value.
+ */
+template
+void Eluna::ReplaceArgument(T value, uint8 index)
+{
+ ASSERT(index < lua_gettop(L) && index > 0);
+ // Stack: event_id, [arguments], [functions], [results]
+
+ Eluna::Push(L, value);
+ // Stack: event_id, [arguments], [functions], [results], value
+
+ lua_replace(L, index + 1);
+ // Stack: event_id, [arguments and value], [functions], [results]
+}
+
+/*
+ * Call all event handlers registered to the event ID/entry combination and ignore any results.
+ */
+template
+void Eluna::CallAllFunctions(EventBind* event_bindings, EntryBind* entry_bindings, UniqueBind* guid_bindings, T event_id, uint32 entry, uint64 guid, uint32 instanceId)
+{
+ 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);
+ // Stack: event_id, [arguments], [functions]
+
+ while (number_of_functions > 0)
+ {
+ CallOneFunction(number_of_functions, number_of_arguments, 0);
+ --number_of_functions;
+ // Stack: event_id, [arguments], [functions - 1]
+ }
+ // Stack: event_id, [arguments]
+
+ CleanUpStack(number_of_arguments);
+ // Stack: (empty)
+}
+
+/*
+ * Call all event handlers registered to the event ID/entry combination,
+ * and returns `default_value` if ALL event handlers returned `default_value`,
+ * otherwise returns the opposite of `default_value`.
+ */
+template
+bool Eluna::CallAllFunctionsBool(EventBind* event_bindings, EntryBind* entry_bindings, UniqueBind* guid_bindings, T event_id, uint32 entry, uint64 guid, uint32 instanceId, bool default_value)
+{
+ 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);
+ // Stack: event_id, [arguments], [functions]
+
+ while (number_of_functions > 0)
+ {
+ int r = CallOneFunction(number_of_functions, number_of_arguments, 1);
+ --number_of_functions;
+ // Stack: event_id, [arguments], [functions - 1], result
+
+ if (lua_isboolean(L, r) && (lua_toboolean(L, r) == 1) != default_value)
+ result = !default_value;
+
+ lua_pop(L, 1);
+ // Stack: event_id, [arguments], [functions - 1]
+ }
+ // Stack: event_id, [arguments]
+
+ CleanUpStack(number_of_arguments);
+ // Stack: (empty)
+ return result;
+}
+
+#endif // _HOOK_HELPERS_H
\ No newline at end of file
diff --git a/HookMgr.cpp b/HookMgr.cpp
deleted file mode 100644
index 4d0cfc0..0000000
--- a/HookMgr.cpp
+++ /dev/null
@@ -1,2446 +0,0 @@
-/*
- * Copyright (C) 2010 - 2015 Eluna Lua Engine
- * This program is free software licensed under GPL version 3
- * Please see the included DOCS/LICENSE.md for more information
- */
-
-#include "HookMgr.h"
-#include "LuaEngine.h"
-#include "ElunaBinding.h"
-#include "ElunaEventMgr.h"
-#include "ElunaIncludes.h"
-#include "ElunaTemplate.h"
-#include "ElunaCreatureAI.h"
-
-extern "C"
-{
-#include "lua.h"
-#include "lualib.h"
-#include "lauxlib.h"
-};
-
-using namespace HookMgr;
-
-/*
- * A hook should be written in one of the following forms:
- *
- * A. If results will be IGNORED:
- *
- * // Return early if there are no bindings.
- * if (!WhateverBindings->HasEvents(SOME_EVENT_TYPE))
- * return;
- *
- * // Lock out any other threads.
- * LOCK_ELUNA;
- *
- * // Push extra arguments, if any.
- * Push(a);
- * Push(b);
- * Push(c);
- *
- * // Call all event handlers.
- * CallAllFunctions(WhateverBindings, SOME_EVENT_TYPE);
- *
- *
- * B. If results will be USED:
- *
- * // Return early if there are no bindings.
- * if (!WhateverBindings->HasEvents(SOME_EVENT_TYPE))
- * return;
- *
- * // Lock out any other threads.
- * LOCK_ELUNA;
- *
- * // Push extra arguments, if any.
- * Push(a);
- * Push(b);
- * Push(c);
- *
- * // Setup the stack and get the number of functions pushed.
- * // Last argument is 3 because we did 3 Pushes.
- * int n = SetupStack(WhateverBindings, SOME_EVENT_TYPE, 3);
- *
- * // Call each event handler in order and check results.
- * while (n > 0)
- * {
- * // Call an event handler and decrement the function counter afterward.
- * // Second-last argument is 3 because we did 3 Pushes.
- * // Last argument is 2 because we want 2 results.
- * int r = CallOneFunction(n--, 3, 2);
- *
- * // Results can be popped using `r`.
- * int first = CHECKVAL(L, r + 0);
- * int second = CHECKVAL(L, r + 1);
- *
- * // Pop the results off the stack.
- * lua_pop(L, 2);
- * }
- *
- * // Clean-up the stack. Argument is 3 because we did 3 Pushes.
- * CleanUpStack(3);
- */
-
-/*
- * 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
-int Eluna::SetupStack(EventBind* event_bindings, EntryBind* entry_bindings, UniqueBind* guid_bindings, T event_id, uint32 entry, uint64 guid, uint32 instanceId, 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);
- // Stack: [arguments]
-
- Push(event_id);
- this->push_counter = 0;
- ++number_of_arguments;
- // Stack: [arguments], event_id
-
- int arguments_top = lua_gettop(L);
- int first_argument_index = arguments_top - number_of_arguments + 1;
- ASSERT(arguments_top >= number_of_arguments);
-
- 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);
- // Stack: event_id, [arguments], [functions]
-
- int number_of_functions = lua_gettop(L) - arguments_top;
- return number_of_functions;
-}
-
-/*
- * Replace one of the arguments pushed before `SetupStack` with a new value.
- */
-template
-void Eluna::ReplaceArgument(T value, uint8 index)
-{
- ASSERT(index < lua_gettop(L) && index > 0);
- // Stack: event_id, [arguments], [functions], [results]
-
- Eluna::Push(L, value);
- // Stack: event_id, [arguments], [functions], [results], value
-
- lua_replace(L, index + 1);
- // Stack: event_id, [arguments and value], [functions], [results]
-}
-
-/*
- * Call a single event handler that was put on the stack with `Setup` and removes it from the stack.
- *
- * The caller is responsible for keeping track of how many times this should be called.
- */
-int Eluna::CallOneFunction(int number_of_functions, int number_of_arguments, int number_of_results)
-{
- ++number_of_arguments; // Caller doesn't know about `event_id`.
- ASSERT(number_of_functions > 0 && number_of_arguments > 0 && number_of_results >= 0);
- // Stack: event_id, [arguments], [functions]
-
- int functions_top = lua_gettop(L);
- int first_function_index = functions_top - number_of_functions + 1;
- int arguments_top = first_function_index - 1;
- int first_argument_index = arguments_top - number_of_arguments + 1;
-
- // Copy the arguments from the bottom of the stack to the top.
- for (int argument_index = first_argument_index; argument_index <= arguments_top; ++argument_index)
- {
- lua_pushvalue(L, argument_index);
- }
- // Stack: event_id, [arguments], [functions], event_id, [arguments]
-
- ExecuteCall(number_of_arguments, number_of_results);
- --functions_top;
- // Stack: event_id, [arguments], [functions - 1], [results]
-
- return functions_top + 1; // Return the location of the first result (if any exist).
-}
-
-/*
- * Cleans up the stack, effectively undoing all Push calls and the Setup call.
- */
-void Eluna::CleanUpStack(int number_of_arguments)
-{
- // Stack: event_id, [arguments]
-
- lua_pop(L, number_of_arguments + 1); // Add 1 because the caller doesn't know about `event_id`.
- // Stack: (empty)
-
- if (event_level == 0)
- InvalidateObjects();
-}
-
-/*
- * Call all event handlers registered to the event ID/entry combination and ignore any results.
- */
-template
-void Eluna::CallAllFunctions(EventBind* event_bindings, EntryBind* entry_bindings, UniqueBind* guid_bindings, T event_id, uint32 entry, uint64 guid, uint32 instanceId)
-{
- 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);
- // Stack: event_id, [arguments], [functions]
-
- while (number_of_functions > 0)
- {
- CallOneFunction(number_of_functions, number_of_arguments, 0);
- --number_of_functions;
- // Stack: event_id, [arguments], [functions - 1]
- }
- // Stack: event_id, [arguments]
-
- CleanUpStack(number_of_arguments);
- // Stack: (empty)
-}
-
-/*
- * Call all event handlers registered to the event ID/entry combination,
- * and returns `default_value` if ALL event handlers returned `default_value`,
- * otherwise returns the opposite of `default_value`.
- */
-template
-bool Eluna::CallAllFunctionsBool(EventBind* event_bindings, EntryBind* entry_bindings, UniqueBind* guid_bindings, T event_id, uint32 entry, uint64 guid, uint32 instanceId, bool default_value)
-{
- 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);
- // Stack: event_id, [arguments], [functions]
-
- while (number_of_functions > 0)
- {
- int r = CallOneFunction(number_of_functions, number_of_arguments, 1);
- --number_of_functions;
- // Stack: event_id, [arguments], [functions - 1], result
-
- if (lua_isboolean(L, r) && (lua_toboolean(L, r) == 1) != default_value)
- result = !default_value;
-
- lua_pop(L, 1);
- // Stack: event_id, [arguments], [functions - 1]
- }
- // Stack: event_id, [arguments]
-
- CleanUpStack(number_of_arguments);
- // Stack: (empty)
- return result;
-}
-
-void Eluna::OnLuaStateClose()
-{
- if (!ServerEventBindings->HasEvents(ELUNA_EVENT_ON_LUA_STATE_CLOSE))
- return;
-
- LOCK_ELUNA;
- CallAllFunctions(ServerEventBindings, ELUNA_EVENT_ON_LUA_STATE_CLOSE);
-}
-
-void Eluna::OnLuaStateOpen()
-{
- if (!ServerEventBindings->HasEvents(ELUNA_EVENT_ON_LUA_STATE_OPEN))
- return;
-
- LOCK_ELUNA;
- CallAllFunctions(ServerEventBindings, ELUNA_EVENT_ON_LUA_STATE_OPEN);
-}
-
-// areatrigger
-bool Eluna::OnAreaTrigger(Player* pPlayer, AreaTriggerEntry const* pTrigger)
-{
- if (!ServerEventBindings->HasEvents(TRIGGER_EVENT_ON_TRIGGER))
- return false;
-
- LOCK_ELUNA;
- Push(pPlayer);
- Push(pTrigger->id);
- return CallAllFunctionsBool(ServerEventBindings, TRIGGER_EVENT_ON_TRIGGER);
-}
-// weather
-void Eluna::OnChange(Weather* weather, uint32 zone, WeatherState state, float grade)
-{
- if (!ServerEventBindings->HasEvents(WEATHER_EVENT_ON_CHANGE))
- return;
-
- LOCK_ELUNA;
- Push(zone);
- Push(state);
- Push(grade);
- CallAllFunctions(ServerEventBindings, WEATHER_EVENT_ON_CHANGE);
-}
-// Auction House
-void Eluna::OnAdd(AuctionHouseObject* ah)
-{
- if (!ServerEventBindings->HasEvents(AUCTION_EVENT_ON_ADD))
- return;
-
- LOCK_ELUNA;
- Push(ah);
- CallAllFunctions(ServerEventBindings, AUCTION_EVENT_ON_ADD);
-}
-
-void Eluna::OnRemove(AuctionHouseObject* ah)
-{
- if (!ServerEventBindings->HasEvents(AUCTION_EVENT_ON_REMOVE))
- return;
-
- LOCK_ELUNA;
- Push(ah);
- CallAllFunctions(ServerEventBindings, AUCTION_EVENT_ON_REMOVE);
-}
-
-void Eluna::OnSuccessful(AuctionHouseObject* ah)
-{
- if (!ServerEventBindings->HasEvents(AUCTION_EVENT_ON_SUCCESSFUL))
- return;
-
- LOCK_ELUNA;
- Push(ah);
- CallAllFunctions(ServerEventBindings, AUCTION_EVENT_ON_SUCCESSFUL);
-}
-
-void Eluna::OnExpire(AuctionHouseObject* ah)
-{
- if (!ServerEventBindings->HasEvents(AUCTION_EVENT_ON_EXPIRE))
- return;
-
- LOCK_ELUNA;
- Push(ah);
- 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(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(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(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(L, r + 1, false))
- packet = *data;
-
- lua_pop(L, 2);
- }
-
- CleanUpStack(2);
-}
-
-void Eluna::OnOpenStateChange(bool open)
-{
- if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_OPEN_STATE_CHANGE))
- return;
-
- LOCK_ELUNA;
- Push(open);
- CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_OPEN_STATE_CHANGE);
-}
-
-void Eluna::OnConfigLoad(bool reload)
-{
- if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_CONFIG_LOAD))
- return;
-
- LOCK_ELUNA;
- Push(reload);
- CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_CONFIG_LOAD);
-}
-
-void Eluna::OnShutdownInitiate(ShutdownExitCode code, ShutdownMask mask)
-{
- if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_SHUTDOWN_INIT))
- return;
-
- LOCK_ELUNA;
- Push(code);
- Push(mask);
- CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_SHUTDOWN_INIT);
-}
-
-void Eluna::OnShutdownCancel()
-{
- if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_SHUTDOWN_CANCEL))
- return;
-
- LOCK_ELUNA;
- CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_SHUTDOWN_CANCEL);
-}
-
-void Eluna::OnWorldUpdate(uint32 diff)
-{
- LOCK_ELUNA;
-
- if (reload)
- {
- ReloadEluna();
- return;
- }
-
- eventMgr->globalProcessor->Update(diff);
-
- if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_UPDATE))
- return;
-
- Push(diff);
- CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_UPDATE);
-}
-
-void Eluna::OnStartup()
-{
- if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_STARTUP))
- return;
-
- LOCK_ELUNA;
- CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_STARTUP);
-}
-
-void Eluna::OnShutdown()
-{
- if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_SHUTDOWN))
- return;
-
- LOCK_ELUNA;
- CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_SHUTDOWN);
-}
-
-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);
-}
-
-// item
-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;
- Push(pCaster);
- Push(spellId);
- Push(effIndex);
- Push(pTarget);
- return CallAllFunctionsBool(ItemEventBindings, ITEM_EVENT_ON_DUMMY_EFFECT, pTarget->GetEntry());
-}
-
-bool Eluna::OnQuestAccept(Player* pPlayer, Item* pItem, Quest const* pQuest)
-{
- if (!ItemEventBindings->HasEvents(ITEM_EVENT_ON_QUEST_ACCEPT, pItem->GetEntry()))
- return false;
-
- LOCK_ELUNA;
- Push(pPlayer);
- Push(pItem);
- Push(pQuest);
- return CallAllFunctionsBool(ItemEventBindings, ITEM_EVENT_ON_QUEST_ACCEPT, pItem->GetEntry());
-}
-
-bool Eluna::OnUse(Player* pPlayer, Item* pItem, SpellCastTargets const& targets)
-{
- ObjectGuid guid = pItem->GET_GUID();
- bool castSpell = true;
-
- if (!OnItemUse(pPlayer, pItem, targets))
- castSpell = false;
-
- pItem = pPlayer->GetItemByGuid(guid);
- if (pItem)
- {
- if (!OnItemGossip(pPlayer, pItem, targets))
- castSpell = false;
- pItem = pPlayer->GetItemByGuid(guid);
- }
-
- if (pItem && castSpell)
- return true;
-
- // Send equip error that shows no message
- // This is a hack fix to stop spell casting visual bug when a spell is not cast on use
- WorldPacket data(SMSG_INVENTORY_CHANGE_FAILURE, 18);
- data << uint8(59); // EQUIP_ERR_NONE / EQUIP_ERR_CANT_BE_DISENCHANTED
- data << ObjectGuid(guid);
- data << ObjectGuid(uint64(0));
- data << uint8(0);
- pPlayer->GetSession()->SendPacket(&data);
- return false;
-}
-
-bool Eluna::OnItemUse(Player* pPlayer, Item* pItem, SpellCastTargets const& targets)
-{
- if (!ItemEventBindings->HasEvents(ITEM_EVENT_ON_USE, pItem->GetEntry()))
- return true;
-
- LOCK_ELUNA;
- Push(pPlayer);
- Push(pItem);
-#ifndef TRINITY
- if (GameObject* target = targets.getGOTarget())
- Push(target);
- else if (Item* target = targets.getItemTarget())
- Push(target);
- else if (Corpse* target = pPlayer->GetMap()->GetCorpse(targets.getCorpseTargetGuid()))
- Push(target);
- else if (Unit* target = targets.getUnitTarget())
- Push(target);
- else
- Push();
-#else
- if (GameObject* target = targets.GetGOTarget())
- Push(target);
- else if (Item* target = targets.GetItemTarget())
- Push(target);
- else if (Corpse* target = targets.GetCorpseTarget())
- Push(target);
- else if (Unit* target = targets.GetUnitTarget())
- Push(target);
- else if (WorldObject* target = targets.GetObjectTarget())
- Push(target);
- else
- 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);
-}
-
-bool Eluna::OnExpire(Player* pPlayer, ItemTemplate const* pProto)
-{
- if (!ItemEventBindings->HasEvents(ITEM_EVENT_ON_EXPIRE, pProto->ItemId))
- return false;
-
- LOCK_ELUNA;
- Push(pPlayer);
- Push(pProto->ItemId);
- return CallAllFunctionsBool(ItemEventBindings, ITEM_EVENT_ON_EXPIRE, pProto->ItemId);
-}
-
-bool Eluna::OnRemove(Player* pPlayer, Item* item)
-{
- if (!ItemEventBindings->HasEvents(ITEM_EVENT_ON_REMOVE, item->GetEntry()))
- return false;
-
- LOCK_ELUNA;
- Push(pPlayer);
- Push(item);
- return CallAllFunctionsBool(ItemEventBindings, ITEM_EVENT_ON_REMOVE, item->GetEntry());
-}
-
-// Player
-bool Eluna::OnCommand(Player* player, const char* text)
-{
- // If from console, player is NULL
- std::string fullcmd(text);
- if (!player || player->GetSession()->GetSecurity() >= SEC_ADMINISTRATOR)
- {
- char* creload = strtok((char*)text, " ");
- char* celuna = strtok(NULL, "");
- if (creload && celuna)
- {
- std::string reload(creload);
- std::string eluna(celuna);
- std::transform(reload.begin(), reload.end(), reload.begin(), ::tolower);
- if (reload == "reload")
- {
- std::transform(eluna.begin(), eluna.end(), eluna.begin(), ::tolower);
- if (std::string("eluna").find(eluna) == 0)
- {
- Eluna::reload = true;
- return false;
- }
- }
- }
- }
-
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_COMMAND))
- return true;
-
- LOCK_ELUNA;
- Push(player);
- Push(fullcmd);
- return CallAllFunctionsBool(PlayerEventBindings, PLAYER_EVENT_ON_COMMAND, true);
-}
-
-void Eluna::OnLootItem(Player* pPlayer, Item* pItem, uint32 count, uint64 guid)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_LOOT_ITEM))
- return;
-
- LOCK_ELUNA;
- Push(pPlayer);
- Push(pItem);
- Push(count);
- Push(guid);
- CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_LOOT_ITEM);
-}
-
-void Eluna::OnLootMoney(Player* pPlayer, uint32 amount)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_LOOT_MONEY))
- return;
-
- LOCK_ELUNA;
- Push(pPlayer);
- Push(amount);
- CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_LOOT_MONEY);
-}
-
-void Eluna::OnFirstLogin(Player* pPlayer)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_FIRST_LOGIN))
- return;
-
- LOCK_ELUNA;
- Push(pPlayer);
- CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_FIRST_LOGIN);
-}
-
-void Eluna::OnRepop(Player* pPlayer)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_REPOP))
- return;
-
- LOCK_ELUNA;
- Push(pPlayer);
- CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_REPOP);
-}
-
-void Eluna::OnResurrect(Player* pPlayer)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_RESURRECT))
- return;
-
- LOCK_ELUNA;
- Push(pPlayer);
- CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_RESURRECT);
-}
-
-void Eluna::OnQuestAbandon(Player* pPlayer, uint32 questId)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_QUEST_ABANDON))
- return;
-
- LOCK_ELUNA;
- Push(pPlayer);
- Push(questId);
- CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_QUEST_ABANDON);
-}
-
-void Eluna::OnEquip(Player* pPlayer, Item* pItem, uint8 bag, uint8 slot)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_EQUIP))
- return;
-
- LOCK_ELUNA;
- Push(pPlayer);
- Push(pItem);
- Push(bag);
- Push(slot);
- CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_EQUIP);
-}
-
-InventoryResult Eluna::OnCanUseItem(const Player* pPlayer, uint32 itemEntry)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_CAN_USE_ITEM))
- return EQUIP_ERR_OK;
-
- LOCK_ELUNA;
- InventoryResult result = EQUIP_ERR_OK;
- Push(pPlayer);
- Push(itemEntry);
- int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_CAN_USE_ITEM, 2);
-
- while (n > 0)
- {
- int r = CallOneFunction(n--, 2, 1);
-
- if (lua_isnumber(L, r))
- result = (InventoryResult)CHECKVAL(L, r);
-
- lua_pop(L, 1);
- }
-
- CleanUpStack(2);
- return result;
-}
-void Eluna::OnPlayerEnterCombat(Player* pPlayer, Unit* pEnemy)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_ENTER_COMBAT))
- return;
-
- LOCK_ELUNA;
- Push(pPlayer);
- Push(pEnemy);
- CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_ENTER_COMBAT);
-}
-
-void Eluna::OnPlayerLeaveCombat(Player* pPlayer)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_LEAVE_COMBAT))
- return;
-
- LOCK_ELUNA;
- Push(pPlayer);
- CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_LEAVE_COMBAT);
-}
-
-void Eluna::OnPVPKill(Player* pKiller, Player* pKilled)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_KILL_PLAYER))
- return;
-
- LOCK_ELUNA;
- Push(pKiller);
- Push(pKilled);
- CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_KILL_PLAYER);
-}
-
-void Eluna::OnCreatureKill(Player* pKiller, Creature* pKilled)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_KILL_CREATURE))
- return;
-
- LOCK_ELUNA;
- Push(pKiller);
- Push(pKilled);
- CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_KILL_CREATURE);
-}
-
-void Eluna::OnPlayerKilledByCreature(Creature* pKiller, Player* pKilled)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_KILLED_BY_CREATURE))
- return;
-
- LOCK_ELUNA;
- Push(pKiller);
- Push(pKilled);
- CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_KILLED_BY_CREATURE);
-}
-
-void Eluna::OnLevelChanged(Player* pPlayer, uint8 oldLevel)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_LEVEL_CHANGE))
- return;
-
- LOCK_ELUNA;
- Push(pPlayer);
- Push(oldLevel);
- CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_LEVEL_CHANGE);
-}
-
-void Eluna::OnFreeTalentPointsChanged(Player* pPlayer, uint32 newPoints)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_TALENTS_CHANGE))
- return;
-
- LOCK_ELUNA;
- Push(pPlayer);
- Push(newPoints);
- CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_TALENTS_CHANGE);
-}
-
-void Eluna::OnTalentsReset(Player* pPlayer, bool noCost)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_TALENTS_RESET))
- return;
-
- LOCK_ELUNA;
- Push(pPlayer);
- Push(noCost);
- CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_TALENTS_RESET);
-}
-
-void Eluna::OnMoneyChanged(Player* pPlayer, int32& amount)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_MONEY_CHANGE))
- return;
-
- LOCK_ELUNA;
- Push(pPlayer);
- Push(amount);
- int amountIndex = lua_gettop(L);
- int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_MONEY_CHANGE, 2);
-
- while (n > 0)
- {
- int r = CallOneFunction(n--, 2, 1);
-
- if (lua_isnumber(L, r))
- {
- amount = CHECKVAL(L, r);
- // Update the stack for subsequent calls.
- ReplaceArgument(amount, amountIndex);
- }
-
- lua_pop(L, 1);
- }
-
- CleanUpStack(2);
-}
-
-void Eluna::OnGiveXP(Player* pPlayer, uint32& amount, Unit* pVictim)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_GIVE_XP))
- return;
-
- LOCK_ELUNA;
- Push(pPlayer);
- Push(amount);
- Push(pVictim);
- int amountIndex = lua_gettop(L) - 1;
- int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_GIVE_XP, 3);
-
- while (n > 0)
- {
- int r = CallOneFunction(n--, 3, 1);
-
- if (lua_isnumber(L, r))
- {
- amount = CHECKVAL(L, r);
- // Update the stack for subsequent calls.
- ReplaceArgument(amount, amountIndex);
- }
-
- lua_pop(L, 1);
- }
-
- CleanUpStack(3);
-}
-
-void Eluna::OnReputationChange(Player* pPlayer, uint32 factionID, int32& standing, bool incremental)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_REPUTATION_CHANGE))
- return;
-
- LOCK_ELUNA;
- Push(pPlayer);
- Push(factionID);
- Push(standing);
- Push(incremental);
- int standingIndex = lua_gettop(L) - 1;
- int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_REPUTATION_CHANGE, 4);
-
- while (n > 0)
- {
- int r = CallOneFunction(n--, 4, 1);
-
- if (lua_isnumber(L, r))
- {
- standing = CHECKVAL(L, r);
- // Update the stack for subsequent calls.
- ReplaceArgument(standing, standingIndex);
- }
-
- lua_pop(L, 1);
- }
-
- CleanUpStack(4);
-}
-
-void Eluna::OnDuelRequest(Player* pTarget, Player* pChallenger)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_DUEL_REQUEST))
- return;
-
- LOCK_ELUNA;
- Push(pTarget);
- Push(pChallenger);
- CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_DUEL_REQUEST);
-}
-
-void Eluna::OnDuelStart(Player* pStarter, Player* pChallenger)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_DUEL_START))
- return;
-
- LOCK_ELUNA;
- Push(pStarter);
- Push(pChallenger);
- CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_DUEL_START);
-}
-
-void Eluna::OnDuelEnd(Player* pWinner, Player* pLoser, DuelCompleteType type)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_DUEL_END))
- return;
-
- LOCK_ELUNA;
- Push(pWinner);
- Push(pLoser);
- Push(type);
- CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_DUEL_END);
-}
-
-void Eluna::OnEmote(Player* pPlayer, uint32 emote)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_EMOTE))
- return;
-
- LOCK_ELUNA;
- Push(pPlayer);
- Push(emote);
- CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_EMOTE);
-}
-
-void Eluna::OnTextEmote(Player* pPlayer, uint32 textEmote, uint32 emoteNum, uint64 guid)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_TEXT_EMOTE))
- return;
-
- LOCK_ELUNA;
- Push(pPlayer);
- Push(textEmote);
- Push(emoteNum);
- Push(guid);
- CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_TEXT_EMOTE);
-}
-
-void Eluna::OnSpellCast(Player* pPlayer, Spell* pSpell, bool skipCheck)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_SPELL_CAST))
- return;
-
- LOCK_ELUNA;
- Push(pPlayer);
- Push(pSpell);
- Push(skipCheck);
- CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_SPELL_CAST);
-}
-
-void Eluna::OnLogin(Player* pPlayer)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_LOGIN))
- return;
-
- LOCK_ELUNA;
- Push(pPlayer);
- CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_LOGIN);
-}
-
-void Eluna::OnLogout(Player* pPlayer)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_LOGOUT))
- return;
-
- LOCK_ELUNA;
- Push(pPlayer);
- CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_LOGOUT);
-}
-
-void Eluna::OnCreate(Player* pPlayer)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_CHARACTER_CREATE))
- return;
-
- LOCK_ELUNA;
- Push(pPlayer);
- CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_CHARACTER_CREATE);
-}
-
-void Eluna::OnDelete(uint32 guidlow)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_CHARACTER_DELETE))
- return;
-
- LOCK_ELUNA;
- Push(guidlow);
- CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_CHARACTER_DELETE);
-}
-
-void Eluna::OnSave(Player* pPlayer)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_SAVE))
- return;
-
- LOCK_ELUNA;
- Push(pPlayer);
- CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_SAVE);
-}
-
-void Eluna::OnBindToInstance(Player* pPlayer, Difficulty difficulty, uint32 mapid, bool permanent)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_BIND_TO_INSTANCE))
- return;
-
- LOCK_ELUNA;
- Push(pPlayer);
- Push(difficulty);
- Push(mapid);
- Push(permanent);
- CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_BIND_TO_INSTANCE);
-}
-
-void Eluna::OnUpdateZone(Player* pPlayer, uint32 newZone, uint32 newArea)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_UPDATE_ZONE))
- return;
-
- LOCK_ELUNA;
- Push(pPlayer);
- Push(newZone);
- Push(newArea);
- CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_UPDATE_ZONE);
-}
-
-void Eluna::OnMapChanged(Player* player)
-{
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_MAP_CHANGE))
- return;
-
- LOCK_ELUNA;
- 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);
-}
-
-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;
- bool result = true;
- Push(pPlayer);
- Push(msg);
- Push(type);
- Push(lang);
- int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_CHAT, 4);
-
- while (n > 0)
- {
- int r = CallOneFunction(n--, 4, 2);
-
- if (lua_isboolean(L, r + 0) && !lua_toboolean(L, r + 0))
- result = false;
-
- if (lua_isstring(L, r + 1))
- msg = std::string(lua_tostring(L, r + 1));
-
- lua_pop(L, 2);
- }
-
- CleanUpStack(4);
- return result;
-}
-
-bool Eluna::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg, Group* pGroup)
-{
- 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;
- bool result = true;
- Push(pPlayer);
- Push(msg);
- Push(type);
- Push(lang);
- Push(pGroup);
- int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_GROUP_CHAT, 5);
-
- while (n > 0)
- {
- int r = CallOneFunction(n--, 5, 2);
-
- if (lua_isboolean(L, r + 0) && !lua_toboolean(L, r + 0))
- result = false;
-
- if (lua_isstring(L, r + 1))
- msg = std::string(lua_tostring(L, r + 1));
-
- lua_pop(L, 2);
- }
-
- CleanUpStack(5);
- return result;
-}
-
-bool Eluna::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg, Guild* pGuild)
-{
- 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;
- bool result = true;
- Push(pPlayer);
- Push(msg);
- Push(type);
- Push(lang);
- Push(pGuild);
- int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_GUILD_CHAT, 5);
-
- while (n > 0)
- {
- int r = CallOneFunction(n--, 5, 2);
-
- if (lua_isboolean(L, r + 0) && !lua_toboolean(L, r + 0))
- result = false;
-
- if (lua_isstring(L, r + 1))
- msg = std::string(lua_tostring(L, r + 1));
-
- lua_pop(L, 2);
- }
-
- CleanUpStack(5);
- return result;
-}
-
-bool Eluna::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg, Channel* pChannel)
-{
- 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;
- bool result = true;
- Push(pPlayer);
- Push(msg);
- Push(type);
- Push(lang);
- Push(pChannel->GetChannelId());
- int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_CHANNEL_CHAT, 5);
-
- while (n > 0)
- {
- int r = CallOneFunction(n--, 5, 2);
-
- if (lua_isboolean(L, r + 0) && !lua_toboolean(L, r + 0))
- result = false;
-
- if (lua_isstring(L, r + 1))
- msg = std::string(lua_tostring(L, r + 1));
-
- lua_pop(L, 2);
- }
-
- CleanUpStack(5);
- return result;
-}
-
-bool Eluna::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg, Player* pReceiver)
-{
- if (lang == LANG_ADDON)
- return OnAddonMessage(pPlayer, type, msg, pReceiver, NULL, NULL, NULL);
-
- if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_WHISPER))
- return true;
-
- LOCK_ELUNA;
- bool result = true;
- Push(pPlayer);
- Push(msg);
- Push(type);
- Push(lang);
- Push(pReceiver);
- int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_WHISPER, 5);
-
- while (n > 0)
- {
- int r = CallOneFunction(n--, 5, 2);
-
- if (lua_isboolean(L, r + 0) && !lua_toboolean(L, r + 0))
- result = false;
-
- if (lua_isstring(L, r + 1))
- msg = std::string(lua_tostring(L, r + 1));
-
- lua_pop(L, 2);
- }
-
- CleanUpStack(5);
- return result;
-}
-
-#ifndef CLASSIC
-#ifndef TBC
-// Vehicle
-void Eluna::OnInstall(Vehicle* vehicle)
-{
- if (!VehicleEventBindings->HasEvents(VEHICLE_EVENT_ON_INSTALL))
- return;
-
- LOCK_ELUNA;
- Push(vehicle);
- CallAllFunctions(VehicleEventBindings, VEHICLE_EVENT_ON_INSTALL);
-}
-
-void Eluna::OnUninstall(Vehicle* vehicle)
-{
- if (!VehicleEventBindings->HasEvents(VEHICLE_EVENT_ON_UNINSTALL))
- return;
-
- LOCK_ELUNA;
- Push(vehicle);
- CallAllFunctions(VehicleEventBindings, VEHICLE_EVENT_ON_UNINSTALL);
-}
-
-void Eluna::OnInstallAccessory(Vehicle* vehicle, Creature* accessory)
-{
- if (!VehicleEventBindings->HasEvents(VEHICLE_EVENT_ON_INSTALL_ACCESSORY))
- return;
-
- LOCK_ELUNA;
- Push(vehicle);
- Push(accessory);
- CallAllFunctions(VehicleEventBindings, VEHICLE_EVENT_ON_INSTALL_ACCESSORY);
-}
-
-void Eluna::OnAddPassenger(Vehicle* vehicle, Unit* passenger, int8 seatId)
-{
- if (!VehicleEventBindings->HasEvents(VEHICLE_EVENT_ON_ADD_PASSENGER))
- return;
-
- LOCK_ELUNA;
- Push(vehicle);
- Push(passenger);
- Push(seatId);
- CallAllFunctions(VehicleEventBindings, VEHICLE_EVENT_ON_ADD_PASSENGER);
-}
-
-void Eluna::OnRemovePassenger(Vehicle* vehicle, Unit* passenger)
-{
- if (!VehicleEventBindings->HasEvents(VEHICLE_EVENT_ON_REMOVE_PASSENGER))
- return;
-
- LOCK_ELUNA;
- Push(vehicle);
- Push(passenger);
- CallAllFunctions(VehicleEventBindings, VEHICLE_EVENT_ON_REMOVE_PASSENGER);
-}
-#endif
-#endif
-
-void Eluna::OnAddMember(Guild* guild, Player* player, uint32 plRank)
-{
- if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_ADD_MEMBER))
- return;
-
- LOCK_ELUNA;
- Push(guild);
- Push(player);
- Push(plRank);
- CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_ADD_MEMBER);
-}
-
-void Eluna::OnRemoveMember(Guild* guild, Player* player, bool isDisbanding)
-{
- if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_REMOVE_MEMBER))
- return;
-
- LOCK_ELUNA;
- Push(guild);
- Push(player);
- Push(isDisbanding);
- CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_REMOVE_MEMBER);
-}
-
-void Eluna::OnMOTDChanged(Guild* guild, const std::string& newMotd)
-{
- if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_MOTD_CHANGE))
- return;
-
- LOCK_ELUNA;
- Push(guild);
- Push(newMotd);
- CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_MOTD_CHANGE);
-}
-
-void Eluna::OnInfoChanged(Guild* guild, const std::string& newInfo)
-{
- if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_INFO_CHANGE))
- return;
-
- LOCK_ELUNA;
- Push(guild);
- Push(newInfo);
- CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_INFO_CHANGE);
-}
-
-void Eluna::OnCreate(Guild* guild, Player* leader, const std::string& name)
-{
- if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_CREATE))
- return;
-
- LOCK_ELUNA;
- Push(guild);
- Push(leader);
- Push(name);
- CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_CREATE);
-}
-
-void Eluna::OnDisband(Guild* guild)
-{
- if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_DISBAND))
- return;
-
- LOCK_ELUNA;
- Push(guild);
- CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_DISBAND);
-}
-
-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;
- 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);
-
- while (n > 0)
- {
- int r = CallOneFunction(n--, 4, 1);
-
- if (lua_isnumber(L, r))
- {
- amount = CHECKVAL(L, r);
- // Update the stack for subsequent calls.
- ReplaceArgument(amount, amountIndex);
- }
-
- lua_pop(L, 1);
- }
-
- CleanUpStack(4);
-}
-
-void Eluna::OnMemberDepositMoney(Guild* guild, Player* player, uint32& amount)
-{
- if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_MONEY_DEPOSIT))
- return;
-
- LOCK_ELUNA;
- Push(guild);
- Push(player);
- Push(amount);
- int amountIndex = lua_gettop(L);
- int n = SetupStack(GuildEventBindings, GUILD_EVENT_ON_MONEY_DEPOSIT, 3);
-
- while (n > 0)
- {
- int r = CallOneFunction(n--, 3, 1);
-
- if (lua_isnumber(L, r))
- {
- amount = CHECKVAL(L, r);
- // Update the stack for subsequent calls.
- ReplaceArgument(amount, amountIndex);
- }
-
- lua_pop(L, 1);
- }
-
- CleanUpStack(3);
-}
-
-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;
- Push(guild);
- Push(player);
- Push(pItem);
- Push(isSrcBank);
- Push(srcContainer);
- Push(srcSlotId);
- Push(isDestBank);
- Push(destContainer);
- Push(destSlotId);
- CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_ITEM_MOVE);
-}
-
-void Eluna::OnEvent(Guild* guild, uint8 eventType, uint32 playerGuid1, uint32 playerGuid2, uint8 newRank)
-{
- if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_EVENT))
- return;
-
- LOCK_ELUNA;
- Push(guild);
- Push(eventType);
- Push(playerGuid1);
- Push(playerGuid2);
- Push(newRank);
- CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_EVENT);
-}
-
-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;
- Push(guild);
- Push(eventType);
- Push(tabId);
- Push(playerGuid);
- Push(itemOrMoney);
- Push(itemStackCount);
- Push(destTabId);
- CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_BANK_EVENT);
-}
-// Group
-void Eluna::OnAddMember(Group* group, uint64 guid)
-{
- if (!GroupEventBindings->HasEvents(GROUP_EVENT_ON_MEMBER_ADD))
- return;
-
- LOCK_ELUNA;
- Push(group);
- Push(guid);
- CallAllFunctions(GroupEventBindings, GROUP_EVENT_ON_MEMBER_ADD);
-}
-
-void Eluna::OnInviteMember(Group* group, uint64 guid)
-{
- if (!GroupEventBindings->HasEvents(GROUP_EVENT_ON_MEMBER_INVITE))
- return;
-
- LOCK_ELUNA;
- Push(group);
- Push(guid);
- CallAllFunctions(GroupEventBindings, GROUP_EVENT_ON_MEMBER_INVITE);
-}
-
-void Eluna::OnRemoveMember(Group* group, uint64 guid, uint8 method)
-{
- if (!GroupEventBindings->HasEvents(GROUP_EVENT_ON_MEMBER_REMOVE))
- return;
-
- LOCK_ELUNA;
- Push(group);
- Push(guid);
- Push(method);
- CallAllFunctions(GroupEventBindings, GROUP_EVENT_ON_MEMBER_REMOVE);
-}
-
-void Eluna::OnChangeLeader(Group* group, uint64 newLeaderGuid, uint64 oldLeaderGuid)
-{
- if (!GroupEventBindings->HasEvents(GROUP_EVENT_ON_LEADER_CHANGE))
- return;
-
- LOCK_ELUNA;
- Push(group);
- Push(newLeaderGuid);
- Push(oldLeaderGuid);
- CallAllFunctions(GroupEventBindings, GROUP_EVENT_ON_LEADER_CHANGE);
-}
-
-void Eluna::OnDisband(Group* group)
-{
- if (!GroupEventBindings->HasEvents(GROUP_EVENT_ON_DISBAND))
- return;
-
- LOCK_ELUNA;
- Push(group);
- CallAllFunctions(GroupEventBindings, GROUP_EVENT_ON_DISBAND);
-}
-
-void Eluna::OnCreate(Group* group, uint64 leaderGuid, GroupType groupType)
-{
- if (!GroupEventBindings->HasEvents(GROUP_EVENT_ON_CREATE))
- return;
-
- LOCK_ELUNA;
- Push(group);
- Push(leaderGuid);
- Push(groupType);
- CallAllFunctions(GroupEventBindings, GROUP_EVENT_ON_CREATE);
-}
-
-/* Map */
-void Eluna::OnCreate(Map* map)
-{
- if (!ServerEventBindings->HasEvents(MAP_EVENT_ON_CREATE))
- return;
-
- LOCK_ELUNA;
- Push(map);
- CallAllFunctions(ServerEventBindings, MAP_EVENT_ON_CREATE);
-}
-void Eluna::OnDestroy(Map* map)
-{
- if (!ServerEventBindings->HasEvents(MAP_EVENT_ON_DESTROY))
- return;
-
- LOCK_ELUNA;
- Push(map);
- CallAllFunctions(ServerEventBindings, MAP_EVENT_ON_DESTROY);
-}
-void Eluna::OnPlayerEnter(Map* map, Player* player)
-{
- if (!ServerEventBindings->HasEvents(MAP_EVENT_ON_PLAYER_ENTER))
- return;
-
- LOCK_ELUNA;
- Push(map);
- Push(player);
- CallAllFunctions(ServerEventBindings, MAP_EVENT_ON_PLAYER_ENTER);
-}
-void Eluna::OnPlayerLeave(Map* map, Player* player)
-{
- if (!ServerEventBindings->HasEvents(MAP_EVENT_ON_PLAYER_LEAVE))
- return;
-
- LOCK_ELUNA;
- Push(map);
- Push(player);
- CallAllFunctions(ServerEventBindings, MAP_EVENT_ON_PLAYER_LEAVE);
-}
-void Eluna::OnUpdate(Map* map, uint32 diff)
-{
- if (!ServerEventBindings->HasEvents(MAP_EVENT_ON_UPDATE))
- return;
-
- LOCK_ELUNA;
- // enable this for multithread
- // eventMgr->globalProcessor->Update(diff);
- Push(map);
- Push(diff);
- CallAllFunctions(ServerEventBindings, MAP_EVENT_ON_UPDATE);
-}
-void Eluna::OnRemove(GameObject* gameobject)
-{
- if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_DELETE_GAMEOBJECT))
- return;
-
- LOCK_ELUNA;
- Push(gameobject);
- CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_DELETE_GAMEOBJECT);
-}
-void Eluna::OnRemove(Creature* creature)
-{
- if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_DELETE_CREATURE))
- return;
-
- LOCK_ELUNA;
- Push(creature);
- CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_DELETE_CREATURE);
-}
-
-// creature
-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;
- 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);
-}
-
-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;
- Push(pPlayer);
- Push(pCreature);
- Push(pQuest);
- return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_QUEST_ACCEPT, pCreature->GetEntry(), pCreature->GET_GUID(), pCreature->GetInstanceId());
-}
-
-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;
- Push(pPlayer);
- Push(pCreature);
- Push(pQuest);
- Push(opt);
- return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_QUEST_REWARD, pCreature->GetEntry(), pCreature->GET_GUID(), pCreature->GetInstanceId());
-}
-
-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;
- Push(pPlayer);
- Push(pCreature);
- CallAllFunctions(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_DIALOG_STATUS, pCreature->GetEntry(), pCreature->GET_GUID(), pCreature->GetInstanceId());
- return DIALOG_STATUS_SCRIPTED_NO_STATUS;
-}
-
-void Eluna::OnAddToWorld(Creature* creature)
-{
- 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());
-}
-
-void Eluna::OnRemoveFromWorld(Creature* creature)
-{
- 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());
-}
-
-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;
- Push(pCreature);
- Push(pSummoner);
- return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_SUMMONED, pCreature->GetEntry(), pCreature->GET_GUID(), pCreature->GetInstanceId());
-}
-
-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;
- Push(me);
- Push(diff);
- return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_AIUPDATE, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
-}
-
-//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;
- Push(me);
- Push(target);
- return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_ENTER_COMBAT, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
-}
-
-// 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;
- 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);
-
- while (n > 0)
- {
- int r = CallOneFunction(n--, 3, 2);
-
- if (lua_isboolean(L, r + 0) && lua_toboolean(L, r + 0))
- result = true;
-
- if (lua_isnumber(L, r + 1))
- {
- damage = Eluna::CHECKVAL(L, r + 1);
- // Update the stack for subsequent calls.
- ReplaceArgument(damage, damageIndex);
- }
-
- lua_pop(L, 2);
- }
-
- CleanUpStack(3);
- return result;
-}
-
-//Called at creature death
-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;
- Push(me);
- Push(killer);
- return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_DIED, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
-}
-
-//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;
- Push(me);
- Push(victim);
- return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_TARGET_DIED, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
-}
-
-// 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;
- Push(me);
- Push(summon);
- return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_JUST_SUMMONED_CREATURE, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
-}
-
-// 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;
- Push(me);
- Push(summon);
- return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_SUMMONED_CREATURE_DESPAWN, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
-}
-
-//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;
- Push(me);
- Push(type);
- Push(id);
- return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_REACH_WP, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
-}
-
-// 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;
- Push(me);
- Push(target);
- return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_PRE_COMBAT, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
-}
-
-// 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;
- Push(me);
- return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_LEAVE_COMBAT, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
-}
-
-// 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;
- Push(me);
- Push(attacker);
- return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_ATTACKED_AT, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
-}
-
-// 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;
- Push(me);
- return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_SPAWN, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
-}
-
-// 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;
- Push(me);
- return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_REACH_HOME, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
-}
-
-// 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;
- Push(me);
- Push(player);
- Push(emoteId);
- return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_RECEIVE_EMOTE, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
-}
-
-// 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;
- 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);
-
- while (n > 0)
- {
- int r = CallOneFunction(n--, 2, 2);
-
- if (lua_isboolean(L, r + 0) && lua_toboolean(L, r + 0))
- result = true;
-
- if (lua_isnumber(L, r + 1))
- {
- respawnDelay = Eluna::CHECKVAL(L, r + 1);
- // Update the stack for subsequent calls.
- ReplaceArgument(respawnDelay, respawnDelayIndex);
- }
-
- lua_pop(L, 2);
- }
-
- CleanUpStack(2);
- return result;
-}
-
-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;
- Push(me);
- Push(who);
- return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_MOVE_IN_LOS, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
-}
-
-// 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;
- Push(me);
- CallAllFunctions(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_RESET, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
-}
-
-// 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;
- 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());
-}
-
-// 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;
- 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());
-}
-
-#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;
- Push(me);
- Push(summon);
- Push(killer);
- return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_SUMMONED_CREATURE_DIED, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
-}
-
-// 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;
- Push(me);
- Push(attacker);
- return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_OWNER_ATTACKED_AT, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
-}
-
-// 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;
- Push(me);
- Push(target);
- return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, CREATURE_EVENT_ON_OWNER_ATTACKED, me->GetEntry(), me->GET_GUID(), me->GetInstanceId());
-}
-#endif
-
-// gameobject
-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;
- 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());
-}
-
-void Eluna::UpdateAI(GameObject* pGameObject, uint32 diff)
-{
- if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_AIUPDATE, pGameObject->GetEntry()))
- return;
-
- LOCK_ELUNA;
- pGameObject->elunaEvents->Update(diff);
- Push(pGameObject);
- Push(diff);
- CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_AIUPDATE, pGameObject->GetEntry());
-}
-
-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;
- Push(pPlayer);
- Push(pGameObject);
- Push(pQuest);
- Push(opt);
- return CallAllFunctionsBool(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_QUEST_REWARD, pGameObject->GetEntry());
-}
-
-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;
- Push(pPlayer);
- Push(pGameObject);
- CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_DIALOG_STATUS, pGameObject->GetEntry());
- return DIALOG_STATUS_SCRIPTED_NO_STATUS; // DIALOG_STATUS_UNDEFINED
-}
-
-#ifndef CLASSIC
-#ifndef TBC
-void Eluna::OnDestroyed(GameObject* pGameObject, Player* pPlayer)
-{
- if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_DESTROYED, pGameObject->GetEntry()))
- return;
-
- LOCK_ELUNA;
- Push(pGameObject);
- Push(pPlayer);
- CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_DESTROYED, pGameObject->GetEntry());
-}
-
-void Eluna::OnDamaged(GameObject* pGameObject, Player* pPlayer)
-{
- if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_DAMAGED, pGameObject->GetEntry()))
- return;
-
- LOCK_ELUNA;
- Push(pGameObject);
- Push(pPlayer);
- CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_DAMAGED, pGameObject->GetEntry());
-}
-#endif
-#endif
-
-void Eluna::OnLootStateChanged(GameObject* pGameObject, uint32 state)
-{
- if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_LOOT_STATE_CHANGE, pGameObject->GetEntry()))
- return;
-
- LOCK_ELUNA;
- Push(pGameObject);
- Push(state);
- CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_LOOT_STATE_CHANGE, pGameObject->GetEntry());
-}
-
-void Eluna::OnGameObjectStateChanged(GameObject* pGameObject, uint32 state)
-{
- if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_GO_STATE_CHANGED, pGameObject->GetEntry()))
- return;
-
- LOCK_ELUNA;
- Push(pGameObject);
- Push(state);
- CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_GO_STATE_CHANGED, pGameObject->GetEntry());
-}
-
-void Eluna::OnSpawn(GameObject* gameobject)
-{
- if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_SPAWN, gameobject->GetEntry()))
- return;
-
- LOCK_ELUNA;
- Push(gameobject);
- CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_SPAWN, gameobject->GetEntry());
-}
-
-void Eluna::OnAddToWorld(GameObject* gameobject)
-{
- if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_ADD, gameobject->GetEntry()))
- return;
-
- LOCK_ELUNA;
- Push(gameobject);
- CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_ADD, gameobject->GetEntry());
-}
-
-void Eluna::OnRemoveFromWorld(GameObject* gameobject)
-{
- if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_REMOVE, gameobject->GetEntry()))
- return;
-
- LOCK_ELUNA;
- Push(gameobject);
- CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_REMOVE, gameobject->GetEntry());
-}
-
-bool Eluna::OnGameObjectUse(Player* pPlayer, GameObject* pGameObject)
-{
- if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_USE, pGameObject->GetEntry()))
- return false;
-
- LOCK_ELUNA;
- Push(pGameObject);
- Push(pPlayer);
- return CallAllFunctionsBool(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_USE, pGameObject->GetEntry());
-}
-
-CreatureAI* Eluna::GetAI(Creature* creature)
-{
- if (!CreatureEventBindings->HasEvents(creature->GetEntry()) && !CreatureUniqueBindings->HasEvents(creature->GET_GUID(), creature->GetInstanceId()))
- return NULL;
- return new ElunaCreatureAI(creature);
-}
-
-void Eluna::OnBGStart(BattleGround* bg, BattleGroundTypeId bgId, uint32 instanceId)
-{
- if (!BGEventBindings->HasEvents(BG_EVENT_ON_START))
- return;
-
- LOCK_ELUNA;
- Push(bg);
- Push(bgId);
- Push(instanceId);
- CallAllFunctions(BGEventBindings, BG_EVENT_ON_START);
-}
-
-void Eluna::OnBGEnd(BattleGround* bg, BattleGroundTypeId bgId, uint32 instanceId, Team winner)
-{
- if (!BGEventBindings->HasEvents(BG_EVENT_ON_END))
- return;
-
- LOCK_ELUNA;
- Push(bg);
- Push(bgId);
- Push(instanceId);
- Push(winner);
- CallAllFunctions(BGEventBindings, BG_EVENT_ON_END);
-}
-
-void Eluna::OnBGCreate(BattleGround* bg, BattleGroundTypeId bgId, uint32 instanceId)
-{
- if (!BGEventBindings->HasEvents(BG_EVENT_ON_CREATE))
- return;
-
- LOCK_ELUNA;
- Push(bg);
- Push(bgId);
- Push(instanceId);
- CallAllFunctions(BGEventBindings, BG_EVENT_ON_CREATE);
-}
-
-void Eluna::OnBGDestroy(BattleGround* bg, BattleGroundTypeId bgId, uint32 instanceId)
-{
- if (!BGEventBindings->HasEvents(BG_EVENT_ON_PRE_DESTROY))
- return;
-
- LOCK_ELUNA;
- Push(bg);
- Push(bgId);
- Push(instanceId);
- CallAllFunctions(BGEventBindings, BG_EVENT_ON_PRE_DESTROY);
-}
diff --git a/Hooks.cpp b/Hooks.cpp
new file mode 100644
index 0000000..5fd8be4
--- /dev/null
+++ b/Hooks.cpp
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2010 - 2015 Eluna Lua Engine
+ * This program is free software licensed under GPL version 3
+ * Please see the included DOCS/LICENSE.md for more information
+ */
+
+#include "Hooks.h"
+#include "LuaEngine.h"
+#include "ElunaBinding.h"
+#include "ElunaEventMgr.h"
+#include "ElunaIncludes.h"
+#include "ElunaTemplate.h"
+#include "ElunaCreatureAI.h"
+
+extern "C"
+{
+#include "lua.h"
+};
+
diff --git a/HookMgr.h b/Hooks.h
similarity index 90%
rename from HookMgr.h
rename to Hooks.h
index f5d45fb..2c8531a 100644
--- a/HookMgr.h
+++ b/Hooks.h
@@ -1,13 +1,72 @@
/*
-* Copyright (C) 2010 - 2015 Eluna Lua Engine
-* This program is free software licensed under GPL version 3
-* Please see the included DOCS/LICENSE.md for more information
-*/
+ * Copyright (C) 2010 - 2015 Eluna Lua Engine
+ * This program is free software licensed under GPL version 3
+ * Please see the included DOCS/LICENSE.md for more information
+ */
-#ifndef LUAHOOKS_H
-#define LUAHOOKS_H
+#ifndef _HOOKS_H
+#define _HOOKS_H
-namespace HookMgr
+/*
+ * A hook should be written in one of the following forms:
+ *
+ * A. If results will be IGNORED:
+ *
+ * // Return early if there are no bindings.
+ * if (!WhateverBindings->HasEvents(SOME_EVENT_TYPE))
+ * return;
+ *
+ * // Lock out any other threads.
+ * LOCK_ELUNA;
+ *
+ * // Push extra arguments, if any.
+ * Push(a);
+ * Push(b);
+ * Push(c);
+ *
+ * // Call all event handlers.
+ * CallAllFunctions(WhateverBindings, SOME_EVENT_TYPE);
+ *
+ *
+ * B. If results will be USED:
+ *
+ * // Return early if there are no bindings.
+ * if (!WhateverBindings->HasEvents(SOME_EVENT_TYPE))
+ * return;
+ *
+ * // Lock out any other threads.
+ * LOCK_ELUNA;
+ *
+ * // Push extra arguments, if any.
+ * Push(a);
+ * Push(b);
+ * Push(c);
+ *
+ * // Setup the stack and get the number of functions pushed.
+ * // Last argument is 3 because we did 3 Pushes.
+ * int n = SetupStack(WhateverBindings, SOME_EVENT_TYPE, 3);
+ *
+ * // Call each event handler in order and check results.
+ * while (n > 0)
+ * {
+ * // Call an event handler and decrement the function counter afterward.
+ * // Second-last argument is 3 because we did 3 Pushes.
+ * // Last argument is 2 because we want 2 results.
+ * int r = CallOneFunction(n--, 3, 2);
+ *
+ * // Results can be popped using `r`.
+ * int first = CHECKVAL(L, r + 0);
+ * int second = CHECKVAL(L, r + 1);
+ *
+ * // Pop the results off the stack.
+ * lua_pop(L, 2);
+ * }
+ *
+ * // Clean-up the stack. Argument is 3 because we did 3 Pushes.
+ * CleanUpStack(3);
+ */
+
+namespace Hooks
{
enum RegisterTypes
{
@@ -28,7 +87,6 @@ namespace HookMgr
REGTYPE_COUNT
};
- // RegisterPacketEvent(Opcode, event, function)
enum PacketEvents
{
PACKET_EVENT_ON_PACKET_RECEIVE = 5, // (event, packet, player) - Player only if accessible. Can return false, newPacket
@@ -38,7 +96,6 @@ namespace HookMgr
PACKET_EVENT_COUNT
};
- // RegisterServerEvent(EventId, function)
enum ServerEvents
{
// Server
@@ -96,7 +153,6 @@ namespace HookMgr
SERVER_EVENT_COUNT
};
- // RegisterPlayerEvent(eventId, function)
enum PlayerEvents
{
PLAYER_EVENT_ON_CHARACTER_CREATE = 1, // (event, player)
@@ -147,7 +203,6 @@ namespace HookMgr
PLAYER_EVENT_COUNT
};
- // RegisterGuildEvent(eventId, function)
enum GuildEvents
{
// Guild
@@ -166,7 +221,6 @@ namespace HookMgr
GUILD_EVENT_COUNT
};
- // RegisterGroupEvent(eventId, function)
enum GroupEvents
{
// Group
@@ -180,7 +234,6 @@ namespace HookMgr
GROUP_EVENT_COUNT
};
- // RegisterVehicleEvent(eventId, function)
enum VehicleEvents
{
VEHICLE_EVENT_ON_INSTALL = 1, // (event, vehicle)
@@ -193,7 +246,6 @@ namespace HookMgr
VEHICLE_EVENT_COUNT
};
- // RegisterCreatureEvent(entry, EventId, function)
enum CreatureEvents
{
CREATURE_EVENT_ON_ENTER_COMBAT = 1, // (event, creature, target) - Can return true to stop normal action
@@ -236,7 +288,6 @@ namespace HookMgr
CREATURE_EVENT_COUNT
};
- // RegisterGameObjectEvent(entry, EventId, function)
enum GameObjectEvents
{
GAMEOBJECT_EVENT_ON_AIUPDATE = 1, // (event, go, diff)
@@ -256,7 +307,6 @@ namespace HookMgr
GAMEOBJECT_EVENT_COUNT
};
- // RegisterItemEvent(entry, EventId, function)
enum ItemEvents
{
ITEM_EVENT_ON_DUMMY_EFFECT = 1, // (event, caster, spellid, effindex, item) - Can return true
@@ -267,10 +317,6 @@ namespace HookMgr
ITEM_EVENT_COUNT
};
- // RegisterCreatureGossipEvent(entry, EventId, function)
- // RegisterGameObjectGossipEvent(entry, EventId, function)
- // RegisterItemGossipEvent(entry, EventId, function)
- // RegisterPlayerGossipEvent(menu_id, EventId, function)
enum GossipEvents
{
GOSSIP_EVENT_ON_HELLO = 1, // (event, player, object) - Object is the Creature/GameObject/Item. Can return false to do default action. For item gossip can return false to stop spell casting.
@@ -278,7 +324,6 @@ namespace HookMgr
GOSSIP_EVENT_COUNT
};
- // RegisterBGEvent(EventId, function)
enum BGEvents
{
BG_EVENT_ON_START = 1, // (event, bg, bgId, instanceId) - Needs to be added to TC
@@ -288,4 +333,5 @@ namespace HookMgr
BG_EVENT_COUNT
};
};
-#endif
+
+#endif // _HOOKS_H
\ No newline at end of file
diff --git a/ItemHooks.cpp b/ItemHooks.cpp
new file mode 100644
index 0000000..e357be6
--- /dev/null
+++ b/ItemHooks.cpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2010 - 2015 Eluna Lua Engine
+ * This program is free software licensed under GPL version 3
+ * 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 "ElunaIncludes.h"
+
+using namespace Hooks;
+
+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;
+ Push(pCaster);
+ Push(spellId);
+ Push(effIndex);
+ Push(pTarget);
+ return CallAllFunctionsBool(ItemEventBindings, ITEM_EVENT_ON_DUMMY_EFFECT, pTarget->GetEntry());
+}
+
+bool Eluna::OnQuestAccept(Player* pPlayer, Item* pItem, Quest const* pQuest)
+{
+ if (!ItemEventBindings->HasEvents(ITEM_EVENT_ON_QUEST_ACCEPT, pItem->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(pItem);
+ Push(pQuest);
+ return CallAllFunctionsBool(ItemEventBindings, ITEM_EVENT_ON_QUEST_ACCEPT, pItem->GetEntry());
+}
+
+bool Eluna::OnUse(Player* pPlayer, Item* pItem, SpellCastTargets const& targets)
+{
+ ObjectGuid guid = pItem->GET_GUID();
+ bool castSpell = true;
+
+ if (!OnItemUse(pPlayer, pItem, targets))
+ castSpell = false;
+
+ pItem = pPlayer->GetItemByGuid(guid);
+ if (pItem)
+ {
+ if (!OnItemGossip(pPlayer, pItem, targets))
+ castSpell = false;
+ pItem = pPlayer->GetItemByGuid(guid);
+ }
+
+ if (pItem && castSpell)
+ return true;
+
+ // Send equip error that shows no message
+ // This is a hack fix to stop spell casting visual bug when a spell is not cast on use
+ WorldPacket data(SMSG_INVENTORY_CHANGE_FAILURE, 18);
+ data << uint8(59); // EQUIP_ERR_NONE / EQUIP_ERR_CANT_BE_DISENCHANTED
+ data << ObjectGuid(guid);
+ data << ObjectGuid(uint64(0));
+ data << uint8(0);
+ pPlayer->GetSession()->SendPacket(&data);
+ return false;
+}
+
+bool Eluna::OnItemUse(Player* pPlayer, Item* pItem, SpellCastTargets const& targets)
+{
+ if (!ItemEventBindings->HasEvents(ITEM_EVENT_ON_USE, pItem->GetEntry()))
+ return true;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(pItem);
+#ifndef TRINITY
+ if (GameObject* target = targets.getGOTarget())
+ Push(target);
+ else if (Item* target = targets.getItemTarget())
+ Push(target);
+ else if (Corpse* target = pPlayer->GetMap()->GetCorpse(targets.getCorpseTargetGuid()))
+ Push(target);
+ else if (Unit* target = targets.getUnitTarget())
+ Push(target);
+ else
+ Push();
+#else
+ if (GameObject* target = targets.GetGOTarget())
+ Push(target);
+ else if (Item* target = targets.GetItemTarget())
+ Push(target);
+ else if (Corpse* target = targets.GetCorpseTarget())
+ Push(target);
+ else if (Unit* target = targets.GetUnitTarget())
+ Push(target);
+ else if (WorldObject* target = targets.GetObjectTarget())
+ Push(target);
+ else
+ 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);
+}
+
+bool Eluna::OnExpire(Player* pPlayer, ItemTemplate const* pProto)
+{
+ if (!ItemEventBindings->HasEvents(ITEM_EVENT_ON_EXPIRE, pProto->ItemId))
+ return false;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(pProto->ItemId);
+ return CallAllFunctionsBool(ItemEventBindings, ITEM_EVENT_ON_EXPIRE, pProto->ItemId);
+}
+
+bool Eluna::OnRemove(Player* pPlayer, Item* item)
+{
+ if (!ItemEventBindings->HasEvents(ITEM_EVENT_ON_REMOVE, item->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(item);
+ return CallAllFunctionsBool(ItemEventBindings, ITEM_EVENT_ON_REMOVE, item->GetEntry());
+}
+
+#endif // _ITEM_HOOKS_H
\ No newline at end of file
diff --git a/LuaEngine.cpp b/LuaEngine.cpp
index dbf1c0c..60399d5 100644
--- a/LuaEngine.cpp
+++ b/LuaEngine.cpp
@@ -4,13 +4,14 @@
* Please see the included DOCS/LICENSE.md for more information
*/
-#include "HookMgr.h"
+#include "Hooks.h"
#include "LuaEngine.h"
#include "ElunaBinding.h"
#include "ElunaEventMgr.h"
#include "ElunaIncludes.h"
#include "ElunaTemplate.h"
#include "ElunaUtility.h"
+#include "ElunaCreatureAI.h"
#ifdef USING_BOOST
#include
@@ -123,23 +124,23 @@ push_counter(0),
eventMgr(NULL),
-ServerEventBindings(new EventBind("ServerEvents", *this)),
-PlayerEventBindings(new EventBind("PlayerEvents", *this)),
-GuildEventBindings(new EventBind("GuildEvents", *this)),
-GroupEventBindings(new EventBind("GroupEvents", *this)),
-VehicleEventBindings(new EventBind("VehicleEvents", *this)),
-BGEventBindings(new EventBind("BGEvents", *this)),
+ServerEventBindings(new EventBind("ServerEvents", *this)),
+PlayerEventBindings(new EventBind("PlayerEvents", *this)),
+GuildEventBindings(new EventBind("GuildEvents", *this)),
+GroupEventBindings(new EventBind("GroupEvents", *this)),
+VehicleEventBindings(new EventBind("VehicleEvents", *this)),
+BGEventBindings(new EventBind("BGEvents", *this)),
-PacketEventBindings(new EntryBind("PacketEvents", *this)),
-CreatureEventBindings(new EntryBind("CreatureEvents", *this)),
-CreatureGossipBindings(new EntryBind("GossipEvents (creature)", *this)),
-GameObjectEventBindings(new EntryBind("GameObjectEvents", *this)),
-GameObjectGossipBindings(new EntryBind("GossipEvents (gameobject)", *this)),
-ItemEventBindings(new EntryBind("ItemEvents", *this)),
-ItemGossipBindings(new EntryBind("GossipEvents (item)", *this)),
-playerGossipBindings(new EntryBind("GossipEvents (player)", *this)),
+PacketEventBindings(new EntryBind("PacketEvents", *this)),
+CreatureEventBindings(new EntryBind("CreatureEvents", *this)),
+CreatureGossipBindings(new EntryBind("GossipEvents (creature)", *this)),
+GameObjectEventBindings(new EntryBind("GameObjectEvents", *this)),
+GameObjectGossipBindings(new EntryBind("GossipEvents (gameobject)", *this)),
+ItemEventBindings(new EntryBind("ItemEvents", *this)),
+ItemGossipBindings(new EntryBind("GossipEvents (item)", *this)),
+playerGossipBindings(new EntryBind("GossipEvents (player)", *this)),
-CreatureUniqueBindings(new UniqueBind("CreatureEvents", *this))
+CreatureUniqueBindings(new UniqueBind("CreatureEvents", *this))
{
// open base lua libraries
luaL_openlibs(L);
@@ -767,56 +768,56 @@ void Eluna::Register(uint8 regtype, uint32 id, uint64 guid, uint32 instanceId, u
{
switch (regtype)
{
- case HookMgr::REGTYPE_SERVER:
- if (evt < HookMgr::SERVER_EVENT_COUNT)
+ case Hooks::REGTYPE_SERVER:
+ if (evt < Hooks::SERVER_EVENT_COUNT)
{
ServerEventBindings->Insert(evt, functionRef, shots);
return;
}
break;
- case HookMgr::REGTYPE_PLAYER:
- if (evt < HookMgr::PLAYER_EVENT_COUNT)
+ case Hooks::REGTYPE_PLAYER:
+ if (evt < Hooks::PLAYER_EVENT_COUNT)
{
PlayerEventBindings->Insert(evt, functionRef, shots);
return;
}
break;
- case HookMgr::REGTYPE_GUILD:
- if (evt < HookMgr::GUILD_EVENT_COUNT)
+ case Hooks::REGTYPE_GUILD:
+ if (evt < Hooks::GUILD_EVENT_COUNT)
{
GuildEventBindings->Insert(evt, functionRef, shots);
return;
}
break;
- case HookMgr::REGTYPE_GROUP:
- if (evt < HookMgr::GROUP_EVENT_COUNT)
+ case Hooks::REGTYPE_GROUP:
+ if (evt < Hooks::GROUP_EVENT_COUNT)
{
GroupEventBindings->Insert(evt, functionRef, shots);
return;
}
break;
- case HookMgr::REGTYPE_VEHICLE:
- if (evt < HookMgr::VEHICLE_EVENT_COUNT)
+ case Hooks::REGTYPE_VEHICLE:
+ if (evt < Hooks::VEHICLE_EVENT_COUNT)
{
VehicleEventBindings->Insert(evt, functionRef, shots);
return;
}
break;
- case HookMgr::REGTYPE_BG:
- if (evt < HookMgr::BG_EVENT_COUNT)
+ case Hooks::REGTYPE_BG:
+ if (evt < Hooks::BG_EVENT_COUNT)
{
BGEventBindings->Insert(evt, functionRef, shots);
return;
}
break;
- case HookMgr::REGTYPE_PACKET:
- if (evt < HookMgr::PACKET_EVENT_COUNT)
+ case Hooks::REGTYPE_PACKET:
+ if (evt < Hooks::PACKET_EVENT_COUNT)
{
if (id >= NUM_MSG_TYPES)
{
@@ -830,8 +831,8 @@ void Eluna::Register(uint8 regtype, uint32 id, uint64 guid, uint32 instanceId, u
}
break;
- case HookMgr::REGTYPE_CREATURE:
- if (evt < HookMgr::CREATURE_EVENT_COUNT)
+ case Hooks::REGTYPE_CREATURE:
+ if (evt < Hooks::CREATURE_EVENT_COUNT)
{
if (id != 0)
{
@@ -853,8 +854,8 @@ void Eluna::Register(uint8 regtype, uint32 id, uint64 guid, uint32 instanceId, u
}
break;
- case HookMgr::REGTYPE_CREATURE_GOSSIP:
- if (evt < HookMgr::GOSSIP_EVENT_COUNT)
+ case Hooks::REGTYPE_CREATURE_GOSSIP:
+ if (evt < Hooks::GOSSIP_EVENT_COUNT)
{
if (!eObjectMgr->GetCreatureTemplate(id))
{
@@ -868,8 +869,8 @@ void Eluna::Register(uint8 regtype, uint32 id, uint64 guid, uint32 instanceId, u
}
break;
- case HookMgr::REGTYPE_GAMEOBJECT:
- if (evt < HookMgr::GAMEOBJECT_EVENT_COUNT)
+ case Hooks::REGTYPE_GAMEOBJECT:
+ if (evt < Hooks::GAMEOBJECT_EVENT_COUNT)
{
if (!eObjectMgr->GetGameObjectTemplate(id))
{
@@ -883,8 +884,8 @@ void Eluna::Register(uint8 regtype, uint32 id, uint64 guid, uint32 instanceId, u
}
break;
- case HookMgr::REGTYPE_GAMEOBJECT_GOSSIP:
- if (evt < HookMgr::GOSSIP_EVENT_COUNT)
+ case Hooks::REGTYPE_GAMEOBJECT_GOSSIP:
+ if (evt < Hooks::GOSSIP_EVENT_COUNT)
{
if (!eObjectMgr->GetGameObjectTemplate(id))
{
@@ -898,8 +899,8 @@ void Eluna::Register(uint8 regtype, uint32 id, uint64 guid, uint32 instanceId, u
}
break;
- case HookMgr::REGTYPE_ITEM:
- if (evt < HookMgr::ITEM_EVENT_COUNT)
+ case Hooks::REGTYPE_ITEM:
+ if (evt < Hooks::ITEM_EVENT_COUNT)
{
if (!eObjectMgr->GetItemTemplate(id))
{
@@ -913,8 +914,8 @@ void Eluna::Register(uint8 regtype, uint32 id, uint64 guid, uint32 instanceId, u
}
break;
- case HookMgr::REGTYPE_ITEM_GOSSIP:
- if (evt < HookMgr::GOSSIP_EVENT_COUNT)
+ case Hooks::REGTYPE_ITEM_GOSSIP:
+ if (evt < Hooks::GOSSIP_EVENT_COUNT)
{
if (!eObjectMgr->GetItemTemplate(id))
{
@@ -928,8 +929,8 @@ void Eluna::Register(uint8 regtype, uint32 id, uint64 guid, uint32 instanceId, u
}
break;
- case HookMgr::REGTYPE_PLAYER_GOSSIP:
- if (evt < HookMgr::GOSSIP_EVENT_COUNT)
+ case Hooks::REGTYPE_PLAYER_GOSSIP:
+ if (evt < Hooks::GOSSIP_EVENT_COUNT)
{
playerGossipBindings->Insert(id, evt, functionRef, shots);
return;
@@ -939,3 +940,56 @@ void Eluna::Register(uint8 regtype, uint32 id, uint64 guid, uint32 instanceId, u
luaL_unref(L, LUA_REGISTRYINDEX, functionRef);
luaL_error(L, "Unknown event type (regtype %d, id %d, event %d)", regtype, id, evt);
}
+
+/*
+ * Cleans up the stack, effectively undoing all Push calls and the Setup call.
+ */
+void Eluna::CleanUpStack(int number_of_arguments)
+{
+ // Stack: event_id, [arguments]
+
+ lua_pop(L, number_of_arguments + 1); // Add 1 because the caller doesn't know about `event_id`.
+ // Stack: (empty)
+
+ if (event_level == 0)
+ InvalidateObjects();
+}
+
+/*
+ * Call a single event handler that was put on the stack with `Setup` and removes it from the stack.
+ *
+ * The caller is responsible for keeping track of how many times this should be called.
+ */
+int Eluna::CallOneFunction(int number_of_functions, int number_of_arguments, int number_of_results)
+{
+ ++number_of_arguments; // Caller doesn't know about `event_id`.
+ ASSERT(number_of_functions > 0 && number_of_arguments > 0 && number_of_results >= 0);
+ // Stack: event_id, [arguments], [functions]
+
+ int functions_top = lua_gettop(L);
+ int first_function_index = functions_top - number_of_functions + 1;
+ int arguments_top = first_function_index - 1;
+ int first_argument_index = arguments_top - number_of_arguments + 1;
+
+ // Copy the arguments from the bottom of the stack to the top.
+ for (int argument_index = first_argument_index; argument_index <= arguments_top; ++argument_index)
+ {
+ lua_pushvalue(L, argument_index);
+ }
+ // Stack: event_id, [arguments], [functions], event_id, [arguments]
+
+ ExecuteCall(number_of_arguments, number_of_results);
+ --functions_top;
+ // Stack: event_id, [arguments], [functions - 1], [results]
+
+ return functions_top + 1; // Return the location of the first result (if any exist).
+}
+
+CreatureAI* Eluna::GetAI(Creature* creature)
+{
+ if (CreatureEventBindings->HasEvents(creature->GetEntry()) ||
+ CreatureUniqueBindings->HasEvents(creature->GET_GUID(), creature->GetInstanceId()))
+ return new ElunaCreatureAI(creature);
+
+ return NULL;
+}
diff --git a/LuaEngine.h b/LuaEngine.h
index c51c7ce..d0c5cd7 100644
--- a/LuaEngine.h
+++ b/LuaEngine.h
@@ -18,7 +18,7 @@
#endif
#include "Weather.h"
#include "World.h"
-#include "HookMgr.h"
+#include "Hooks.h"
extern "C"
{
@@ -112,6 +112,7 @@ private:
Eluna& operator=(const Eluna&);
// 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 int SetupStack(EventBind* event_bindings, EntryBind* entry_bindings, UniqueBind* 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);
@@ -183,23 +184,23 @@ public:
EventMgr* eventMgr;
- EventBind* ServerEventBindings;
- EventBind* PlayerEventBindings;
- EventBind* GuildEventBindings;
- EventBind* GroupEventBindings;
- EventBind* VehicleEventBindings;
- EventBind* BGEventBindings;
+ EventBind* ServerEventBindings;
+ EventBind* PlayerEventBindings;
+ EventBind* GuildEventBindings;
+ EventBind* GroupEventBindings;
+ EventBind* VehicleEventBindings;
+ EventBind* BGEventBindings;
- EntryBind* PacketEventBindings;
- EntryBind* CreatureEventBindings;
- EntryBind* CreatureGossipBindings;
- EntryBind* GameObjectEventBindings;
- EntryBind* GameObjectGossipBindings;
- EntryBind* ItemEventBindings;
- EntryBind* ItemGossipBindings;
- EntryBind* playerGossipBindings;
+ EntryBind* PacketEventBindings;
+ EntryBind* CreatureEventBindings;
+ EntryBind* CreatureGossipBindings;
+ EntryBind* GameObjectEventBindings;
+ EntryBind* GameObjectGossipBindings;
+ EntryBind* ItemEventBindings;
+ EntryBind* ItemGossipBindings;
+ EntryBind* playerGossipBindings;
- UniqueBind* CreatureUniqueBindings;
+ UniqueBind* CreatureUniqueBindings;
Eluna();
~Eluna();
@@ -235,16 +236,18 @@ public:
static void Push(lua_State* luastate, const double);
static void Push(lua_State* luastate, const std::string&);
static void Push(lua_State* luastate, const char*);
- template static void Push(lua_State* luastate, T const* ptr)
- {
- ElunaTemplate::Push(luastate, ptr);
- }
static void Push(lua_State* luastate, Object const* obj);
static void Push(lua_State* luastate, WorldObject const* obj);
static void Push(lua_State* luastate, Unit const* unit);
static void Push(lua_State* luastate, Pet const* pet);
static void Push(lua_State* luastate, TempSummon const* summon);
+ template
+ static void Push(lua_State* luastate, T const* ptr)
+ {
+ ElunaTemplate::Push(luastate, ptr);
+ }
+
// When a hook pushes arguments to be passed to event handlers
// this is used to keep track of how many arguments were pushed.
uint8 push_counter;
@@ -263,7 +266,8 @@ public:
void Push(const double value) { Push(L, value); ++push_counter; }
void Push(const std::string& value) { Push(L, value); ++push_counter; }
void Push(const char* value) { Push(L, value); ++push_counter; }
- template void Push(T const* ptr){ Push(L, ptr); ++push_counter; }
+ template
+ void Push(T const* ptr) { Push(L, ptr); ++push_counter; }
// Checks
template static T CHECKVAL(lua_State* luastate, int narg);
diff --git a/PlayerHooks.cpp b/PlayerHooks.cpp
new file mode 100644
index 0000000..f80b73f
--- /dev/null
+++ b/PlayerHooks.cpp
@@ -0,0 +1,719 @@
+/*
+ * Copyright (C) 2010 - 2015 Eluna Lua Engine
+ * This program is free software licensed under GPL version 3
+ * 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 "ElunaIncludes.h"
+
+using namespace Hooks;
+
+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);
+}
+
+// Player
+bool Eluna::OnCommand(Player* player, const char* text)
+{
+ // If from console, player is NULL
+ std::string fullcmd(text);
+ if (!player || player->GetSession()->GetSecurity() >= SEC_ADMINISTRATOR)
+ {
+ char* creload = strtok((char*)text, " ");
+ char* celuna = strtok(NULL, "");
+ if (creload && celuna)
+ {
+ std::string reload(creload);
+ std::string eluna(celuna);
+ std::transform(reload.begin(), reload.end(), reload.begin(), ::tolower);
+ if (reload == "reload")
+ {
+ std::transform(eluna.begin(), eluna.end(), eluna.begin(), ::tolower);
+ if (std::string("eluna").find(eluna) == 0)
+ {
+ Eluna::reload = true;
+ return false;
+ }
+ }
+ }
+ }
+
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_COMMAND))
+ return true;
+
+ LOCK_ELUNA;
+ Push(player);
+ Push(fullcmd);
+ return CallAllFunctionsBool(PlayerEventBindings, PLAYER_EVENT_ON_COMMAND, true);
+}
+
+void Eluna::OnLootItem(Player* pPlayer, Item* pItem, uint32 count, uint64 guid)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_LOOT_ITEM))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(pItem);
+ Push(count);
+ Push(guid);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_LOOT_ITEM);
+}
+
+void Eluna::OnLootMoney(Player* pPlayer, uint32 amount)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_LOOT_MONEY))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(amount);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_LOOT_MONEY);
+}
+
+void Eluna::OnFirstLogin(Player* pPlayer)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_FIRST_LOGIN))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_FIRST_LOGIN);
+}
+
+void Eluna::OnRepop(Player* pPlayer)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_REPOP))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_REPOP);
+}
+
+void Eluna::OnResurrect(Player* pPlayer)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_RESURRECT))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_RESURRECT);
+}
+
+void Eluna::OnQuestAbandon(Player* pPlayer, uint32 questId)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_QUEST_ABANDON))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(questId);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_QUEST_ABANDON);
+}
+
+void Eluna::OnEquip(Player* pPlayer, Item* pItem, uint8 bag, uint8 slot)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_EQUIP))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(pItem);
+ Push(bag);
+ Push(slot);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_EQUIP);
+}
+
+InventoryResult Eluna::OnCanUseItem(const Player* pPlayer, uint32 itemEntry)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_CAN_USE_ITEM))
+ return EQUIP_ERR_OK;
+
+ LOCK_ELUNA;
+ InventoryResult result = EQUIP_ERR_OK;
+ Push(pPlayer);
+ Push(itemEntry);
+ int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_CAN_USE_ITEM, 2);
+
+ while (n > 0)
+ {
+ int r = CallOneFunction(n--, 2, 1);
+
+ if (lua_isnumber(L, r))
+ result = (InventoryResult)CHECKVAL(L, r);
+
+ lua_pop(L, 1);
+ }
+
+ CleanUpStack(2);
+ return result;
+}
+void Eluna::OnPlayerEnterCombat(Player* pPlayer, Unit* pEnemy)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_ENTER_COMBAT))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(pEnemy);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_ENTER_COMBAT);
+}
+
+void Eluna::OnPlayerLeaveCombat(Player* pPlayer)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_LEAVE_COMBAT))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_LEAVE_COMBAT);
+}
+
+void Eluna::OnPVPKill(Player* pKiller, Player* pKilled)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_KILL_PLAYER))
+ return;
+
+ LOCK_ELUNA;
+ Push(pKiller);
+ Push(pKilled);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_KILL_PLAYER);
+}
+
+void Eluna::OnCreatureKill(Player* pKiller, Creature* pKilled)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_KILL_CREATURE))
+ return;
+
+ LOCK_ELUNA;
+ Push(pKiller);
+ Push(pKilled);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_KILL_CREATURE);
+}
+
+void Eluna::OnPlayerKilledByCreature(Creature* pKiller, Player* pKilled)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_KILLED_BY_CREATURE))
+ return;
+
+ LOCK_ELUNA;
+ Push(pKiller);
+ Push(pKilled);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_KILLED_BY_CREATURE);
+}
+
+void Eluna::OnLevelChanged(Player* pPlayer, uint8 oldLevel)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_LEVEL_CHANGE))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(oldLevel);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_LEVEL_CHANGE);
+}
+
+void Eluna::OnFreeTalentPointsChanged(Player* pPlayer, uint32 newPoints)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_TALENTS_CHANGE))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(newPoints);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_TALENTS_CHANGE);
+}
+
+void Eluna::OnTalentsReset(Player* pPlayer, bool noCost)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_TALENTS_RESET))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(noCost);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_TALENTS_RESET);
+}
+
+void Eluna::OnMoneyChanged(Player* pPlayer, int32& amount)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_MONEY_CHANGE))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(amount);
+ int amountIndex = lua_gettop(L);
+ int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_MONEY_CHANGE, 2);
+
+ while (n > 0)
+ {
+ int r = CallOneFunction(n--, 2, 1);
+
+ if (lua_isnumber(L, r))
+ {
+ amount = CHECKVAL(L, r);
+ // Update the stack for subsequent calls.
+ ReplaceArgument(amount, amountIndex);
+ }
+
+ lua_pop(L, 1);
+ }
+
+ CleanUpStack(2);
+}
+
+void Eluna::OnGiveXP(Player* pPlayer, uint32& amount, Unit* pVictim)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_GIVE_XP))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(amount);
+ Push(pVictim);
+ int amountIndex = lua_gettop(L) - 1;
+ int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_GIVE_XP, 3);
+
+ while (n > 0)
+ {
+ int r = CallOneFunction(n--, 3, 1);
+
+ if (lua_isnumber(L, r))
+ {
+ amount = CHECKVAL(L, r);
+ // Update the stack for subsequent calls.
+ ReplaceArgument(amount, amountIndex);
+ }
+
+ lua_pop(L, 1);
+ }
+
+ CleanUpStack(3);
+}
+
+void Eluna::OnReputationChange(Player* pPlayer, uint32 factionID, int32& standing, bool incremental)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_REPUTATION_CHANGE))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(factionID);
+ Push(standing);
+ Push(incremental);
+ int standingIndex = lua_gettop(L) - 1;
+ int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_REPUTATION_CHANGE, 4);
+
+ while (n > 0)
+ {
+ int r = CallOneFunction(n--, 4, 1);
+
+ if (lua_isnumber(L, r))
+ {
+ standing = CHECKVAL(L, r);
+ // Update the stack for subsequent calls.
+ ReplaceArgument(standing, standingIndex);
+ }
+
+ lua_pop(L, 1);
+ }
+
+ CleanUpStack(4);
+}
+
+void Eluna::OnDuelRequest(Player* pTarget, Player* pChallenger)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_DUEL_REQUEST))
+ return;
+
+ LOCK_ELUNA;
+ Push(pTarget);
+ Push(pChallenger);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_DUEL_REQUEST);
+}
+
+void Eluna::OnDuelStart(Player* pStarter, Player* pChallenger)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_DUEL_START))
+ return;
+
+ LOCK_ELUNA;
+ Push(pStarter);
+ Push(pChallenger);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_DUEL_START);
+}
+
+void Eluna::OnDuelEnd(Player* pWinner, Player* pLoser, DuelCompleteType type)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_DUEL_END))
+ return;
+
+ LOCK_ELUNA;
+ Push(pWinner);
+ Push(pLoser);
+ Push(type);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_DUEL_END);
+}
+
+void Eluna::OnEmote(Player* pPlayer, uint32 emote)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_EMOTE))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(emote);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_EMOTE);
+}
+
+void Eluna::OnTextEmote(Player* pPlayer, uint32 textEmote, uint32 emoteNum, uint64 guid)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_TEXT_EMOTE))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(textEmote);
+ Push(emoteNum);
+ Push(guid);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_TEXT_EMOTE);
+}
+
+void Eluna::OnSpellCast(Player* pPlayer, Spell* pSpell, bool skipCheck)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_SPELL_CAST))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(pSpell);
+ Push(skipCheck);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_SPELL_CAST);
+}
+
+void Eluna::OnLogin(Player* pPlayer)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_LOGIN))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_LOGIN);
+}
+
+void Eluna::OnLogout(Player* pPlayer)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_LOGOUT))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_LOGOUT);
+}
+
+void Eluna::OnCreate(Player* pPlayer)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_CHARACTER_CREATE))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_CHARACTER_CREATE);
+}
+
+void Eluna::OnDelete(uint32 guidlow)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_CHARACTER_DELETE))
+ return;
+
+ LOCK_ELUNA;
+ Push(guidlow);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_CHARACTER_DELETE);
+}
+
+void Eluna::OnSave(Player* pPlayer)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_SAVE))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_SAVE);
+}
+
+void Eluna::OnBindToInstance(Player* pPlayer, Difficulty difficulty, uint32 mapid, bool permanent)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_BIND_TO_INSTANCE))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(difficulty);
+ Push(mapid);
+ Push(permanent);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_BIND_TO_INSTANCE);
+}
+
+void Eluna::OnUpdateZone(Player* pPlayer, uint32 newZone, uint32 newArea)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_UPDATE_ZONE))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(newZone);
+ Push(newArea);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_UPDATE_ZONE);
+}
+
+void Eluna::OnMapChanged(Player* player)
+{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_MAP_CHANGE))
+ return;
+
+ LOCK_ELUNA;
+ 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);
+}
+
+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;
+ bool result = true;
+ Push(pPlayer);
+ Push(msg);
+ Push(type);
+ Push(lang);
+ int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_CHAT, 4);
+
+ while (n > 0)
+ {
+ int r = CallOneFunction(n--, 4, 2);
+
+ if (lua_isboolean(L, r + 0) && !lua_toboolean(L, r + 0))
+ result = false;
+
+ if (lua_isstring(L, r + 1))
+ msg = std::string(lua_tostring(L, r + 1));
+
+ lua_pop(L, 2);
+ }
+
+ CleanUpStack(4);
+ return result;
+}
+
+bool Eluna::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg, Group* pGroup)
+{
+ 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;
+ bool result = true;
+ Push(pPlayer);
+ Push(msg);
+ Push(type);
+ Push(lang);
+ Push(pGroup);
+ int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_GROUP_CHAT, 5);
+
+ while (n > 0)
+ {
+ int r = CallOneFunction(n--, 5, 2);
+
+ if (lua_isboolean(L, r + 0) && !lua_toboolean(L, r + 0))
+ result = false;
+
+ if (lua_isstring(L, r + 1))
+ msg = std::string(lua_tostring(L, r + 1));
+
+ lua_pop(L, 2);
+ }
+
+ CleanUpStack(5);
+ return result;
+}
+
+bool Eluna::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg, Guild* pGuild)
+{
+ 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;
+ bool result = true;
+ Push(pPlayer);
+ Push(msg);
+ Push(type);
+ Push(lang);
+ Push(pGuild);
+ int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_GUILD_CHAT, 5);
+
+ while (n > 0)
+ {
+ int r = CallOneFunction(n--, 5, 2);
+
+ if (lua_isboolean(L, r + 0) && !lua_toboolean(L, r + 0))
+ result = false;
+
+ if (lua_isstring(L, r + 1))
+ msg = std::string(lua_tostring(L, r + 1));
+
+ lua_pop(L, 2);
+ }
+
+ CleanUpStack(5);
+ return result;
+}
+
+bool Eluna::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg, Channel* pChannel)
+{
+ 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;
+ bool result = true;
+ Push(pPlayer);
+ Push(msg);
+ Push(type);
+ Push(lang);
+ Push(pChannel->GetChannelId());
+ int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_CHANNEL_CHAT, 5);
+
+ while (n > 0)
+ {
+ int r = CallOneFunction(n--, 5, 2);
+
+ if (lua_isboolean(L, r + 0) && !lua_toboolean(L, r + 0))
+ result = false;
+
+ if (lua_isstring(L, r + 1))
+ msg = std::string(lua_tostring(L, r + 1));
+
+ lua_pop(L, 2);
+ }
+
+ CleanUpStack(5);
+ return result;
+}
+
+bool Eluna::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg, Player* pReceiver)
+{
+ if (lang == LANG_ADDON)
+ return OnAddonMessage(pPlayer, type, msg, pReceiver, NULL, NULL, NULL);
+
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_WHISPER))
+ return true;
+
+ LOCK_ELUNA;
+ bool result = true;
+ Push(pPlayer);
+ Push(msg);
+ Push(type);
+ Push(lang);
+ Push(pReceiver);
+ int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_WHISPER, 5);
+
+ while (n > 0)
+ {
+ int r = CallOneFunction(n--, 5, 2);
+
+ if (lua_isboolean(L, r + 0) && !lua_toboolean(L, r + 0))
+ result = false;
+
+ if (lua_isstring(L, r + 1))
+ msg = std::string(lua_tostring(L, r + 1));
+
+ lua_pop(L, 2);
+ }
+
+ CleanUpStack(5);
+ return result;
+}
+
+#endif // _PLAYER_HOOKS_H
\ No newline at end of file
diff --git a/ServerHooks.cpp b/ServerHooks.cpp
new file mode 100644
index 0000000..d041247
--- /dev/null
+++ b/ServerHooks.cpp
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2010 - 2015 Eluna Lua Engine
+ * This program is free software licensed under GPL version 3
+ * 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 "ElunaTemplate.h" // Needed to be able to push AuctionHouseObjects.
+#include "ElunaEventMgr.h"
+
+using namespace Hooks;
+
+void Eluna::OnLuaStateClose()
+{
+ if (!ServerEventBindings->HasEvents(ELUNA_EVENT_ON_LUA_STATE_CLOSE))
+ return;
+
+ LOCK_ELUNA;
+ CallAllFunctions(ServerEventBindings, ELUNA_EVENT_ON_LUA_STATE_CLOSE);
+}
+
+void Eluna::OnLuaStateOpen()
+{
+ if (!ServerEventBindings->HasEvents(ELUNA_EVENT_ON_LUA_STATE_OPEN))
+ return;
+
+ LOCK_ELUNA;
+ CallAllFunctions(ServerEventBindings, ELUNA_EVENT_ON_LUA_STATE_OPEN);
+}
+
+// areatrigger
+bool Eluna::OnAreaTrigger(Player* pPlayer, AreaTriggerEntry const* pTrigger)
+{
+ if (!ServerEventBindings->HasEvents(TRIGGER_EVENT_ON_TRIGGER))
+ return false;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(pTrigger->id);
+ return CallAllFunctionsBool(ServerEventBindings, TRIGGER_EVENT_ON_TRIGGER);
+}
+
+// weather
+void Eluna::OnChange(Weather* weather, uint32 zone, WeatherState state, float grade)
+{
+ if (!ServerEventBindings->HasEvents(WEATHER_EVENT_ON_CHANGE))
+ return;
+
+ LOCK_ELUNA;
+ Push(zone);
+ Push(state);
+ Push(grade);
+ CallAllFunctions(ServerEventBindings, WEATHER_EVENT_ON_CHANGE);
+}
+
+// Auction House
+void Eluna::OnAdd(AuctionHouseObject* ah)
+{
+ if (!ServerEventBindings->HasEvents(AUCTION_EVENT_ON_ADD))
+ return;
+
+ LOCK_ELUNA;
+ Push(ah);
+ CallAllFunctions(ServerEventBindings, AUCTION_EVENT_ON_ADD);
+}
+
+void Eluna::OnRemove(AuctionHouseObject* ah)
+{
+ if (!ServerEventBindings->HasEvents(AUCTION_EVENT_ON_REMOVE))
+ return;
+
+ LOCK_ELUNA;
+ Push(ah);
+ CallAllFunctions(ServerEventBindings, AUCTION_EVENT_ON_REMOVE);
+}
+
+void Eluna::OnSuccessful(AuctionHouseObject* ah)
+{
+ if (!ServerEventBindings->HasEvents(AUCTION_EVENT_ON_SUCCESSFUL))
+ return;
+
+ LOCK_ELUNA;
+ Push(ah);
+ CallAllFunctions(ServerEventBindings, AUCTION_EVENT_ON_SUCCESSFUL);
+}
+
+void Eluna::OnExpire(AuctionHouseObject* ah)
+{
+ if (!ServerEventBindings->HasEvents(AUCTION_EVENT_ON_EXPIRE))
+ return;
+
+ LOCK_ELUNA;
+ Push(ah);
+ 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(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(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(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(L, r + 1, false))
+ packet = *data;
+
+ lua_pop(L, 2);
+ }
+
+ CleanUpStack(2);
+}
+
+void Eluna::OnOpenStateChange(bool open)
+{
+ if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_OPEN_STATE_CHANGE))
+ return;
+
+ LOCK_ELUNA;
+ Push(open);
+ CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_OPEN_STATE_CHANGE);
+}
+
+void Eluna::OnConfigLoad(bool reload)
+{
+ if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_CONFIG_LOAD))
+ return;
+
+ LOCK_ELUNA;
+ Push(reload);
+ CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_CONFIG_LOAD);
+}
+
+void Eluna::OnShutdownInitiate(ShutdownExitCode code, ShutdownMask mask)
+{
+ if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_SHUTDOWN_INIT))
+ return;
+
+ LOCK_ELUNA;
+ Push(code);
+ Push(mask);
+ CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_SHUTDOWN_INIT);
+}
+
+void Eluna::OnShutdownCancel()
+{
+ if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_SHUTDOWN_CANCEL))
+ return;
+
+ LOCK_ELUNA;
+ CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_SHUTDOWN_CANCEL);
+}
+
+void Eluna::OnWorldUpdate(uint32 diff)
+{
+ LOCK_ELUNA;
+
+ if (reload)
+ {
+ ReloadEluna();
+ return;
+ }
+
+ eventMgr->globalProcessor->Update(diff);
+
+ if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_UPDATE))
+ return;
+
+ Push(diff);
+ CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_UPDATE);
+}
+
+void Eluna::OnStartup()
+{
+ if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_STARTUP))
+ return;
+
+ LOCK_ELUNA;
+ CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_STARTUP);
+}
+
+void Eluna::OnShutdown()
+{
+ if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_SHUTDOWN))
+ return;
+
+ LOCK_ELUNA;
+ CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_SHUTDOWN);
+}
+
+/* Map */
+void Eluna::OnCreate(Map* map)
+{
+ if (!ServerEventBindings->HasEvents(MAP_EVENT_ON_CREATE))
+ return;
+
+ LOCK_ELUNA;
+ Push(map);
+ CallAllFunctions(ServerEventBindings, MAP_EVENT_ON_CREATE);
+}
+
+void Eluna::OnDestroy(Map* map)
+{
+ if (!ServerEventBindings->HasEvents(MAP_EVENT_ON_DESTROY))
+ return;
+
+ LOCK_ELUNA;
+ Push(map);
+ CallAllFunctions(ServerEventBindings, MAP_EVENT_ON_DESTROY);
+}
+
+void Eluna::OnPlayerEnter(Map* map, Player* player)
+{
+ if (!ServerEventBindings->HasEvents(MAP_EVENT_ON_PLAYER_ENTER))
+ return;
+
+ LOCK_ELUNA;
+ Push(map);
+ Push(player);
+ CallAllFunctions(ServerEventBindings, MAP_EVENT_ON_PLAYER_ENTER);
+}
+
+void Eluna::OnPlayerLeave(Map* map, Player* player)
+{
+ if (!ServerEventBindings->HasEvents(MAP_EVENT_ON_PLAYER_LEAVE))
+ return;
+
+ LOCK_ELUNA;
+ Push(map);
+ Push(player);
+ CallAllFunctions(ServerEventBindings, MAP_EVENT_ON_PLAYER_LEAVE);
+}
+
+void Eluna::OnUpdate(Map* map, uint32 diff)
+{
+ if (!ServerEventBindings->HasEvents(MAP_EVENT_ON_UPDATE))
+ return;
+
+ LOCK_ELUNA;
+ // enable this for multithread
+ // eventMgr->globalProcessor->Update(diff);
+ Push(map);
+ Push(diff);
+ CallAllFunctions(ServerEventBindings, MAP_EVENT_ON_UPDATE);
+}
+
+void Eluna::OnRemove(GameObject* gameobject)
+{
+ if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_DELETE_GAMEOBJECT))
+ return;
+
+ LOCK_ELUNA;
+ Push(gameobject);
+ CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_DELETE_GAMEOBJECT);
+}
+
+void Eluna::OnRemove(Creature* creature)
+{
+ if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_DELETE_CREATURE))
+ return;
+
+ LOCK_ELUNA;
+ Push(creature);
+ CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_DELETE_CREATURE);
+}
+
+#endif // _SERVER_HOOKS_H
\ No newline at end of file
diff --git a/VehicleHooks.cpp b/VehicleHooks.cpp
new file mode 100644
index 0000000..a5db54d
--- /dev/null
+++ b/VehicleHooks.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2010 - 2015 Eluna Lua Engine
+ * This program is free software licensed under GPL version 3
+ * Please see the included DOCS/LICENSE.md for more information
+ */
+
+#ifndef _VEHICLE_HOOKS_H
+#define _VEHICLE_HOOKS_H
+
+#ifndef CLASSIC
+#ifndef TBC
+
+#include "Hooks.h"
+#include "HookHelpers.h"
+#include "LuaEngine.h"
+#include "ElunaBinding.h"
+
+using namespace Hooks;
+
+// Vehicle
+void Eluna::OnInstall(Vehicle* vehicle)
+{
+ if (!VehicleEventBindings->HasEvents(VEHICLE_EVENT_ON_INSTALL))
+ return;
+
+ LOCK_ELUNA;
+ Push(vehicle);
+ CallAllFunctions(VehicleEventBindings, VEHICLE_EVENT_ON_INSTALL);
+}
+
+void Eluna::OnUninstall(Vehicle* vehicle)
+{
+ if (!VehicleEventBindings->HasEvents(VEHICLE_EVENT_ON_UNINSTALL))
+ return;
+
+ LOCK_ELUNA;
+ Push(vehicle);
+ CallAllFunctions(VehicleEventBindings, VEHICLE_EVENT_ON_UNINSTALL);
+}
+
+void Eluna::OnInstallAccessory(Vehicle* vehicle, Creature* accessory)
+{
+ if (!VehicleEventBindings->HasEvents(VEHICLE_EVENT_ON_INSTALL_ACCESSORY))
+ return;
+
+ LOCK_ELUNA;
+ Push(vehicle);
+ Push(accessory);
+ CallAllFunctions(VehicleEventBindings, VEHICLE_EVENT_ON_INSTALL_ACCESSORY);
+}
+
+void Eluna::OnAddPassenger(Vehicle* vehicle, Unit* passenger, int8 seatId)
+{
+ if (!VehicleEventBindings->HasEvents(VEHICLE_EVENT_ON_ADD_PASSENGER))
+ return;
+
+ LOCK_ELUNA;
+ Push(vehicle);
+ Push(passenger);
+ Push(seatId);
+ CallAllFunctions(VehicleEventBindings, VEHICLE_EVENT_ON_ADD_PASSENGER);
+}
+
+void Eluna::OnRemovePassenger(Vehicle* vehicle, Unit* passenger)
+{
+ if (!VehicleEventBindings->HasEvents(VEHICLE_EVENT_ON_REMOVE_PASSENGER))
+ return;
+
+ LOCK_ELUNA;
+ Push(vehicle);
+ Push(passenger);
+ CallAllFunctions(VehicleEventBindings, VEHICLE_EVENT_ON_REMOVE_PASSENGER);
+}
+
+#endif // CLASSIC
+#endif // TBC
+#endif // _VEHICLE_HOOKS_H
\ No newline at end of file