Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
344 lines (298 sloc) 11.3 KB
/*
* Copyright (C) 2010 - 2016 Eluna Lua Engine <http://emudevs.com/>
* This program is free software licensed under GPL version 3
* Please see the included DOCS/LICENSE.md for more information
*/
#include "Hooks.h"
#include "HookHelpers.h"
#include "LuaEngine.h"
#include "BindingMap.h"
#include "ElunaIncludes.h"
#include "ElunaTemplate.h"
using namespace Hooks;
#define START_HOOK(EVENT, CREATURE) \
if (!IsEnabled())\
return;\
auto entry_key = EntryKey<CreatureEvents>(EVENT, CREATURE->GetEntry());\
auto unique_key = UniqueObjectKey<CreatureEvents>(EVENT, CREATURE->GET_GUID(), CREATURE->GetInstanceId());\
if (!CreatureEventBindings->HasBindingsFor(entry_key))\
if (!CreatureUniqueBindings->HasBindingsFor(unique_key))\
return;\
LOCK_ELUNA
#define START_HOOK_WITH_RETVAL(EVENT, CREATURE, RETVAL) \
if (!IsEnabled())\
return RETVAL;\
auto entry_key = EntryKey<CreatureEvents>(EVENT, CREATURE->GetEntry());\
auto unique_key = UniqueObjectKey<CreatureEvents>(EVENT, CREATURE->GET_GUID(), CREATURE->GetInstanceId());\
if (!CreatureEventBindings->HasBindingsFor(entry_key))\
if (!CreatureUniqueBindings->HasBindingsFor(unique_key))\
return RETVAL;\
LOCK_ELUNA
bool Eluna::OnDummyEffect(Unit* pCaster, uint32 spellId, SpellEffIndex effIndex, Creature* pTarget)
{
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_DUMMY_EFFECT, pTarget, false);
Push(pCaster);
Push(spellId);
Push(effIndex);
Push(pTarget);
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
}
bool Eluna::OnQuestAccept(Player* pPlayer, Creature* pCreature, Quest const* pQuest)
{
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_QUEST_ACCEPT, pCreature, false);
Push(pPlayer);
Push(pCreature);
Push(pQuest);
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
}
bool Eluna::OnQuestReward(Player* pPlayer, Creature* pCreature, Quest const* pQuest, uint32 opt)
{
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_QUEST_REWARD, pCreature, false);
Push(pPlayer);
Push(pCreature);
Push(pQuest);
Push(opt);
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
}
uint32 Eluna::GetDialogStatus(const Player* pPlayer, const Creature* pCreature)
{
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_DIALOG_STATUS, pCreature, DIALOG_STATUS_SCRIPTED_NO_STATUS);
Push(pPlayer);
Push(pCreature);
CallAllFunctions(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
return DIALOG_STATUS_SCRIPTED_NO_STATUS;
}
void Eluna::OnAddToWorld(Creature* pCreature)
{
START_HOOK(CREATURE_EVENT_ON_ADD, pCreature);
Push(pCreature);
CallAllFunctions(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
}
void Eluna::OnRemoveFromWorld(Creature* pCreature)
{
START_HOOK(CREATURE_EVENT_ON_REMOVE, pCreature);
Push(pCreature);
CallAllFunctions(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
}
bool Eluna::OnSummoned(Creature* pCreature, Unit* pSummoner)
{
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_SUMMONED, pCreature, false);
Push(pCreature);
Push(pSummoner);
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
}
bool Eluna::UpdateAI(Creature* me, const uint32 diff)
{
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_AIUPDATE, me, false);
Push(me);
Push(diff);
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
}
//Called for reaction at enter to combat if not in combat yet (enemy can be NULL)
//Called at creature aggro either by MoveInLOS or Attack Start
bool Eluna::EnterCombat(Creature* me, Unit* target)
{
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_ENTER_COMBAT, me, false);
Push(me);
Push(target);
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
}
// Called at any Damage from any attacker (before damage apply)
bool Eluna::DamageTaken(Creature* me, Unit* attacker, uint32& damage)
{
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_DAMAGE_TAKEN, me, false);
bool result = false;
Push(me);
Push(attacker);
Push(damage);
int damageIndex = lua_gettop(L);
int n = SetupStack(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key, 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<uint32>(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);
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_DIED, me, false);
Push(me);
Push(killer);
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
}
//Called at creature killing another unit
bool Eluna::KilledUnit(Creature* me, Unit* victim)
{
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_TARGET_DIED, me, false);
Push(me);
Push(victim);
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
}
// Called when the creature summon successfully other creature
bool Eluna::JustSummoned(Creature* me, Creature* summon)
{
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_JUST_SUMMONED_CREATURE, me, false);
Push(me);
Push(summon);
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
}
// Called when a summoned creature is despawned
bool Eluna::SummonedCreatureDespawn(Creature* me, Creature* summon)
{
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_SUMMONED_CREATURE_DESPAWN, me, false);
Push(me);
Push(summon);
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
}
//Called at waypoint reached or PointMovement end
bool Eluna::MovementInform(Creature* me, uint32 type, uint32 id)
{
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_REACH_WP, me, false);
Push(me);
Push(type);
Push(id);
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
}
// Called before EnterCombat even before the creature is in combat.
bool Eluna::AttackStart(Creature* me, Unit* target)
{
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_PRE_COMBAT, me, false);
Push(me);
Push(target);
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
}
// Called for reaction at stopping attack at no attackers or targets
bool Eluna::EnterEvadeMode(Creature* me)
{
On_Reset(me);
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_LEAVE_COMBAT, me, false);
Push(me);
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
}
// Called when the creature is target of hostile action: swing, hostile spell landed, fear/etc)
bool Eluna::AttackedBy(Creature* me, Unit* attacker)
{
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_ATTACKED_AT, me, false);
Push(me);
Push(attacker);
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
}
// Called when creature is spawned or respawned (for reseting variables)
bool Eluna::JustRespawned(Creature* me)
{
On_Reset(me);
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_SPAWN, me, false);
Push(me);
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
}
// Called at reaching home after evade
bool Eluna::JustReachedHome(Creature* me)
{
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_REACH_HOME, me, false);
Push(me);
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
}
// Called at text emote receive from player
bool Eluna::ReceiveEmote(Creature* me, Player* player, uint32 emoteId)
{
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_RECEIVE_EMOTE, me, false);
Push(me);
Push(player);
Push(emoteId);
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
}
// called when the corpse of this creature gets removed
bool Eluna::CorpseRemoved(Creature* me, uint32& respawnDelay)
{
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_CORPSE_REMOVED, me, false);
bool result = false;
Push(me);
Push(respawnDelay);
int respawnDelayIndex = lua_gettop(L);
int n = SetupStack(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key, 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<uint32>(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)
{
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_MOVE_IN_LOS, me, false);
Push(me);
Push(who);
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
}
// Called on creature initial spawn, respawn, death, evade (leave combat)
void Eluna::On_Reset(Creature* me) // Not an override, custom
{
START_HOOK(CREATURE_EVENT_ON_RESET, me);
Push(me);
CallAllFunctions(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
}
// Called when hit by a spell
bool Eluna::SpellHit(Creature* me, Unit* caster, SpellInfo const* spell)
{
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_HIT_BY_SPELL, me, false);
Push(me);
Push(caster);
Push(spell->Id); // Pass spell object?
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
}
// Called when spell hits a target
bool Eluna::SpellHitTarget(Creature* me, Unit* target, SpellInfo const* spell)
{
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_SPELL_HIT_TARGET, me, false);
Push(me);
Push(target);
Push(spell->Id); // Pass spell object?
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
}
#ifdef TRINITY
bool Eluna::SummonedCreatureDies(Creature* me, Creature* summon, Unit* killer)
{
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_SUMMONED_CREATURE_DIED, me, false);
Push(me);
Push(summon);
Push(killer);
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
}
// Called when owner takes damage
bool Eluna::OwnerAttackedBy(Creature* me, Unit* attacker)
{
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_OWNER_ATTACKED_AT, me, false);
Push(me);
Push(attacker);
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
}
// Called when owner attacks something
bool Eluna::OwnerAttacked(Creature* me, Unit* target)
{
START_HOOK_WITH_RETVAL(CREATURE_EVENT_ON_OWNER_ATTACKED, me, false);
Push(me);
Push(target);
return CallAllFunctionsBool(CreatureEventBindings, CreatureUniqueBindings, entry_key, unique_key);
}
#endif // TRINITY