From d09b5b04ba71a2b58f505afea0df1967770c3747 Mon Sep 17 00:00:00 2001 From: Rochet2 Date: Tue, 1 Jul 2014 00:35:06 +0300 Subject: [PATCH] Eluna Closes: #70, #69, #83, http://emudevs.com/showthread.php/3438-Custom-Items-and-On-Item-Use-Events Fixes Object::~Object crash log from #71 --- HookMgr.cpp | 10 ++++++---- LuaEngine.cpp | 12 ++++++++++++ LuaEngine.h | 31 +++++++++++++++++++------------ LuaFunctions.cpp | 1 + PlayerMethods.h | 2 +- UnitMethods.h | 31 +++++++++++++++++++++++++++++++ 6 files changed, 70 insertions(+), 17 deletions(-) diff --git a/HookMgr.cpp b/HookMgr.cpp index a44399f..4eccaf1 100644 --- a/HookMgr.cpp +++ b/HookMgr.cpp @@ -401,14 +401,16 @@ bool Eluna::OnUse(Player* pPlayer, Item* pItem, SpellCastTargets const& targets) ObjectGuid guid = pItem->GET_GUID(); bool castSpell = true; - if (!OnItemGossip(pPlayer, pItem, targets)) + if (!OnItemUse(pPlayer, pItem, targets)) castSpell = false; pItem = pPlayer->GetItemByGuid(guid); - if (pItem && OnItemUse(pPlayer, pItem, targets)) + if (pItem) + { + if (!OnItemGossip(pPlayer, pItem, targets)) + castSpell = false; pItem = pPlayer->GetItemByGuid(guid); - else - castSpell = false; + } if (pItem && castSpell) return true; diff --git a/LuaEngine.cpp b/LuaEngine.cpp index 078a196..9879239 100644 --- a/LuaEngine.cpp +++ b/LuaEngine.cpp @@ -50,6 +50,18 @@ void Eluna::ReloadEluna() Uninitialize(); Initialize(); +#ifdef TRINITY + // Re initialize creature AI restoring C++ AI or applying lua AI + { + TRINITY_READ_GUARD(HashMapHolder::LockType, *HashMapHolder::GetLock()); + HashMapHolder::MapType const& m = ObjectAccessor::GetCreatures(); + for (HashMapHolder::MapType::const_iterator iter = m.begin(); iter != m.end(); ++iter) + { + iter->second->AIM_Initialize(); + } + } +#endif + reload = false; } diff --git a/LuaEngine.h b/LuaEngine.h index e8b525e..c7aac94 100644 --- a/LuaEngine.h +++ b/LuaEngine.h @@ -859,28 +859,35 @@ public: luaL_newmetatable(L, tname); int metatable = lua_gettop(L); + // tostring + lua_pushcfunction(L, tostringT); + lua_setfield(L, metatable, "__tostring"); + + // garbage collecting + if (manageMemory) + { + lua_pushcfunction(L, gcT); + lua_setfield(L, metatable, "__gc"); + } + // hide metatable lua_pushvalue(L, methods); lua_setfield(L, metatable, "__metatable"); - // required to access methods + // make methods accessible through metatable lua_pushvalue(L, methods); lua_setfield(L, metatable, "__index"); - // metamethods - lua_pushcfunction(L, tostringT); - lua_setfield(L, metatable, "__tostring"); - - lua_pushcfunction(L, gcT); - lua_setfield(L, metatable, "__gc"); + // make new indexes saved to methods + lua_pushvalue(L, methods); + lua_setfield(L, metatable, "__newindex"); // special method to get the object type lua_pushcfunction(L, typeT); - lua_setfield(L, methods, "GetObjectType"); + lua_setfield(L, metatable, "GetObjectType"); - lua_setmetatable(L, methods); - - lua_remove(L, methods); + // pop methods and metatable + lua_pop(L, 2); } template @@ -897,7 +904,7 @@ public: return; } - lua_getfield(L, -1, "__metatable"); + lua_getfield(L, -1, "__index"); lua_remove(L, -2); if (!lua_istable(L, -1)) { diff --git a/LuaFunctions.cpp b/LuaFunctions.cpp index 50fd4ac..cf93fb8 100644 --- a/LuaFunctions.cpp +++ b/LuaFunctions.cpp @@ -333,6 +333,7 @@ ElunaRegister UnitMethods[] = { "SendUnitSay", &LuaUnit::SendUnitSay }, // :SendUnitSay(msg, language) - Sends a "Say" message with the specified language (all languages: 0) { "SendUnitYell", &LuaUnit::SendUnitYell }, // :SendUnitYell(msg, language) - Sends a "Yell" message with the specified language (all languages: 0) { "CastSpell", &LuaUnit::CastSpell }, // :CastSpell(target, spellID[, triggered]) - Casts spell on target (player/npc/creature), if triggered is true then instant cast + { "CastCustomSpell", &LuaUnit::CastCustomSpell }, // :CastCustomSpell(&Unit target, uint32 spell, bool triggered = false, int32 bp0 = nil, int32 bp1 = nil, int32 bp2 = nil, &Item castItem = nil, uint64 originalCaster = 0) - Casts spell on target (player/npc/creature), if triggered is true then instant cast. pb0, 1 and 2 are modifiers for the base points of the spell. { "CastSpellAoF", &LuaUnit::CastSpellAoF }, // :CastSpellAoF(x, y, z, spellID[, triggered]) - Casts the spell on coordinates, if triggered is false has mana cost and cast time { "PlayDirectSound", &LuaUnit::PlayDirectSound }, // :PlayDirectSound(soundId, player) - Unit plays soundID to player, or everyone around if no player { "PlayDistanceSound", &LuaUnit::PlayDistanceSound }, // :PlayDistanceSound(soundId, player) - Unit plays soundID to player, or everyone around if no player. The sound fades the further you are diff --git a/PlayerMethods.h b/PlayerMethods.h index d8868cc..b2da4c4 100644 --- a/PlayerMethods.h +++ b/PlayerMethods.h @@ -1962,7 +1962,7 @@ namespace LuaPlayer if (!item) { uint32 itemId = Eluna::CHECKVAL(L, 2); - player->DestroyItemCount(itemId, itemCount, false); + player->DestroyItemCount(itemId, itemCount, true); } else player->DestroyItemCount(item, itemCount, true); diff --git a/UnitMethods.h b/UnitMethods.h index 71f1af7..3093934 100644 --- a/UnitMethods.h +++ b/UnitMethods.h @@ -1420,6 +1420,37 @@ namespace LuaUnit return 0; } + /** + Casts the spell at target. + pb0, 1 and 2 are modifiers for the base points of the spell. + + @param &Unit target + @param uint32 spell + @param bool triggered = false + @param int32 bp0 = nil + @param int32 bp1 = nil + @param int32 bp2 = nil + @param &Item castItem = nil + @param uint64 originalCaster = 0 + */ + int CastCustomSpell(lua_State* L, Unit* unit) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + uint32 spell = Eluna::CHECKVAL(L, 3); + bool triggered = Eluna::CHECKVAL(L, 4, false); + bool has_bp0 = lua_isnoneornil(L, 5); + int32 bp0 = Eluna::CHECKVAL(L, 5, 0); + bool has_bp1 = lua_isnoneornil(L, 6); + int32 bp1 = Eluna::CHECKVAL(L, 6, 0); + bool has_bp2 = lua_isnoneornil(L, 7); + int32 bp2 = Eluna::CHECKVAL(L, 7, 0); + Item* castItem = Eluna::CHECKOBJ(L, 8, false); + uint64 originalCaster = Eluna::CHECKVAL(L, 9, 0); + + unit->CastCustomSpell(target, spell, has_bp0 ? &bp0 : NULL, has_bp1 ? &bp1 : NULL, has_bp2 ? &bp2 : NULL, triggered, castItem, NULL, ObjectGuid(originalCaster)); + return 0; + } + int CastSpellAoF(lua_State* L, Unit* unit) { float _x = Eluna::CHECKVAL(L, 2);