/** * Tibia GIMUD Server - a free and open-source MMORPG server emulator * Copyright (C) 2019 Sabrehaven and Mark Samman * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "otpch.h" #include #include "luascript.h" #include "chat.h" #include "player.h" #include "game.h" #include "protocolstatus.h" #include "spells.h" #include "iologindata.h" #include "configmanager.h" #include "teleport.h" #include "databasemanager.h" #include "bed.h" #include "monster.h" #include "scheduler.h" #include "databasetasks.h" extern Chat* g_chat; extern Game g_game; extern Monsters g_monsters; extern ConfigManager g_config; extern Vocations g_vocations; extern Spells* g_spells; ScriptEnvironment::DBResultMap ScriptEnvironment::tempResults; uint32_t ScriptEnvironment::lastResultId = 0; std::multimap ScriptEnvironment::tempItems; LuaEnvironment g_luaEnvironment; ScriptEnvironment::ScriptEnvironment() { resetEnv(); } ScriptEnvironment::~ScriptEnvironment() { resetEnv(); } void ScriptEnvironment::resetEnv() { scriptId = 0; callbackId = 0; timerEvent = false; interface = nullptr; localMap.clear(); tempResults.clear(); auto pair = tempItems.equal_range(this); auto it = pair.first; while (it != pair.second) { Item* item = it->second; if (item->getParent() == VirtualCylinder::virtualCylinder) { g_game.ReleaseItem(item); } it = tempItems.erase(it); } } bool ScriptEnvironment::setCallbackId(int32_t callbackId, LuaScriptInterface* scriptInterface) { if (this->callbackId != 0) { //nested callbacks are not allowed if (interface) { interface->reportErrorFunc("Nested callbacks!"); } return false; } this->callbackId = callbackId; interface = scriptInterface; return true; } void ScriptEnvironment::getEventInfo(int32_t& scriptId, LuaScriptInterface*& scriptInterface, int32_t& callbackId, bool& timerEvent) const { scriptId = this->scriptId; scriptInterface = interface; callbackId = this->callbackId; timerEvent = this->timerEvent; } uint32_t ScriptEnvironment::addThing(Thing* thing) { if (!thing || thing->isRemoved()) { return 0; } Creature* creature = thing->getCreature(); if (creature) { return creature->getID(); } Item* item = thing->getItem(); for (const auto& it : localMap) { if (it.second == item) { return it.first; } } localMap[++lastUID] = item; return lastUID; } void ScriptEnvironment::insertItem(uint32_t uid, Item* item) { auto result = localMap.emplace(uid, item); if (!result.second) { std::cout << std::endl << "Lua Script Error: Thing uid already taken."; } } Thing* ScriptEnvironment::getThingByUID(uint32_t uid) { if (uid >= 0x10000000) { return g_game.getCreatureByID(uid); } auto it = localMap.find(uid); if (it != localMap.end()) { Item* item = it->second; if (!item->isRemoved()) { return item; } } return nullptr; } Item* ScriptEnvironment::getItemByUID(uint32_t uid) { Thing* thing = getThingByUID(uid); if (!thing) { return nullptr; } return thing->getItem(); } Container* ScriptEnvironment::getContainerByUID(uint32_t uid) { Item* item = getItemByUID(uid); if (!item) { return nullptr; } return item->getContainer(); } void ScriptEnvironment::removeItemByUID(uint32_t uid) { auto it = localMap.find(uid); if (it != localMap.end()) { localMap.erase(it); } } void ScriptEnvironment::addTempItem(Item* item) { tempItems.emplace(this, item); } void ScriptEnvironment::removeTempItem(Item* item) { for (auto it = tempItems.begin(), end = tempItems.end(); it != end; ++it) { if (it->second == item) { tempItems.erase(it); break; } } } uint32_t ScriptEnvironment::addResult(DBResult_ptr res) { tempResults[++lastResultId] = res; return lastResultId; } bool ScriptEnvironment::removeResult(uint32_t id) { auto it = tempResults.find(id); if (it == tempResults.end()) { return false; } tempResults.erase(it); return true; } DBResult_ptr ScriptEnvironment::getResultByID(uint32_t id) { auto it = tempResults.find(id); if (it == tempResults.end()) { return nullptr; } return it->second; } std::string LuaScriptInterface::getErrorDesc(ErrorCode_t code) { switch (code) { case LUA_ERROR_PLAYER_NOT_FOUND: return "Player not found"; case LUA_ERROR_CREATURE_NOT_FOUND: return "Creature not found"; case LUA_ERROR_ITEM_NOT_FOUND: return "Item not found"; case LUA_ERROR_THING_NOT_FOUND: return "Thing not found"; case LUA_ERROR_TILE_NOT_FOUND: return "Tile not found"; case LUA_ERROR_HOUSE_NOT_FOUND: return "House not found"; case LUA_ERROR_COMBAT_NOT_FOUND: return "Combat not found"; case LUA_ERROR_CONDITION_NOT_FOUND: return "Condition not found"; case LUA_ERROR_AREA_NOT_FOUND: return "Area not found"; case LUA_ERROR_CONTAINER_NOT_FOUND: return "Container not found"; case LUA_ERROR_VARIANT_NOT_FOUND: return "Variant not found"; case LUA_ERROR_VARIANT_UNKNOWN: return "Unknown variant type"; case LUA_ERROR_SPELL_NOT_FOUND: return "Spell not found"; default: return "Bad error code"; } } ScriptEnvironment LuaScriptInterface::scriptEnv[16]; int32_t LuaScriptInterface::scriptEnvIndex = -1; LuaScriptInterface::LuaScriptInterface(std::string interfaceName) : interfaceName(std::move(interfaceName)) { if (!g_luaEnvironment.getLuaState()) { g_luaEnvironment.initState(); } } LuaScriptInterface::~LuaScriptInterface() { closeState(); } bool LuaScriptInterface::reInitState() { g_luaEnvironment.clearCombatObjects(this); g_luaEnvironment.clearAreaObjects(this); closeState(); return initState(); } /// Same as lua_pcall, but adds stack trace to error strings in called function. int LuaScriptInterface::protectedCall(lua_State* L, int nargs, int nresults) { int error_index = lua_gettop(L) - nargs; lua_pushcfunction(L, luaErrorHandler); lua_insert(L, error_index); int ret = lua_pcall(L, nargs, nresults, error_index); lua_remove(L, error_index); return ret; } int32_t LuaScriptInterface::loadFile(const std::string& file, Npc* npc /* = nullptr*/) { //loads file as a chunk at stack top int ret = luaL_loadfile(luaState, file.c_str()); if (ret != 0) { lastLuaError = popString(luaState); return -1; } //check that it is loaded as a function if (!isFunction(luaState, -1)) { return -1; } loadingFile = file; if (!reserveScriptEnv()) { return -1; } ScriptEnvironment* env = getScriptEnv(); env->setScriptId(EVENT_ID_LOADING, this); env->setNpc(npc); //execute it ret = protectedCall(luaState, 0, 0); if (ret != 0) { reportError(nullptr, popString(luaState)); resetScriptEnv(); return -1; } resetScriptEnv(); return 0; } int32_t LuaScriptInterface::getEvent(const std::string& eventName) { //get our events table lua_rawgeti(luaState, LUA_REGISTRYINDEX, eventTableRef); if (!isTable(luaState, -1)) { lua_pop(luaState, 1); return -1; } //get current event function pointer lua_getglobal(luaState, eventName.c_str()); if (!isFunction(luaState, -1)) { lua_pop(luaState, 2); return -1; } //save in our events table lua_pushvalue(luaState, -1); lua_rawseti(luaState, -3, runningEventId); lua_pop(luaState, 2); //reset global value of this event lua_pushnil(luaState); lua_setglobal(luaState, eventName.c_str()); cacheFiles[runningEventId] = loadingFile + ":" + eventName; return runningEventId++; } int32_t LuaScriptInterface::getMetaEvent(const std::string& globalName, const std::string& eventName) { //get our events table lua_rawgeti(luaState, LUA_REGISTRYINDEX, eventTableRef); if (!isTable(luaState, -1)) { lua_pop(luaState, 1); return -1; } //get current event function pointer lua_getglobal(luaState, globalName.c_str()); lua_getfield(luaState, -1, eventName.c_str()); if (!isFunction(luaState, -1)) { lua_pop(luaState, 3); return -1; } //save in our events table lua_pushvalue(luaState, -1); lua_rawseti(luaState, -4, runningEventId); lua_pop(luaState, 1); //reset global value of this event lua_pushnil(luaState); lua_setfield(luaState, -2, eventName.c_str()); lua_pop(luaState, 2); cacheFiles[runningEventId] = loadingFile + ":" + globalName + "@" + eventName; return runningEventId++; } const std::string& LuaScriptInterface::getFileById(int32_t scriptId) { if (scriptId == EVENT_ID_LOADING) { return loadingFile; } auto it = cacheFiles.find(scriptId); if (it == cacheFiles.end()) { static const std::string& unk = "(Unknown scriptfile)"; return unk; } return it->second; } std::string LuaScriptInterface::getStackTrace(const std::string& error_desc) { lua_getglobal(luaState, "debug"); if (!isTable(luaState, -1)) { lua_pop(luaState, 1); return error_desc; } lua_getfield(luaState, -1, "traceback"); if (!isFunction(luaState, -1)) { lua_pop(luaState, 2); return error_desc; } lua_replace(luaState, -2); pushString(luaState, error_desc); lua_call(luaState, 1, 1); return popString(luaState); } void LuaScriptInterface::reportError(const char* function, const std::string& error_desc, bool stack_trace/* = false*/) { int32_t scriptId; int32_t callbackId; bool timerEvent; LuaScriptInterface* scriptInterface; getScriptEnv()->getEventInfo(scriptId, scriptInterface, callbackId, timerEvent); std::cout << std::endl << "Lua Script Error: "; if (scriptInterface) { std::cout << '[' << scriptInterface->getInterfaceName() << "] " << std::endl; if (timerEvent) { std::cout << "in a timer event called from: " << std::endl; } if (callbackId) { std::cout << "in callback: " << scriptInterface->getFileById(callbackId) << std::endl; } std::cout << scriptInterface->getFileById(scriptId) << std::endl; } if (function) { std::cout << function << "(). "; } if (stack_trace && scriptInterface) { std::cout << scriptInterface->getStackTrace(error_desc) << std::endl; } else { std::cout << error_desc << std::endl; } } bool LuaScriptInterface::pushFunction(int32_t functionId) { lua_rawgeti(luaState, LUA_REGISTRYINDEX, eventTableRef); if (!isTable(luaState, -1)) { return false; } lua_rawgeti(luaState, -1, functionId); lua_replace(luaState, -2); return isFunction(luaState, -1); } bool LuaScriptInterface::initState() { luaState = g_luaEnvironment.getLuaState(); if (!luaState) { return false; } lua_newtable(luaState); eventTableRef = luaL_ref(luaState, LUA_REGISTRYINDEX); runningEventId = EVENT_ID_USER; return true; } bool LuaScriptInterface::closeState() { if (!g_luaEnvironment.getLuaState() || !luaState) { return false; } cacheFiles.clear(); if (eventTableRef != -1) { luaL_unref(luaState, LUA_REGISTRYINDEX, eventTableRef); eventTableRef = -1; } luaState = nullptr; return true; } int LuaScriptInterface::luaErrorHandler(lua_State* L) { const std::string& errorMessage = popString(L); auto interface = getScriptEnv()->getScriptInterface(); assert(interface); //This fires if the ScriptEnvironment hasn't been setup pushString(L, interface->getStackTrace(errorMessage)); return 1; } bool LuaScriptInterface::callFunction(int params) { bool result = false; int size = lua_gettop(luaState); if (protectedCall(luaState, params, 1) != 0) { LuaScriptInterface::reportError(nullptr, LuaScriptInterface::getString(luaState, -1)); } else { result = LuaScriptInterface::getBoolean(luaState, -1); } lua_pop(luaState, 1); if ((lua_gettop(luaState) + params + 1) != size) { LuaScriptInterface::reportError(nullptr, "Stack size changed!"); } resetScriptEnv(); return result; } void LuaScriptInterface::callVoidFunction(int params) { int size = lua_gettop(luaState); if (protectedCall(luaState, params, 0) != 0) { LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(luaState)); } if ((lua_gettop(luaState) + params + 1) != size) { LuaScriptInterface::reportError(nullptr, "Stack size changed!"); } resetScriptEnv(); } void LuaScriptInterface::pushVariant(lua_State* L, const LuaVariant& var) { lua_createtable(L, 0, 2); setField(L, "type", var.type); switch (var.type) { case VARIANT_NUMBER: setField(L, "number", var.number); break; case VARIANT_STRING: setField(L, "string", var.text); break; case VARIANT_TARGETPOSITION: case VARIANT_POSITION: { pushPosition(L, var.pos); lua_setfield(L, -2, "pos"); break; } default: break; } setMetatable(L, -1, "Variant"); } void LuaScriptInterface::pushThing(lua_State* L, Thing* thing) { if (!thing) { lua_createtable(L, 0, 4); setField(L, "uid", 0); setField(L, "itemid", 0); setField(L, "actionid", 0); setField(L, "type", 0); return; } if (Item* item = thing->getItem()) { pushUserdata(L, item); setItemMetatable(L, -1, item); } else if (Creature* creature = thing->getCreature()) { pushUserdata(L, creature); setCreatureMetatable(L, -1, creature); } else { lua_pushnil(L); } } void LuaScriptInterface::pushCylinder(lua_State* L, Cylinder* cylinder) { if (Creature* creature = cylinder->getCreature()) { pushUserdata(L, creature); setCreatureMetatable(L, -1, creature); } else if (Item* parentItem = cylinder->getItem()) { pushUserdata(L, parentItem); setItemMetatable(L, -1, parentItem); } else if (Tile* tile = cylinder->getTile()) { pushUserdata(L, tile); setMetatable(L, -1, "Tile"); } else if (cylinder == VirtualCylinder::virtualCylinder) { pushBoolean(L, true); } else { lua_pushnil(L); } } void LuaScriptInterface::pushString(lua_State* L, const std::string& value) { lua_pushlstring(L, value.c_str(), value.length()); } void LuaScriptInterface::pushCallback(lua_State* L, int32_t callback) { lua_rawgeti(L, LUA_REGISTRYINDEX, callback); } std::string LuaScriptInterface::popString(lua_State* L) { if (lua_gettop(L) == 0) { return std::string(); } std::string str(getString(L, -1)); lua_pop(L, 1); return str; } int32_t LuaScriptInterface::popCallback(lua_State* L) { return luaL_ref(L, LUA_REGISTRYINDEX); } // Metatables void LuaScriptInterface::setMetatable(lua_State* L, int32_t index, const std::string& name) { luaL_getmetatable(L, name.c_str()); lua_setmetatable(L, index - 1); } void LuaScriptInterface::setWeakMetatable(lua_State* L, int32_t index, const std::string& name) { static std::set weakObjectTypes; const std::string& weakName = name + "_weak"; auto result = weakObjectTypes.emplace(name); if (result.second) { luaL_getmetatable(L, name.c_str()); int childMetatable = lua_gettop(L); luaL_newmetatable(L, weakName.c_str()); int metatable = lua_gettop(L); static const std::vector methodKeys = {"__index", "__metatable", "__eq"}; for (const std::string& metaKey : methodKeys) { lua_getfield(L, childMetatable, metaKey.c_str()); lua_setfield(L, metatable, metaKey.c_str()); } static const std::vector methodIndexes = {'h', 'p', 't'}; for (int metaIndex : methodIndexes) { lua_rawgeti(L, childMetatable, metaIndex); lua_rawseti(L, metatable, metaIndex); } lua_pushnil(L); lua_setfield(L, metatable, "__gc"); lua_remove(L, childMetatable); } else { luaL_getmetatable(L, weakName.c_str()); } lua_setmetatable(L, index - 1); } void LuaScriptInterface::setItemMetatable(lua_State* L, int32_t index, const Item* item) { if (item->getContainer()) { luaL_getmetatable(L, "Container"); } else if (item->getTeleport()) { luaL_getmetatable(L, "Teleport"); } else { luaL_getmetatable(L, "Item"); } lua_setmetatable(L, index - 1); } void LuaScriptInterface::setCreatureMetatable(lua_State* L, int32_t index, const Creature* creature) { if (creature->getPlayer()) { luaL_getmetatable(L, "Player"); } else if (creature->getMonster()) { luaL_getmetatable(L, "Monster"); } else { luaL_getmetatable(L, "Npc"); } lua_setmetatable(L, index - 1); } // Get CombatDamage LuaScriptInterface::getCombatDamage(lua_State* L) { CombatDamage damage; damage.value = getNumber(L, -4); damage.type = getNumber(L, -3); damage.min = getNumber(L, -2); damage.max = getNumber(L, -1); lua_pop(L, 4); return damage; } std::string LuaScriptInterface::getString(lua_State* L, int32_t arg) { size_t len; const char* c_str = lua_tolstring(L, arg, &len); if (!c_str || len == 0) { return std::string(); } return std::string(c_str, len); } Position LuaScriptInterface::getPosition(lua_State* L, int32_t arg, int32_t& stackpos) { Position position; position.x = getField(L, arg, "x"); position.y = getField(L, arg, "y"); position.z = getField(L, arg, "z"); lua_getfield(L, arg, "stackpos"); if (lua_isnil(L, -1) == 1) { stackpos = 0; } else { stackpos = getNumber(L, -1); } lua_pop(L, 4); return position; } Position LuaScriptInterface::getPosition(lua_State* L, int32_t arg) { Position position; position.x = getField(L, arg, "x"); position.y = getField(L, arg, "y"); position.z = getField(L, arg, "z"); lua_pop(L, 3); return position; } Outfit_t LuaScriptInterface::getOutfit(lua_State* L, int32_t arg) { Outfit_t outfit; outfit.lookAddons = getField(L, arg, "lookAddons"); outfit.lookFeet = getField(L, arg, "lookFeet"); outfit.lookLegs = getField(L, arg, "lookLegs"); outfit.lookBody = getField(L, arg, "lookBody"); outfit.lookHead = getField(L, arg, "lookHead"); outfit.lookTypeEx = getField(L, arg, "lookTypeEx"); outfit.lookType = getField(L, arg, "lookType"); lua_pop(L, 6); return outfit; } LuaVariant LuaScriptInterface::getVariant(lua_State* L, int32_t arg) { LuaVariant var; switch (var.type = getField(L, arg, "type")) { case VARIANT_NUMBER: { var.number = getField(L, arg, "number"); lua_pop(L, 2); break; } case VARIANT_STRING: { var.text = getFieldString(L, arg, "string"); lua_pop(L, 2); break; } case VARIANT_POSITION: case VARIANT_TARGETPOSITION: { lua_getfield(L, arg, "pos"); var.pos = getPosition(L, lua_gettop(L)); lua_pop(L, 2); break; } default: { var.type = VARIANT_NONE; lua_pop(L, 1); break; } } return var; } Thing* LuaScriptInterface::getThing(lua_State* L, int32_t arg) { Thing* thing; if (lua_getmetatable(L, arg) != 0) { lua_rawgeti(L, -1, 't'); switch(getNumber(L, -1)) { case LuaData_Item: thing = getUserdata(L, arg); break; case LuaData_Container: thing = getUserdata(L, arg); break; case LuaData_Teleport: thing = getUserdata(L, arg); break; case LuaData_Player: thing = getUserdata(L, arg); break; case LuaData_Monster: thing = getUserdata(L, arg); break; case LuaData_Npc: thing = getUserdata(L, arg); break; default: thing = nullptr; break; } lua_pop(L, 2); } else { thing = getScriptEnv()->getThingByUID(getNumber(L, arg)); } return thing; } Creature* LuaScriptInterface::getCreature(lua_State* L, int32_t arg) { if (isUserdata(L, arg)) { return getUserdata(L, arg); } return g_game.getCreatureByID(getNumber(L, arg)); } Player* LuaScriptInterface::getPlayer(lua_State* L, int32_t arg) { if (isUserdata(L, arg)) { return getUserdata(L, arg); } return g_game.getPlayerByID(getNumber(L, arg)); } std::string LuaScriptInterface::getFieldString(lua_State* L, int32_t arg, const std::string& key) { lua_getfield(L, arg, key.c_str()); return getString(L, -1); } LuaDataType LuaScriptInterface::getUserdataType(lua_State* L, int32_t arg) { if (lua_getmetatable(L, arg) == 0) { return LuaData_Unknown; } lua_rawgeti(L, -1, 't'); LuaDataType type = getNumber(L, -1); lua_pop(L, 2); return type; } // Push void LuaScriptInterface::pushBoolean(lua_State* L, bool value) { lua_pushboolean(L, value ? 1 : 0); } void LuaScriptInterface::pushCombatDamage(lua_State* L, const CombatDamage& damage) { lua_pushnumber(L, damage.value); lua_pushnumber(L, damage.type); lua_pushnumber(L, damage.min); lua_pushnumber(L, damage.max); lua_pushnumber(L, damage.origin); } void LuaScriptInterface::pushPosition(lua_State* L, const Position& position, int32_t stackpos/* = 0*/) { lua_createtable(L, 0, 4); setField(L, "x", position.x); setField(L, "y", position.y); setField(L, "z", position.z); setField(L, "stackpos", stackpos); setMetatable(L, -1, "Position"); } void LuaScriptInterface::pushOutfit(lua_State* L, const Outfit_t& outfit) { lua_createtable(L, 0, 6); setField(L, "lookType", outfit.lookType); setField(L, "lookTypeEx", outfit.lookTypeEx); setField(L, "lookHead", outfit.lookHead); setField(L, "lookBody", outfit.lookBody); setField(L, "lookLegs", outfit.lookLegs); setField(L, "lookFeet", outfit.lookFeet); setField(L, "lookAddons", outfit.lookAddons); } #define registerEnum(value) { std::string enumName = #value; registerGlobalVariable(enumName.substr(enumName.find_last_of(':') + 1), value); } #define registerEnumIn(tableName, value) { std::string enumName = #value; registerVariable(tableName, enumName.substr(enumName.find_last_of(':') + 1), value); } void LuaScriptInterface::registerFunctions() { //getPlayerFlagValue(cid, flag) lua_register(luaState, "getPlayerFlagValue", LuaScriptInterface::luaGetPlayerFlagValue); //getPlayerInstantSpellCount(cid) lua_register(luaState, "getPlayerInstantSpellCount", LuaScriptInterface::luaGetPlayerInstantSpellCount); //getPlayerInstantSpellInfo(cid, index) lua_register(luaState, "getPlayerInstantSpellInfo", LuaScriptInterface::luaGetPlayerInstantSpellInfo); //doPlayerAddItem(uid, itemid, count/subtype) //doPlayerAddItem(cid, itemid, count, canDropOnMap, subtype) //Returns uid of the created item lua_register(luaState, "doPlayerAddItem", LuaScriptInterface::luaDoPlayerAddItem); //doCreateItem(itemid, type/count, pos) //Returns uid of the created item, only works on tiles. lua_register(luaState, "doCreateItem", LuaScriptInterface::luaDoCreateItem); //doCreateItemEx(itemid, count/subtype) lua_register(luaState, "doCreateItemEx", LuaScriptInterface::luaDoCreateItemEx); //doTileAddItemEx(pos, uid) lua_register(luaState, "doTileAddItemEx", LuaScriptInterface::luaDoTileAddItemEx); //doMoveCreature(cid, direction) lua_register(luaState, "doMoveCreature", LuaScriptInterface::luaDoMoveCreature); //doSetCreatureLight(cid, lightLevel, lightColor, time) lua_register(luaState, "doSetCreatureLight", LuaScriptInterface::luaDoSetCreatureLight); //getCreatureCondition(cid, condition[, subId]) lua_register(luaState, "getCreatureCondition", LuaScriptInterface::luaGetCreatureCondition); //isValidUID(uid) lua_register(luaState, "isValidUID", LuaScriptInterface::luaIsValidUID); //isDepot(uid) lua_register(luaState, "isDepot", LuaScriptInterface::luaIsDepot); //isMovable(uid) lua_register(luaState, "isMovable", LuaScriptInterface::luaIsMoveable); //doAddContainerItem(uid, itemid, count/subtype) lua_register(luaState, "doAddContainerItem", LuaScriptInterface::luaDoAddContainerItem); //getDepotId(uid) lua_register(luaState, "getDepotId", LuaScriptInterface::luaGetDepotId); //getWorldTime() lua_register(luaState, "getWorldTime", LuaScriptInterface::luaGetWorldTime); //getWorldLight() lua_register(luaState, "getWorldLight", LuaScriptInterface::luaGetWorldLight); //getWorldUpTime() lua_register(luaState, "getWorldUpTime", LuaScriptInterface::luaGetWorldUpTime); //createCombatArea( {area}, {extArea} ) lua_register(luaState, "createCombatArea", LuaScriptInterface::luaCreateCombatArea); //doAreaCombatHealth(cid, type, pos, area, min, max, effect) lua_register(luaState, "doAreaCombatHealth", LuaScriptInterface::luaDoAreaCombatHealth); //doTargetCombatHealth(cid, target, type, min, max, effect) lua_register(luaState, "doTargetCombatHealth", LuaScriptInterface::luaDoTargetCombatHealth); //doAreaCombatMana(cid, pos, area, min, max, effect) lua_register(luaState, "doAreaCombatMana", LuaScriptInterface::luaDoAreaCombatMana); //doTargetCombatMana(cid, target, min, max, effect) lua_register(luaState, "doTargetCombatMana", LuaScriptInterface::luaDoTargetCombatMana); //doAreaCombatCondition(cid, pos, area, condition, effect) lua_register(luaState, "doAreaCombatCondition", LuaScriptInterface::luaDoAreaCombatCondition); //doTargetCombatCondition(cid, target, condition, effect) lua_register(luaState, "doTargetCombatCondition", LuaScriptInterface::luaDoTargetCombatCondition); //doAreaCombatDispel(cid, pos, area, type, effect) lua_register(luaState, "doAreaCombatDispel", LuaScriptInterface::luaDoAreaCombatDispel); //doTargetCombatDispel(cid, target, type, effect) lua_register(luaState, "doTargetCombatDispel", LuaScriptInterface::luaDoTargetCombatDispel); //doChallengeCreature(cid, target) lua_register(luaState, "doChallengeCreature", LuaScriptInterface::luaDoChallengeCreature); //doSetMonsterOutfit(cid, name, time) lua_register(luaState, "doSetMonsterOutfit", LuaScriptInterface::luaSetMonsterOutfit); //doSetItemOutfit(cid, item, time) lua_register(luaState, "doSetItemOutfit", LuaScriptInterface::luaSetItemOutfit); //doSetCreatureOutfit(cid, outfit, time) lua_register(luaState, "doSetCreatureOutfit", LuaScriptInterface::luaSetCreatureOutfit); //isInArray(array, value) lua_register(luaState, "isInArray", LuaScriptInterface::luaIsInArray); //addEvent(callback, delay, ...) lua_register(luaState, "addEvent", LuaScriptInterface::luaAddEvent); //stopEvent(eventid) lua_register(luaState, "stopEvent", LuaScriptInterface::luaStopEvent); //saveServer() lua_register(luaState, "saveServer", LuaScriptInterface::luaSaveServer); //cleanMap() lua_register(luaState, "cleanMap", LuaScriptInterface::luaCleanMap); //debugPrint(text) lua_register(luaState, "debugPrint", LuaScriptInterface::luaDebugPrint); //isInWar(cid, target) lua_register(luaState, "isInWar", LuaScriptInterface::luaIsInWar); //getWaypointPosition(name) lua_register(luaState, "getWaypointPositionByName", LuaScriptInterface::luaGetWaypointPositionByName); #ifndef LUAJIT_VERSION //bit operations for Lua, based on bitlib project release 24 //bit.bnot, bit.band, bit.bor, bit.bxor, bit.lshift, bit.rshift luaL_register(luaState, "bit", LuaScriptInterface::luaBitReg); #endif //configManager table luaL_register(luaState, "configManager", LuaScriptInterface::luaConfigManagerTable); //db table luaL_register(luaState, "db", LuaScriptInterface::luaDatabaseTable); //result table luaL_register(luaState, "result", LuaScriptInterface::luaResultTable); /* New functions */ //registerClass(className, baseClass, newFunction) //registerTable(tableName) //registerMethod(className, functionName, function) //registerMetaMethod(className, functionName, function) //registerGlobalMethod(functionName, function) //registerVariable(tableName, name, value) //registerGlobalVariable(name, value) //registerEnum(value) //registerEnumIn(tableName, value) // Enums registerEnum(ACCOUNT_TYPE_NORMAL) registerEnum(ACCOUNT_TYPE_TUTOR) registerEnum(ACCOUNT_TYPE_SENIORTUTOR) registerEnum(ACCOUNT_TYPE_GAMEMASTER) registerEnum(ACCOUNT_TYPE_GOD) registerEnum(CALLBACK_PARAM_LEVELMAGICVALUE) registerEnum(CALLBACK_PARAM_SKILLVALUE) registerEnum(CALLBACK_PARAM_TARGETTILE) registerEnum(CALLBACK_PARAM_TARGETCREATURE) registerEnum(COMBAT_FORMULA_UNDEFINED) registerEnum(COMBAT_FORMULA_LEVELMAGIC) registerEnum(COMBAT_FORMULA_SKILL) registerEnum(COMBAT_FORMULA_DAMAGE) registerEnum(DIRECTION_NORTH) registerEnum(DIRECTION_EAST) registerEnum(DIRECTION_SOUTH) registerEnum(DIRECTION_WEST) registerEnum(DIRECTION_SOUTHWEST) registerEnum(DIRECTION_SOUTHEAST) registerEnum(DIRECTION_NORTHWEST) registerEnum(DIRECTION_NORTHEAST) registerEnum(COMBAT_NONE) registerEnum(COMBAT_PHYSICALDAMAGE) registerEnum(COMBAT_ENERGYDAMAGE) registerEnum(COMBAT_EARTHDAMAGE) registerEnum(COMBAT_FIREDAMAGE) registerEnum(COMBAT_DROWNDAMAGE) registerEnum(COMBAT_UNDEFINEDDAMAGE) registerEnum(COMBAT_LIFEDRAIN) registerEnum(COMBAT_MANADRAIN) registerEnum(COMBAT_HEALING) registerEnum(COMBAT_PARAM_TYPE) registerEnum(COMBAT_PARAM_EFFECT) registerEnum(COMBAT_PARAM_DISTANCEEFFECT) registerEnum(COMBAT_PARAM_BLOCKSHIELD) registerEnum(COMBAT_PARAM_BLOCKARMOR) registerEnum(COMBAT_PARAM_TARGETCASTERORTOPMOST) registerEnum(COMBAT_PARAM_CREATEITEM) registerEnum(COMBAT_PARAM_AGGRESSIVE) registerEnum(COMBAT_PARAM_DISPEL) registerEnum(COMBAT_PARAM_USECHARGES) registerEnum(COMBAT_PARAM_DECREASEDAMAGE) registerEnum(COMBAT_PARAM_MAXIMUMDECREASEDDAMAGE) registerEnum(CONDITION_NONE) registerEnum(CONDITION_POISON) registerEnum(CONDITION_FIRE) registerEnum(CONDITION_ENERGY) registerEnum(CONDITION_DROWN) registerEnum(CONDITION_HASTE) registerEnum(CONDITION_PARALYZE) registerEnum(CONDITION_OUTFIT) registerEnum(CONDITION_INVISIBLE) registerEnum(CONDITION_LIGHT) registerEnum(CONDITION_MANASHIELD) registerEnum(CONDITION_INFIGHT) registerEnum(CONDITION_DRUNK) registerEnum(CONDITION_REGENERATION) registerEnum(CONDITION_SOUL) registerEnum(CONDITION_MUTED) registerEnum(CONDITION_CHANNELMUTEDTICKS) registerEnum(CONDITION_YELLTICKS) registerEnum(CONDITION_ATTRIBUTES) registerEnum(CONDITION_EXHAUST) registerEnum(CONDITION_PACIFIED) registerEnum(CONDITIONID_DEFAULT) registerEnum(CONDITIONID_COMBAT) registerEnum(CONDITIONID_HEAD) registerEnum(CONDITIONID_NECKLACE) registerEnum(CONDITIONID_BACKPACK) registerEnum(CONDITIONID_ARMOR) registerEnum(CONDITIONID_RIGHT) registerEnum(CONDITIONID_LEFT) registerEnum(CONDITIONID_LEGS) registerEnum(CONDITIONID_FEET) registerEnum(CONDITIONID_RING) registerEnum(CONDITIONID_AMMO) registerEnum(CONDITION_PARAM_OWNER) registerEnum(CONDITION_PARAM_TICKS) registerEnum(CONDITION_PARAM_HEALTHGAIN) registerEnum(CONDITION_PARAM_HEALTHTICKS) registerEnum(CONDITION_PARAM_MANAGAIN) registerEnum(CONDITION_PARAM_MANATICKS) registerEnum(CONDITION_PARAM_DELAYED) registerEnum(CONDITION_PARAM_SPEED) registerEnum(CONDITION_PARAM_LIGHT_LEVEL) registerEnum(CONDITION_PARAM_LIGHT_COLOR) registerEnum(CONDITION_PARAM_SOULGAIN) registerEnum(CONDITION_PARAM_SOULTICKS) registerEnum(CONDITION_PARAM_MINVALUE) registerEnum(CONDITION_PARAM_MAXVALUE) registerEnum(CONDITION_PARAM_STARTVALUE) registerEnum(CONDITION_PARAM_TICKINTERVAL) registerEnum(CONDITION_PARAM_SKILL_MELEE) registerEnum(CONDITION_PARAM_SKILL_FIST) registerEnum(CONDITION_PARAM_SKILL_CLUB) registerEnum(CONDITION_PARAM_SKILL_SWORD) registerEnum(CONDITION_PARAM_SKILL_AXE) registerEnum(CONDITION_PARAM_SKILL_DISTANCE) registerEnum(CONDITION_PARAM_SKILL_SHIELD) registerEnum(CONDITION_PARAM_SKILL_FISHING) registerEnum(CONDITION_PARAM_STAT_MAXHITPOINTS) registerEnum(CONDITION_PARAM_STAT_MAXMANAPOINTS) registerEnum(CONDITION_PARAM_STAT_MAGICPOINTS) registerEnum(CONDITION_PARAM_STAT_MAXHITPOINTSPERCENT) registerEnum(CONDITION_PARAM_STAT_MAXMANAPOINTSPERCENT) registerEnum(CONDITION_PARAM_STAT_MAGICPOINTSPERCENT) registerEnum(CONDITION_PARAM_PERIODICDAMAGE) registerEnum(CONDITION_PARAM_HIT_DAMAGE) registerEnum(CONDITION_PARAM_SKILL_MELEEPERCENT) registerEnum(CONDITION_PARAM_SKILL_FISTPERCENT) registerEnum(CONDITION_PARAM_SKILL_CLUBPERCENT) registerEnum(CONDITION_PARAM_SKILL_SWORDPERCENT) registerEnum(CONDITION_PARAM_SKILL_AXEPERCENT) registerEnum(CONDITION_PARAM_SKILL_DISTANCEPERCENT) registerEnum(CONDITION_PARAM_SKILL_SHIELDPERCENT) registerEnum(CONDITION_PARAM_SKILL_FISHINGPERCENT) registerEnum(CONDITION_PARAM_SUBID) registerEnum(CONDITION_PARAM_FIELD) registerEnum(CONST_ME_NONE) registerEnum(CONST_ME_DRAWBLOOD) registerEnum(CONST_ME_LOSEENERGY) registerEnum(CONST_ME_POFF) registerEnum(CONST_ME_BLOCKHIT) registerEnum(CONST_ME_EXPLOSIONAREA) registerEnum(CONST_ME_EXPLOSIONHIT) registerEnum(CONST_ME_FIREAREA) registerEnum(CONST_ME_YELLOW_RINGS) registerEnum(CONST_ME_GREEN_RINGS) registerEnum(CONST_ME_HITAREA) registerEnum(CONST_ME_TELEPORT) registerEnum(CONST_ME_ENERGYHIT) registerEnum(CONST_ME_MAGIC_BLUE) registerEnum(CONST_ME_MAGIC_RED) registerEnum(CONST_ME_MAGIC_GREEN) registerEnum(CONST_ME_HITBYFIRE) registerEnum(CONST_ME_HITBYPOISON) registerEnum(CONST_ME_MORTAREA) registerEnum(CONST_ME_SOUND_GREEN) registerEnum(CONST_ME_SOUND_RED) registerEnum(CONST_ME_POISONAREA) registerEnum(CONST_ME_SOUND_YELLOW) registerEnum(CONST_ME_SOUND_PURPLE) registerEnum(CONST_ME_SOUND_BLUE) registerEnum(CONST_ME_SOUND_WHITE) registerEnum(CONST_ME_BUBBLES) registerEnum(CONST_ME_CRAPS) registerEnum(CONST_ME_GIFT_WRAPS) registerEnum(CONST_ME_FIREWORK_YELLOW) registerEnum(CONST_ME_FIREWORK_RED) registerEnum(CONST_ME_FIREWORK_BLUE) registerEnum(CONST_ANI_NONE) registerEnum(CONST_ANI_SPEAR) registerEnum(CONST_ANI_BOLT) registerEnum(CONST_ANI_ARROW) registerEnum(CONST_ANI_FIRE) registerEnum(CONST_ANI_ENERGY) registerEnum(CONST_ANI_POISONARROW) registerEnum(CONST_ANI_BURSTARROW) registerEnum(CONST_ANI_THROWINGSTAR) registerEnum(CONST_ANI_THROWINGKNIFE) registerEnum(CONST_ANI_SMALLSTONE) registerEnum(CONST_ANI_DEATH) registerEnum(CONST_ANI_LARGEROCK) registerEnum(CONST_ANI_SNOWBALL) registerEnum(CONST_ANI_POWERBOLT) registerEnum(CONST_ANI_POISON) registerEnum(CONST_ANI_INFERNALBOLT) registerEnum(CONST_PROP_BLOCKSOLID) registerEnum(CONST_PROP_HASHEIGHT) registerEnum(CONST_PROP_BLOCKPROJECTILE) registerEnum(CONST_PROP_BLOCKPATH) registerEnum(CONST_PROP_ISVERTICAL) registerEnum(CONST_PROP_ISHORIZONTAL) registerEnum(CONST_PROP_MOVEABLE) registerEnum(CONST_PROP_IMMOVABLEBLOCKSOLID) registerEnum(CONST_PROP_IMMOVABLEBLOCKPATH) registerEnum(CONST_PROP_IMMOVABLENOFIELDBLOCKPATH) registerEnum(CONST_PROP_NOFIELDBLOCKPATH) registerEnum(CONST_PROP_SUPPORTHANGABLE) registerEnum(CONST_SLOT_HEAD) registerEnum(CONST_SLOT_NECKLACE) registerEnum(CONST_SLOT_BACKPACK) registerEnum(CONST_SLOT_ARMOR) registerEnum(CONST_SLOT_RIGHT) registerEnum(CONST_SLOT_LEFT) registerEnum(CONST_SLOT_LEGS) registerEnum(CONST_SLOT_FEET) registerEnum(CONST_SLOT_RING) registerEnum(CONST_SLOT_AMMO) registerEnum(CREATURE_EVENT_NONE) registerEnum(CREATURE_EVENT_LOGIN) registerEnum(CREATURE_EVENT_LOGOUT) registerEnum(CREATURE_EVENT_THINK) registerEnum(CREATURE_EVENT_PREPAREDEATH) registerEnum(CREATURE_EVENT_DEATH) registerEnum(CREATURE_EVENT_KILL) registerEnum(CREATURE_EVENT_ADVANCE) registerEnum(CREATURE_EVENT_EXTENDED_OPCODE) registerEnum(GAME_STATE_STARTUP) registerEnum(GAME_STATE_INIT) registerEnum(GAME_STATE_NORMAL) registerEnum(GAME_STATE_CLOSED) registerEnum(GAME_STATE_SHUTDOWN) registerEnum(GAME_STATE_CLOSING) registerEnum(GAME_STATE_MAINTAIN) registerEnum(MESSAGE_STATUS_CONSOLE_BLUE) registerEnum(MESSAGE_STATUS_CONSOLE_RED) registerEnum(MESSAGE_STATUS_DEFAULT) registerEnum(MESSAGE_STATUS_WARNING) registerEnum(MESSAGE_EVENT_ADVANCE) registerEnum(MESSAGE_STATUS_SMALL) registerEnum(MESSAGE_INFO_DESCR) registerEnum(MESSAGE_EVENT_DEFAULT) registerEnum(MESSAGE_STATUS_CONSOLE_ORANGE) registerEnum(CLIENTOS_LINUX) registerEnum(CLIENTOS_WINDOWS) registerEnum(CLIENTOS_FLASH) registerEnum(CLIENTOS_OTCLIENT_LINUX) registerEnum(CLIENTOS_OTCLIENT_WINDOWS) registerEnum(CLIENTOS_OTCLIENT_MAC) registerEnum(ITEM_ATTRIBUTE_NONE) registerEnum(ITEM_ATTRIBUTE_ACTIONID) registerEnum(ITEM_ATTRIBUTE_MOVEMENTID) registerEnum(ITEM_ATTRIBUTE_DESCRIPTION) registerEnum(ITEM_ATTRIBUTE_TEXT) registerEnum(ITEM_ATTRIBUTE_DATE) registerEnum(ITEM_ATTRIBUTE_WRITER) registerEnum(ITEM_ATTRIBUTE_NAME) registerEnum(ITEM_ATTRIBUTE_ARTICLE) registerEnum(ITEM_ATTRIBUTE_PLURALNAME) registerEnum(ITEM_ATTRIBUTE_WEIGHT) registerEnum(ITEM_ATTRIBUTE_ATTACK) registerEnum(ITEM_ATTRIBUTE_DEFENSE) registerEnum(ITEM_ATTRIBUTE_ARMOR) registerEnum(ITEM_ATTRIBUTE_SHOOTRANGE) registerEnum(ITEM_ATTRIBUTE_OWNER) registerEnum(ITEM_ATTRIBUTE_DURATION) registerEnum(ITEM_ATTRIBUTE_DECAYSTATE) registerEnum(ITEM_ATTRIBUTE_CORPSEOWNER) registerEnum(ITEM_ATTRIBUTE_CHARGES) registerEnum(ITEM_ATTRIBUTE_FLUIDTYPE) registerEnum(ITEM_ATTRIBUTE_DOORID) registerEnum(ITEM_ATTRIBUTE_KEYNUMBER) registerEnum(ITEM_ATTRIBUTE_KEYHOLENUMBER) registerEnum(ITEM_ATTRIBUTE_DOORQUESTNUMBER) registerEnum(ITEM_ATTRIBUTE_DOORQUESTVALUE) registerEnum(ITEM_ATTRIBUTE_DOORLEVEL) registerEnum(ITEM_ATTRIBUTE_CHESTQUESTNUMBER) registerEnum(ITEM_TYPE_DEPOT) registerEnum(ITEM_TYPE_MAILBOX) registerEnum(ITEM_TYPE_CONTAINER) registerEnum(ITEM_TYPE_DOOR) registerEnum(ITEM_TYPE_MAGICFIELD) registerEnum(ITEM_TYPE_TELEPORT) registerEnum(ITEM_TYPE_BED) registerEnum(ITEM_TYPE_KEY) registerEnum(ITEM_TYPE_RUNE) registerEnum(ITEM_TYPE_CHEST) registerEnum(ITEM_GOLD_COIN) registerEnum(ITEM_PLATINUM_COIN) registerEnum(ITEM_CRYSTAL_COIN) registerEnum(ITEM_AMULETOFLOSS) registerEnum(ITEM_PARCEL) registerEnum(ITEM_LABEL) registerEnum(ITEM_FIREFIELD_PVP_FULL) registerEnum(ITEM_FIREFIELD_PVP_MEDIUM) registerEnum(ITEM_FIREFIELD_PVP_SMALL) registerEnum(ITEM_FIREFIELD_PERSISTENT_FULL) registerEnum(ITEM_FIREFIELD_PERSISTENT_MEDIUM) registerEnum(ITEM_FIREFIELD_PERSISTENT_SMALL) registerEnum(ITEM_FIREFIELD_NOPVP) registerEnum(ITEM_POISONFIELD_PVP) registerEnum(ITEM_POISONFIELD_PERSISTENT) registerEnum(ITEM_POISONFIELD_NOPVP) registerEnum(ITEM_ENERGYFIELD_PVP) registerEnum(ITEM_ENERGYFIELD_PERSISTENT) registerEnum(ITEM_ENERGYFIELD_NOPVP) registerEnum(ITEM_MAGICWALL) registerEnum(ITEM_MAGICWALL_PERSISTENT) registerEnum(ITEM_WILDGROWTH) registerEnum(ITEM_WILDGROWTH_PERSISTENT) registerEnum(PlayerFlag_CannotUseCombat) registerEnum(PlayerFlag_CannotAttackPlayer) registerEnum(PlayerFlag_CannotAttackMonster) registerEnum(PlayerFlag_CannotBeAttacked) registerEnum(PlayerFlag_CanConvinceAll) registerEnum(PlayerFlag_CanSummonAll) registerEnum(PlayerFlag_CanIllusionAll) registerEnum(PlayerFlag_CanSenseInvisibility) registerEnum(PlayerFlag_IgnoredByMonsters) registerEnum(PlayerFlag_NotGainInFight) registerEnum(PlayerFlag_HasInfiniteMana) registerEnum(PlayerFlag_HasInfiniteSoul) registerEnum(PlayerFlag_HasNoExhaustion) registerEnum(PlayerFlag_CannotUseSpells) registerEnum(PlayerFlag_CannotPickupItem) registerEnum(PlayerFlag_CanAlwaysLogin) registerEnum(PlayerFlag_CanBroadcast) registerEnum(PlayerFlag_CanEditHouses) registerEnum(PlayerFlag_CannotBeBanned) registerEnum(PlayerFlag_CannotBePushed) registerEnum(PlayerFlag_HasInfiniteCapacity) registerEnum(PlayerFlag_CanPushAllCreatures) registerEnum(PlayerFlag_CanTalkRedPrivate) registerEnum(PlayerFlag_CanTalkRedChannel) registerEnum(PlayerFlag_TalkOrangeHelpChannel) registerEnum(PlayerFlag_NotGainExperience) registerEnum(PlayerFlag_NotGainMana) registerEnum(PlayerFlag_NotGainHealth) registerEnum(PlayerFlag_NotGainSkill) registerEnum(PlayerFlag_SetMaxSpeed) registerEnum(PlayerFlag_SpecialVIP) registerEnum(PlayerFlag_NotGenerateLoot) registerEnum(PlayerFlag_CanTalkRedChannelAnonymous) registerEnum(PlayerFlag_IgnoreProtectionZone) registerEnum(PlayerFlag_IgnoreSpellCheck) registerEnum(PlayerFlag_IgnoreWeaponCheck) registerEnum(PlayerFlag_CannotBeMuted) registerEnum(PlayerFlag_IsAlwaysPremium) registerEnum(PlayerFlag_SpecialMoveUse) registerEnum(PLAYERSEX_FEMALE) registerEnum(PLAYERSEX_MALE) registerEnum(VOCATION_NONE) registerEnum(FIGHTMODE_ATTACK) registerEnum(FIGHTMODE_BALANCED) registerEnum(FIGHTMODE_DEFENSE) registerEnum(SKILL_FIST) registerEnum(SKILL_CLUB) registerEnum(SKILL_SWORD) registerEnum(SKILL_AXE) registerEnum(SKILL_DISTANCE) registerEnum(SKILL_SHIELD) registerEnum(SKILL_FISHING) registerEnum(SKILL_MAGLEVEL) registerEnum(SKILL_LEVEL) registerEnum(SKULL_NONE) registerEnum(SKULL_YELLOW) registerEnum(SKULL_GREEN) registerEnum(SKULL_WHITE) registerEnum(SKULL_RED) registerEnum(FLUID_NONE) registerEnum(FLUID_WATER) registerEnum(FLUID_WINE) registerEnum(FLUID_BEER) registerEnum(FLUID_MUD) registerEnum(FLUID_BLOOD) registerEnum(FLUID_SLIME) registerEnum(FLUID_OIL) registerEnum(FLUID_URINE) registerEnum(FLUID_MILK) registerEnum(FLUID_MANAFLUID) registerEnum(FLUID_LIFEFLUID) registerEnum(FLUID_LEMONADE) registerEnum(FLUID_RUM) registerEnum(FLUID_COCONUTMILK) registerEnum(FLUID_FRUITJUICE) registerEnum(TALKTYPE_SAY) registerEnum(TALKTYPE_WHISPER) registerEnum(TALKTYPE_YELL) registerEnum(TALKTYPE_CHANNEL_Y) registerEnum(TALKTYPE_CHANNEL_O) registerEnum(TALKTYPE_BROADCAST) registerEnum(TALKTYPE_CHANNEL_R1) registerEnum(TALKTYPE_MONSTER_SAY) registerEnum(TALKTYPE_MONSTER_YELL) registerEnum(TALKTYPE_CHANNEL_R2) registerEnum(TEXTCOLOR_BLUE) registerEnum(TEXTCOLOR_LIGHTGREEN) registerEnum(TEXTCOLOR_LIGHTBLUE) registerEnum(TEXTCOLOR_MAYABLUE) registerEnum(TEXTCOLOR_DARKRED) registerEnum(TEXTCOLOR_LIGHTGREY) registerEnum(TEXTCOLOR_SKYBLUE) registerEnum(TEXTCOLOR_PURPLE) registerEnum(TEXTCOLOR_RED) registerEnum(TEXTCOLOR_ORANGE) registerEnum(TEXTCOLOR_YELLOW) registerEnum(TEXTCOLOR_WHITE_EXP) registerEnum(TEXTCOLOR_NONE) registerEnum(TILESTATE_NONE) registerEnum(TILESTATE_PROTECTIONZONE) registerEnum(TILESTATE_NOPVPZONE) registerEnum(TILESTATE_NOLOGOUT) registerEnum(TILESTATE_PVPZONE) registerEnum(TILESTATE_REFRESH) registerEnum(TILESTATE_TELEPORT) registerEnum(TILESTATE_MAGICFIELD) registerEnum(TILESTATE_MAILBOX) registerEnum(TILESTATE_BED) registerEnum(TILESTATE_DEPOT) registerEnum(TILESTATE_BLOCKSOLID) registerEnum(TILESTATE_BLOCKPATH) registerEnum(TILESTATE_IMMOVABLEBLOCKSOLID) registerEnum(TILESTATE_IMMOVABLEBLOCKPATH) registerEnum(TILESTATE_IMMOVABLENOFIELDBLOCKPATH) registerEnum(TILESTATE_NOFIELDBLOCKPATH) registerEnum(TILESTATE_SUPPORTS_HANGABLE) registerEnum(WEAPON_NONE) registerEnum(WEAPON_SWORD) registerEnum(WEAPON_CLUB) registerEnum(WEAPON_AXE) registerEnum(WEAPON_SHIELD) registerEnum(WEAPON_DISTANCE) registerEnum(WEAPON_WAND) registerEnum(WEAPON_AMMO) registerEnum(WORLD_TYPE_NO_PVP) registerEnum(WORLD_TYPE_PVP) registerEnum(WORLD_TYPE_PVP_ENFORCED) // Use with container:addItem, container:addItemEx and possibly other functions. registerEnum(FLAG_NOLIMIT) registerEnum(FLAG_IGNOREBLOCKITEM) registerEnum(FLAG_IGNOREBLOCKCREATURE) registerEnum(FLAG_CHILDISOWNER) registerEnum(FLAG_PATHFINDING) registerEnum(FLAG_IGNOREFIELDDAMAGE) registerEnum(FLAG_IGNORENOTMOVEABLE) registerEnum(FLAG_IGNOREAUTOSTACK) // Use with itemType:getSlotPosition registerEnum(SLOTP_WHEREEVER) registerEnum(SLOTP_HEAD) registerEnum(SLOTP_NECKLACE) registerEnum(SLOTP_BACKPACK) registerEnum(SLOTP_ARMOR) registerEnum(SLOTP_RIGHT) registerEnum(SLOTP_LEFT) registerEnum(SLOTP_LEGS) registerEnum(SLOTP_FEET) registerEnum(SLOTP_RING) registerEnum(SLOTP_AMMO) registerEnum(SLOTP_DEPOT) registerEnum(SLOTP_TWO_HAND) // Use with combat functions registerEnum(ORIGIN_NONE) registerEnum(ORIGIN_CONDITION) registerEnum(ORIGIN_SPELL) registerEnum(ORIGIN_MELEE) registerEnum(ORIGIN_RANGED) // Use with house:getAccessList, house:setAccessList registerEnum(GUEST_LIST) registerEnum(SUBOWNER_LIST) // Use with Game.getReturnMessage registerEnum(RETURNVALUE_NOERROR) registerEnum(RETURNVALUE_NOTPOSSIBLE) registerEnum(RETURNVALUE_NOTENOUGHROOM) registerEnum(RETURNVALUE_PLAYERISPZLOCKED) registerEnum(RETURNVALUE_PLAYERISNOTINVITED) registerEnum(RETURNVALUE_CANNOTTHROW) registerEnum(RETURNVALUE_THEREISNOWAY) registerEnum(RETURNVALUE_DESTINATIONOUTOFREACH) registerEnum(RETURNVALUE_CREATUREBLOCK) registerEnum(RETURNVALUE_NOTMOVEABLE) registerEnum(RETURNVALUE_DROPTWOHANDEDITEM) registerEnum(RETURNVALUE_BOTHHANDSNEEDTOBEFREE) registerEnum(RETURNVALUE_CANONLYUSEONEWEAPON) registerEnum(RETURNVALUE_NEEDEXCHANGE) registerEnum(RETURNVALUE_CANNOTBEDRESSED) registerEnum(RETURNVALUE_PUTTHISOBJECTINYOURHAND) registerEnum(RETURNVALUE_PUTTHISOBJECTINBOTHHANDS) registerEnum(RETURNVALUE_TOOFARAWAY) registerEnum(RETURNVALUE_FIRSTGODOWNSTAIRS) registerEnum(RETURNVALUE_FIRSTGOUPSTAIRS) registerEnum(RETURNVALUE_CONTAINERNOTENOUGHROOM) registerEnum(RETURNVALUE_NOTENOUGHCAPACITY) registerEnum(RETURNVALUE_CANNOTPICKUP) registerEnum(RETURNVALUE_THISISIMPOSSIBLE) registerEnum(RETURNVALUE_DEPOTISFULL) registerEnum(RETURNVALUE_CREATUREDOESNOTEXIST) registerEnum(RETURNVALUE_CANNOTUSETHISOBJECT) registerEnum(RETURNVALUE_PLAYERWITHTHISNAMEISNOTONLINE) registerEnum(RETURNVALUE_NOTREQUIREDLEVELTOUSERUNE) registerEnum(RETURNVALUE_YOUAREALREADYTRADING) registerEnum(RETURNVALUE_THISPLAYERISALREADYTRADING) registerEnum(RETURNVALUE_YOUMAYNOTLOGOUTDURINGAFIGHT) registerEnum(RETURNVALUE_DIRECTPLAYERSHOOT) registerEnum(RETURNVALUE_NOTENOUGHLEVEL) registerEnum(RETURNVALUE_NOTENOUGHMAGICLEVEL) registerEnum(RETURNVALUE_NOTENOUGHMANA) registerEnum(RETURNVALUE_NOTENOUGHSOUL) registerEnum(RETURNVALUE_YOUAREEXHAUSTED) registerEnum(RETURNVALUE_PLAYERISNOTREACHABLE) registerEnum(RETURNVALUE_CANONLYUSETHISRUNEONCREATURES) registerEnum(RETURNVALUE_ACTIONNOTPERMITTEDINPROTECTIONZONE) registerEnum(RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER) registerEnum(RETURNVALUE_YOUMAYNOTATTACKAPERSONINPROTECTIONZONE) registerEnum(RETURNVALUE_YOUMAYNOTATTACKAPERSONWHILEINPROTECTIONZONE) registerEnum(RETURNVALUE_YOUMAYNOTATTACKTHISCREATURE) registerEnum(RETURNVALUE_YOUCANONLYUSEITONCREATURES) registerEnum(RETURNVALUE_CREATUREISNOTREACHABLE) registerEnum(RETURNVALUE_TURNSECUREMODETOATTACKUNMARKEDPLAYERS) registerEnum(RETURNVALUE_YOUNEEDPREMIUMACCOUNT) registerEnum(RETURNVALUE_YOUNEEDTOLEARNTHISSPELL) registerEnum(RETURNVALUE_YOURVOCATIONCANNOTUSETHISSPELL) registerEnum(RETURNVALUE_YOUNEEDAWEAPONTOUSETHISSPELL) registerEnum(RETURNVALUE_PLAYERISPZLOCKEDLEAVEPVPZONE) registerEnum(RETURNVALUE_PLAYERISPZLOCKEDENTERPVPZONE) registerEnum(RETURNVALUE_ACTIONNOTPERMITTEDINANOPVPZONE) registerEnum(RETURNVALUE_YOUCANNOTLOGOUTHERE) registerEnum(RETURNVALUE_YOUNEEDAMAGICITEMTOCASTSPELL) registerEnum(RETURNVALUE_CANNOTCONJUREITEMHERE) registerEnum(RETURNVALUE_YOUNEEDTOSPLITYOURSPEARS) registerEnum(RETURNVALUE_NAMEISTOOAMBIGIOUS) registerEnum(RETURNVALUE_CANONLYUSEONESHIELD) registerEnum(RETURNVALUE_NOPARTYMEMBERSINRANGE) registerEnum(RETURNVALUE_YOUARENOTTHEOWNER) registerEnum(RETURNVALUE_TRADEPLAYERFARAWAY) registerEnum(RETURNVALUE_YOUDONTOWNTHISHOUSE) registerEnum(RETURNVALUE_TRADEPLAYERALREADYOWNSAHOUSE) registerEnum(RETURNVALUE_TRADEPLAYERHIGHESTBIDDER) registerEnum(RETURNVALUE_YOUCANNOTTRADETHISHOUSE) registerEnum(RELOAD_TYPE_ALL) registerEnum(RELOAD_TYPE_ACTIONS) registerEnum(RELOAD_TYPE_CHAT) registerEnum(RELOAD_TYPE_COMMANDS) registerEnum(RELOAD_TYPE_CONFIG) registerEnum(RELOAD_TYPE_CREATURESCRIPTS) registerEnum(RELOAD_TYPE_EVENTS) registerEnum(RELOAD_TYPE_GLOBAL) registerEnum(RELOAD_TYPE_GLOBALEVENTS) registerEnum(RELOAD_TYPE_ITEMS) registerEnum(RELOAD_TYPE_MONSTERS) registerEnum(RELOAD_TYPE_MOUNTS) registerEnum(RELOAD_TYPE_MOVEMENTS) registerEnum(RELOAD_TYPE_NPCS) registerEnum(RELOAD_TYPE_QUESTS) registerEnum(RELOAD_TYPE_RAIDS) registerEnum(RELOAD_TYPE_SPELLS) registerEnum(RELOAD_TYPE_TALKACTIONS) registerEnum(RELOAD_TYPE_WEAPONS) // _G registerGlobalVariable("INDEX_WHEREEVER", INDEX_WHEREEVER); registerGlobalBoolean("VIRTUAL_PARENT", true); registerGlobalMethod("isType", LuaScriptInterface::luaIsType); registerGlobalMethod("rawgetmetatable", LuaScriptInterface::luaRawGetMetatable); // configKeys registerTable("configKeys"); registerEnumIn("configKeys", ConfigManager::ALLOW_CHANGEOUTFIT) registerEnumIn("configKeys", ConfigManager::ONE_PLAYER_ON_ACCOUNT) registerEnumIn("configKeys", ConfigManager::REMOVE_RUNE_CHARGES) registerEnumIn("configKeys", ConfigManager::EXPERIENCE_FROM_PLAYERS) registerEnumIn("configKeys", ConfigManager::FREE_PREMIUM) registerEnumIn("configKeys", ConfigManager::REPLACE_KICK_ON_LOGIN) registerEnumIn("configKeys", ConfigManager::ALLOW_CLONES) registerEnumIn("configKeys", ConfigManager::BIND_ONLY_GLOBAL_ADDRESS) registerEnumIn("configKeys", ConfigManager::OPTIMIZE_DATABASE) registerEnumIn("configKeys", ConfigManager::STAMINA_SYSTEM) registerEnumIn("configKeys", ConfigManager::WARN_UNSAFE_SCRIPTS) registerEnumIn("configKeys", ConfigManager::CONVERT_UNSAFE_SCRIPTS) registerEnumIn("configKeys", ConfigManager::TELEPORT_NEWBIES) registerEnumIn("configKeys", ConfigManager::MAP_NAME) registerEnumIn("configKeys", ConfigManager::HOUSE_RENT_PERIOD) registerEnumIn("configKeys", ConfigManager::SERVER_NAME) registerEnumIn("configKeys", ConfigManager::OWNER_NAME) registerEnumIn("configKeys", ConfigManager::OWNER_EMAIL) registerEnumIn("configKeys", ConfigManager::URL) registerEnumIn("configKeys", ConfigManager::LOCATION) registerEnumIn("configKeys", ConfigManager::IP) registerEnumIn("configKeys", ConfigManager::MOTD) registerEnumIn("configKeys", ConfigManager::WORLD_TYPE) registerEnumIn("configKeys", ConfigManager::MYSQL_HOST) registerEnumIn("configKeys", ConfigManager::MYSQL_USER) registerEnumIn("configKeys", ConfigManager::MYSQL_PASS) registerEnumIn("configKeys", ConfigManager::MYSQL_DB) registerEnumIn("configKeys", ConfigManager::MYSQL_SOCK) registerEnumIn("configKeys", ConfigManager::DEFAULT_PRIORITY) registerEnumIn("configKeys", ConfigManager::MAP_AUTHOR) registerEnumIn("configKeys", ConfigManager::SQL_PORT) registerEnumIn("configKeys", ConfigManager::MAX_PLAYERS) registerEnumIn("configKeys", ConfigManager::PZ_LOCKED) registerEnumIn("configKeys", ConfigManager::DEFAULT_DESPAWNRANGE) registerEnumIn("configKeys", ConfigManager::DEFAULT_DESPAWNRADIUS) registerEnumIn("configKeys", ConfigManager::RATE_EXPERIENCE) registerEnumIn("configKeys", ConfigManager::RATE_SKILL) registerEnumIn("configKeys", ConfigManager::RATE_LOOT) registerEnumIn("configKeys", ConfigManager::RATE_MAGIC) registerEnumIn("configKeys", ConfigManager::RATE_SPAWN) registerEnumIn("configKeys", ConfigManager::MAX_MESSAGEBUFFER) registerEnumIn("configKeys", ConfigManager::ACTIONS_DELAY_INTERVAL) registerEnumIn("configKeys", ConfigManager::EX_ACTIONS_DELAY_INTERVAL) registerEnumIn("configKeys", ConfigManager::KICK_AFTER_MINUTES) registerEnumIn("configKeys", ConfigManager::PROTECTION_LEVEL) registerEnumIn("configKeys", ConfigManager::DEATH_LOSE_PERCENT) registerEnumIn("configKeys", ConfigManager::KNIGHT_CLOSE_ATTACK_DAMAGE_INCREASE_PERCENT) registerEnumIn("configKeys", ConfigManager::PALADIN_RANGE_ATTACK_DAMAGE_INCREASE_PERCENT) registerEnumIn("configKeys", ConfigManager::STATUSQUERY_TIMEOUT) registerEnumIn("configKeys", ConfigManager::WHITE_SKULL_TIME) registerEnumIn("configKeys", ConfigManager::RED_SKULL_TIME) registerEnumIn("configKeys", ConfigManager::KILLS_DAY_RED_SKULL) registerEnumIn("configKeys", ConfigManager::KILLS_WEEK_RED_SKULL) registerEnumIn("configKeys", ConfigManager::KILLS_MONTH_RED_SKULL) registerEnumIn("configKeys", ConfigManager::KILLS_DAY_BANISHMENT) registerEnumIn("configKeys", ConfigManager::KILLS_WEEK_BANISHMENT) registerEnumIn("configKeys", ConfigManager::KILLS_MONTH_BANISHMENT) registerEnumIn("configKeys", ConfigManager::GAME_PORT) registerEnumIn("configKeys", ConfigManager::LOGIN_PORT) registerEnumIn("configKeys", ConfigManager::STATUS_PORT) registerEnumIn("configKeys", ConfigManager::STAIRHOP_DELAY) registerEnumIn("configKeys", ConfigManager::EXP_FROM_PLAYERS_LEVEL_RANGE) registerEnumIn("configKeys", ConfigManager::MAX_PACKETS_PER_SECOND) registerEnumIn("configKeys", ConfigManager::NEWBIE_TOWN) registerEnumIn("configKeys", ConfigManager::NEWBIE_LEVEL_THRESHOLD) registerEnumIn("configKeys", ConfigManager::BLOCK_HEIGHT) registerEnumIn("configKeys", ConfigManager::DROP_ITEMS) registerEnumIn("configKeys", ConfigManager::CLIENT_VERSION) // os registerMethod("os", "mtime", LuaScriptInterface::luaSystemTime); // table registerMethod("table", "create", LuaScriptInterface::luaTableCreate); // Game registerTable("Game"); registerMethod("Game", "getSpectators", LuaScriptInterface::luaGameGetSpectators); registerMethod("Game", "getPlayers", LuaScriptInterface::luaGameGetPlayers); registerMethod("Game", "loadMap", LuaScriptInterface::luaGameLoadMap); registerMethod("Game", "getExperienceStage", LuaScriptInterface::luaGameGetExperienceStage); registerMethod("Game", "getMonsterCount", LuaScriptInterface::luaGameGetMonsterCount); registerMethod("Game", "getPlayerCount", LuaScriptInterface::luaGameGetPlayerCount); registerMethod("Game", "getNpcCount", LuaScriptInterface::luaGameGetNpcCount); registerMethod("Game", "getTowns", LuaScriptInterface::luaGameGetTowns); registerMethod("Game", "getHouses", LuaScriptInterface::luaGameGetHouses); registerMethod("Game", "getGameState", LuaScriptInterface::luaGameGetGameState); registerMethod("Game", "setGameState", LuaScriptInterface::luaGameSetGameState); registerMethod("Game", "getWorldType", LuaScriptInterface::luaGameGetWorldType); registerMethod("Game", "setWorldType", LuaScriptInterface::luaGameSetWorldType); registerMethod("Game", "getReturnMessage", LuaScriptInterface::luaGameGetReturnMessage); registerMethod("Game", "createItem", LuaScriptInterface::luaGameCreateItem); registerMethod("Game", "createContainer", LuaScriptInterface::luaGameCreateContainer); registerMethod("Game", "createMonster", LuaScriptInterface::luaGameCreateMonster); registerMethod("Game", "createNpc", LuaScriptInterface::luaGameCreateNpc); registerMethod("Game", "createTile", LuaScriptInterface::luaGameCreateTile); registerMethod("Game", "startRaid", LuaScriptInterface::luaGameStartRaid); registerMethod("Game", "reload", LuaScriptInterface::luaGameReload); // Variant registerClass("Variant", "", LuaScriptInterface::luaVariantCreate); registerMethod("Variant", "getNumber", LuaScriptInterface::luaVariantGetNumber); registerMethod("Variant", "getString", LuaScriptInterface::luaVariantGetString); registerMethod("Variant", "getPosition", LuaScriptInterface::luaVariantGetPosition); // Position registerClass("Position", "", LuaScriptInterface::luaPositionCreate); registerMetaMethod("Position", "__add", LuaScriptInterface::luaPositionAdd); registerMetaMethod("Position", "__sub", LuaScriptInterface::luaPositionSub); registerMetaMethod("Position", "__eq", LuaScriptInterface::luaPositionCompare); registerMethod("Position", "getDistance", LuaScriptInterface::luaPositionGetDistance); registerMethod("Position", "isSightClear", LuaScriptInterface::luaPositionIsSightClear); registerMethod("Position", "sendMagicEffect", LuaScriptInterface::luaPositionSendMagicEffect); registerMethod("Position", "sendDistanceEffect", LuaScriptInterface::luaPositionSendDistanceEffect); registerMethod("Position", "sendMonsterSay", LuaScriptInterface::luaPositionSendMonsterSay); // Tile registerClass("Tile", "", LuaScriptInterface::luaTileCreate); registerMetaMethod("Tile", "__eq", LuaScriptInterface::luaUserdataCompare); registerMethod("Tile", "getPosition", LuaScriptInterface::luaTileGetPosition); registerMethod("Tile", "getGround", LuaScriptInterface::luaTileGetGround); registerMethod("Tile", "getThing", LuaScriptInterface::luaTileGetThing); registerMethod("Tile", "getThingCount", LuaScriptInterface::luaTileGetThingCount); registerMethod("Tile", "getTopVisibleThing", LuaScriptInterface::luaTileGetTopVisibleThing); registerMethod("Tile", "getTopTopItem", LuaScriptInterface::luaTileGetTopTopItem); registerMethod("Tile", "getTopDownItem", LuaScriptInterface::luaTileGetTopDownItem); registerMethod("Tile", "getFieldItem", LuaScriptInterface::luaTileGetFieldItem); registerMethod("Tile", "getItemById", LuaScriptInterface::luaTileGetItemById); registerMethod("Tile", "getItemByType", LuaScriptInterface::luaTileGetItemByType); registerMethod("Tile", "getItemByTopOrder", LuaScriptInterface::luaTileGetItemByTopOrder); registerMethod("Tile", "getItemCountById", LuaScriptInterface::luaTileGetItemCountById); registerMethod("Tile", "getBottomCreature", LuaScriptInterface::luaTileGetBottomCreature); registerMethod("Tile", "getTopCreature", LuaScriptInterface::luaTileGetTopCreature); registerMethod("Tile", "getBottomVisibleCreature", LuaScriptInterface::luaTileGetBottomVisibleCreature); registerMethod("Tile", "getTopVisibleCreature", LuaScriptInterface::luaTileGetTopVisibleCreature); registerMethod("Tile", "getItems", LuaScriptInterface::luaTileGetItems); registerMethod("Tile", "getItemCount", LuaScriptInterface::luaTileGetItemCount); registerMethod("Tile", "getDownItemCount", LuaScriptInterface::luaTileGetDownItemCount); registerMethod("Tile", "getTopItemCount", LuaScriptInterface::luaTileGetTopItemCount); registerMethod("Tile", "getCreatures", LuaScriptInterface::luaTileGetCreatures); registerMethod("Tile", "getCreatureCount", LuaScriptInterface::luaTileGetCreatureCount); registerMethod("Tile", "getThingIndex", LuaScriptInterface::luaTileGetThingIndex); registerMethod("Tile", "hasProperty", LuaScriptInterface::luaTileHasProperty); registerMethod("Tile", "hasFlag", LuaScriptInterface::luaTileHasFlag); registerMethod("Tile", "queryAdd", LuaScriptInterface::luaTileQueryAdd); registerMethod("Tile", "getHouse", LuaScriptInterface::luaTileGetHouse); // NetworkMessage registerClass("NetworkMessage", "", LuaScriptInterface::luaNetworkMessageCreate); registerMetaMethod("NetworkMessage", "__eq", LuaScriptInterface::luaUserdataCompare); registerMetaMethod("NetworkMessage", "__gc", LuaScriptInterface::luaNetworkMessageDelete); registerMethod("NetworkMessage", "delete", LuaScriptInterface::luaNetworkMessageDelete); registerMethod("NetworkMessage", "getByte", LuaScriptInterface::luaNetworkMessageGetByte); registerMethod("NetworkMessage", "getU16", LuaScriptInterface::luaNetworkMessageGetU16); registerMethod("NetworkMessage", "getU32", LuaScriptInterface::luaNetworkMessageGetU32); registerMethod("NetworkMessage", "getU64", LuaScriptInterface::luaNetworkMessageGetU64); registerMethod("NetworkMessage", "getString", LuaScriptInterface::luaNetworkMessageGetString); registerMethod("NetworkMessage", "getPosition", LuaScriptInterface::luaNetworkMessageGetPosition); registerMethod("NetworkMessage", "addByte", LuaScriptInterface::luaNetworkMessageAddByte); registerMethod("NetworkMessage", "addU16", LuaScriptInterface::luaNetworkMessageAddU16); registerMethod("NetworkMessage", "addU32", LuaScriptInterface::luaNetworkMessageAddU32); registerMethod("NetworkMessage", "addU64", LuaScriptInterface::luaNetworkMessageAddU64); registerMethod("NetworkMessage", "addString", LuaScriptInterface::luaNetworkMessageAddString); registerMethod("NetworkMessage", "addPosition", LuaScriptInterface::luaNetworkMessageAddPosition); registerMethod("NetworkMessage", "addDouble", LuaScriptInterface::luaNetworkMessageAddDouble); registerMethod("NetworkMessage", "addItem", LuaScriptInterface::luaNetworkMessageAddItem); registerMethod("NetworkMessage", "addItemId", LuaScriptInterface::luaNetworkMessageAddItemId); registerMethod("NetworkMessage", "reset", LuaScriptInterface::luaNetworkMessageReset); registerMethod("NetworkMessage", "skipBytes", LuaScriptInterface::luaNetworkMessageSkipBytes); registerMethod("NetworkMessage", "sendToPlayer", LuaScriptInterface::luaNetworkMessageSendToPlayer); // Item registerClass("Item", "", LuaScriptInterface::luaItemCreate); registerMetaMethod("Item", "__eq", LuaScriptInterface::luaUserdataCompare); registerMethod("Item", "isItem", LuaScriptInterface::luaItemIsItem); registerMethod("Item", "getParent", LuaScriptInterface::luaItemGetParent); registerMethod("Item", "getTopParent", LuaScriptInterface::luaItemGetTopParent); registerMethod("Item", "getId", LuaScriptInterface::luaItemGetId); registerMethod("Item", "clone", LuaScriptInterface::luaItemClone); registerMethod("Item", "split", LuaScriptInterface::luaItemSplit); registerMethod("Item", "remove", LuaScriptInterface::luaItemRemove); registerMethod("Item", "getMovementId", LuaScriptInterface::luaItemGetMovementId); registerMethod("Item", "setMovementId", LuaScriptInterface::luaItemSetMovementId); registerMethod("Item", "getActionId", LuaScriptInterface::luaItemGetActionId); registerMethod("Item", "setActionId", LuaScriptInterface::luaItemSetActionId); registerMethod("Item", "getUniqueId", LuaScriptInterface::luaItemGetUniqueId); registerMethod("Item", "getCount", LuaScriptInterface::luaItemGetCount); registerMethod("Item", "getCharges", LuaScriptInterface::luaItemGetCharges); registerMethod("Item", "getFluidType", LuaScriptInterface::luaItemGetFluidType); registerMethod("Item", "getWeight", LuaScriptInterface::luaItemGetWeight); registerMethod("Item", "getSubType", LuaScriptInterface::luaItemGetSubType); registerMethod("Item", "getName", LuaScriptInterface::luaItemGetName); registerMethod("Item", "getPluralName", LuaScriptInterface::luaItemGetPluralName); registerMethod("Item", "getArticle", LuaScriptInterface::luaItemGetArticle); registerMethod("Item", "getPosition", LuaScriptInterface::luaItemGetPosition); registerMethod("Item", "getTile", LuaScriptInterface::luaItemGetTile); registerMethod("Item", "hasAttribute", LuaScriptInterface::luaItemHasAttribute); registerMethod("Item", "getAttribute", LuaScriptInterface::luaItemGetAttribute); registerMethod("Item", "setAttribute", LuaScriptInterface::luaItemSetAttribute); registerMethod("Item", "removeAttribute", LuaScriptInterface::luaItemRemoveAttribute); registerMethod("Item", "moveTo", LuaScriptInterface::luaItemMoveTo); registerMethod("Item", "transform", LuaScriptInterface::luaItemTransform); registerMethod("Item", "decay", LuaScriptInterface::luaItemDecay); registerMethod("Item", "getDescription", LuaScriptInterface::luaItemGetDescription); registerMethod("Item", "hasProperty", LuaScriptInterface::luaItemHasProperty); // Container registerClass("Container", "Item", LuaScriptInterface::luaContainerCreate); registerMetaMethod("Container", "__eq", LuaScriptInterface::luaUserdataCompare); registerMethod("Container", "getSize", LuaScriptInterface::luaContainerGetSize); registerMethod("Container", "getCapacity", LuaScriptInterface::luaContainerGetCapacity); registerMethod("Container", "getEmptySlots", LuaScriptInterface::luaContainerGetEmptySlots); registerMethod("Container", "getItemHoldingCount", LuaScriptInterface::luaContainerGetItemHoldingCount); registerMethod("Container", "getItemCountById", LuaScriptInterface::luaContainerGetItemCountById); registerMethod("Container", "getItem", LuaScriptInterface::luaContainerGetItem); registerMethod("Container", "hasItem", LuaScriptInterface::luaContainerHasItem); registerMethod("Container", "addItem", LuaScriptInterface::luaContainerAddItem); registerMethod("Container", "addItemEx", LuaScriptInterface::luaContainerAddItemEx); // Teleport registerClass("Teleport", "Item", LuaScriptInterface::luaTeleportCreate); registerMetaMethod("Teleport", "__eq", LuaScriptInterface::luaUserdataCompare); registerMethod("Teleport", "getDestination", LuaScriptInterface::luaTeleportGetDestination); registerMethod("Teleport", "setDestination", LuaScriptInterface::luaTeleportSetDestination); // Creature registerClass("Creature", "", LuaScriptInterface::luaCreatureCreate); registerMetaMethod("Creature", "__eq", LuaScriptInterface::luaUserdataCompare); registerMethod("Creature", "getEvents", LuaScriptInterface::luaCreatureGetEvents); registerMethod("Creature", "registerEvent", LuaScriptInterface::luaCreatureRegisterEvent); registerMethod("Creature", "unregisterEvent", LuaScriptInterface::luaCreatureUnregisterEvent); registerMethod("Creature", "isRemoved", LuaScriptInterface::luaCreatureIsRemoved); registerMethod("Creature", "isCreature", LuaScriptInterface::luaCreatureIsCreature); registerMethod("Creature", "isInGhostMode", LuaScriptInterface::luaCreatureIsInGhostMode); registerMethod("Creature", "canSee", LuaScriptInterface::luaCreatureCanSee); registerMethod("Creature", "canSeeCreature", LuaScriptInterface::luaCreatureCanSeeCreature); registerMethod("Creature", "getParent", LuaScriptInterface::luaCreatureGetParent); registerMethod("Creature", "getId", LuaScriptInterface::luaCreatureGetId); registerMethod("Creature", "getName", LuaScriptInterface::luaCreatureGetName); registerMethod("Creature", "getTarget", LuaScriptInterface::luaCreatureGetTarget); registerMethod("Creature", "setTarget", LuaScriptInterface::luaCreatureSetTarget); registerMethod("Creature", "getFollowCreature", LuaScriptInterface::luaCreatureGetFollowCreature); registerMethod("Creature", "setFollowCreature", LuaScriptInterface::luaCreatureSetFollowCreature); registerMethod("Creature", "getMaster", LuaScriptInterface::luaCreatureGetMaster); registerMethod("Creature", "setMaster", LuaScriptInterface::luaCreatureSetMaster); registerMethod("Creature", "getLight", LuaScriptInterface::luaCreatureGetLight); registerMethod("Creature", "setLight", LuaScriptInterface::luaCreatureSetLight); registerMethod("Creature", "getSpeed", LuaScriptInterface::luaCreatureGetSpeed); registerMethod("Creature", "getBaseSpeed", LuaScriptInterface::luaCreatureGetBaseSpeed); registerMethod("Creature", "changeSpeed", LuaScriptInterface::luaCreatureChangeSpeed); registerMethod("Creature", "setDropLoot", LuaScriptInterface::luaCreatureSetDropLoot); registerMethod("Creature", "getPosition", LuaScriptInterface::luaCreatureGetPosition); registerMethod("Creature", "getTile", LuaScriptInterface::luaCreatureGetTile); registerMethod("Creature", "getDirection", LuaScriptInterface::luaCreatureGetDirection); registerMethod("Creature", "setDirection", LuaScriptInterface::luaCreatureSetDirection); registerMethod("Creature", "getHealth", LuaScriptInterface::luaCreatureGetHealth); registerMethod("Creature", "addHealth", LuaScriptInterface::luaCreatureAddHealth); registerMethod("Creature", "getMaxHealth", LuaScriptInterface::luaCreatureGetMaxHealth); registerMethod("Creature", "setMaxHealth", LuaScriptInterface::luaCreatureSetMaxHealth); registerMethod("Creature", "setHiddenHealth", LuaScriptInterface::luaCreatureSetHiddenHealth); registerMethod("Creature", "getSkull", LuaScriptInterface::luaCreatureGetSkull); registerMethod("Creature", "setSkull", LuaScriptInterface::luaCreatureSetSkull); registerMethod("Creature", "getOutfit", LuaScriptInterface::luaCreatureGetOutfit); registerMethod("Creature", "setOutfit", LuaScriptInterface::luaCreatureSetOutfit); registerMethod("Creature", "getCondition", LuaScriptInterface::luaCreatureGetCondition); registerMethod("Creature", "addCondition", LuaScriptInterface::luaCreatureAddCondition); registerMethod("Creature", "removeCondition", LuaScriptInterface::luaCreatureRemoveCondition); registerMethod("Creature", "remove", LuaScriptInterface::luaCreatureRemove); registerMethod("Creature", "teleportTo", LuaScriptInterface::luaCreatureTeleportTo); registerMethod("Creature", "say", LuaScriptInterface::luaCreatureSay); registerMethod("Creature", "getDamageMap", LuaScriptInterface::luaCreatureGetDamageMap); registerMethod("Creature", "getSummons", LuaScriptInterface::luaCreatureGetSummons); registerMethod("Creature", "getDescription", LuaScriptInterface::luaCreatureGetDescription); registerMethod("Creature", "getPathTo", LuaScriptInterface::luaCreatureGetPathTo); // Player registerClass("Player", "Creature", LuaScriptInterface::luaPlayerCreate); registerMetaMethod("Player", "__eq", LuaScriptInterface::luaUserdataCompare); registerMethod("Player", "isPlayer", LuaScriptInterface::luaPlayerIsPlayer); registerMethod("Player", "getGuid", LuaScriptInterface::luaPlayerGetGuid); registerMethod("Player", "getIp", LuaScriptInterface::luaPlayerGetIp); registerMethod("Player", "getAccountId", LuaScriptInterface::luaPlayerGetAccountId); registerMethod("Player", "getLastLoginSaved", LuaScriptInterface::luaPlayerGetLastLoginSaved); registerMethod("Player", "getLastLogout", LuaScriptInterface::luaPlayerGetLastLogout); registerMethod("Player", "hasFlag", LuaScriptInterface::luaPlayerHasFlag); registerMethod("Player", "getAccountType", LuaScriptInterface::luaPlayerGetAccountType); registerMethod("Player", "setAccountType", LuaScriptInterface::luaPlayerSetAccountType); registerMethod("Player", "getCapacity", LuaScriptInterface::luaPlayerGetCapacity); registerMethod("Player", "setCapacity", LuaScriptInterface::luaPlayerSetCapacity); registerMethod("Player", "getFreeCapacity", LuaScriptInterface::luaPlayerGetFreeCapacity); registerMethod("Player", "getDepotChest", LuaScriptInterface::luaPlayerGetDepotChest); registerMethod("Player", "getMurderTimestamps", LuaScriptInterface::luaPlayerGetMurderTimestamps); registerMethod("Player", "getPlayerKillerEnd", LuaScriptInterface::luaPlayerGetPlayerKillerEnd); registerMethod("Player", "setPlayerKillerEnd", LuaScriptInterface::luaPlayerSetPlayerKillerEnd); registerMethod("Player", "getDeathPenalty", LuaScriptInterface::luaPlayerGetDeathPenalty); registerMethod("Player", "getExperience", LuaScriptInterface::luaPlayerGetExperience); registerMethod("Player", "addExperience", LuaScriptInterface::luaPlayerAddExperience); registerMethod("Player", "removeExperience", LuaScriptInterface::luaPlayerRemoveExperience); registerMethod("Player", "getLevel", LuaScriptInterface::luaPlayerGetLevel); registerMethod("Player", "getMagicLevel", LuaScriptInterface::luaPlayerGetMagicLevel); registerMethod("Player", "getBaseMagicLevel", LuaScriptInterface::luaPlayerGetBaseMagicLevel); registerMethod("Player", "getMana", LuaScriptInterface::luaPlayerGetMana); registerMethod("Player", "addMana", LuaScriptInterface::luaPlayerAddMana); registerMethod("Player", "getMaxMana", LuaScriptInterface::luaPlayerGetMaxMana); registerMethod("Player", "setMaxMana", LuaScriptInterface::luaPlayerSetMaxMana); registerMethod("Player", "getManaSpent", LuaScriptInterface::luaPlayerGetManaSpent); registerMethod("Player", "addManaSpent", LuaScriptInterface::luaPlayerAddManaSpent); registerMethod("Player", "getBaseMaxHealth", LuaScriptInterface::luaPlayerGetBaseMaxHealth); registerMethod("Player", "getBaseMaxMana", LuaScriptInterface::luaPlayerGetBaseMaxMana); registerMethod("Player", "getSkillLevel", LuaScriptInterface::luaPlayerGetSkillLevel); registerMethod("Player", "getEffectiveSkillLevel", LuaScriptInterface::luaPlayerGetEffectiveSkillLevel); registerMethod("Player", "getSkillPercent", LuaScriptInterface::luaPlayerGetSkillPercent); registerMethod("Player", "getSkillTries", LuaScriptInterface::luaPlayerGetSkillTries); registerMethod("Player", "addSkillTries", LuaScriptInterface::luaPlayerAddSkillTries); registerMethod("Player", "getItemCount", LuaScriptInterface::luaPlayerGetItemCount); registerMethod("Player", "getItemById", LuaScriptInterface::luaPlayerGetItemById); registerMethod("Player", "getVocation", LuaScriptInterface::luaPlayerGetVocation); registerMethod("Player", "setVocation", LuaScriptInterface::luaPlayerSetVocation); registerMethod("Player", "getSex", LuaScriptInterface::luaPlayerGetSex); registerMethod("Player", "setSex", LuaScriptInterface::luaPlayerSetSex); registerMethod("Player", "getTown", LuaScriptInterface::luaPlayerGetTown); registerMethod("Player", "setTown", LuaScriptInterface::luaPlayerSetTown); registerMethod("Player", "getGuild", LuaScriptInterface::luaPlayerGetGuild); registerMethod("Player", "setGuild", LuaScriptInterface::luaPlayerSetGuild); registerMethod("Player", "getGuildLevel", LuaScriptInterface::luaPlayerGetGuildLevel); registerMethod("Player", "setGuildLevel", LuaScriptInterface::luaPlayerSetGuildLevel); registerMethod("Player", "getGuildNick", LuaScriptInterface::luaPlayerGetGuildNick); registerMethod("Player", "setGuildNick", LuaScriptInterface::luaPlayerSetGuildNick); registerMethod("Player", "getGroup", LuaScriptInterface::luaPlayerGetGroup); registerMethod("Player", "setGroup", LuaScriptInterface::luaPlayerSetGroup); registerMethod("Player", "getStamina", LuaScriptInterface::luaPlayerGetStamina); registerMethod("Player", "setStamina", LuaScriptInterface::luaPlayerSetStamina); registerMethod("Player", "getSoul", LuaScriptInterface::luaPlayerGetSoul); registerMethod("Player", "addSoul", LuaScriptInterface::luaPlayerAddSoul); registerMethod("Player", "getMaxSoul", LuaScriptInterface::luaPlayerGetMaxSoul); registerMethod("Player", "getBankBalance", LuaScriptInterface::luaPlayerGetBankBalance); registerMethod("Player", "setBankBalance", LuaScriptInterface::luaPlayerSetBankBalance); registerMethod("Player", "getStorageValue", LuaScriptInterface::luaPlayerGetStorageValue); registerMethod("Player", "setStorageValue", LuaScriptInterface::luaPlayerSetStorageValue); registerMethod("Player", "addItem", LuaScriptInterface::luaPlayerAddItem); registerMethod("Player", "addItemEx", LuaScriptInterface::luaPlayerAddItemEx); registerMethod("Player", "removeItem", LuaScriptInterface::luaPlayerRemoveItem); registerMethod("Player", "getMoney", LuaScriptInterface::luaPlayerGetMoney); registerMethod("Player", "addMoney", LuaScriptInterface::luaPlayerAddMoney); registerMethod("Player", "removeMoney", LuaScriptInterface::luaPlayerRemoveMoney); registerMethod("Player", "showTextDialog", LuaScriptInterface::luaPlayerShowTextDialog); registerMethod("Player", "sendTextMessage", LuaScriptInterface::luaPlayerSendTextMessage); registerMethod("Player", "sendPrivateMessage", LuaScriptInterface::luaPlayerSendPrivateMessage); registerMethod("Player", "channelSay", LuaScriptInterface::luaPlayerChannelSay); registerMethod("Player", "openChannel", LuaScriptInterface::luaPlayerOpenChannel); registerMethod("Player", "getSlotItem", LuaScriptInterface::luaPlayerGetSlotItem); registerMethod("Player", "getParty", LuaScriptInterface::luaPlayerGetParty); registerMethod("Player", "addOutfit", LuaScriptInterface::luaPlayerAddOutfit); registerMethod("Player", "addOutfitAddon", LuaScriptInterface::luaPlayerAddOutfitAddon); registerMethod("Player", "removeOutfit", LuaScriptInterface::luaPlayerRemoveOutfit); registerMethod("Player", "removeOutfitAddon", LuaScriptInterface::luaPlayerRemoveOutfitAddon); registerMethod("Player", "hasOutfit", LuaScriptInterface::luaPlayerHasOutfit); registerMethod("Player", "sendOutfitWindow", LuaScriptInterface::luaPlayerSendOutfitWindow); registerMethod("Player", "getPremiumDays", LuaScriptInterface::luaPlayerGetPremiumDays); registerMethod("Player", "addPremiumDays", LuaScriptInterface::luaPlayerAddPremiumDays); registerMethod("Player", "removePremiumDays", LuaScriptInterface::luaPlayerRemovePremiumDays); registerMethod("Player", "hasBlessing", LuaScriptInterface::luaPlayerHasBlessing); registerMethod("Player", "addBlessing", LuaScriptInterface::luaPlayerAddBlessing); registerMethod("Player", "removeBlessing", LuaScriptInterface::luaPlayerRemoveBlessing); registerMethod("Player", "canLearnSpell", LuaScriptInterface::luaPlayerCanLearnSpell); registerMethod("Player", "learnSpell", LuaScriptInterface::luaPlayerLearnSpell); registerMethod("Player", "forgetSpell", LuaScriptInterface::luaPlayerForgetSpell); registerMethod("Player", "hasLearnedSpell", LuaScriptInterface::luaPlayerHasLearnedSpell); registerMethod("Player", "save", LuaScriptInterface::luaPlayerSave); registerMethod("Player", "isPzLocked", LuaScriptInterface::luaPlayerIsPzLocked); registerMethod("Player", "getClient", LuaScriptInterface::luaPlayerGetClient); registerMethod("Player", "getHouse", LuaScriptInterface::luaPlayerGetHouse); registerMethod("Player", "setGhostMode", LuaScriptInterface::luaPlayerSetGhostMode); registerMethod("Player", "getContainerId", LuaScriptInterface::luaPlayerGetContainerId); registerMethod("Player", "getContainerById", LuaScriptInterface::luaPlayerGetContainerById); registerMethod("Player", "getContainerIndex", LuaScriptInterface::luaPlayerGetContainerIndex); registerMethod("Player", "getTotalDamage", LuaScriptInterface::luaPlayerGetTotalDamage); // Monster registerClass("Monster", "Creature", LuaScriptInterface::luaMonsterCreate); registerMetaMethod("Monster", "__eq", LuaScriptInterface::luaUserdataCompare); registerMethod("Monster", "isMonster", LuaScriptInterface::luaMonsterIsMonster); registerMethod("Monster", "getType", LuaScriptInterface::luaMonsterGetType); registerMethod("Monster", "getSpawnPosition", LuaScriptInterface::luaMonsterGetSpawnPosition); registerMethod("Monster", "isInSpawnRange", LuaScriptInterface::luaMonsterIsInSpawnRange); registerMethod("Monster", "isIdle", LuaScriptInterface::luaMonsterIsIdle); registerMethod("Monster", "setIdle", LuaScriptInterface::luaMonsterSetIdle); registerMethod("Monster", "isTarget", LuaScriptInterface::luaMonsterIsTarget); registerMethod("Monster", "isOpponent", LuaScriptInterface::luaMonsterIsOpponent); registerMethod("Monster", "isFriend", LuaScriptInterface::luaMonsterIsFriend); registerMethod("Monster", "addFriend", LuaScriptInterface::luaMonsterAddFriend); registerMethod("Monster", "removeFriend", LuaScriptInterface::luaMonsterRemoveFriend); registerMethod("Monster", "getFriendList", LuaScriptInterface::luaMonsterGetFriendList); registerMethod("Monster", "getFriendCount", LuaScriptInterface::luaMonsterGetFriendCount); registerMethod("Monster", "addTarget", LuaScriptInterface::luaMonsterAddTarget); registerMethod("Monster", "removeTarget", LuaScriptInterface::luaMonsterRemoveTarget); registerMethod("Monster", "getTargetList", LuaScriptInterface::luaMonsterGetTargetList); registerMethod("Monster", "getTargetCount", LuaScriptInterface::luaMonsterGetTargetCount); registerMethod("Monster", "selectTarget", LuaScriptInterface::luaMonsterSelectTarget); registerMethod("Monster", "searchTarget", LuaScriptInterface::luaMonsterSearchTarget); // Npc registerClass("Npc", "Creature", LuaScriptInterface::luaNpcCreate); registerMetaMethod("Npc", "__eq", LuaScriptInterface::luaUserdataCompare); registerMethod("Npc", "isNpc", LuaScriptInterface::luaNpcIsNpc); registerMethod("Npc", "setMasterPos", LuaScriptInterface::luaNpcSetMasterPos); // Guild registerClass("Guild", "", LuaScriptInterface::luaGuildCreate); registerMetaMethod("Guild", "__eq", LuaScriptInterface::luaUserdataCompare); registerMethod("Guild", "getId", LuaScriptInterface::luaGuildGetId); registerMethod("Guild", "getName", LuaScriptInterface::luaGuildGetName); registerMethod("Guild", "getMembersOnline", LuaScriptInterface::luaGuildGetMembersOnline); registerMethod("Guild", "addRank", LuaScriptInterface::luaGuildAddRank); registerMethod("Guild", "getRankById", LuaScriptInterface::luaGuildGetRankById); registerMethod("Guild", "getRankByLevel", LuaScriptInterface::luaGuildGetRankByLevel); // Group registerClass("Group", "", LuaScriptInterface::luaGroupCreate); registerMetaMethod("Group", "__eq", LuaScriptInterface::luaUserdataCompare); registerMethod("Group", "getId", LuaScriptInterface::luaGroupGetId); registerMethod("Group", "getName", LuaScriptInterface::luaGroupGetName); registerMethod("Group", "getFlags", LuaScriptInterface::luaGroupGetFlags); registerMethod("Group", "getAccess", LuaScriptInterface::luaGroupGetAccess); registerMethod("Group", "getMaxDepotItems", LuaScriptInterface::luaGroupGetMaxDepotItems); registerMethod("Group", "getMaxVipEntries", LuaScriptInterface::luaGroupGetMaxVipEntries); // Vocation registerClass("Vocation", "", LuaScriptInterface::luaVocationCreate); registerMetaMethod("Vocation", "__eq", LuaScriptInterface::luaUserdataCompare); registerMethod("Vocation", "getId", LuaScriptInterface::luaVocationGetId); registerMethod("Vocation", "getName", LuaScriptInterface::luaVocationGetName); registerMethod("Vocation", "getDescription", LuaScriptInterface::luaVocationGetDescription); registerMethod("Vocation", "getRequiredSkillTries", LuaScriptInterface::luaVocationGetRequiredSkillTries); registerMethod("Vocation", "getRequiredManaSpent", LuaScriptInterface::luaVocationGetRequiredManaSpent); registerMethod("Vocation", "getCapacityGain", LuaScriptInterface::luaVocationGetCapacityGain); registerMethod("Vocation", "getHealthGain", LuaScriptInterface::luaVocationGetHealthGain); registerMethod("Vocation", "getHealthGainTicks", LuaScriptInterface::luaVocationGetHealthGainTicks); registerMethod("Vocation", "getHealthGainAmount", LuaScriptInterface::luaVocationGetHealthGainAmount); registerMethod("Vocation", "getManaGain", LuaScriptInterface::luaVocationGetManaGain); registerMethod("Vocation", "getManaGainTicks", LuaScriptInterface::luaVocationGetManaGainTicks); registerMethod("Vocation", "getManaGainAmount", LuaScriptInterface::luaVocationGetManaGainAmount); registerMethod("Vocation", "getMaxSoul", LuaScriptInterface::luaVocationGetMaxSoul); registerMethod("Vocation", "getSoulGainTicks", LuaScriptInterface::luaVocationGetSoulGainTicks); registerMethod("Vocation", "getAttackSpeed", LuaScriptInterface::luaVocationGetAttackSpeed); registerMethod("Vocation", "getBaseSpeed", LuaScriptInterface::luaVocationGetBaseSpeed); registerMethod("Vocation", "getDemotion", LuaScriptInterface::luaVocationGetDemotion); registerMethod("Vocation", "getPromotion", LuaScriptInterface::luaVocationGetPromotion); // Town registerClass("Town", "", LuaScriptInterface::luaTownCreate); registerMetaMethod("Town", "__eq", LuaScriptInterface::luaUserdataCompare); registerMethod("Town", "getId", LuaScriptInterface::luaTownGetId); registerMethod("Town", "getName", LuaScriptInterface::luaTownGetName); registerMethod("Town", "getTemplePosition", LuaScriptInterface::luaTownGetTemplePosition); // House registerClass("House", "", LuaScriptInterface::luaHouseCreate); registerMetaMethod("House", "__eq", LuaScriptInterface::luaUserdataCompare); registerMethod("House", "getId", LuaScriptInterface::luaHouseGetId); registerMethod("House", "getName", LuaScriptInterface::luaHouseGetName); registerMethod("House", "getTown", LuaScriptInterface::luaHouseGetTown); registerMethod("House", "getExitPosition", LuaScriptInterface::luaHouseGetExitPosition); registerMethod("House", "getRent", LuaScriptInterface::luaHouseGetRent); registerMethod("House", "getOwnerGuid", LuaScriptInterface::luaHouseGetOwnerGuid); registerMethod("House", "setOwnerGuid", LuaScriptInterface::luaHouseSetOwnerGuid); registerMethod("House", "startTrade", LuaScriptInterface::luaHouseStartTrade); registerMethod("House", "getBeds", LuaScriptInterface::luaHouseGetBeds); registerMethod("House", "getBedCount", LuaScriptInterface::luaHouseGetBedCount); registerMethod("House", "getDoors", LuaScriptInterface::luaHouseGetDoors); registerMethod("House", "getDoorCount", LuaScriptInterface::luaHouseGetDoorCount); registerMethod("House", "getTiles", LuaScriptInterface::luaHouseGetTiles); registerMethod("House", "getTileCount", LuaScriptInterface::luaHouseGetTileCount); registerMethod("House", "getAccessList", LuaScriptInterface::luaHouseGetAccessList); registerMethod("House", "setAccessList", LuaScriptInterface::luaHouseSetAccessList); // ItemType registerClass("ItemType", "", LuaScriptInterface::luaItemTypeCreate); registerMetaMethod("ItemType", "__eq", LuaScriptInterface::luaUserdataCompare); registerMethod("ItemType", "isCorpse", LuaScriptInterface::luaItemTypeIsCorpse); registerMethod("ItemType", "isDoor", LuaScriptInterface::luaItemTypeIsDoor); registerMethod("ItemType", "isContainer", LuaScriptInterface::luaItemTypeIsContainer); registerMethod("ItemType", "isChest", LuaScriptInterface::luaItemTypeIsChest); registerMethod("ItemType", "isFluidContainer", LuaScriptInterface::luaItemTypeIsFluidContainer); registerMethod("ItemType", "isMovable", LuaScriptInterface::luaItemTypeIsMovable); registerMethod("ItemType", "isRune", LuaScriptInterface::luaItemTypeIsRune); registerMethod("ItemType", "isStackable", LuaScriptInterface::luaItemTypeIsStackable); registerMethod("ItemType", "isReadable", LuaScriptInterface::luaItemTypeIsReadable); registerMethod("ItemType", "isWritable", LuaScriptInterface::luaItemTypeIsWritable); registerMethod("ItemType", "isMagicField", LuaScriptInterface::luaItemTypeIsMagicField); registerMethod("ItemType", "isSplash", LuaScriptInterface::luaItemTypeIsSplash); registerMethod("ItemType", "isKey", LuaScriptInterface::luaItemTypeIsKey); registerMethod("ItemType", "isDisguised", LuaScriptInterface::luaItemTypeIsDisguised); registerMethod("ItemType", "isDestroyable", LuaScriptInterface::luaItemTypeIsDestroyable); registerMethod("ItemType", "isGroundTile", LuaScriptInterface::luaItemTypeIsGroundTile); registerMethod("ItemType", "getType", LuaScriptInterface::luaItemTypeGetType); registerMethod("ItemType", "getId", LuaScriptInterface::luaItemTypeGetId); registerMethod("ItemType", "getDisguiseId", LuaScriptInterface::luaItemTypeGetDisguiseId); registerMethod("ItemType", "getName", LuaScriptInterface::luaItemTypeGetName); registerMethod("ItemType", "getPluralName", LuaScriptInterface::luaItemTypeGetPluralName); registerMethod("ItemType", "getArticle", LuaScriptInterface::luaItemTypeGetArticle); registerMethod("ItemType", "getDescription", LuaScriptInterface::luaItemTypeGetDescription); registerMethod("ItemType", "getSlotPosition", LuaScriptInterface::luaItemTypeGetSlotPosition); registerMethod("ItemType", "getDestroyTarget", LuaScriptInterface::luaItemTypeGetDestroyTarget); registerMethod("ItemType", "getCharges", LuaScriptInterface::luaItemTypeGetCharges); registerMethod("ItemType", "getFluidSource", LuaScriptInterface::luaItemTypeGetFluidSource); registerMethod("ItemType", "getCapacity", LuaScriptInterface::luaItemTypeGetCapacity); registerMethod("ItemType", "getWeight", LuaScriptInterface::luaItemTypeGetWeight); registerMethod("ItemType", "getShootRange", LuaScriptInterface::luaItemTypeGetShootRange); registerMethod("ItemType", "getAttack", LuaScriptInterface::luaItemTypeGetAttack); registerMethod("ItemType", "getDefense", LuaScriptInterface::luaItemTypeGetDefense); registerMethod("ItemType", "getArmor", LuaScriptInterface::luaItemTypeGetArmor); registerMethod("ItemType", "getWeaponType", LuaScriptInterface::luaItemTypeGetWeaponType); registerMethod("ItemType", "getTransformEquipId", LuaScriptInterface::luaItemTypeGetTransformEquipId); registerMethod("ItemType", "getTransformDeEquipId", LuaScriptInterface::luaItemTypeGetTransformDeEquipId); registerMethod("ItemType", "getDecayId", LuaScriptInterface::luaItemTypeGetDecayId); registerMethod("ItemType", "getNutrition", LuaScriptInterface::luaItemTypeGetNutrition); registerMethod("ItemType", "getRequiredLevel", LuaScriptInterface::luaItemTypeGetRequiredLevel); registerMethod("ItemType", "hasSubType", LuaScriptInterface::luaItemTypeHasSubType); // Combat registerClass("Combat", "", LuaScriptInterface::luaCombatCreate); registerMetaMethod("Combat", "__eq", LuaScriptInterface::luaUserdataCompare); registerMethod("Combat", "setParameter", LuaScriptInterface::luaCombatSetParameter); registerMethod("Combat", "setFormula", LuaScriptInterface::luaCombatSetFormula); registerMethod("Combat", "setArea", LuaScriptInterface::luaCombatSetArea); registerMethod("Combat", "setCondition", LuaScriptInterface::luaCombatSetCondition); registerMethod("Combat", "setCallback", LuaScriptInterface::luaCombatSetCallback); registerMethod("Combat", "setOrigin", LuaScriptInterface::luaCombatSetOrigin); registerMethod("Combat", "execute", LuaScriptInterface::luaCombatExecute); // Condition registerClass("Condition", "", LuaScriptInterface::luaConditionCreate); registerMetaMethod("Condition", "__eq", LuaScriptInterface::luaUserdataCompare); registerMetaMethod("Condition", "__gc", LuaScriptInterface::luaConditionDelete); registerMethod("Condition", "delete", LuaScriptInterface::luaConditionDelete); registerMethod("Condition", "getId", LuaScriptInterface::luaConditionGetId); registerMethod("Condition", "getSubId", LuaScriptInterface::luaConditionGetSubId); registerMethod("Condition", "getType", LuaScriptInterface::luaConditionGetType); registerMethod("Condition", "getIcons", LuaScriptInterface::luaConditionGetIcons); registerMethod("Condition", "getEndTime", LuaScriptInterface::luaConditionGetEndTime); registerMethod("Condition", "clone", LuaScriptInterface::luaConditionClone); registerMethod("Condition", "getTicks", LuaScriptInterface::luaConditionGetTicks); registerMethod("Condition", "setTicks", LuaScriptInterface::luaConditionSetTicks); registerMethod("Condition", "setParameter", LuaScriptInterface::luaConditionSetParameter); registerMethod("Condition", "setSpeedDelta", LuaScriptInterface::luaConditionSetSpeedDelta); registerMethod("Condition", "setOutfit", LuaScriptInterface::luaConditionSetOutfit); registerMethod("Condition", "setTiming", LuaScriptInterface::luaConditionSetTiming); // MonsterType registerClass("MonsterType", "", LuaScriptInterface::luaMonsterTypeCreate); registerMetaMethod("MonsterType", "__eq", LuaScriptInterface::luaUserdataCompare); registerMethod("MonsterType", "isAttackable", LuaScriptInterface::luaMonsterTypeIsAttackable); registerMethod("MonsterType", "isConvinceable", LuaScriptInterface::luaMonsterTypeIsConvinceable); registerMethod("MonsterType", "isSummonable", LuaScriptInterface::luaMonsterTypeIsSummonable); registerMethod("MonsterType", "isIllusionable", LuaScriptInterface::luaMonsterTypeIsIllusionable); registerMethod("MonsterType", "isHostile", LuaScriptInterface::luaMonsterTypeIsHostile); registerMethod("MonsterType", "isPushable", LuaScriptInterface::luaMonsterTypeIsPushable); registerMethod("MonsterType", "isHealthShown", LuaScriptInterface::luaMonsterTypeIsHealthShown); registerMethod("MonsterType", "canPushItems", LuaScriptInterface::luaMonsterTypeCanPushItems); registerMethod("MonsterType", "canPushCreatures", LuaScriptInterface::luaMonsterTypeCanPushCreatures); registerMethod("MonsterType", "getName", LuaScriptInterface::luaMonsterTypeGetName); registerMethod("MonsterType", "getNameDescription", LuaScriptInterface::luaMonsterTypeGetNameDescription); registerMethod("MonsterType", "getHealth", LuaScriptInterface::luaMonsterTypeGetHealth); registerMethod("MonsterType", "getMaxHealth", LuaScriptInterface::luaMonsterTypeGetMaxHealth); registerMethod("MonsterType", "getRunHealth", LuaScriptInterface::luaMonsterTypeGetRunHealth); registerMethod("MonsterType", "getExperience", LuaScriptInterface::luaMonsterTypeGetExperience); registerMethod("MonsterType", "getCombatImmunities", LuaScriptInterface::luaMonsterTypeGetCombatImmunities); registerMethod("MonsterType", "getConditionImmunities", LuaScriptInterface::luaMonsterTypeGetConditionImmunities); registerMethod("MonsterType", "getAttackList", LuaScriptInterface::luaMonsterTypeGetAttackList); registerMethod("MonsterType", "getDefenseList", LuaScriptInterface::luaMonsterTypeGetDefenseList); registerMethod("MonsterType", "getElementList", LuaScriptInterface::luaMonsterTypeGetElementList); registerMethod("MonsterType", "getVoices", LuaScriptInterface::luaMonsterTypeGetVoices); registerMethod("MonsterType", "getLoot", LuaScriptInterface::luaMonsterTypeGetLoot); registerMethod("MonsterType", "getCreatureEvents", LuaScriptInterface::luaMonsterTypeGetCreatureEvents); registerMethod("MonsterType", "getSummonList", LuaScriptInterface::luaMonsterTypeGetSummonList); registerMethod("MonsterType", "getMaxSummons", LuaScriptInterface::luaMonsterTypeGetMaxSummons); registerMethod("MonsterType", "getArmor", LuaScriptInterface::luaMonsterTypeGetArmor); registerMethod("MonsterType", "getDefense", LuaScriptInterface::luaMonsterTypeGetDefense); registerMethod("MonsterType", "getOutfit", LuaScriptInterface::luaMonsterTypeGetOutfit); registerMethod("MonsterType", "getRace", LuaScriptInterface::luaMonsterTypeGetRace); registerMethod("MonsterType", "getCorpseId", LuaScriptInterface::luaMonsterTypeGetCorpseId); registerMethod("MonsterType", "getManaCost", LuaScriptInterface::luaMonsterTypeGetManaCost); registerMethod("MonsterType", "getBaseSpeed", LuaScriptInterface::luaMonsterTypeGetBaseSpeed); registerMethod("MonsterType", "getLight", LuaScriptInterface::luaMonsterTypeGetLight); registerMethod("MonsterType", "getTargetDistance", LuaScriptInterface::luaMonsterTypeGetTargetDistance); registerMethod("MonsterType", "getChangeTargetChance", LuaScriptInterface::luaMonsterTypeGetChangeTargetChance); registerMethod("MonsterType", "getChangeTargetSpeed", LuaScriptInterface::luaMonsterTypeGetChangeTargetSpeed); // Party registerClass("Party", "", nullptr); registerMetaMethod("Party", "__eq", LuaScriptInterface::luaUserdataCompare); registerMethod("Party", "disband", LuaScriptInterface::luaPartyDisband); registerMethod("Party", "getLeader", LuaScriptInterface::luaPartyGetLeader); registerMethod("Party", "setLeader", LuaScriptInterface::luaPartySetLeader); registerMethod("Party", "getMembers", LuaScriptInterface::luaPartyGetMembers); registerMethod("Party", "getMemberCount", LuaScriptInterface::luaPartyGetMemberCount); registerMethod("Party", "getInvitees", LuaScriptInterface::luaPartyGetInvitees); registerMethod("Party", "getInviteeCount", LuaScriptInterface::luaPartyGetInviteeCount); registerMethod("Party", "addInvite", LuaScriptInterface::luaPartyAddInvite); registerMethod("Party", "removeInvite", LuaScriptInterface::luaPartyRemoveInvite); registerMethod("Party", "addMember", LuaScriptInterface::luaPartyAddMember); registerMethod("Party", "removeMember", LuaScriptInterface::luaPartyRemoveMember); registerMethod("Party", "isSharedExperienceActive", LuaScriptInterface::luaPartyIsSharedExperienceActive); registerMethod("Party", "isSharedExperienceEnabled", LuaScriptInterface::luaPartyIsSharedExperienceEnabled); registerMethod("Party", "shareExperience", LuaScriptInterface::luaPartyShareExperience); registerMethod("Party", "setSharedExperience", LuaScriptInterface::luaPartySetSharedExperience); } #undef registerEnum #undef registerEnumIn void LuaScriptInterface::registerClass(const std::string& className, const std::string& baseClass, lua_CFunction newFunction/* = nullptr*/) { // className = {} lua_newtable(luaState); lua_pushvalue(luaState, -1); lua_setglobal(luaState, className.c_str()); int methods = lua_gettop(luaState); // methodsTable = {} lua_newtable(luaState); int methodsTable = lua_gettop(luaState); if (newFunction) { // className.__call = newFunction lua_pushcfunction(luaState, newFunction); lua_setfield(luaState, methodsTable, "__call"); } uint32_t parents = 0; if (!baseClass.empty()) { lua_getglobal(luaState, baseClass.c_str()); lua_rawgeti(luaState, -1, 'p'); parents = getNumber(luaState, -1) + 1; lua_pop(luaState, 1); lua_setfield(luaState, methodsTable, "__index"); } // setmetatable(className, methodsTable) lua_setmetatable(luaState, methods); // className.metatable = {} luaL_newmetatable(luaState, className.c_str()); int metatable = lua_gettop(luaState); // className.metatable.__metatable = className lua_pushvalue(luaState, methods); lua_setfield(luaState, metatable, "__metatable"); // className.metatable.__index = className lua_pushvalue(luaState, methods); lua_setfield(luaState, metatable, "__index"); // className.metatable['h'] = hash lua_pushnumber(luaState, std::hash()(className)); lua_rawseti(luaState, metatable, 'h'); // className.metatable['p'] = parents lua_pushnumber(luaState, parents); lua_rawseti(luaState, metatable, 'p'); // className.metatable['t'] = type if (className == "Item") { lua_pushnumber(luaState, LuaData_Item); } else if (className == "Container") { lua_pushnumber(luaState, LuaData_Container); } else if (className == "Teleport") { lua_pushnumber(luaState, LuaData_Teleport); } else if (className == "Player") { lua_pushnumber(luaState, LuaData_Player); } else if (className == "Monster") { lua_pushnumber(luaState, LuaData_Monster); } else if (className == "Npc") { lua_pushnumber(luaState, LuaData_Npc); } else if (className == "Tile") { lua_pushnumber(luaState, LuaData_Tile); } else { lua_pushnumber(luaState, LuaData_Unknown); } lua_rawseti(luaState, metatable, 't'); // pop className, className.metatable lua_pop(luaState, 2); } void LuaScriptInterface::registerTable(const std::string& tableName) { // _G[tableName] = {} lua_newtable(luaState); lua_setglobal(luaState, tableName.c_str()); } void LuaScriptInterface::registerMethod(const std::string& globalName, const std::string& methodName, lua_CFunction func) { // globalName.methodName = func lua_getglobal(luaState, globalName.c_str()); lua_pushcfunction(luaState, func); lua_setfield(luaState, -2, methodName.c_str()); // pop globalName lua_pop(luaState, 1); } void LuaScriptInterface::registerMetaMethod(const std::string& className, const std::string& methodName, lua_CFunction func) { // className.metatable.methodName = func luaL_getmetatable(luaState, className.c_str()); lua_pushcfunction(luaState, func); lua_setfield(luaState, -2, methodName.c_str()); // pop className.metatable lua_pop(luaState, 1); } void LuaScriptInterface::registerGlobalMethod(const std::string& functionName, lua_CFunction func) { // _G[functionName] = func lua_pushcfunction(luaState, func); lua_setglobal(luaState, functionName.c_str()); } void LuaScriptInterface::registerVariable(const std::string& tableName, const std::string& name, lua_Number value) { // tableName.name = value lua_getglobal(luaState, tableName.c_str()); setField(luaState, name.c_str(), value); // pop tableName lua_pop(luaState, 1); } void LuaScriptInterface::registerGlobalVariable(const std::string& name, lua_Number value) { // _G[name] = value lua_pushnumber(luaState, value); lua_setglobal(luaState, name.c_str()); } void LuaScriptInterface::registerGlobalBoolean(const std::string& name, bool value) { // _G[name] = value pushBoolean(luaState, value); lua_setglobal(luaState, name.c_str()); } int LuaScriptInterface::luaGetPlayerFlagValue(lua_State* L) { //getPlayerFlagValue(cid, flag) Player* player = getPlayer(L, 1); if (player) { PlayerFlags flag = getNumber(L, 2); pushBoolean(L, player->hasFlag(flag)); } else { reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); pushBoolean(L, false); } return 1; } int LuaScriptInterface::luaGetPlayerInstantSpellCount(lua_State* L) { //getPlayerInstantSpellCount(cid) Player* player = getPlayer(L, 1); if (player) { lua_pushnumber(L, g_spells->getInstantSpellCount(player)); } else { reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); pushBoolean(L, false); } return 1; } int LuaScriptInterface::luaGetPlayerInstantSpellInfo(lua_State* L) { //getPlayerInstantSpellInfo(cid, index) Player* player = getPlayer(L, 1); if (!player) { reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); pushBoolean(L, false); return 1; } uint32_t index = getNumber(L, 2); InstantSpell* spell = g_spells->getInstantSpellByIndex(player, index); if (!spell) { reportErrorFunc(getErrorDesc(LUA_ERROR_SPELL_NOT_FOUND)); pushBoolean(L, false); return 1; } lua_createtable(L, 0, 6); setField(L, "name", spell->getName()); setField(L, "words", spell->getWords()); setField(L, "level", spell->getLevel()); setField(L, "mlevel", spell->getMagicLevel()); setField(L, "mana", spell->getManaCost(player)); setField(L, "manapercent", spell->getManaPercent()); return 1; } int LuaScriptInterface::luaDoPlayerAddItem(lua_State* L) { //doPlayerAddItem(cid, itemid, count/subtype, canDropOnMap) //doPlayerAddItem(cid, itemid, count, canDropOnMap, subtype) Player* player = getPlayer(L, 1); if (!player) { reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); pushBoolean(L, false); return 1; } uint16_t itemId = getNumber(L, 2); int32_t count = getNumber(L, 3, 1); bool canDropOnMap = getBoolean(L, 4, true); uint16_t subType = getNumber(L, 5, 1); const ItemType& it = Item::items[itemId]; int32_t itemCount; auto parameters = lua_gettop(L); if (parameters > 4) { //subtype already supplied, count then is the amount itemCount = std::max(1, count); } else if (it.hasSubType()) { if (it.stackable) { itemCount = static_cast(std::ceil(static_cast(count) / 100)); } else { itemCount = 1; } subType = count; } else { itemCount = std::max(1, count); } while (itemCount > 0) { uint16_t stackCount = subType; if (it.stackable && stackCount > 100) { stackCount = 100; } Item* newItem = Item::CreateItem(itemId, stackCount); if (!newItem) { reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); pushBoolean(L, false); return 1; } if (it.stackable) { subType -= stackCount; } ReturnValue ret = g_game.internalPlayerAddItem(player, newItem, canDropOnMap); if (ret != RETURNVALUE_NOERROR) { delete newItem; pushBoolean(L, false); return 1; } if (--itemCount == 0) { if (newItem->getParent()) { uint32_t uid = getScriptEnv()->addThing(newItem); lua_pushnumber(L, uid); return 1; } else { //stackable item stacked with existing object, newItem will be released pushBoolean(L, false); return 1; } } } pushBoolean(L, false); return 1; } int LuaScriptInterface::luaDoTileAddItemEx(lua_State* L) { //doTileAddItemEx(pos, uid) const Position& pos = getPosition(L, 1); Tile* tile = g_game.map.getTile(pos); if (!tile) { std::ostringstream ss; ss << pos << ' ' << getErrorDesc(LUA_ERROR_TILE_NOT_FOUND); reportErrorFunc(ss.str()); pushBoolean(L, false); return 1; } uint32_t uid = getNumber(L, 2); Item* item = getScriptEnv()->getItemByUID(uid); if (!item) { reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); pushBoolean(L, false); return 1; } if (item->getParent() != VirtualCylinder::virtualCylinder) { reportErrorFunc("Item already has a parent"); pushBoolean(L, false); return 1; } lua_pushnumber(L, g_game.internalAddItem(tile, item)); return 1; } int LuaScriptInterface::luaDoCreateItem(lua_State* L) { //doCreateItem(itemid, type/count, pos) //Returns uid of the created item, only works on tiles. const Position& pos = getPosition(L, 3); Tile* tile = g_game.map.getTile(pos); if (!tile) { std::ostringstream ss; ss << pos << ' ' << getErrorDesc(LUA_ERROR_TILE_NOT_FOUND); reportErrorFunc(ss.str()); pushBoolean(L, false); return 1; } ScriptEnvironment* env = getScriptEnv(); int32_t itemCount = 1; int32_t subType = 1; uint16_t itemId = getNumber(L, 1); uint32_t count = getNumber(L, 2, 1); const ItemType& it = Item::items[itemId]; if (it.hasSubType()) { if (it.stackable) { itemCount = static_cast(std::ceil(static_cast(count) / 100)); } subType = count; } else { itemCount = std::max(1, count); } while (itemCount > 0) { int32_t stackCount = std::min(100, subType); Item* newItem = Item::CreateItem(itemId, stackCount); if (!newItem) { reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); pushBoolean(L, false); return 1; } if (it.stackable) { subType -= stackCount; } ReturnValue ret = g_game.internalAddItem(tile, newItem, INDEX_WHEREEVER, FLAG_NOLIMIT); if (ret != RETURNVALUE_NOERROR) { delete newItem; pushBoolean(L, false); return 1; } if (--itemCount == 0) { if (newItem->getParent()) { uint32_t uid = env->addThing(newItem); lua_pushnumber(L, uid); return 1; } else { //stackable item stacked with existing object, newItem will be released pushBoolean(L, false); return 1; } } } pushBoolean(L, false); return 1; } int LuaScriptInterface::luaDoCreateItemEx(lua_State* L) { //doCreateItemEx(itemid, count/subtype) //Returns uid of the created item uint16_t itemId = getNumber(L, 1); uint32_t count = getNumber(L, 2, 1); const ItemType& it = Item::items[itemId]; if (it.stackable && count > 100) { reportErrorFunc("Stack count cannot be higher than 100."); count = 100; } Item* newItem = Item::CreateItem(itemId, count); if (!newItem) { reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); pushBoolean(L, false); return 1; } newItem->setParent(VirtualCylinder::virtualCylinder); ScriptEnvironment* env = getScriptEnv(); env->addTempItem(newItem); uint32_t uid = env->addThing(newItem); lua_pushnumber(L, uid); return 1; } int LuaScriptInterface::luaDebugPrint(lua_State* L) { //debugPrint(text) reportErrorFunc(getString(L, -1)); return 0; } int LuaScriptInterface::luaGetWorldTime(lua_State* L) { //getWorldTime() uint32_t time = g_game.getLightHour(); lua_pushnumber(L, time); return 1; } int LuaScriptInterface::luaGetWorldLight(lua_State* L) { //getWorldLight() LightInfo lightInfo = g_game.getWorldLightInfo(); lua_pushnumber(L, lightInfo.level); lua_pushnumber(L, lightInfo.color); return 2; } int LuaScriptInterface::luaGetWorldUpTime(lua_State* L) { //getWorldUpTime() uint64_t uptime = (OTSYS_TIME() - ProtocolStatus::start) / 1000; lua_pushnumber(L, uptime); return 1; } bool LuaScriptInterface::getArea(lua_State* L, std::list& list, uint32_t& rows) { lua_pushnil(L); for (rows = 0; lua_next(L, -2) != 0; ++rows) { if (!isTable(L, -1)) { return false; } lua_pushnil(L); while (lua_next(L, -2) != 0) { if (!isNumber(L, -1)) { return false; } list.push_back(getNumber(L, -1)); lua_pop(L, 1); } lua_pop(L, 1); } lua_pop(L, 1); return (rows != 0); } int LuaScriptInterface::luaCreateCombatArea(lua_State* L) { //createCombatArea( {area}, {extArea} ) ScriptEnvironment* env = getScriptEnv(); if (env->getScriptId() != EVENT_ID_LOADING) { reportErrorFunc("This function can only be used while loading the script."); pushBoolean(L, false); return 1; } uint32_t areaId = g_luaEnvironment.createAreaObject(env->getScriptInterface()); AreaCombat* area = g_luaEnvironment.getAreaObject(areaId); int parameters = lua_gettop(L); if (parameters >= 2) { uint32_t rowsExtArea; std::list listExtArea; if (!isTable(L, 2) || !getArea(L, listExtArea, rowsExtArea)) { reportErrorFunc("Invalid extended area table."); pushBoolean(L, false); return 1; } area->setupExtArea(listExtArea, rowsExtArea); } uint32_t rowsArea = 0; std::list listArea; if (!isTable(L, 1) || !getArea(L, listArea, rowsArea)) { reportErrorFunc("Invalid area table."); pushBoolean(L, false); return 1; } area->setupArea(listArea, rowsArea); lua_pushnumber(L, areaId); return 1; } int LuaScriptInterface::luaDoAreaCombatHealth(lua_State* L) { //doAreaCombatHealth(cid, type, pos, area, min, max, effect[, origin = ORIGIN_SPELL]) Creature* creature = getCreature(L, 1); if (!creature && (!isNumber(L, 1) || getNumber(L, 1) != 0)) { reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); pushBoolean(L, false); return 1; } uint32_t areaId = getNumber(L, 4); const AreaCombat* area = g_luaEnvironment.getAreaObject(areaId); if (area || areaId == 0) { CombatType_t combatType = getNumber(L, 2); CombatParams params; params.combatType = combatType; params.impactEffect = getNumber(L, 7); CombatDamage damage; damage.origin = getNumber(L, 8, ORIGIN_SPELL); damage.type = combatType; damage.value = normal_random(getNumber(L, 6), getNumber(L, 5)); Combat::doCombatHealth(creature, getPosition(L, 3), area, damage, params); pushBoolean(L, true); } else { reportErrorFunc(getErrorDesc(LUA_ERROR_AREA_NOT_FOUND)); pushBoolean(L, false); } return 1; } int LuaScriptInterface::luaDoTargetCombatHealth(lua_State* L) { //doTargetCombatHealth(cid, target, type, min, max, effect[, origin = ORIGIN_SPELL]) Creature* creature = getCreature(L, 1); if (!creature && (!isNumber(L, 1) || getNumber(L, 1) != 0)) { reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); pushBoolean(L, false); return 1; } Creature* target = getCreature(L, 2); if (!target) { reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); pushBoolean(L, false); return 1; } CombatType_t combatType = getNumber(L, 3); CombatParams params; params.combatType = combatType; params.impactEffect = getNumber(L, 6); CombatDamage damage; damage.origin = getNumber(L, 7, ORIGIN_SPELL); damage.type = combatType; damage.value = normal_random(getNumber(L, 4), getNumber(L, 5)); Combat::doCombatHealth(creature, target, damage, params); pushBoolean(L, true); return 1; } int LuaScriptInterface::luaDoAreaCombatMana(lua_State* L) { //doAreaCombatMana(cid, pos, area, min, max, effect[, origin = ORIGIN_SPELL]) Creature* creature = getCreature(L, 1); if (!creature && (!isNumber(L, 1) || getNumber(L, 1) != 0)) { reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); pushBoolean(L, false); return 1; } uint32_t areaId = getNumber(L, 3); const AreaCombat* area = g_luaEnvironment.getAreaObject(areaId); if (area || areaId == 0) { CombatParams params; params.impactEffect = getNumber(L, 6); CombatDamage damage; damage.origin = getNumber(L, 7, ORIGIN_SPELL); damage.type = COMBAT_MANADRAIN; damage.value = normal_random(getNumber(L, 4), getNumber(L, 5)); Position pos = getPosition(L, 2); Combat::doCombatMana(creature, pos, area, damage, params); pushBoolean(L, true); } else { reportErrorFunc(getErrorDesc(LUA_ERROR_AREA_NOT_FOUND)); pushBoolean(L, false); } return 1; } int LuaScriptInterface::luaDoTargetCombatMana(lua_State* L) { //doTargetCombatMana(cid, target, min, max, effect[, origin = ORIGIN_SPELL) Creature* creature = getCreature(L, 1); if (!creature && (!isNumber(L, 1) || getNumber(L, 1) != 0)) { reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); pushBoolean(L, false); return 1; } Creature* target = getCreature(L, 2); if (!target) { reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); pushBoolean(L, false); return 1; } CombatParams params; params.impactEffect = getNumber(L, 5); CombatDamage damage; damage.origin = getNumber(L, 6, ORIGIN_SPELL); damage.type = COMBAT_MANADRAIN; damage.value = normal_random(getNumber(L, 3), getNumber(L, 4)); Combat::doCombatMana(creature, target, damage, params); pushBoolean(L, true); return 1; } int LuaScriptInterface::luaDoAreaCombatCondition(lua_State* L) { //doAreaCombatCondition(cid, pos, area, condition, effect) Creature* creature = getCreature(L, 1); if (!creature && (!isNumber(L, 1) || getNumber(L, 1) != 0)) { reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); pushBoolean(L, false); return 1; } const Condition* condition = getUserdata(L, 4); if (!condition) { reportErrorFunc(getErrorDesc(LUA_ERROR_CONDITION_NOT_FOUND)); pushBoolean(L, false); return 1; } uint32_t areaId = getNumber(L, 3); const AreaCombat* area = g_luaEnvironment.getAreaObject(areaId); if (area || areaId == 0) { CombatParams params; params.impactEffect = getNumber(L, 5); params.conditionList.emplace_front(condition); Combat::doCombatCondition(creature, getPosition(L, 2), area, params); pushBoolean(L, true); } else { reportErrorFunc(getErrorDesc(LUA_ERROR_AREA_NOT_FOUND)); pushBoolean(L, false); } return 1; } int LuaScriptInterface::luaDoTargetCombatCondition(lua_State* L) { //doTargetCombatCondition(cid, target, condition, effect) Creature* creature = getCreature(L, 1); if (!creature && (!isNumber(L, 1) || getNumber(L, 1) != 0)) { reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); pushBoolean(L, false); return 1; } Creature* target = getCreature(L, 2); if (!target) { reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); pushBoolean(L, false); return 1; } const Condition* condition = getUserdata(L, 3); if (!condition) { reportErrorFunc(getErrorDesc(LUA_ERROR_CONDITION_NOT_FOUND)); pushBoolean(L, false); return 1; } CombatParams params; params.impactEffect = getNumber(L, 4); params.conditionList.emplace_front(condition); Combat::doCombatCondition(creature, target, params); pushBoolean(L, true); return 1; } int LuaScriptInterface::luaDoAreaCombatDispel(lua_State* L) { //doAreaCombatDispel(cid, pos, area, type, effect) Creature* creature = getCreature(L, 1); if (!creature && (!isNumber(L, 1) || getNumber(L, 1) != 0)) { reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); pushBoolean(L, false); return 1; } uint32_t areaId = getNumber(L, 3); const AreaCombat* area = g_luaEnvironment.getAreaObject(areaId); if (area || areaId == 0) { CombatParams params; params.impactEffect = getNumber(L, 5); params.dispelType = getNumber(L, 4); Combat::doCombatDispel(creature, getPosition(L, 2), area, params); pushBoolean(L, true); } else { reportErrorFunc(getErrorDesc(LUA_ERROR_AREA_NOT_FOUND)); pushBoolean(L, false); } return 1; } int LuaScriptInterface::luaDoTargetCombatDispel(lua_State* L) { //doTargetCombatDispel(cid, target, type, effect) Creature* creature = getCreature(L, 1); if (!creature && (!isNumber(L, 1) || getNumber(L, 1) != 0)) { reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); pushBoolean(L, false); return 1; } Creature* target = getCreature(L, 2); if (!target) { reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); pushBoolean(L, false); return 1; } CombatParams params; params.dispelType = getNumber(L, 3); params.impactEffect = getNumber(L, 4); Combat::doCombatDispel(creature, target, params); pushBoolean(L, true); return 1; } int LuaScriptInterface::luaDoChallengeCreature(lua_State* L) { //doChallengeCreature(cid, target) Creature* creature = getCreature(L, 1); if (!creature) { reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); pushBoolean(L, false); return 1; } Creature* target = getCreature(L, 2); if (!target) { reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); pushBoolean(L, false); return 1; } target->challengeCreature(creature); pushBoolean(L, true); return 1; } int LuaScriptInterface::luaSetCreatureOutfit(lua_State* L) { //doSetCreatureOutfit(cid, outfit, time) Creature* creature = getCreature(L, 1); if (!creature) { reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); pushBoolean(L, false); return 1; } Outfit_t outfit = getOutfit(L, 2); int32_t time = getNumber(L, 3); pushBoolean(L, Spell::CreateIllusion(creature, outfit, time) == RETURNVALUE_NOERROR); return 1; } int LuaScriptInterface::luaSetMonsterOutfit(lua_State* L) { //doSetMonsterOutfit(cid, name, time) Creature* creature = getCreature(L, 1); if (!creature) { reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); pushBoolean(L, false); return 1; } std::string name = getString(L, 2); int32_t time = getNumber(L, 3); pushBoolean(L, Spell::CreateIllusion(creature, name, time) == RETURNVALUE_NOERROR); return 1; } int LuaScriptInterface::luaSetItemOutfit(lua_State* L) { //doSetItemOutfit(cid, item, time) Creature* creature = getCreature(L, 1); if (!creature) { reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); pushBoolean(L, false); return 1; } uint32_t item = getNumber(L, 2); int32_t time = getNumber(L, 3); pushBoolean(L, Spell::CreateIllusion(creature, item, time) == RETURNVALUE_NOERROR); return 1; } int LuaScriptInterface::luaDoMoveCreature(lua_State* L) { //doMoveCreature(cid, direction) Creature* creature = getCreature(L, 1); if (!creature) { reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); pushBoolean(L, false); return 1; } Direction direction = getNumber(L, 2); if (direction > DIRECTION_LAST) { reportErrorFunc("No valid direction"); pushBoolean(L, false); return 1; } ReturnValue ret = g_game.internalMoveCreature(creature, direction, FLAG_NOLIMIT); lua_pushnumber(L, ret); return 1; } int LuaScriptInterface::luaIsValidUID(lua_State* L) { //isValidUID(uid) pushBoolean(L, getScriptEnv()->getThingByUID(getNumber(L, -1)) != nullptr); return 1; } int LuaScriptInterface::luaIsDepot(lua_State* L) { //isDepot(uid) Container* container = getScriptEnv()->getContainerByUID(getNumber(L, -1)); pushBoolean(L, container && container->getDepotLocker()); return 1; } int LuaScriptInterface::luaIsMoveable(lua_State* L) { //isMoveable(uid) //isMovable(uid) Thing* thing = getScriptEnv()->getThingByUID(getNumber(L, -1)); pushBoolean(L, thing && thing->isPushable()); return 1; } int LuaScriptInterface::luaDoAddContainerItem(lua_State* L) { //doAddContainerItem(uid, itemid, count/subtype) uint32_t uid = getNumber(L, 1); ScriptEnvironment* env = getScriptEnv(); Container* container = env->getContainerByUID(uid); if (!container) { reportErrorFunc(getErrorDesc(LUA_ERROR_CONTAINER_NOT_FOUND)); pushBoolean(L, false); return 1; } uint16_t itemId = getNumber(L, 2); const ItemType& it = Item::items[itemId]; int32_t itemCount = 1; int32_t subType = 1; uint32_t count = getNumber(L, 3, 1); if (it.hasSubType()) { if (it.stackable) { itemCount = static_cast(std::ceil(static_cast(count) / 100)); } subType = count; } else { itemCount = std::max(1, count); } while (itemCount > 0) { int32_t stackCount = std::min(100, subType); Item* newItem = Item::CreateItem(itemId, stackCount); if (!newItem) { reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); pushBoolean(L, false); return 1; } if (it.stackable) { subType -= stackCount; } ReturnValue ret = g_game.internalAddItem(container, newItem); if (ret != RETURNVALUE_NOERROR) { delete newItem; pushBoolean(L, false); return 1; } if (--itemCount == 0) { if (newItem->getParent()) { lua_pushnumber(L, env->addThing(newItem)); } else { //stackable item stacked with existing object, newItem will be released pushBoolean(L, false); } return 1; } } pushBoolean(L, false); return 1; } int LuaScriptInterface::luaGetDepotId(lua_State* L) { //getDepotId(uid) uint32_t uid = getNumber(L, -1); Container* container = getScriptEnv()->getContainerByUID(uid); if (!container) { reportErrorFunc(getErrorDesc(LUA_ERROR_CONTAINER_NOT_FOUND)); pushBoolean(L, false); return 1; } DepotLocker* depotLocker = container->getDepotLocker(); if (!depotLocker) { reportErrorFunc("Depot not found"); pushBoolean(L, false); return 1; } lua_pushnumber(L, depotLocker->getDepotId()); return 1; } int LuaScriptInterface::luaIsInArray(lua_State* L) { //isInArray(array, value) if (!isTable(L, 1)) { pushBoolean(L, false); return 1; } lua_pushnil(L); while (lua_next(L, 1)) { if (lua_equal(L, 2, -1) != 0) { pushBoolean(L, true); return 1; } lua_pop(L, 1); } pushBoolean(L, false); return 1; } int LuaScriptInterface::luaDoSetCreatureLight(lua_State* L) { //doSetCreatureLight(cid, lightLevel, lightColor, time) Creature* creature = getCreature(L, 1); if (!creature) { reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); pushBoolean(L, false); return 1; } uint16_t level = getNumber(L, 2); uint16_t color = getNumber(L, 3); uint32_t time = getNumber(L, 4); Condition* condition = Condition::createCondition(CONDITIONID_COMBAT, CONDITION_LIGHT, time, level | (color << 8)); creature->addCondition(condition); pushBoolean(L, true); return 1; } int LuaScriptInterface::luaAddEvent(lua_State* L) { //addEvent(callback, delay, ...) lua_State* globalState = g_luaEnvironment.getLuaState(); if (!globalState) { reportErrorFunc("No valid script interface!"); pushBoolean(L, false); return 1; } else if (globalState != L) { lua_xmove(L, globalState, lua_gettop(L)); } int parameters = lua_gettop(globalState); if (!isFunction(globalState, -parameters)) { //-parameters means the first parameter from left to right reportErrorFunc("callback parameter should be a function."); pushBoolean(L, false); return 1; } if (g_config.getBoolean(ConfigManager::WARN_UNSAFE_SCRIPTS) || g_config.getBoolean(ConfigManager::CONVERT_UNSAFE_SCRIPTS)) { std::vector> indexes; for (int i = 3; i <= parameters; ++i) { if (lua_getmetatable(globalState, i) == 0) { continue; } lua_rawgeti(L, -1, 't'); LuaDataType type = getNumber(L, -1); if (type != LuaData_Unknown && type != LuaData_Tile) { indexes.push_back({i, type}); } lua_pop(globalState, 2); } if (!indexes.empty()) { if (g_config.getBoolean(ConfigManager::WARN_UNSAFE_SCRIPTS)) { bool plural = indexes.size() > 1; std::string warningString = "Argument"; if (plural) { warningString += 's'; } for (const auto& entry : indexes) { if (entry == indexes.front()) { warningString += ' '; } else if (entry == indexes.back()) { warningString += " and "; } else { warningString += ", "; } warningString += '#'; warningString += std::to_string(entry.first); } if (plural) { warningString += " are unsafe"; } else { warningString += " is unsafe"; } reportErrorFunc(warningString); } if (g_config.getBoolean(ConfigManager::CONVERT_UNSAFE_SCRIPTS)) { for (const auto& entry : indexes) { switch (entry.second) { case LuaData_Item: case LuaData_Container: case LuaData_Teleport: { lua_getglobal(globalState, "Item"); lua_getfield(globalState, -1, "getMovementId"); break; } case LuaData_Player: case LuaData_Monster: case LuaData_Npc: { lua_getglobal(globalState, "Creature"); lua_getfield(globalState, -1, "getId"); break; } default: break; } lua_replace(globalState, -2); lua_pushvalue(globalState, entry.first); lua_call(globalState, 1, 1); lua_replace(globalState, entry.first); } } } } LuaTimerEventDesc eventDesc; for (int i = 0; i < parameters - 2; ++i) { //-2 because addEvent needs at least two parameters eventDesc.parameters.push_back(luaL_ref(globalState, LUA_REGISTRYINDEX)); } uint32_t delay = std::max(100, getNumber(globalState, 2)); lua_pop(globalState, 1); eventDesc.function = luaL_ref(globalState, LUA_REGISTRYINDEX); eventDesc.scriptId = getScriptEnv()->getScriptId(); auto& lastTimerEventId = g_luaEnvironment.lastEventTimerId; eventDesc.eventId = g_scheduler.addEvent(createSchedulerTask( delay, std::bind(&LuaEnvironment::executeTimerEvent, &g_luaEnvironment, lastTimerEventId) )); g_luaEnvironment.timerEvents.emplace(lastTimerEventId, std::move(eventDesc)); lua_pushnumber(L, lastTimerEventId++); return 1; } int LuaScriptInterface::luaStopEvent(lua_State* L) { //stopEvent(eventid) lua_State* globalState = g_luaEnvironment.getLuaState(); if (!globalState) { reportErrorFunc("No valid script interface!"); pushBoolean(L, false); return 1; } uint32_t eventId = getNumber(L, 1); auto& timerEvents = g_luaEnvironment.timerEvents; auto it = timerEvents.find(eventId); if (it == timerEvents.end()) { pushBoolean(L, false); return 1; } LuaTimerEventDesc timerEventDesc = std::move(it->second); timerEvents.erase(it); g_scheduler.stopEvent(timerEventDesc.eventId); luaL_unref(globalState, LUA_REGISTRYINDEX, timerEventDesc.function); for (auto parameter : timerEventDesc.parameters) { luaL_unref(globalState, LUA_REGISTRYINDEX, parameter); } pushBoolean(L, true); return 1; } int LuaScriptInterface::luaGetCreatureCondition(lua_State* L) { Creature* creature = getCreature(L, 1); if (!creature) { reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); pushBoolean(L, false); return 1; } ConditionType_t condition = getNumber(L, 2); uint32_t subId = getNumber(L, 3, 0); pushBoolean(L, creature->hasCondition(condition, subId)); return 1; } int LuaScriptInterface::luaSaveServer(lua_State* L) { g_game.saveGameState(); pushBoolean(L, true); return 1; } int LuaScriptInterface::luaCleanMap(lua_State* L) { lua_pushnumber(L, g_game.map.clean()); return 1; } int LuaScriptInterface::luaIsInWar(lua_State* L) { //isInWar(cid, target) Player* player = getPlayer(L, 1); if (!player) { reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); pushBoolean(L, false); return 1; } Player* targetPlayer = getPlayer(L, 2); if (!targetPlayer) { reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); pushBoolean(L, false); return 1; } pushBoolean(L, player->isInWar(targetPlayer)); return 1; } int LuaScriptInterface::luaGetWaypointPositionByName(lua_State* L) { //getWaypointPositionByName(name) auto& waypoints = g_game.map.waypoints; auto it = waypoints.find(getString(L, -1)); if (it != waypoints.end()) { pushPosition(L, it->second); } else { pushBoolean(L, false); } return 1; } std::string LuaScriptInterface::escapeString(const std::string& string) { std::string s = string; replaceString(s, "\\", "\\\\"); replaceString(s, "\"", "\\\""); replaceString(s, "'", "\\'"); replaceString(s, "[[", "\\[["); return s; } #ifndef LUAJIT_VERSION const luaL_Reg LuaScriptInterface::luaBitReg[] = { //{"tobit", LuaScriptInterface::luaBitToBit}, {"bnot", LuaScriptInterface::luaBitNot}, {"band", LuaScriptInterface::luaBitAnd}, {"bor", LuaScriptInterface::luaBitOr}, {"bxor", LuaScriptInterface::luaBitXor}, {"lshift", LuaScriptInterface::luaBitLeftShift}, {"rshift", LuaScriptInterface::luaBitRightShift}, //{"arshift", LuaScriptInterface::luaBitArithmeticalRightShift}, //{"rol", LuaScriptInterface::luaBitRotateLeft}, //{"ror", LuaScriptInterface::luaBitRotateRight}, //{"bswap", LuaScriptInterface::luaBitSwapEndian}, //{"tohex", LuaScriptInterface::luaBitToHex}, {nullptr, nullptr} }; int LuaScriptInterface::luaBitNot(lua_State* L) { lua_pushnumber(L, ~getNumber(L, -1)); return 1; } #define MULTIOP(name, op) \ int LuaScriptInterface::luaBit##name(lua_State* L) \ { \ int n = lua_gettop(L); \ uint32_t w = getNumber(L, -1); \ for (int i = 1; i < n; ++i) \ w op getNumber(L, i); \ lua_pushnumber(L, w); \ return 1; \ } MULTIOP(And, &= ) MULTIOP(Or, |= ) MULTIOP(Xor, ^= ) #define SHIFTOP(name, op) \ int LuaScriptInterface::luaBit##name(lua_State* L) \ { \ uint32_t n1 = getNumber(L, 1), n2 = getNumber(L, 2); \ lua_pushnumber(L, (n1 op n2)); \ return 1; \ } SHIFTOP(LeftShift, << ) SHIFTOP(RightShift, >> ) #endif const luaL_Reg LuaScriptInterface::luaConfigManagerTable[] = { {"getString", LuaScriptInterface::luaConfigManagerGetString}, {"getNumber", LuaScriptInterface::luaConfigManagerGetNumber}, {"getBoolean", LuaScriptInterface::luaConfigManagerGetBoolean}, {nullptr, nullptr} }; int LuaScriptInterface::luaConfigManagerGetString(lua_State* L) { pushString(L, g_config.getString(getNumber(L, -1))); return 1; } int LuaScriptInterface::luaConfigManagerGetNumber(lua_State* L) { lua_pushnumber(L, g_config.getNumber(getNumber(L, -1))); return 1; } int LuaScriptInterface::luaConfigManagerGetBoolean(lua_State* L) { pushBoolean(L, g_config.getBoolean(getNumber(L, -1))); return 1; } const luaL_Reg LuaScriptInterface::luaDatabaseTable[] = { {"query", LuaScriptInterface::luaDatabaseExecute}, {"asyncQuery", LuaScriptInterface::luaDatabaseAsyncExecute}, {"storeQuery", LuaScriptInterface::luaDatabaseStoreQuery}, {"asyncStoreQuery", LuaScriptInterface::luaDatabaseAsyncStoreQuery}, {"escapeString", LuaScriptInterface::luaDatabaseEscapeString}, {"escapeBlob", LuaScriptInterface::luaDatabaseEscapeBlob}, {"lastInsertId", LuaScriptInterface::luaDatabaseLastInsertId}, {"tableExists", LuaScriptInterface::luaDatabaseTableExists}, {nullptr, nullptr} }; int LuaScriptInterface::luaDatabaseExecute(lua_State* L) { pushBoolean(L, Database::getInstance()->executeQuery(getString(L, -1))); return 1; } int LuaScriptInterface::luaDatabaseAsyncExecute(lua_State* L) { std::function callback; if (lua_gettop(L) > 1) { int32_t ref = luaL_ref(L, LUA_REGISTRYINDEX); auto scriptId = getScriptEnv()->getScriptId(); callback = [ref, scriptId](DBResult_ptr, bool success) { lua_State* luaState = g_luaEnvironment.getLuaState(); if (!luaState) { return; } if (!LuaScriptInterface::reserveScriptEnv()) { luaL_unref(luaState, LUA_REGISTRYINDEX, ref); return; } lua_rawgeti(luaState, LUA_REGISTRYINDEX, ref); pushBoolean(luaState, success); auto env = getScriptEnv(); env->setScriptId(scriptId, &g_luaEnvironment); g_luaEnvironment.callFunction(1); luaL_unref(luaState, LUA_REGISTRYINDEX, ref); }; } g_databaseTasks.addTask(getString(L, -1), callback); return 0; } int LuaScriptInterface::luaDatabaseStoreQuery(lua_State* L) { if (DBResult_ptr res = Database::getInstance()->storeQuery(getString(L, -1))) { lua_pushnumber(L, ScriptEnvironment::addResult(res)); } else { pushBoolean(L, false); } return 1; } int LuaScriptInterface::luaDatabaseAsyncStoreQuery(lua_State* L) { std::function callback; if (lua_gettop(L) > 1) { int32_t ref = luaL_ref(L, LUA_REGISTRYINDEX); auto scriptId = getScriptEnv()->getScriptId(); callback = [ref, scriptId](DBResult_ptr result, bool) { lua_State* luaState = g_luaEnvironment.getLuaState(); if (!luaState) { return; } if (!LuaScriptInterface::reserveScriptEnv()) { luaL_unref(luaState, LUA_REGISTRYINDEX, ref); return; } lua_rawgeti(luaState, LUA_REGISTRYINDEX, ref); if (result) { lua_pushnumber(luaState, ScriptEnvironment::addResult(result)); } else { pushBoolean(luaState, false); } auto env = getScriptEnv(); env->setScriptId(scriptId, &g_luaEnvironment); g_luaEnvironment.callFunction(1); luaL_unref(luaState, LUA_REGISTRYINDEX, ref); }; } g_databaseTasks.addTask(getString(L, -1), callback, true); return 0; } int LuaScriptInterface::luaDatabaseEscapeString(lua_State* L) { pushString(L, Database::getInstance()->escapeString(getString(L, -1))); return 1; } int LuaScriptInterface::luaDatabaseEscapeBlob(lua_State* L) { uint32_t length = getNumber(L, 2); pushString(L, Database::getInstance()->escapeBlob(getString(L, 1).c_str(), length)); return 1; } int LuaScriptInterface::luaDatabaseLastInsertId(lua_State* L) { lua_pushnumber(L, Database::getInstance()->getLastInsertId()); return 1; } int LuaScriptInterface::luaDatabaseTableExists(lua_State* L) { pushBoolean(L, DatabaseManager::tableExists(getString(L, -1))); return 1; } const luaL_Reg LuaScriptInterface::luaResultTable[] = { {"getNumber", LuaScriptInterface::luaResultGetNumber}, {"getString", LuaScriptInterface::luaResultGetString}, {"getStream", LuaScriptInterface::luaResultGetStream}, {"next", LuaScriptInterface::luaResultNext}, {"free", LuaScriptInterface::luaResultFree}, {nullptr, nullptr} }; int LuaScriptInterface::luaResultGetNumber(lua_State* L) { DBResult_ptr res = ScriptEnvironment::getResultByID(getNumber(L, 1)); if (!res) { pushBoolean(L, false); return 1; } const std::string& s = getString(L, 2); lua_pushnumber(L, res->getNumber(s)); return 1; } int LuaScriptInterface::luaResultGetString(lua_State* L) { DBResult_ptr res = ScriptEnvironment::getResultByID(getNumber(L, 1)); if (!res) { pushBoolean(L, false); return 1; } const std::string& s = getString(L, 2); pushString(L, res->getString(s)); return 1; } int LuaScriptInterface::luaResultGetStream(lua_State* L) { DBResult_ptr res = ScriptEnvironment::getResultByID(getNumber(L, 1)); if (!res) { pushBoolean(L, false); return 1; } unsigned long length; const char* stream = res->getStream(getString(L, 2), length); lua_pushlstring(L, stream, length); lua_pushnumber(L, length); return 2; } int LuaScriptInterface::luaResultNext(lua_State* L) { DBResult_ptr res = ScriptEnvironment::getResultByID(getNumber(L, -1)); if (!res) { pushBoolean(L, false); return 1; } pushBoolean(L, res->next()); return 1; } int LuaScriptInterface::luaResultFree(lua_State* L) { pushBoolean(L, ScriptEnvironment::removeResult(getNumber(L, -1))); return 1; } // Userdata int LuaScriptInterface::luaUserdataCompare(lua_State* L) { // userdataA == userdataB pushBoolean(L, getUserdata(L, 1) == getUserdata(L, 2)); return 1; } // _G int LuaScriptInterface::luaIsType(lua_State* L) { // isType(derived, base) lua_getmetatable(L, -2); lua_getmetatable(L, -2); lua_rawgeti(L, -2, 'p'); uint_fast8_t parentsB = getNumber(L, 1); lua_rawgeti(L, -3, 'h'); size_t hashB = getNumber(L, 1); lua_rawgeti(L, -3, 'p'); uint_fast8_t parentsA = getNumber(L, 1); for (uint_fast8_t i = parentsA; i < parentsB; ++i) { lua_getfield(L, -3, "__index"); lua_replace(L, -4); } lua_rawgeti(L, -4, 'h'); size_t hashA = getNumber(L, 1); pushBoolean(L, hashA == hashB); return 1; } int LuaScriptInterface::luaRawGetMetatable(lua_State* L) { // rawgetmetatable(metatableName) luaL_getmetatable(L, getString(L, 1).c_str()); return 1; } // os int LuaScriptInterface::luaSystemTime(lua_State* L) { // os.mtime() lua_pushnumber(L, OTSYS_TIME()); return 1; } // table int LuaScriptInterface::luaTableCreate(lua_State* L) { // table.create(arrayLength, keyLength) lua_createtable(L, getNumber(L, 1), getNumber(L, 2)); return 1; } // Game int LuaScriptInterface::luaGameGetSpectators(lua_State* L) { // Game.getSpectators(position[, multifloor = false[, onlyPlayer = false[, minRangeX = 0[, maxRangeX = 0[, minRangeY = 0[, maxRangeY = 0]]]]]]) const Position& position = getPosition(L, 1); bool multifloor = getBoolean(L, 2, false); bool onlyPlayers = getBoolean(L, 3, false); int32_t minRangeX = getNumber(L, 4, 0); int32_t maxRangeX = getNumber(L, 5, 0); int32_t minRangeY = getNumber(L, 6, 0); int32_t maxRangeY = getNumber(L, 7, 0); SpectatorVec spectators; g_game.map.getSpectators(spectators, position, multifloor, onlyPlayers, minRangeX, maxRangeX, minRangeY, maxRangeY); lua_createtable(L, spectators.size(), 0); int index = 0; for (Creature* creature : spectators) { pushUserdata(L, creature); setCreatureMetatable(L, -1, creature); lua_rawseti(L, -2, ++index); } return 1; } int LuaScriptInterface::luaGameGetPlayers(lua_State* L) { // Game.getPlayers() lua_createtable(L, g_game.getPlayersOnline(), 0); int index = 0; for (const auto& playerEntry : g_game.getPlayers()) { pushUserdata(L, playerEntry.second); setMetatable(L, -1, "Player"); lua_rawseti(L, -2, ++index); } return 1; } int LuaScriptInterface::luaGameLoadMap(lua_State* L) { // Game.loadMap(path) const std::string& path = getString(L, 1); g_dispatcher.addTask(createTask(std::bind(&Game::loadMap, &g_game, path))); return 0; } int LuaScriptInterface::luaGameGetExperienceStage(lua_State* L) { // Game.getExperienceStage(level) uint32_t level = getNumber(L, 1); lua_pushnumber(L, g_game.getExperienceStage(level)); return 1; } int LuaScriptInterface::luaGameGetMonsterCount(lua_State* L) { // Game.getMonsterCount() lua_pushnumber(L, g_game.getMonstersOnline()); return 1; } int LuaScriptInterface::luaGameGetPlayerCount(lua_State* L) { // Game.getPlayerCount() lua_pushnumber(L, g_game.getPlayersOnline()); return 1; } int LuaScriptInterface::luaGameGetNpcCount(lua_State* L) { // Game.getNpcCount() lua_pushnumber(L, g_game.getNpcsOnline()); return 1; } int LuaScriptInterface::luaGameGetTowns(lua_State* L) { // Game.getTowns() const auto& towns = g_game.map.towns.getTowns(); lua_createtable(L, towns.size(), 0); int index = 0; for (auto townEntry : towns) { pushUserdata(L, townEntry.second); setMetatable(L, -1, "Town"); lua_rawseti(L, -2, ++index); } return 1; } int LuaScriptInterface::luaGameGetHouses(lua_State* L) { // Game.getHouses() const auto& houses = g_game.map.houses.getHouses(); lua_createtable(L, houses.size(), 0); int index = 0; for (auto houseEntry : houses) { pushUserdata(L, houseEntry.second); setMetatable(L, -1, "House"); lua_rawseti(L, -2, ++index); } return 1; } int LuaScriptInterface::luaGameGetGameState(lua_State* L) { // Game.getGameState() lua_pushnumber(L, g_game.getGameState()); return 1; } int LuaScriptInterface::luaGameSetGameState(lua_State* L) { // Game.setGameState(state) GameState_t state = getNumber(L, 1); g_game.setGameState(state); pushBoolean(L, true); return 1; } int LuaScriptInterface::luaGameGetWorldType(lua_State* L) { // Game.getWorldType() lua_pushnumber(L, g_game.getWorldType()); return 1; } int LuaScriptInterface::luaGameSetWorldType(lua_State* L) { // Game.setWorldType(type) WorldType_t type = getNumber(L, 1); g_game.setWorldType(type); pushBoolean(L, true); return 1; } int LuaScriptInterface::luaGameGetReturnMessage(lua_State* L) { // Game.getReturnMessage(value) ReturnValue value = getNumber(L, 1); pushString(L, getReturnMessage(value)); return 1; } int LuaScriptInterface::luaGameCreateItem(lua_State* L) { // Game.createItem(itemId[, count[, position]]) uint16_t count = getNumber(L, 2, 1); uint16_t id; if (isNumber(L, 1)) { id = getNumber(L, 1); } else { id = Item::items.getItemIdByName(getString(L, 1)); if (id == 0) { lua_pushnil(L); return 1; } } const ItemType& it = Item::items[id]; if (it.stackable) { count = std::min(count, 100); } Item* item = Item::CreateItem(id, count); if (!item) { lua_pushnil(L); return 1; } if (lua_gettop(L) >= 3) { const Position& position = getPosition(L, 3); Tile* tile = g_game.map.getTile(position); if (!tile) { delete item; lua_pushnil(L); return 1; } g_game.internalAddItem(tile, item, INDEX_WHEREEVER, FLAG_NOLIMIT); } else { getScriptEnv()->addTempItem(item); item->setParent(VirtualCylinder::virtualCylinder); } pushUserdata(L, item); setItemMetatable(L, -1, item); return 1; } int LuaScriptInterface::luaGameCreateContainer(lua_State* L) { // Game.createContainer(itemId, size[, position]) uint16_t size = getNumber(L, 2); uint16_t id; if (isNumber(L, 1)) { id = getNumber(L, 1); } else { id = Item::items.getItemIdByName(getString(L, 1)); if (id == 0) { lua_pushnil(L); return 1; } } Container* container = Item::CreateItemAsContainer(id, size); if (!container) { lua_pushnil(L); return 1; } if (lua_gettop(L) >= 3) { const Position& position = getPosition(L, 3); Tile* tile = g_game.map.getTile(position); if (!tile) { delete container; lua_pushnil(L); return 1; } g_game.internalAddItem(tile, container, INDEX_WHEREEVER, FLAG_NOLIMIT); } else { getScriptEnv()->addTempItem(container); container->setParent(VirtualCylinder::virtualCylinder); } pushUserdata(L, container); setMetatable(L, -1, "Container"); return 1; } int LuaScriptInterface::luaGameCreateMonster(lua_State* L) { // Game.createMonster(monsterName, position[, extended = false[, force = false]]) Monster* monster = Monster::createMonster(getString(L, 1)); if (!monster) { lua_pushnil(L); return 1; } const Position& position = getPosition(L, 2); bool extended = getBoolean(L, 3, false); bool force = getBoolean(L, 4, false); if (g_game.placeCreature(monster, position, extended, force)) { pushUserdata(L, monster); setMetatable(L, -1, "Monster"); } else { delete monster; lua_pushnil(L); } return 1; } int LuaScriptInterface::luaGameCreateNpc(lua_State* L) { // Game.createNpc(npcName, position[, extended = false[, force = false]]) Npc* npc = Npc::createNpc(getString(L, 1)); if (!npc) { lua_pushnil(L); return 1; } const Position& position = getPosition(L, 2); bool extended = getBoolean(L, 3, false); bool force = getBoolean(L, 4, false); if (g_game.placeCreature(npc, position, extended, force)) { pushUserdata(L, npc); setMetatable(L, -1, "Npc"); } else { delete npc; lua_pushnil(L); } return 1; } int LuaScriptInterface::luaGameCreateTile(lua_State* L) { // Game.createTile(x, y, z[, isDynamic = false]) // Game.createTile(position[, isDynamic = false]) Position position; bool isDynamic; if (isTable(L, 1)) { position = getPosition(L, 1); isDynamic = getBoolean(L, 2, false); } else { position.x = getNumber(L, 1); position.y = getNumber(L, 2); position.z = getNumber(L, 3); isDynamic = getBoolean(L, 4, false); } Tile* tile = g_game.map.getTile(position); if (!tile) { if (isDynamic) { tile = new DynamicTile(position.x, position.y, position.z); } else { tile = new StaticTile(position.x, position.y, position.z); } g_game.map.setTile(position, tile); } pushUserdata(L, tile); setMetatable(L, -1, "Tile"); return 1; } int LuaScriptInterface::luaGameStartRaid(lua_State* L) { // Game.startRaid(raidName) const std::string& raidName = getString(L, 1); Raid* raid = g_game.raids.getRaidByName(raidName); if (!raid || !raid->isLoaded()) { lua_pushnil(L); return 1; } if (g_game.raids.getRunning()) { lua_pushnil(L); return 1; } g_game.raids.setRunning(raid); raid->startRaid(); lua_pushnumber(L, RETURNVALUE_NOERROR); return 1; } int LuaScriptInterface::luaGameReload(lua_State* L) { // Game.reload(reloadType) ReloadTypes_t reloadType = getNumber(L, 1); if (!reloadType) { lua_pushnil(L); return 1; } if (reloadType == RELOAD_TYPE_GLOBAL) { pushBoolean(L, g_luaEnvironment.loadFile("data/global.lua") == 0); } else { pushBoolean(L, g_game.reload(reloadType)); } lua_gc(g_luaEnvironment.getLuaState(), LUA_GCCOLLECT, 0); return 1; } // Variant int LuaScriptInterface::luaVariantCreate(lua_State* L) { // Variant(number or string or position or thing) LuaVariant variant; if (isUserdata(L, 2)) { if (Thing* thing = getThing(L, 2)) { variant.type = VARIANT_TARGETPOSITION; variant.pos = thing->getPosition(); } } else if (isTable(L, 2)) { variant.type = VARIANT_POSITION; variant.pos = getPosition(L, 2); } else if (isNumber(L, 2)) { variant.type = VARIANT_NUMBER; variant.number = getNumber(L, 2); } else if (isString(L, 2)) { variant.type = VARIANT_STRING; variant.text = getString(L, 2); } pushVariant(L, variant); return 1; } int LuaScriptInterface::luaVariantGetNumber(lua_State* L) { // Variant:getNumber() const LuaVariant& variant = getVariant(L, 1); if (variant.type == VARIANT_NUMBER) { lua_pushnumber(L, variant.number); } else { lua_pushnumber(L, 0); } return 1; } int LuaScriptInterface::luaVariantGetString(lua_State* L) { // Variant:getString() const LuaVariant& variant = getVariant(L, 1); if (variant.type == VARIANT_STRING) { pushString(L, variant.text); } else { pushString(L, std::string()); } return 1; } int LuaScriptInterface::luaVariantGetPosition(lua_State* L) { // Variant:getPosition() const LuaVariant& variant = getVariant(L, 1); if (variant.type == VARIANT_POSITION || variant.type == VARIANT_TARGETPOSITION) { pushPosition(L, variant.pos); } else { pushPosition(L, Position()); } return 1; } // Position int LuaScriptInterface::luaPositionCreate(lua_State* L) { // Position([x = 0[, y = 0[, z = 0[, stackpos = 0]]]]) // Position([position]) if (lua_gettop(L) <= 1) { pushPosition(L, Position()); return 1; } int32_t stackpos; if (isTable(L, 2)) { const Position& position = getPosition(L, 2, stackpos); pushPosition(L, position, stackpos); } else { uint16_t x = getNumber(L, 2, 0); uint16_t y = getNumber(L, 3, 0); uint8_t z = getNumber(L, 4, 0); stackpos = getNumber(L, 5, 0); pushPosition(L, Position(x, y, z), stackpos); } return 1; } int LuaScriptInterface::luaPositionAdd(lua_State* L) { // positionValue = position + positionEx int32_t stackpos; const Position& position = getPosition(L, 1, stackpos); Position positionEx; if (stackpos == 0) { positionEx = getPosition(L, 2, stackpos); } else { positionEx = getPosition(L, 2); } pushPosition(L, position + positionEx, stackpos); return 1; } int LuaScriptInterface::luaPositionSub(lua_State* L) { // positionValue = position - positionEx int32_t stackpos; const Position& position = getPosition(L, 1, stackpos); Position positionEx; if (stackpos == 0) { positionEx = getPosition(L, 2, stackpos); } else { positionEx = getPosition(L, 2); } pushPosition(L, position - positionEx, stackpos); return 1; } int LuaScriptInterface::luaPositionCompare(lua_State* L) { // position == positionEx const Position& positionEx = getPosition(L, 2); const Position& position = getPosition(L, 1); pushBoolean(L, position == positionEx); return 1; } int LuaScriptInterface::luaPositionGetDistance(lua_State* L) { // position:getDistance(positionEx) const Position& positionEx = getPosition(L, 2); const Position& position = getPosition(L, 1); lua_pushnumber(L, std::max( std::max( std::abs(Position::getDistanceX(position, positionEx)), std::abs(Position::getDistanceY(position, positionEx)) ), std::abs(Position::getDistanceZ(position, positionEx)) )); return 1; } int LuaScriptInterface::luaPositionIsSightClear(lua_State* L) { // position:isSightClear(positionEx[, sameFloor = true]) bool sameFloor = getBoolean(L, 3, true); const Position& positionEx = getPosition(L, 2); const Position& position = getPosition(L, 1); pushBoolean(L, g_game.isSightClear(position, positionEx, sameFloor)); return 1; } int LuaScriptInterface::luaPositionSendMagicEffect(lua_State* L) { // position:sendMagicEffect(magicEffect[, player = nullptr]) SpectatorVec list; if (lua_gettop(L) >= 3) { Player* player = getPlayer(L, 3); if (player) { list.insert(player); } } MagicEffectClasses magicEffect = getNumber(L, 2); const Position& position = getPosition(L, 1); if (!list.empty()) { Game::addMagicEffect(list, position, magicEffect); } else { g_game.addMagicEffect(position, magicEffect); } pushBoolean(L, true); return 1; } int LuaScriptInterface::luaPositionSendDistanceEffect(lua_State* L) { // position:sendDistanceEffect(positionEx, distanceEffect[, player = nullptr]) SpectatorVec list; if (lua_gettop(L) >= 4) { Player* player = getPlayer(L, 4); if (player) { list.insert(player); } } ShootType_t distanceEffect = getNumber(L, 3); const Position& positionEx = getPosition(L, 2); const Position& position = getPosition(L, 1); if (!list.empty()) { Game::addDistanceEffect(list, position, positionEx, distanceEffect); } else { g_game.addDistanceEffect(position, positionEx, distanceEffect); } pushBoolean(L, true); return 1; } int LuaScriptInterface::luaPositionSendMonsterSay(lua_State * L) { // position:sendMonsterSay(text) const std::string& text = getString(L, 2); const Position& position = getPosition(L, 1); g_game.addMonsterSayText(position, text); pushBoolean(L, true); return 1; } // Tile int LuaScriptInterface::luaTileCreate(lua_State* L) { // Tile(x, y, z) // Tile(position) Tile* tile; if (isTable(L, 2)) { tile = g_game.map.getTile(getPosition(L, 2)); } else { uint8_t z = getNumber(L, 4); uint16_t y = getNumber(L, 3); uint16_t x = getNumber(L, 2); tile = g_game.map.getTile(x, y, z); } if (tile) { pushUserdata(L, tile); setMetatable(L, -1, "Tile"); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaTileGetPosition(lua_State* L) { // tile:getPosition() Tile* tile = getUserdata(L, 1); if (tile) { pushPosition(L, tile->getPosition()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaTileGetGround(lua_State* L) { // tile:getGround() Tile* tile = getUserdata(L, 1); if (tile && tile->getGround()) { pushUserdata(L, tile->getGround()); setItemMetatable(L, -1, tile->getGround()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaTileGetThing(lua_State* L) { // tile:getThing(index) int32_t index = getNumber(L, 2); Tile* tile = getUserdata(L, 1); if (!tile) { lua_pushnil(L); return 1; } Thing* thing = tile->getThing(index); if (!thing) { lua_pushnil(L); return 1; } if (Creature* creature = thing->getCreature()) { pushUserdata(L, creature); setCreatureMetatable(L, -1, creature); } else if (Item* item = thing->getItem()) { pushUserdata(L, item); setItemMetatable(L, -1, item); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaTileGetThingCount(lua_State* L) { // tile:getThingCount() Tile* tile = getUserdata(L, 1); if (tile) { lua_pushnumber(L, tile->getThingCount()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaTileGetTopVisibleThing(lua_State* L) { // tile:getTopVisibleThing(creature) Creature* creature = getCreature(L, 2); Tile* tile = getUserdata(L, 1); if (!tile) { lua_pushnil(L); return 1; } Thing* thing = tile->getTopVisibleThing(creature); if (!thing) { lua_pushnil(L); return 1; } if (Creature* visibleCreature = thing->getCreature()) { pushUserdata(L, visibleCreature); setCreatureMetatable(L, -1, visibleCreature); } else if (Item* visibleItem = thing->getItem()) { pushUserdata(L, visibleItem); setItemMetatable(L, -1, visibleItem); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaTileGetTopTopItem(lua_State* L) { // tile:getTopTopItem() Tile* tile = getUserdata(L, 1); if (!tile) { lua_pushnil(L); return 1; } Item* item = tile->getTopTopItem(); if (item) { pushUserdata(L, item); setItemMetatable(L, -1, item); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaTileGetTopDownItem(lua_State* L) { // tile:getTopDownItem() Tile* tile = getUserdata(L, 1); if (!tile) { lua_pushnil(L); return 1; } Item* item = tile->getTopDownItem(); if (item) { pushUserdata(L, item); setItemMetatable(L, -1, item); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaTileGetFieldItem(lua_State* L) { // tile:getFieldItem() Tile* tile = getUserdata(L, 1); if (!tile) { lua_pushnil(L); return 1; } Item* item = tile->getFieldItem(); if (item) { pushUserdata(L, item); setItemMetatable(L, -1, item); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaTileGetItemById(lua_State* L) { // tile:getItemById(itemId[, subType = -1]) Tile* tile = getUserdata(L, 1); if (!tile) { lua_pushnil(L); return 1; } uint16_t itemId; if (isNumber(L, 2)) { itemId = getNumber(L, 2); } else { itemId = Item::items.getItemIdByName(getString(L, 2)); if (itemId == 0) { lua_pushnil(L); return 1; } } int32_t subType = getNumber(L, 3, -1); Item* item = g_game.findItemOfType(tile, itemId, false, subType); if (item) { pushUserdata(L, item); setItemMetatable(L, -1, item); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaTileGetItemByType(lua_State* L) { // tile:getItemByType(itemType) Tile* tile = getUserdata(L, 1); if (!tile) { lua_pushnil(L); return 1; } bool found; ItemTypes_t itemType = getNumber(L, 2); switch (itemType) { case ITEM_TYPE_TELEPORT: found = tile->hasFlag(TILESTATE_TELEPORT); break; case ITEM_TYPE_MAGICFIELD: found = tile->hasFlag(TILESTATE_MAGICFIELD); break; case ITEM_TYPE_MAILBOX: found = tile->hasFlag(TILESTATE_MAILBOX); break; case ITEM_TYPE_BED: found = tile->hasFlag(TILESTATE_BED); break; case ITEM_TYPE_DEPOT: found = tile->hasFlag(TILESTATE_DEPOT); break; default: found = true; break; } if (!found) { lua_pushnil(L); return 1; } if (Item* item = tile->getGround()) { const ItemType& it = Item::items[item->getID()]; if (it.type == itemType) { pushUserdata(L, item); setItemMetatable(L, -1, item); return 1; } } if (const TileItemVector* items = tile->getItemList()) { for (Item* item : *items) { const ItemType& it = Item::items[item->getID()]; if (it.type == itemType) { pushUserdata(L, item); setItemMetatable(L, -1, item); return 1; } } } lua_pushnil(L); return 1; } int LuaScriptInterface::luaTileGetItemByTopOrder(lua_State* L) { // tile:getItemByTopOrder(topOrder) Tile* tile = getUserdata(L, 1); if (!tile) { lua_pushnil(L); return 1; } int32_t topOrder = getNumber(L, 2); Item* item = tile->getItemByTopOrder(topOrder); if (!item) { lua_pushnil(L); return 1; } pushUserdata(L, item); setItemMetatable(L, -1, item); return 1; } int LuaScriptInterface::luaTileGetItemCountById(lua_State* L) { // tile:getItemCountById(itemId[, subType = -1]) Tile* tile = getUserdata(L, 1); if (!tile) { lua_pushnil(L); return 1; } int32_t subType = getNumber(L, 3, -1); uint16_t itemId; if (isNumber(L, 2)) { itemId = getNumber(L, 2); } else { itemId = Item::items.getItemIdByName(getString(L, 2)); if (itemId == 0) { lua_pushnil(L); return 1; } } lua_pushnumber(L, tile->getItemTypeCount(itemId, subType)); return 1; } int LuaScriptInterface::luaTileGetBottomCreature(lua_State* L) { // tile:getBottomCreature() Tile* tile = getUserdata(L, 1); if (!tile) { lua_pushnil(L); return 1; } const Creature* creature = tile->getBottomCreature(); if (!creature) { lua_pushnil(L); return 1; } pushUserdata(L, creature); setCreatureMetatable(L, -1, creature); return 1; } int LuaScriptInterface::luaTileGetTopCreature(lua_State* L) { // tile:getTopCreature() Tile* tile = getUserdata(L, 1); if (!tile) { lua_pushnil(L); return 1; } Creature* creature = tile->getTopCreature(); if (!creature) { lua_pushnil(L); return 1; } pushUserdata(L, creature); setCreatureMetatable(L, -1, creature); return 1; } int LuaScriptInterface::luaTileGetBottomVisibleCreature(lua_State* L) { // tile:getBottomVisibleCreature(creature) Tile* tile = getUserdata(L, 1); if (!tile) { lua_pushnil(L); return 1; } Creature* creature = getCreature(L, 2); if (!creature) { lua_pushnil(L); return 1; } const Creature* visibleCreature = tile->getBottomVisibleCreature(creature); if (visibleCreature) { pushUserdata(L, visibleCreature); setCreatureMetatable(L, -1, visibleCreature); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaTileGetTopVisibleCreature(lua_State* L) { // tile:getTopVisibleCreature(creature) Tile* tile = getUserdata(L, 1); if (!tile) { lua_pushnil(L); return 1; } Creature* creature = getCreature(L, 2); if (!creature) { lua_pushnil(L); return 1; } Creature* visibleCreature = tile->getTopVisibleCreature(creature); if (visibleCreature) { pushUserdata(L, visibleCreature); setCreatureMetatable(L, -1, visibleCreature); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaTileGetItems(lua_State* L) { // tile:getItems() Tile* tile = getUserdata(L, 1); if (!tile) { lua_pushnil(L); return 1; } TileItemVector* itemVector = tile->getItemList(); if (!itemVector) { lua_pushnil(L); return 1; } lua_createtable(L, itemVector->size(), 0); int index = 0; for (Item* item : *itemVector) { pushUserdata(L, item); setItemMetatable(L, -1, item); lua_rawseti(L, -2, ++index); } return 1; } int LuaScriptInterface::luaTileGetItemCount(lua_State* L) { // tile:getItemCount() Tile* tile = getUserdata(L, 1); if (!tile) { lua_pushnil(L); return 1; } lua_pushnumber(L, tile->getItemCount()); return 1; } int LuaScriptInterface::luaTileGetDownItemCount(lua_State* L) { // tile:getDownItemCount() Tile* tile = getUserdata(L, 1); if (tile) { lua_pushnumber(L, tile->getDownItemCount()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaTileGetTopItemCount(lua_State* L) { // tile:getTopItemCount() Tile* tile = getUserdata(L, 1); if (!tile) { lua_pushnil(L); return 1; } lua_pushnumber(L, tile->getTopItemCount()); return 1; } int LuaScriptInterface::luaTileGetCreatures(lua_State* L) { // tile:getCreatures() Tile* tile = getUserdata(L, 1); if (!tile) { lua_pushnil(L); return 1; } CreatureVector* creatureVector = tile->getCreatures(); if (!creatureVector) { lua_pushnil(L); return 1; } lua_createtable(L, creatureVector->size(), 0); int index = 0; for (Creature* creature : *creatureVector) { pushUserdata(L, creature); setCreatureMetatable(L, -1, creature); lua_rawseti(L, -2, ++index); } return 1; } int LuaScriptInterface::luaTileGetCreatureCount(lua_State* L) { // tile:getCreatureCount() Tile* tile = getUserdata(L, 1); if (!tile) { lua_pushnil(L); return 1; } lua_pushnumber(L, tile->getCreatureCount()); return 1; } int LuaScriptInterface::luaTileHasProperty(lua_State* L) { // tile:hasProperty(property[, item]) Tile* tile = getUserdata(L, 1); if (!tile) { lua_pushnil(L); return 1; } Item* item; if (lua_gettop(L) >= 3) { item = getUserdata(L, 3); } else { item = nullptr; } ITEMPROPERTY property = getNumber(L, 2); if (item) { pushBoolean(L, tile->hasProperty(item, property)); } else { pushBoolean(L, tile->hasProperty(property)); } return 1; } int LuaScriptInterface::luaTileGetThingIndex(lua_State* L) { // tile:getThingIndex(thing) Tile* tile = getUserdata(L, 1); if (!tile) { lua_pushnil(L); return 1; } Thing* thing = getThing(L, 2); if (thing) { lua_pushnumber(L, tile->getThingIndex(thing)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaTileHasFlag(lua_State* L) { // tile:hasFlag(flag) Tile* tile = getUserdata(L, 1); if (tile) { tileflags_t flag = getNumber(L, 2); pushBoolean(L, tile->hasFlag(flag)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaTileQueryAdd(lua_State* L) { // tile:queryAdd(thing[, flags]) Tile* tile = getUserdata(L, 1); if (!tile) { lua_pushnil(L); return 1; } Thing* thing = getThing(L, 2); if (thing) { uint32_t flags = getNumber(L, 3, 0); lua_pushnumber(L, tile->queryAdd(0, *thing, 1, flags)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaTileGetHouse(lua_State* L) { // tile:getHouse() Tile* tile = getUserdata(L, 1); if (!tile) { lua_pushnil(L); return 1; } if (HouseTile* houseTile = dynamic_cast(tile)) { pushUserdata(L, houseTile->getHouse()); setMetatable(L, -1, "House"); } else { lua_pushnil(L); } return 1; } // NetworkMessage int LuaScriptInterface::luaNetworkMessageCreate(lua_State* L) { // NetworkMessage() pushUserdata(L, new NetworkMessage); setMetatable(L, -1, "NetworkMessage"); return 1; } int LuaScriptInterface::luaNetworkMessageDelete(lua_State* L) { NetworkMessage** messagePtr = getRawUserdata(L, 1); if (messagePtr && *messagePtr) { delete *messagePtr; *messagePtr = nullptr; } return 0; } int LuaScriptInterface::luaNetworkMessageGetByte(lua_State* L) { // networkMessage:getByte() NetworkMessage* message = getUserdata(L, 1); if (message) { lua_pushnumber(L, message->getByte()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaNetworkMessageGetU16(lua_State* L) { // networkMessage:getU16() NetworkMessage* message = getUserdata(L, 1); if (message) { lua_pushnumber(L, message->get()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaNetworkMessageGetU32(lua_State* L) { // networkMessage:getU32() NetworkMessage* message = getUserdata(L, 1); if (message) { lua_pushnumber(L, message->get()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaNetworkMessageGetU64(lua_State* L) { // networkMessage:getU64() NetworkMessage* message = getUserdata(L, 1); if (message) { lua_pushnumber(L, message->get()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaNetworkMessageGetString(lua_State* L) { // networkMessage:getString() NetworkMessage* message = getUserdata(L, 1); if (message) { pushString(L, message->getString()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaNetworkMessageGetPosition(lua_State* L) { // networkMessage:getPosition() NetworkMessage* message = getUserdata(L, 1); if (message) { pushPosition(L, message->getPosition()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaNetworkMessageAddByte(lua_State* L) { // networkMessage:addByte(number) uint8_t number = getNumber(L, 2); NetworkMessage* message = getUserdata(L, 1); if (message) { message->addByte(number); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaNetworkMessageAddU16(lua_State* L) { // networkMessage:addU16(number) uint16_t number = getNumber(L, 2); NetworkMessage* message = getUserdata(L, 1); if (message) { message->add(number); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaNetworkMessageAddU32(lua_State* L) { // networkMessage:addU32(number) uint32_t number = getNumber(L, 2); NetworkMessage* message = getUserdata(L, 1); if (message) { message->add(number); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaNetworkMessageAddU64(lua_State* L) { // networkMessage:addU64(number) uint64_t number = getNumber(L, 2); NetworkMessage* message = getUserdata(L, 1); if (message) { message->add(number); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaNetworkMessageAddString(lua_State* L) { // networkMessage:addString(string) const std::string& string = getString(L, 2); NetworkMessage* message = getUserdata(L, 1); if (message) { message->addString(string); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaNetworkMessageAddPosition(lua_State* L) { // networkMessage:addPosition(position) const Position& position = getPosition(L, 2); NetworkMessage* message = getUserdata(L, 1); if (message) { message->addPosition(position); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaNetworkMessageAddDouble(lua_State* L) { // networkMessage:addDouble(number) double number = getNumber(L, 2); NetworkMessage* message = getUserdata(L, 1); if (message) { message->addDouble(number); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaNetworkMessageAddItem(lua_State* L) { // networkMessage:addItem(item) Item* item = getUserdata(L, 2); if (!item) { reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); lua_pushnil(L); return 1; } NetworkMessage* message = getUserdata(L, 1); if (message) { message->addItem(item); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaNetworkMessageAddItemId(lua_State* L) { // networkMessage:addItemId(itemId) NetworkMessage* message = getUserdata(L, 1); if (!message) { lua_pushnil(L); return 1; } uint16_t itemId; if (isNumber(L, 2)) { itemId = getNumber(L, 2); } else { itemId = Item::items.getItemIdByName(getString(L, 2)); if (itemId == 0) { lua_pushnil(L); return 1; } } message->addItemId(itemId); pushBoolean(L, true); return 1; } int LuaScriptInterface::luaNetworkMessageReset(lua_State* L) { // networkMessage:reset() NetworkMessage* message = getUserdata(L, 1); if (message) { message->reset(); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaNetworkMessageSkipBytes(lua_State* L) { // networkMessage:skipBytes(number) int16_t number = getNumber(L, 2); NetworkMessage* message = getUserdata(L, 1); if (message) { message->skipBytes(number); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaNetworkMessageSendToPlayer(lua_State* L) { // networkMessage:sendToPlayer(player) NetworkMessage* message = getUserdata(L, 1); if (!message) { lua_pushnil(L); return 1; } Player* player = getPlayer(L, 2); if (player) { player->sendNetworkMessage(*message); pushBoolean(L, true); } else { reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); lua_pushnil(L); } return 1; } // Item int LuaScriptInterface::luaItemCreate(lua_State* L) { // Item(uid) uint32_t id = getNumber(L, 2); Item* item = getScriptEnv()->getItemByUID(id); if (item) { pushUserdata(L, item); setItemMetatable(L, -1, item); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemIsItem(lua_State* L) { // item:isItem() pushBoolean(L, getUserdata(L, 1) != nullptr); return 1; } int LuaScriptInterface::luaItemGetParent(lua_State* L) { // item:getParent() Item* item = getUserdata(L, 1); if (!item) { lua_pushnil(L); return 1; } Cylinder* parent = item->getParent(); if (!parent) { lua_pushnil(L); return 1; } pushCylinder(L, parent); return 1; } int LuaScriptInterface::luaItemGetTopParent(lua_State* L) { // item:getTopParent() Item* item = getUserdata(L, 1); if (!item) { lua_pushnil(L); return 1; } Cylinder* topParent = item->getTopParent(); if (!topParent) { lua_pushnil(L); return 1; } pushCylinder(L, topParent); return 1; } int LuaScriptInterface::luaItemGetId(lua_State* L) { // item:getId() Item* item = getUserdata(L, 1); if (item) { lua_pushnumber(L, item->getID()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemClone(lua_State* L) { // item:clone() Item* item = getUserdata(L, 1); if (!item) { lua_pushnil(L); return 1; } Item* clone = item->clone(); if (!clone) { lua_pushnil(L); return 1; } getScriptEnv()->addTempItem(clone); clone->setParent(VirtualCylinder::virtualCylinder); pushUserdata(L, clone); setItemMetatable(L, -1, clone); return 1; } int LuaScriptInterface::luaItemSplit(lua_State* L) { // item:split([count = 1]) Item** itemPtr = getRawUserdata(L, 1); if (!itemPtr) { lua_pushnil(L); return 1; } Item* item = *itemPtr; if (!item || !item->isStackable()) { lua_pushnil(L); return 1; } uint16_t count = std::min(getNumber(L, 2, 1), item->getItemCount()); uint16_t diff = item->getItemCount() - count; Item* splitItem = item->clone(); if (!splitItem) { lua_pushnil(L); return 1; } ScriptEnvironment* env = getScriptEnv(); uint32_t uid = env->addThing(item); Item* newItem = g_game.transformItem(item, item->getID(), diff); if (item->isRemoved()) { env->removeItemByUID(uid); } if (newItem && newItem != item) { env->insertItem(uid, newItem); } *itemPtr = newItem; splitItem->setParent(VirtualCylinder::virtualCylinder); env->addTempItem(splitItem); pushUserdata(L, splitItem); setItemMetatable(L, -1, splitItem); return 1; } int LuaScriptInterface::luaItemRemove(lua_State* L) { // item:remove([count = -1]) Item* item = getUserdata(L, 1); if (item) { int32_t count = getNumber(L, 2, -1); pushBoolean(L, g_game.internalRemoveItem(item, count) == RETURNVALUE_NOERROR); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemGetMovementId(lua_State* L) { // item:getMovementId() Item* item = getUserdata(L, 1); if (item) { lua_pushnumber(L, item->getMovementId()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemGetActionId(lua_State* L) { // item:getActionId() Item* item = getUserdata(L, 1); if (item) { lua_pushnumber(L, item->getActionId()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemSetActionId(lua_State* L) { // item:setActionId(actionId) uint16_t actionId = getNumber(L, 2); Item* item = getUserdata(L, 1); if (item) { item->setActionId(actionId); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemSetMovementId(lua_State* L) { // item:setMovementId(movementId) uint16_t movementId = getNumber(L, 2); Item* item = getUserdata(L, 1); if (item) { item->setMovementID(movementId); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemGetUniqueId(lua_State * L) { // item:getUniqueId() Item* item = getUserdata(L, 1); if (item) { lua_pushnumber(L, getScriptEnv()->addThing(item)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemGetCount(lua_State* L) { // item:getCount() Item* item = getUserdata(L, 1); if (item) { lua_pushnumber(L, item->getItemCount()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemGetCharges(lua_State* L) { // item:getCharges() Item* item = getUserdata(L, 1); if (item) { lua_pushnumber(L, item->getCharges()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemGetFluidType(lua_State* L) { // item:getFluidType() Item* item = getUserdata(L, 1); if (item) { lua_pushnumber(L, item->getFluidType()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemGetWeight(lua_State* L) { // item:getWeight() Item* item = getUserdata(L, 1); if (item) { lua_pushnumber(L, item->getWeight()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemGetSubType(lua_State* L) { // item:getSubType() Item* item = getUserdata(L, 1); if (item) { lua_pushnumber(L, item->getSubType()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemGetName(lua_State* L) { // item:getName() Item* item = getUserdata(L, 1); if (item) { pushString(L, item->getName()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemGetPluralName(lua_State* L) { // item:getPluralName() Item* item = getUserdata(L, 1); if (item) { pushString(L, item->getPluralName()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemGetArticle(lua_State* L) { // item:getArticle() Item* item = getUserdata(L, 1); if (item) { pushString(L, item->getArticle()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemGetPosition(lua_State* L) { // item:getPosition() Item* item = getUserdata(L, 1); if (item) { pushPosition(L, item->getPosition()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemGetTile(lua_State* L) { // item:getTile() Item* item = getUserdata(L, 1); if (!item) { lua_pushnil(L); return 1; } Tile* tile = item->getTile(); if (tile) { pushUserdata(L, tile); setMetatable(L, -1, "Tile"); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemHasAttribute(lua_State* L) { // item:hasAttribute(key) Item* item = getUserdata(L, 1); if (!item) { lua_pushnil(L); return 1; } itemAttrTypes attribute; if (isNumber(L, 2)) { attribute = getNumber(L, 2); } else if (isString(L, 2)) { attribute = stringToItemAttribute(getString(L, 2)); } else { attribute = ITEM_ATTRIBUTE_NONE; } pushBoolean(L, item->hasAttribute(attribute)); return 1; } int LuaScriptInterface::luaItemGetAttribute(lua_State* L) { // item:getAttribute(key) Item* item = getUserdata(L, 1); if (!item) { lua_pushnil(L); return 1; } itemAttrTypes attribute; if (isNumber(L, 2)) { attribute = getNumber(L, 2); } else if (isString(L, 2)) { attribute = stringToItemAttribute(getString(L, 2)); } else { attribute = ITEM_ATTRIBUTE_NONE; } if (ItemAttributes::isIntAttrType(attribute)) { lua_pushnumber(L, item->getIntAttr(attribute)); } else if (ItemAttributes::isStrAttrType(attribute)) { pushString(L, item->getStrAttr(attribute)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemSetAttribute(lua_State* L) { // item:setAttribute(key, value) Item* item = getUserdata(L, 1); if (!item) { lua_pushnil(L); return 1; } itemAttrTypes attribute; if (isNumber(L, 2)) { attribute = getNumber(L, 2); } else if (isString(L, 2)) { attribute = stringToItemAttribute(getString(L, 2)); } else { attribute = ITEM_ATTRIBUTE_NONE; } if (ItemAttributes::isIntAttrType(attribute)) { item->setIntAttr(attribute, getNumber(L, 3)); pushBoolean(L, true); } else if (ItemAttributes::isStrAttrType(attribute)) { item->setStrAttr(attribute, getString(L, 3)); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemRemoveAttribute(lua_State* L) { // item:removeAttribute(key) Item* item = getUserdata(L, 1); if (!item) { lua_pushnil(L); return 1; } itemAttrTypes attribute; if (isNumber(L, 2)) { attribute = getNumber(L, 2); } else if (isString(L, 2)) { attribute = stringToItemAttribute(getString(L, 2)); } else { attribute = ITEM_ATTRIBUTE_NONE; } item->removeAttribute(attribute); pushBoolean(L, true); return 1; } int LuaScriptInterface::luaItemMoveTo(lua_State* L) { // item:moveTo(position or cylinder) Item** itemPtr = getRawUserdata(L, 1); if (!itemPtr) { lua_pushnil(L); return 1; } Item* item = *itemPtr; if (!item || item->isRemoved()) { lua_pushnil(L); return 1; } Cylinder* toCylinder; if (isUserdata(L, 2)) { const LuaDataType type = getUserdataType(L, 2); switch (type) { case LuaData_Container: toCylinder = getUserdata(L, 2); break; case LuaData_Player: toCylinder = getUserdata(L, 2); break; case LuaData_Tile: toCylinder = getUserdata(L, 2); break; default: toCylinder = nullptr; break; } } else { toCylinder = g_game.map.getTile(getPosition(L, 2)); } if (!toCylinder) { lua_pushnil(L); return 1; } if (item->getParent() == toCylinder) { pushBoolean(L, true); return 1; } if (item->getParent() == VirtualCylinder::virtualCylinder) { pushBoolean(L, g_game.internalAddItem(toCylinder, item) == RETURNVALUE_NOERROR); } else { Item* moveItem = nullptr; ReturnValue ret = g_game.internalMoveItem(item->getParent(), toCylinder, INDEX_WHEREEVER, item, item->getItemCount(), &moveItem, FLAG_NOLIMIT | FLAG_IGNOREBLOCKITEM | FLAG_IGNOREBLOCKCREATURE | FLAG_IGNORENOTMOVEABLE); if (moveItem) { *itemPtr = moveItem; } pushBoolean(L, ret == RETURNVALUE_NOERROR); } return 1; } int LuaScriptInterface::luaItemTransform(lua_State* L) { // item:transform(itemId[, count/subType = -1]) Item** itemPtr = getRawUserdata(L, 1); if (!itemPtr) { lua_pushnil(L); return 1; } Item*& item = *itemPtr; if (!item) { lua_pushnil(L); return 1; } uint16_t itemId; if (isNumber(L, 2)) { itemId = getNumber(L, 2); } else { itemId = Item::items.getItemIdByName(getString(L, 2)); if (itemId == 0) { lua_pushnil(L); return 1; } } int32_t subType = getNumber(L, 3, -1); if (item->getID() == itemId && (subType == -1 || subType == item->getSubType())) { pushBoolean(L, true); return 1; } const ItemType& it = Item::items[itemId]; if (it.stackable) { subType = std::min(subType, 100); } ScriptEnvironment* env = getScriptEnv(); uint32_t uid = env->addThing(item); Item* newItem = g_game.transformItem(item, itemId, subType); if (item->isRemoved()) { env->removeItemByUID(uid); } if (newItem && newItem != item) { env->insertItem(uid, newItem); } item = newItem; pushBoolean(L, true); return 1; } int LuaScriptInterface::luaItemDecay(lua_State* L) { // item:decay() Item* item = getUserdata(L, 1); if (item) { g_game.startDecay(item); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemGetDescription(lua_State* L) { // item:getDescription(distance) Item* item = getUserdata(L, 1); if (item) { int32_t distance = getNumber(L, 2); pushString(L, item->getDescription(distance)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemHasProperty(lua_State* L) { // item:hasProperty(property) Item* item = getUserdata(L, 1); if (item) { ITEMPROPERTY property = getNumber(L, 2); pushBoolean(L, item->hasProperty(property)); } else { lua_pushnil(L); } return 1; } // Container int LuaScriptInterface::luaContainerCreate(lua_State* L) { // Container(uid) uint32_t id = getNumber(L, 2); Container* container = getScriptEnv()->getContainerByUID(id); if (container) { pushUserdata(L, container); setMetatable(L, -1, "Container"); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaContainerGetSize(lua_State* L) { // container:getSize() Container* container = getUserdata(L, 1); if (container) { lua_pushnumber(L, container->size()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaContainerGetCapacity(lua_State* L) { // container:getCapacity() Container* container = getUserdata(L, 1); if (container) { lua_pushnumber(L, container->capacity()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaContainerGetEmptySlots(lua_State* L) { // container:getEmptySlots([recursive = false]) Container* container = getUserdata(L, 1); if (!container) { lua_pushnil(L); return 1; } uint32_t slots = container->capacity() - container->size(); bool recursive = getBoolean(L, 2, false); if (recursive) { for (ContainerIterator it = container->iterator(); it.hasNext(); it.advance()) { if (Container* tmpContainer = (*it)->getContainer()) { slots += tmpContainer->capacity() - tmpContainer->size(); } } } lua_pushnumber(L, slots); return 1; } int LuaScriptInterface::luaContainerGetItemHoldingCount(lua_State* L) { // container:getItemHoldingCount() Container* container = getUserdata(L, 1); if (container) { lua_pushnumber(L, container->getItemHoldingCount()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaContainerGetItem(lua_State* L) { // container:getItem(index) Container* container = getUserdata(L, 1); if (!container) { lua_pushnil(L); return 1; } uint32_t index = getNumber(L, 2); Item* item = container->getItemByIndex(index); if (item) { pushUserdata(L, item); setItemMetatable(L, -1, item); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaContainerHasItem(lua_State* L) { // container:hasItem(item) Item* item = getUserdata(L, 2); Container* container = getUserdata(L, 1); if (container) { pushBoolean(L, container->isHoldingItem(item)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaContainerAddItem(lua_State* L) { // container:addItem(itemId[, count/subType = 1[, index = INDEX_WHEREEVER[, flags = 0]]]) Container* container = getUserdata(L, 1); if (!container) { lua_pushnil(L); return 1; } uint16_t itemId; if (isNumber(L, 2)) { itemId = getNumber(L, 2); } else { itemId = Item::items.getItemIdByName(getString(L, 2)); if (itemId == 0) { lua_pushnil(L); return 1; } } uint32_t subType = getNumber(L, 3, 1); Item* item = Item::CreateItem(itemId, std::min(subType, 100)); if (!item) { lua_pushnil(L); return 1; } int32_t index = getNumber(L, 4, INDEX_WHEREEVER); uint32_t flags = getNumber(L, 5, 0); ReturnValue ret = g_game.internalAddItem(container, item, index, flags); if (ret == RETURNVALUE_NOERROR) { pushUserdata(L, item); setItemMetatable(L, -1, item); } else { delete item; lua_pushnil(L); } return 1; } int LuaScriptInterface::luaContainerAddItemEx(lua_State* L) { // container:addItemEx(item[, index = INDEX_WHEREEVER[, flags = 0]]) Item* item = getUserdata(L, 2); if (!item) { lua_pushnil(L); return 1; } Container* container = getUserdata(L, 1); if (!container) { lua_pushnil(L); return 1; } if (item->getParent() != VirtualCylinder::virtualCylinder) { reportErrorFunc("Item already has a parent"); lua_pushnil(L); return 1; } int32_t index = getNumber(L, 3, INDEX_WHEREEVER); uint32_t flags = getNumber(L, 4, 0); ReturnValue ret = g_game.internalAddItem(container, item, index, flags); if (ret == RETURNVALUE_NOERROR) { ScriptEnvironment::removeTempItem(item); } lua_pushnumber(L, ret); return 1; } int LuaScriptInterface::luaContainerGetItemCountById(lua_State* L) { // container:getItemCountById(itemId[, subType = -1]) Container* container = getUserdata(L, 1); if (!container) { lua_pushnil(L); return 1; } uint16_t itemId; if (isNumber(L, 2)) { itemId = getNumber(L, 2); } else { itemId = Item::items.getItemIdByName(getString(L, 2)); if (itemId == 0) { lua_pushnil(L); return 1; } } int32_t subType = getNumber(L, 3, -1); lua_pushnumber(L, container->getItemTypeCount(itemId, subType)); return 1; } // Teleport int LuaScriptInterface::luaTeleportCreate(lua_State* L) { // Teleport(uid) uint32_t id = getNumber(L, 2); Item* item = getScriptEnv()->getItemByUID(id); if (item && item->getTeleport()) { pushUserdata(L, item); setMetatable(L, -1, "Teleport"); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaTeleportGetDestination(lua_State* L) { // teleport:getDestination() Teleport* teleport = getUserdata(L, 1); if (teleport) { pushPosition(L, teleport->getDestPos()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaTeleportSetDestination(lua_State* L) { // teleport:setDestination(position) Teleport* teleport = getUserdata(L, 1); if (teleport) { teleport->setDestPos(getPosition(L, 2)); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } // Creature int LuaScriptInterface::luaCreatureCreate(lua_State* L) { // Creature(id or name or userdata) Creature* creature; if (isNumber(L, 2)) { creature = g_game.getCreatureByID(getNumber(L, 2)); } else if (isString(L, 2)) { creature = g_game.getCreatureByName(getString(L, 2)); } else if (isUserdata(L, 2)) { LuaDataType type = getUserdataType(L, 2); if (type != LuaData_Player && type != LuaData_Monster && type != LuaData_Npc) { lua_pushnil(L); return 1; } creature = getUserdata(L, 2); } else { creature = nullptr; } if (creature) { pushUserdata(L, creature); setCreatureMetatable(L, -1, creature); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureGetEvents(lua_State* L) { // creature:getEvents(type) Creature* creature = getUserdata(L, 1); if (!creature) { lua_pushnil(L); return 1; } CreatureEventType_t eventType = getNumber(L, 2); const auto& eventList = creature->getCreatureEvents(eventType); lua_createtable(L, eventList.size(), 0); int index = 0; for (CreatureEvent* event : eventList) { pushString(L, event->getName()); lua_rawseti(L, -2, ++index); } return 1; } int LuaScriptInterface::luaCreatureRegisterEvent(lua_State* L) { // creature:registerEvent(name) Creature* creature = getUserdata(L, 1); if (creature) { const std::string& name = getString(L, 2); pushBoolean(L, creature->registerCreatureEvent(name)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureUnregisterEvent(lua_State* L) { // creature:unregisterEvent(name) const std::string& name = getString(L, 2); Creature* creature = getUserdata(L, 1); if (creature) { pushBoolean(L, creature->unregisterCreatureEvent(name)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureIsRemoved(lua_State* L) { // creature:isRemoved() const Creature* creature = getUserdata(L, 1); if (creature) { pushBoolean(L, creature->isRemoved()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureIsCreature(lua_State* L) { // creature:isCreature() pushBoolean(L, getUserdata(L, 1) != nullptr); return 1; } int LuaScriptInterface::luaCreatureIsInGhostMode(lua_State* L) { // creature:isInGhostMode() const Creature* creature = getUserdata(L, 1); if (creature) { pushBoolean(L, creature->isInGhostMode()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureCanSee(lua_State* L) { // creature:canSee(position) const Creature* creature = getUserdata(L, 1); if (creature) { const Position& position = getPosition(L, 2); pushBoolean(L, creature->canSee(position)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureCanSeeCreature(lua_State* L) { // creature:canSeeCreature(creature) const Creature* creature = getUserdata(L, 1); if (creature) { const Creature* otherCreature = getCreature(L, 2); pushBoolean(L, creature->canSeeCreature(otherCreature)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureGetParent(lua_State* L) { // creature:getParent() Creature* creature = getUserdata(L, 1); if (!creature) { lua_pushnil(L); return 1; } Cylinder* parent = creature->getParent(); if (!parent) { lua_pushnil(L); return 1; } pushCylinder(L, parent); return 1; } int LuaScriptInterface::luaCreatureGetId(lua_State* L) { // creature:getId() const Creature* creature = getUserdata(L, 1); if (creature) { lua_pushnumber(L, creature->getID()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureGetName(lua_State* L) { // creature:getName() const Creature* creature = getUserdata(L, 1); if (creature) { pushString(L, creature->getName()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureGetTarget(lua_State* L) { // creature:getTarget() Creature* creature = getUserdata(L, 1); if (!creature) { lua_pushnil(L); return 1; } Creature* target = creature->getAttackedCreature(); if (target) { pushUserdata(L, target); setCreatureMetatable(L, -1, target); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureSetTarget(lua_State* L) { // creature:setTarget(target) Creature* creature = getUserdata(L, 1); if (creature) { Creature* target = getCreature(L, 2); pushBoolean(L, creature->setAttackedCreature(target)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureGetFollowCreature(lua_State* L) { // creature:getFollowCreature() Creature* creature = getUserdata(L, 1); if (!creature) { lua_pushnil(L); return 1; } Creature* followCreature = creature->getFollowCreature(); if (followCreature) { pushUserdata(L, followCreature); setCreatureMetatable(L, -1, followCreature); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureSetFollowCreature(lua_State* L) { // creature:setFollowCreature(followedCreature) Creature* creature = getUserdata(L, 1); if (creature) { Creature* followCreature = getCreature(L, 2); pushBoolean(L, creature->setFollowCreature(followCreature)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureGetMaster(lua_State* L) { // creature:getMaster() Creature* creature = getUserdata(L, 1); if (!creature) { lua_pushnil(L); return 1; } Creature* master = creature->getMaster(); if (!master) { lua_pushnil(L); return 1; } pushUserdata(L, master); setCreatureMetatable(L, -1, master); return 1; } int LuaScriptInterface::luaCreatureSetMaster(lua_State* L) { // creature:setMaster(master) Creature* creature = getUserdata(L, 1); if (!creature) { lua_pushnil(L); return 1; } Creature* master = getCreature(L, 2); if (master) { pushBoolean(L, creature->convinceCreature(master)); } else { master = creature->getMaster(); if (master) { master->removeSummon(creature); creature->incrementReferenceCounter(); creature->setDropLoot(true); } pushBoolean(L, true); } return 1; } int LuaScriptInterface::luaCreatureGetLight(lua_State* L) { // creature:getLight() const Creature* creature = getUserdata(L, 1); if (!creature) { lua_pushnil(L); return 1; } LightInfo lightInfo = creature->getCreatureLight(); lua_pushnumber(L, lightInfo.level); lua_pushnumber(L, lightInfo.color); return 2; } int LuaScriptInterface::luaCreatureSetLight(lua_State* L) { // creature:setLight(color, level) Creature* creature = getUserdata(L, 1); if (!creature) { lua_pushnil(L); return 1; } LightInfo light; light.color = getNumber(L, 2); light.level = getNumber(L, 3); creature->setCreatureLight(light); g_game.changeLight(creature); pushBoolean(L, true); return 1; } int LuaScriptInterface::luaCreatureGetSpeed(lua_State* L) { // creature:getSpeed() const Creature* creature = getUserdata(L, 1); if (creature) { lua_pushnumber(L, creature->getSpeed()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureGetBaseSpeed(lua_State* L) { // creature:getBaseSpeed() const Creature* creature = getUserdata(L, 1); if (creature) { lua_pushnumber(L, creature->getBaseSpeed()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureChangeSpeed(lua_State* L) { // creature:changeSpeed(delta) Creature* creature = getCreature(L, 1); if (!creature) { reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); pushBoolean(L, false); return 1; } int32_t delta = getNumber(L, 2); g_game.changeSpeed(creature, delta); pushBoolean(L, true); return 1; } int LuaScriptInterface::luaCreatureSetDropLoot(lua_State* L) { // creature:setDropLoot(doDrop) Creature* creature = getUserdata(L, 1); if (creature) { creature->setDropLoot(getBoolean(L, 2)); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureGetPosition(lua_State* L) { // creature:getPosition() const Creature* creature = getUserdata(L, 1); if (creature) { pushPosition(L, creature->getPosition()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureGetTile(lua_State* L) { // creature:getTile() Creature* creature = getUserdata(L, 1); if (!creature) { lua_pushnil(L); return 1; } Tile* tile = creature->getTile(); if (tile) { pushUserdata(L, tile); setMetatable(L, -1, "Tile"); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureGetDirection(lua_State* L) { // creature:getDirection() const Creature* creature = getUserdata(L, 1); if (creature) { lua_pushnumber(L, creature->getDirection()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureSetDirection(lua_State* L) { // creature:setDirection(direction) Creature* creature = getUserdata(L, 1); if (creature) { pushBoolean(L, g_game.internalCreatureTurn(creature, getNumber(L, 2))); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureGetHealth(lua_State* L) { // creature:getHealth() const Creature* creature = getUserdata(L, 1); if (creature) { lua_pushnumber(L, creature->getHealth()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureAddHealth(lua_State* L) { // creature:addHealth(healthChange) Creature* creature = getUserdata(L, 1); if (!creature) { lua_pushnil(L); return 1; } CombatDamage damage; damage.value = getNumber(L, 2); if (damage.value >= 0) { damage.type = COMBAT_HEALING; } else { damage.type = COMBAT_UNDEFINEDDAMAGE; } pushBoolean(L, g_game.combatChangeHealth(nullptr, creature, damage)); return 1; } int LuaScriptInterface::luaCreatureGetMaxHealth(lua_State* L) { // creature:getMaxHealth() const Creature* creature = getUserdata(L, 1); if (creature) { lua_pushnumber(L, creature->getMaxHealth()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureSetMaxHealth(lua_State* L) { // creature:setMaxHealth(maxHealth) Creature* creature = getUserdata(L, 1); if (!creature) { lua_pushnil(L); return 1; } creature->healthMax = getNumber(L, 2); creature->health = std::min(creature->health, creature->healthMax); g_game.addCreatureHealth(creature); Player* player = creature->getPlayer(); if (player) { player->sendStats(); } pushBoolean(L, true); return 1; } int LuaScriptInterface::luaCreatureSetHiddenHealth(lua_State* L) { // creature:setHiddenHealth(hide) Creature* creature = getUserdata(L, 1); if (creature) { creature->setHiddenHealth(getBoolean(L, 2)); g_game.addCreatureHealth(creature); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureGetSkull(lua_State* L) { // creature:getSkull() Creature* creature = getUserdata(L, 1); if (creature) { lua_pushnumber(L, creature->getSkull()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureSetSkull(lua_State* L) { // creature:setSkull(skull) Creature* creature = getUserdata(L, 1); if (creature) { creature->setSkull(getNumber(L, 2)); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureGetOutfit(lua_State* L) { // creature:getOutfit() const Creature* creature = getUserdata(L, 1); if (creature) { pushOutfit(L, creature->getCurrentOutfit()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureSetOutfit(lua_State* L) { // creature:setOutfit(outfit) Creature* creature = getUserdata(L, 1); if (creature) { creature->defaultOutfit = getOutfit(L, 2); g_game.internalCreatureChangeOutfit(creature, creature->defaultOutfit); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureGetCondition(lua_State* L) { // creature:getCondition(conditionType[, conditionId = CONDITIONID_COMBAT[, subId = 0]]) Creature* creature = getUserdata(L, 1); if (!creature) { lua_pushnil(L); return 1; } ConditionType_t conditionType = getNumber(L, 2); ConditionId_t conditionId = getNumber(L, 3, CONDITIONID_COMBAT); uint32_t subId = getNumber(L, 4, 0); Condition* condition = creature->getCondition(conditionType, conditionId, subId); if (condition) { pushUserdata(L, condition); setWeakMetatable(L, -1, "Condition"); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureAddCondition(lua_State* L) { // creature:addCondition(condition[, force = false]) Creature* creature = getUserdata(L, 1); Condition* condition = getUserdata(L, 2); if (creature && condition) { bool force = getBoolean(L, 3, false); pushBoolean(L, creature->addCondition(condition->clone(), force)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureRemoveCondition(lua_State* L) { // creature:removeCondition(conditionType[, conditionId = CONDITIONID_COMBAT[, subId = 0[, force = false]]]) Creature* creature = getUserdata(L, 1); if (!creature) { lua_pushnil(L); return 1; } ConditionType_t conditionType = getNumber(L, 2); ConditionId_t conditionId = getNumber(L, 3, CONDITIONID_COMBAT); uint32_t subId = getNumber(L, 4, 0); Condition* condition = creature->getCondition(conditionType, conditionId, subId); if (condition) { bool force = getBoolean(L, 5, true); creature->removeCondition(condition, force); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureRemove(lua_State* L) { // creature:remove() Creature** creaturePtr = getRawUserdata(L, 1); if (!creaturePtr) { lua_pushnil(L); return 1; } Creature* creature = *creaturePtr; if (!creature) { lua_pushnil(L); return 1; } Player* player = creature->getPlayer(); if (player) { player->kickPlayer(true); } else { g_game.removeCreature(creature); } *creaturePtr = nullptr; pushBoolean(L, true); return 1; } int LuaScriptInterface::luaCreatureTeleportTo(lua_State* L) { // creature:teleportTo(position[, pushMovement = false]) bool pushMovement = getBoolean(L, 3, false); const Position& position = getPosition(L, 2); Creature* creature = getUserdata(L, 1); if (!creature) { lua_pushnil(L); return 1; } const Position oldPosition = creature->getPosition(); if (g_game.internalTeleport(creature, position, pushMovement) != RETURNVALUE_NOERROR) { pushBoolean(L, false); return 1; } if (!pushMovement) { if (oldPosition.x == position.x) { if (oldPosition.y < position.y) { g_game.internalCreatureTurn(creature, DIRECTION_SOUTH); } else { g_game.internalCreatureTurn(creature, DIRECTION_NORTH); } } else if (oldPosition.x > position.x) { g_game.internalCreatureTurn(creature, DIRECTION_WEST); } else if (oldPosition.x < position.x) { g_game.internalCreatureTurn(creature, DIRECTION_EAST); } } pushBoolean(L, true); return 1; } int LuaScriptInterface::luaCreatureSay(lua_State* L) { // creature:say(text, type[, ghost = false[, target = nullptr[, position]]]) int parameters = lua_gettop(L); Position position; if (parameters >= 6) { position = getPosition(L, 6); if (!position.x || !position.y) { reportErrorFunc("Invalid position specified."); pushBoolean(L, false); return 1; } } Creature* target = nullptr; if (parameters >= 5) { target = getCreature(L, 5); } bool ghost = getBoolean(L, 4, false); SpeakClasses type = getNumber(L, 3); const std::string& text = getString(L, 2); Creature* creature = getUserdata(L, 1); if (!creature) { lua_pushnil(L); return 1; } SpectatorVec list; if (target) { list.insert(target); } if (position.x != 0) { pushBoolean(L, g_game.internalCreatureSay(creature, type, text, ghost, &list, &position)); } else { pushBoolean(L, g_game.internalCreatureSay(creature, type, text, ghost, &list)); } return 1; } int LuaScriptInterface::luaCreatureGetDamageMap(lua_State* L) { // creature:getDamageMap() Creature* creature = getUserdata(L, 1); if (!creature) { lua_pushnil(L); return 1; } lua_createtable(L, creature->damageMap.size(), 0); for (auto damageEntry : creature->damageMap) { lua_createtable(L, 0, 2); setField(L, "total", damageEntry.second.total); setField(L, "ticks", damageEntry.second.ticks); lua_rawseti(L, -2, damageEntry.first); } return 1; } int LuaScriptInterface::luaCreatureGetSummons(lua_State* L) { // creature:getSummons() Creature* creature = getUserdata(L, 1); if (!creature) { lua_pushnil(L); return 1; } lua_createtable(L, creature->getSummonCount(), 0); int index = 0; for (Creature* summon : creature->getSummons()) { pushUserdata(L, summon); setCreatureMetatable(L, -1, summon); lua_rawseti(L, -2, ++index); } return 1; } int LuaScriptInterface::luaCreatureGetDescription(lua_State* L) { // creature:getDescription(distance) int32_t distance = getNumber(L, 2); Creature* creature = getUserdata(L, 1); if (creature) { pushString(L, creature->getDescription(distance)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCreatureGetPathTo(lua_State* L) { // creature:getPathTo(pos[, minTargetDist = 0[, maxTargetDist = 1[, fullPathSearch = true[, clearSight = true[, maxSearchDist = 0]]]]]) Creature* creature = getUserdata(L, 1); if (!creature) { lua_pushnil(L); return 1; } const Position& position = getPosition(L, 2); FindPathParams fpp; fpp.minTargetDist = getNumber(L, 3, 0); fpp.maxTargetDist = getNumber(L, 4, 1); fpp.fullPathSearch = getBoolean(L, 5, fpp.fullPathSearch); fpp.clearSight = getBoolean(L, 6, fpp.clearSight); fpp.maxSearchDist = getNumber(L, 7, fpp.maxSearchDist); std::forward_list dirList; if (creature->getPathTo(position, dirList, fpp)) { lua_newtable(L); int index = 0; for (Direction dir : dirList) { lua_pushnumber(L, dir); lua_rawseti(L, -2, ++index); } } else { pushBoolean(L, false); } return 1; } // Player int LuaScriptInterface::luaPlayerCreate(lua_State* L) { // Player(id or name or userdata) Player* player; if (isNumber(L, 2)) { player = g_game.getPlayerByID(getNumber(L, 2)); } else if (isString(L, 2)) { ReturnValue ret = g_game.getPlayerByNameWildcard(getString(L, 2), player); if (ret != RETURNVALUE_NOERROR) { lua_pushnil(L); lua_pushnumber(L, ret); return 2; } } else if (isUserdata(L, 2)) { if (getUserdataType(L, 2) != LuaData_Player) { lua_pushnil(L); return 1; } player = getUserdata(L, 2); } else { player = nullptr; } if (player) { pushUserdata(L, player); setMetatable(L, -1, "Player"); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerIsPlayer(lua_State* L) { // player:isPlayer() pushBoolean(L, getUserdata(L, 1) != nullptr); return 1; } int LuaScriptInterface::luaPlayerGetGuid(lua_State* L) { // player:getGuid() Player* player = getUserdata(L, 1); if (player) { lua_pushnumber(L, player->getGUID()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetIp(lua_State* L) { // player:getIp() Player* player = getUserdata(L, 1); if (player) { lua_pushnumber(L, player->getIP()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetAccountId(lua_State* L) { // player:getAccountId() Player* player = getUserdata(L, 1); if (player) { lua_pushnumber(L, player->getAccount()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetLastLoginSaved(lua_State* L) { // player:getLastLoginSaved() Player* player = getUserdata(L, 1); if (player) { lua_pushnumber(L, player->getLastLoginSaved()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetLastLogout(lua_State* L) { // player:getLastLogout() Player* player = getUserdata(L, 1); if (player) { lua_pushnumber(L, player->getLastLogout()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerHasFlag(lua_State * L) { // player:hasFlag(flag) Player* player = getUserdata(L, 1); if (player) { PlayerFlags flag = getNumber(L, 2); pushBoolean(L, player->hasFlag(flag)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetAccountType(lua_State* L) { // player:getAccountType() Player* player = getUserdata(L, 1); if (player) { lua_pushnumber(L, player->getAccountType()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerSetAccountType(lua_State* L) { // player:setAccountType(accountType) Player* player = getUserdata(L, 1); if (player) { player->accountType = getNumber(L, 2); IOLoginData::setAccountType(player->getAccount(), player->accountType); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetCapacity(lua_State* L) { // player:getCapacity() Player* player = getUserdata(L, 1); if (player) { lua_pushnumber(L, player->getCapacity()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerSetCapacity(lua_State* L) { // player:setCapacity(capacity) Player* player = getUserdata(L, 1); if (player) { player->capacity = getNumber(L, 2); player->sendStats(); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetFreeCapacity(lua_State* L) { // player:getFreeCapacity() Player* player = getUserdata(L, 1); if (player) { lua_pushnumber(L, player->getFreeCapacity()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetDepotChest(lua_State* L) { // player:getDepotChest(depotId[, autoCreate = false]) Player* player = getUserdata(L, 1); if (!player) { lua_pushnil(L); return 1; } uint32_t depotId = getNumber(L, 2); bool autoCreate = getBoolean(L, 3, false); DepotLocker* depotLocker = player->getDepotLocker(depotId, autoCreate); if (depotLocker) { if (!depotLocker->getParent() && player->getTile()) { depotLocker->setParent(player->getTile()); } pushUserdata(L, depotLocker); setItemMetatable(L, -1, depotLocker); } else { pushBoolean(L, false); } return 1; } int LuaScriptInterface::luaPlayerGetMurderTimestamps(lua_State * L) { // player:getMurderTimestamps() Player* player = getUserdata(L, 1); if (player) { lua_createtable(L, player->murderTimeStamps.size(), 0); uint32_t i = 1; for (time_t currentMurderTimestamp : player->murderTimeStamps) { lua_pushnumber(L, static_cast(currentMurderTimestamp)); lua_rawseti(L, -2, ++i); } } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetPlayerKillerEnd(lua_State* L) { // player:getPlayerKillerEnd() Player* player = getUserdata(L, 1); if (player) { lua_pushnumber(L, player->getPlayerKillerEnd()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerSetPlayerKillerEnd(lua_State* L) { // player:setPlayerKillerEnd(skullTime) Player* player = getUserdata(L, 1); if (player) { player->setPlayerKillerEnd(getNumber(L, 2)); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetDeathPenalty(lua_State* L) { // player:getDeathPenalty() Player* player = getUserdata(L, 1); if (player) { lua_pushnumber(L, static_cast(player->getLostPercent() * 100)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetExperience(lua_State* L) { // player:getExperience() Player* player = getUserdata(L, 1); if (player) { lua_pushnumber(L, player->getExperience()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerAddExperience(lua_State* L) { // player:addExperience(experience[, sendText = false]) Player* player = getUserdata(L, 1); if (player) { int64_t experience = getNumber(L, 2); bool sendText = getBoolean(L, 3, false); player->addExperience(nullptr, experience, sendText); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerRemoveExperience(lua_State* L) { // player:removeExperience(experience) Player* player = getUserdata(L, 1); if (player) { int64_t experience = getNumber(L, 2); player->removeExperience(experience); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetLevel(lua_State* L) { // player:getLevel() Player* player = getUserdata(L, 1); if (player) { lua_pushnumber(L, player->getLevel()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetMagicLevel(lua_State* L) { // player:getMagicLevel() Player* player = getUserdata(L, 1); if (player) { lua_pushnumber(L, player->getMagicLevel()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetBaseMagicLevel(lua_State* L) { // player:getBaseMagicLevel() Player* player = getUserdata(L, 1); if (player) { lua_pushnumber(L, player->getBaseMagicLevel()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetMana(lua_State* L) { // player:getMana() const Player* player = getUserdata(L, 1); if (player) { lua_pushnumber(L, player->getMana()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerAddMana(lua_State* L) { // player:addMana(manaChange[, animationOnLoss = false]) Player* player = getUserdata(L, 1); if (!player) { lua_pushnil(L); return 1; } int32_t manaChange = getNumber(L, 2); bool animationOnLoss = getBoolean(L, 3, false); if (!animationOnLoss && manaChange < 0) { player->changeMana(manaChange); } else { CombatDamage damage; damage.value = manaChange; damage.origin = ORIGIN_NONE; g_game.combatChangeMana(nullptr, player, damage); } pushBoolean(L, true); return 1; } int LuaScriptInterface::luaPlayerGetMaxMana(lua_State* L) { // player:getMaxMana() const Player* player = getUserdata(L, 1); if (player) { lua_pushnumber(L, player->getMaxMana()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerSetMaxMana(lua_State* L) { // player:setMaxMana(maxMana) Player* player = getPlayer(L, 1); if (player) { player->manaMax = getNumber(L, 2); player->mana = std::min(player->mana, player->manaMax); player->sendStats(); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetManaSpent(lua_State* L) { // player:getManaSpent() Player* player = getUserdata(L, 1); if (player) { lua_pushnumber(L, player->getSpentMana()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerAddManaSpent(lua_State* L) { // player:addManaSpent(amount) Player* player = getUserdata(L, 1); if (player) { player->addManaSpent(getNumber(L, 2)); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetBaseMaxHealth(lua_State* L) { // player:getBaseMaxHealth() Player* player = getUserdata(L, 1); if (player) { lua_pushnumber(L, player->healthMax); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetBaseMaxMana(lua_State* L) { // player:getBaseMaxMana() Player* player = getUserdata(L, 1); if (player) { lua_pushnumber(L, player->manaMax); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetSkillLevel(lua_State* L) { // player:getSkillLevel(skillType) skills_t skillType = getNumber(L, 2); Player* player = getUserdata(L, 1); if (player && skillType <= SKILL_LAST) { lua_pushnumber(L, player->skills[skillType].level); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetEffectiveSkillLevel(lua_State* L) { // player:getEffectiveSkillLevel(skillType) skills_t skillType = getNumber(L, 2); Player* player = getUserdata(L, 1); if (player && skillType <= SKILL_LAST) { lua_pushnumber(L, player->getSkillLevel(skillType)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetSkillPercent(lua_State* L) { // player:getSkillPercent(skillType) skills_t skillType = getNumber(L, 2); Player* player = getUserdata(L, 1); if (player && skillType <= SKILL_LAST) { lua_pushnumber(L, player->skills[skillType].percent); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetSkillTries(lua_State* L) { // player:getSkillTries(skillType) skills_t skillType = getNumber(L, 2); Player* player = getUserdata(L, 1); if (player && skillType <= SKILL_LAST) { lua_pushnumber(L, player->skills[skillType].tries); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerAddSkillTries(lua_State* L) { // player:addSkillTries(skillType, tries) Player* player = getUserdata(L, 1); if (player) { skills_t skillType = getNumber(L, 2); uint64_t tries = getNumber(L, 3); player->addSkillAdvance(skillType, tries); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetItemCount(lua_State* L) { // player:getItemCount(itemId[, subType = -1]) Player* player = getUserdata(L, 1); if (!player) { lua_pushnil(L); return 1; } uint16_t itemId; if (isNumber(L, 2)) { itemId = getNumber(L, 2); } else { itemId = Item::items.getItemIdByName(getString(L, 2)); if (itemId == 0) { lua_pushnil(L); return 1; } } int32_t subType = getNumber(L, 3, -1); lua_pushnumber(L, player->getItemTypeCount(itemId, subType)); return 1; } int LuaScriptInterface::luaPlayerGetItemById(lua_State* L) { // player:getItemById(itemId, deepSearch[, subType = -1]) Player* player = getUserdata(L, 1); if (!player) { lua_pushnil(L); return 1; } uint16_t itemId; if (isNumber(L, 2)) { itemId = getNumber(L, 2); } else { itemId = Item::items.getItemIdByName(getString(L, 2)); if (itemId == 0) { lua_pushnil(L); return 1; } } bool deepSearch = getBoolean(L, 3); int32_t subType = getNumber(L, 4, -1); Item* item = g_game.findItemOfType(player, itemId, deepSearch, subType); if (item) { pushUserdata(L, item); setItemMetatable(L, -1, item); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetVocation(lua_State* L) { // player:getVocation() Player* player = getUserdata(L, 1); if (player) { pushUserdata(L, player->getVocation()); setMetatable(L, -1, "Vocation"); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerSetVocation(lua_State* L) { // player:setVocation(id or name or userdata) Player* player = getUserdata(L, 1); if (!player) { lua_pushnil(L); return 1; } Vocation* vocation; if (isNumber(L, 2)) { vocation = g_vocations.getVocation(getNumber(L, 2)); } else if (isString(L, 2)) { vocation = g_vocations.getVocation(g_vocations.getVocationId(getString(L, 2))); } else if (isUserdata(L, 2)) { vocation = getUserdata(L, 2); } else { vocation = nullptr; } if (!vocation) { pushBoolean(L, false); return 1; } player->setVocation(vocation->getId()); pushBoolean(L, true); return 1; } int LuaScriptInterface::luaPlayerGetSex(lua_State* L) { // player:getSex() Player* player = getUserdata(L, 1); if (player) { lua_pushnumber(L, player->getSex()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerSetSex(lua_State* L) { // player:setSex(newSex) Player* player = getUserdata(L, 1); if (player) { PlayerSex_t newSex = getNumber(L, 2); player->setSex(newSex); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetTown(lua_State* L) { // player:getTown() Player* player = getUserdata(L, 1); if (player) { pushUserdata(L, player->getTown()); setMetatable(L, -1, "Town"); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerSetTown(lua_State* L) { // player:setTown(town) Town* town = getUserdata(L, 2); if (!town) { pushBoolean(L, false); return 1; } Player* player = getUserdata(L, 1); if (player) { player->setTown(town); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetGuild(lua_State* L) { // player:getGuild() Player* player = getUserdata(L, 1); if (!player) { lua_pushnil(L); return 1; } Guild* guild = player->getGuild(); if (!guild) { lua_pushnil(L); return 1; } pushUserdata(L, guild); setMetatable(L, -1, "Guild"); return 1; } int LuaScriptInterface::luaPlayerSetGuild(lua_State* L) { // player:setGuild(guild) Player* player = getUserdata(L, 1); if (!player) { lua_pushnil(L); return 1; } player->setGuild(getUserdata(L, 2)); pushBoolean(L, true); return 1; } int LuaScriptInterface::luaPlayerGetGuildLevel(lua_State* L) { // player:getGuildLevel() Player* player = getUserdata(L, 1); if (player && player->getGuild()) { lua_pushnumber(L, player->getGuildRank()->level); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerSetGuildLevel(lua_State* L) { // player:setGuildLevel(level) uint8_t level = getNumber(L, 2); Player* player = getUserdata(L, 1); if (!player || !player->getGuild()) { lua_pushnil(L); return 1; } const GuildRank* rank = player->getGuild()->getRankByLevel(level); if (!rank) { pushBoolean(L, false); } else { player->setGuildRank(rank); pushBoolean(L, true); } return 1; } int LuaScriptInterface::luaPlayerGetGuildNick(lua_State* L) { // player:getGuildNick() Player* player = getUserdata(L, 1); if (player) { pushString(L, player->getGuildNick()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerSetGuildNick(lua_State* L) { // player:setGuildNick(nick) const std::string& nick = getString(L, 2); Player* player = getUserdata(L, 1); if (player) { player->setGuildNick(nick); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetGroup(lua_State* L) { // player:getGroup() Player* player = getUserdata(L, 1); if (player) { pushUserdata(L, player->getGroup()); setMetatable(L, -1, "Group"); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerSetGroup(lua_State* L) { // player:setGroup(group) Group* group = getUserdata(L, 2); if (!group) { pushBoolean(L, false); return 1; } Player* player = getUserdata(L, 1); if (player) { player->setGroup(group); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetStamina(lua_State* L) { // player:getStamina() Player* player = getUserdata(L, 1); if (player) { lua_pushnumber(L, player->getStaminaMinutes()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerSetStamina(lua_State* L) { // player:setStamina(stamina) uint16_t stamina = getNumber(L, 2); Player* player = getUserdata(L, 1); if (player) { player->staminaMinutes = std::min(3360, stamina); player->sendStats(); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetSoul(lua_State* L) { // player:getSoul() Player* player = getUserdata(L, 1); if (player) { lua_pushnumber(L, player->getSoul()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerAddSoul(lua_State* L) { // player:addSoul(soulChange) int32_t soulChange = getNumber(L, 2); Player* player = getUserdata(L, 1); if (player) { player->changeSoul(soulChange); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetMaxSoul(lua_State* L) { // player:getMaxSoul() Player* player = getUserdata(L, 1); if (player && player->vocation) { lua_pushnumber(L, player->vocation->getSoulMax()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetBankBalance(lua_State* L) { // player:getBankBalance() Player* player = getUserdata(L, 1); if (player) { lua_pushnumber(L, player->getBankBalance()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerSetBankBalance(lua_State* L) { // player:setBankBalance(bankBalance) Player* player = getUserdata(L, 1); if (!player) { lua_pushnil(L); return 1; } int64_t balance = getNumber(L, 2); if (balance < 0) { reportErrorFunc("Invalid bank balance value."); lua_pushnil(L); return 1; } player->setBankBalance(balance); pushBoolean(L, true); return 1; } int LuaScriptInterface::luaPlayerGetStorageValue(lua_State* L) { // player:getStorageValue(key) Player* player = getUserdata(L, 1); if (!player) { lua_pushnil(L); return 1; } uint32_t key = getNumber(L, 2); int32_t value; if (player->getStorageValue(key, value)) { lua_pushnumber(L, value); } else { lua_pushnumber(L, 0); } return 1; } int LuaScriptInterface::luaPlayerSetStorageValue(lua_State* L) { // player:setStorageValue(key, value) int32_t value = getNumber(L, 3); uint32_t key = getNumber(L, 2); Player* player = getUserdata(L, 1); if (player) { player->addStorageValue(key, value); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerAddItem(lua_State* L) { // player:addItem(itemId[, count = 1[, canDropOnMap = true[, subType = 1[, slot = CONST_SLOT_WHEREEVER]]]]) Player* player = getUserdata(L, 1); if (!player) { pushBoolean(L, false); return 1; } uint16_t itemId; if (isNumber(L, 2)) { itemId = getNumber(L, 2); } else { itemId = Item::items.getItemIdByName(getString(L, 2)); if (itemId == 0) { lua_pushnil(L); return 1; } } int32_t count = getNumber(L, 3, 1); int32_t subType = getNumber(L, 5, 1); const ItemType& it = Item::items[itemId]; int32_t itemCount = 1; int parameters = lua_gettop(L); if (parameters >= 4) { itemCount = std::max(1, count); } else if (it.hasSubType()) { if (it.stackable) { itemCount = std::ceil(count / 100.f); } subType = count; } else { itemCount = std::max(1, count); } bool hasTable = itemCount > 1; if (hasTable) { lua_newtable(L); } else if (itemCount == 0) { lua_pushnil(L); return 1; } bool canDropOnMap = getBoolean(L, 4, true); slots_t slot = getNumber(L, 6, CONST_SLOT_WHEREEVER); for (int32_t i = 1; i <= itemCount; ++i) { int32_t stackCount = subType; if (it.stackable) { stackCount = std::min(stackCount, 100); subType -= stackCount; } Item* item = Item::CreateItem(itemId, stackCount); if (!item) { if (!hasTable) { lua_pushnil(L); } return 1; } ReturnValue ret = g_game.internalPlayerAddItem(player, item, canDropOnMap, slot); if (ret != RETURNVALUE_NOERROR) { delete item; if (!hasTable) { lua_pushnil(L); } return 1; } if (hasTable) { lua_pushnumber(L, i); pushUserdata(L, item); setItemMetatable(L, -1, item); lua_settable(L, -3); } else { pushUserdata(L, item); setItemMetatable(L, -1, item); } } return 1; } int LuaScriptInterface::luaPlayerAddItemEx(lua_State* L) { // player:addItemEx(item[, canDropOnMap = false[, index = INDEX_WHEREEVER[, flags = 0]]]) // player:addItemEx(item[, canDropOnMap = true[, slot = CONST_SLOT_WHEREEVER]]) Item* item = getUserdata(L, 2); if (!item) { reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); pushBoolean(L, false); return 1; } Player* player = getUserdata(L, 1); if (!player) { lua_pushnil(L); return 1; } if (item->getParent() != VirtualCylinder::virtualCylinder) { reportErrorFunc("Item already has a parent"); pushBoolean(L, false); return 1; } bool canDropOnMap = getBoolean(L, 3, false); ReturnValue returnValue; if (canDropOnMap) { slots_t slot = getNumber(L, 4, CONST_SLOT_WHEREEVER); returnValue = g_game.internalPlayerAddItem(player, item, true, slot); } else { int32_t index = getNumber(L, 4, INDEX_WHEREEVER); uint32_t flags = getNumber(L, 5, 0); returnValue = g_game.internalAddItem(player, item, index, flags); } if (returnValue == RETURNVALUE_NOERROR) { ScriptEnvironment::removeTempItem(item); } lua_pushnumber(L, returnValue); return 1; } int LuaScriptInterface::luaPlayerRemoveItem(lua_State* L) { // player:removeItem(itemId, count[, subType = -1[, ignoreEquipped = false]]) Player* player = getUserdata(L, 1); if (!player) { lua_pushnil(L); return 1; } uint16_t itemId; if (isNumber(L, 2)) { itemId = getNumber(L, 2); } else { itemId = Item::items.getItemIdByName(getString(L, 2)); if (itemId == 0) { lua_pushnil(L); return 1; } } uint32_t count = getNumber(L, 3); int32_t subType = getNumber(L, 4, -1); bool ignoreEquipped = getBoolean(L, 5, false); pushBoolean(L, player->removeItemOfType(itemId, count, subType, ignoreEquipped)); return 1; } int LuaScriptInterface::luaPlayerGetMoney(lua_State* L) { // player:getMoney() Player* player = getUserdata(L, 1); if (player) { lua_pushnumber(L, player->getMoney()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerAddMoney(lua_State* L) { // player:addMoney(money) uint64_t money = getNumber(L, 2); Player* player = getUserdata(L, 1); if (player) { g_game.addMoney(player, money); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerRemoveMoney(lua_State* L) { // player:removeMoney(money) Player* player = getUserdata(L, 1); if (player) { uint64_t money = getNumber(L, 2); pushBoolean(L, g_game.removeMoney(player, money)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerShowTextDialog(lua_State* L) { // player:showTextDialog(itemId[, text[, canWrite[, length]]]) Player* player = getUserdata(L, 1); if (!player) { lua_pushnil(L); return 1; } int32_t length = getNumber(L, 5, -1); bool canWrite = getBoolean(L, 4, false); std::string text; int parameters = lua_gettop(L); if (parameters >= 3) { text = getString(L, 3); } uint16_t itemId; if (isNumber(L, 2)) { itemId = getNumber(L, 2); } else { itemId = Item::items.getItemIdByName(getString(L, 2)); if (itemId == 0) { lua_pushnil(L); return 1; } } Item* item = Item::CreateItem(itemId); if (!item) { reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); pushBoolean(L, false); return 1; } if (length < 0) { length = Item::items[item->getID()].maxTextLen; } if (!text.empty()) { item->setText(text); length = std::max(text.size(), length); } item->setParent(player); player->setWriteItem(item, length); player->sendTextWindow(item, length, canWrite); pushBoolean(L, true); return 1; } int LuaScriptInterface::luaPlayerSendTextMessage(lua_State* L) { // player:sendTextMessage(type, text) TextMessage message(getNumber(L, 2), getString(L, 3)); Player* player = getUserdata(L, 1); if (player) { player->sendTextMessage(message); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerSendPrivateMessage(lua_State* L) { // player:sendPrivateMessage(speaker, text[, type]) Player* player = getUserdata(L, 1); if (!player) { lua_pushnil(L); return 1; } const Player* speaker = getUserdata(L, 2); const std::string& text = getString(L, 3); SpeakClasses type = getNumber(L, 4, TALKTYPE_PRIVATE); player->sendPrivateMessage(speaker, type, text); pushBoolean(L, true); return 1; } int LuaScriptInterface::luaPlayerChannelSay(lua_State* L) { // player:channelSay(speaker, type, text, channelId) Player* player = getUserdata(L, 1); if (!player) { lua_pushnil(L); return 1; } Creature* speaker = getCreature(L, 2); SpeakClasses type = getNumber(L, 3); const std::string& text = getString(L, 4); uint16_t channelId = getNumber(L, 5); player->sendToChannel(speaker, type, text, channelId); pushBoolean(L, true); return 1; } int LuaScriptInterface::luaPlayerOpenChannel(lua_State* L) { // player:openChannel(channelId) uint16_t channelId = getNumber(L, 2); Player* player = getUserdata(L, 1); if (player) { g_game.playerOpenChannel(player->getID(), channelId); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetSlotItem(lua_State* L) { // player:getSlotItem(slot) const Player* player = getUserdata(L, 1); if (!player) { lua_pushnil(L); return 1; } uint32_t slot = getNumber(L, 2); Thing* thing = player->getThing(slot); if (!thing) { lua_pushnil(L); return 1; } Item* item = thing->getItem(); if (item) { pushUserdata(L, item); setItemMetatable(L, -1, item); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetParty(lua_State* L) { // player:getParty() const Player* player = getUserdata(L, 1); if (!player) { lua_pushnil(L); return 1; } Party* party = player->getParty(); if (party) { pushUserdata(L, party); setMetatable(L, -1, "Party"); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerAddOutfit(lua_State* L) { // player:addOutfit(lookType) Player* player = getUserdata(L, 1); if (player) { player->addOutfit(getNumber(L, 2), 0); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerAddOutfitAddon(lua_State* L) { // player:addOutfitAddon(lookType, addon) Player* player = getUserdata(L, 1); if (player) { uint16_t lookType = getNumber(L, 2); uint8_t addon = getNumber(L, 3); player->addOutfit(lookType, addon); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerRemoveOutfit(lua_State* L) { // player:removeOutfit(lookType) Player* player = getUserdata(L, 1); if (player) { uint16_t lookType = getNumber(L, 2); pushBoolean(L, player->removeOutfit(lookType)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerRemoveOutfitAddon(lua_State* L) { // player:removeOutfitAddon(lookType, addon) Player* player = getUserdata(L, 1); if (player) { uint16_t lookType = getNumber(L, 2); uint8_t addon = getNumber(L, 3); pushBoolean(L, player->removeOutfitAddon(lookType, addon)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerHasOutfit(lua_State* L) { // player:hasOutfit(lookType[, addon = 0]) Player* player = getUserdata(L, 1); if (player) { uint16_t lookType = getNumber(L, 2); uint8_t addon = getNumber(L, 3, 0); pushBoolean(L, player->canWear(lookType, addon)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerSendOutfitWindow(lua_State* L) { // player:sendOutfitWindow() Player* player = getUserdata(L, 1); if (player) { player->sendOutfitWindow(); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetPremiumDays(lua_State* L) { // player:getPremiumDays() Player* player = getUserdata(L, 1); if (player) { lua_pushnumber(L, player->premiumDays); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerAddPremiumDays(lua_State* L) { // player:addPremiumDays(days) Player* player = getUserdata(L, 1); if (!player) { lua_pushnil(L); return 1; } if (player->premiumDays != std::numeric_limits::max()) { uint16_t days = getNumber(L, 2); int32_t addDays = std::min(0xFFFE - player->premiumDays, days); if (addDays > 0) { player->setPremiumDays(player->premiumDays + addDays); IOLoginData::addPremiumDays(player->getAccount(), addDays); } } pushBoolean(L, true); return 1; } int LuaScriptInterface::luaPlayerRemovePremiumDays(lua_State* L) { // player:removePremiumDays(days) Player* player = getUserdata(L, 1); if (!player) { lua_pushnil(L); return 1; } if (player->premiumDays != std::numeric_limits::max()) { uint16_t days = getNumber(L, 2); int32_t removeDays = std::min(player->premiumDays, days); if (removeDays > 0) { player->setPremiumDays(player->premiumDays - removeDays); IOLoginData::removePremiumDays(player->getAccount(), removeDays); } } pushBoolean(L, true); return 1; } int LuaScriptInterface::luaPlayerHasBlessing(lua_State* L) { // player:hasBlessing(blessing) uint8_t blessing = getNumber(L, 2) - 1; Player* player = getUserdata(L, 1); if (player) { pushBoolean(L, player->hasBlessing(blessing)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerAddBlessing(lua_State* L) { // player:addBlessing(blessing) Player* player = getUserdata(L, 1); if (!player) { lua_pushnil(L); return 1; } uint8_t blessing = getNumber(L, 2) - 1; if (player->hasBlessing(blessing)) { pushBoolean(L, false); return 1; } player->addBlessing(1 << blessing); pushBoolean(L, true); return 1; } int LuaScriptInterface::luaPlayerRemoveBlessing(lua_State* L) { // player:removeBlessing(blessing) Player* player = getUserdata(L, 1); if (!player) { lua_pushnil(L); return 1; } uint8_t blessing = getNumber(L, 2) - 1; if (!player->hasBlessing(blessing)) { pushBoolean(L, false); return 1; } player->removeBlessing(1 << blessing); pushBoolean(L, true); return 1; } int LuaScriptInterface::luaPlayerCanLearnSpell(lua_State* L) { // player:canLearnSpell(spellName) const Player* player = getUserdata(L, 1); if (!player) { lua_pushnil(L); return 1; } const std::string& spellName = getString(L, 2); InstantSpell* spell = g_spells->getInstantSpellByName(spellName); if (!spell) { reportErrorFunc("Spell \"" + spellName + "\" not found"); pushBoolean(L, false); return 1; } if (player->hasFlag(PlayerFlag_IgnoreSpellCheck)) { pushBoolean(L, true); return 1; } const auto& vocMap = spell->getVocMap(); if (vocMap.count(player->getVocationId()) == 0) { pushBoolean(L, false); } else if (player->getLevel() < spell->getLevel()) { pushBoolean(L, false); } else if (player->getMagicLevel() < spell->getMagicLevel()) { pushBoolean(L, false); } else { pushBoolean(L, true); } return 1; } int LuaScriptInterface::luaPlayerLearnSpell(lua_State* L) { // player:learnSpell(spellName) Player* player = getUserdata(L, 1); if (player) { const std::string& spellName = getString(L, 2); player->learnInstantSpell(spellName); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerForgetSpell(lua_State* L) { // player:forgetSpell(spellName) Player* player = getUserdata(L, 1); if (player) { const std::string& spellName = getString(L, 2); player->forgetInstantSpell(spellName); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerHasLearnedSpell(lua_State* L) { // player:hasLearnedSpell(spellName) Player* player = getUserdata(L, 1); if (player) { const std::string& spellName = getString(L, 2); pushBoolean(L, player->hasLearnedInstantSpell(spellName)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerSave(lua_State* L) { // player:save() Player* player = getUserdata(L, 1); if (player) { player->loginPosition = player->getPosition(); pushBoolean(L, IOLoginData::savePlayer(player)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerIsPzLocked(lua_State* L) { // player:isPzLocked() Player* player = getUserdata(L, 1); if (player) { pushBoolean(L, player->isPzLocked()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetClient(lua_State* L) { // player:getClient() Player* player = getUserdata(L, 1); if (player) { lua_createtable(L, 0, 2); setField(L, "version", player->getProtocolVersion()); setField(L, "os", player->getOperatingSystem()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetHouse(lua_State* L) { // player:getHouse() Player* player = getUserdata(L, 1); if (!player) { lua_pushnil(L); return 1; } House* house = g_game.map.houses.getHouseByPlayerId(player->getGUID()); if (house) { pushUserdata(L, house); setMetatable(L, -1, "House"); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerSetGhostMode(lua_State* L) { // player:setGhostMode(enabled) Player* player = getUserdata(L, 1); if (!player) { lua_pushnil(L); return 1; } bool enabled = getBoolean(L, 2); if (player->isInGhostMode() == enabled) { pushBoolean(L, true); return 1; } player->switchGhostMode(); Tile* tile = player->getTile(); const Position& position = player->getPosition(); SpectatorVec list; g_game.map.getSpectators(list, position, true, true); for (Creature* spectator : list) { Player* tmpPlayer = spectator->getPlayer(); if (tmpPlayer != player && !tmpPlayer->isAccessPlayer()) { if (enabled) { tmpPlayer->sendRemoveTileThing(position, tile->getStackposOfCreature(tmpPlayer, player)); } else { tmpPlayer->sendCreatureAppear(player, position, true); } } else { tmpPlayer->sendCreatureChangeVisible(player, !enabled); } } if (player->isInGhostMode()) { for (const auto& it : g_game.getPlayers()) { if (!it.second->isAccessPlayer()) { it.second->notifyStatusChange(player, VIPSTATUS_OFFLINE); } } IOLoginData::updateOnlineStatus(player->getGUID(), false); } else { for (const auto& it : g_game.getPlayers()) { if (!it.second->isAccessPlayer()) { it.second->notifyStatusChange(player, VIPSTATUS_ONLINE); } } IOLoginData::updateOnlineStatus(player->getGUID(), true); } pushBoolean(L, true); return 1; } int LuaScriptInterface::luaPlayerGetContainerId(lua_State* L) { // player:getContainerId(container) Player* player = getUserdata(L, 1); if (!player) { lua_pushnil(L); return 1; } Container* container = getUserdata(L, 2); if (container) { lua_pushnumber(L, player->getContainerID(container)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetContainerById(lua_State* L) { // player:getContainerById(id) Player* player = getUserdata(L, 1); if (!player) { lua_pushnil(L); return 1; } Container* container = player->getContainerByID(getNumber(L, 2)); if (container) { pushUserdata(L, container); setMetatable(L, -1, "Container"); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetContainerIndex(lua_State* L) { // player:getContainerIndex(id) Player* player = getUserdata(L, 1); if (player) { lua_pushnumber(L, player->getContainerIndex(getNumber(L, 2))); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPlayerGetTotalDamage(lua_State * L) { // player:getTotalDamage(attackSkill, attackValue, fightMode) Player* player = getUserdata(L, 1); if (player) { uint32_t attackSkill = getNumber(L, 2); uint32_t attackValue = getNumber(L, 3); fightMode_t fightMode = static_cast(getNumber(L, 4, FIGHTMODE_BALANCED)); lua_pushnumber(L, Combat::getTotalDamage(attackSkill, attackValue, fightMode)); } else { lua_pushnil(L); } return 1; } // Monster int LuaScriptInterface::luaMonsterCreate(lua_State* L) { // Monster(id or userdata) Monster* monster; if (isNumber(L, 2)) { monster = g_game.getMonsterByID(getNumber(L, 2)); } else if (isUserdata(L, 2)) { if (getUserdataType(L, 2) != LuaData_Monster) { lua_pushnil(L); return 1; } monster = getUserdata(L, 2); } else { monster = nullptr; } if (monster) { pushUserdata(L, monster); setMetatable(L, -1, "Monster"); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterIsMonster(lua_State* L) { // monster:isMonster() pushBoolean(L, getUserdata(L, 1) != nullptr); return 1; } int LuaScriptInterface::luaMonsterGetType(lua_State* L) { // monster:getType() const Monster* monster = getUserdata(L, 1); if (monster) { pushUserdata(L, monster->mType); setMetatable(L, -1, "MonsterType"); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterGetSpawnPosition(lua_State* L) { // monster:getSpawnPosition() const Monster* monster = getUserdata(L, 1); if (monster) { pushPosition(L, monster->getMasterPos()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterIsInSpawnRange(lua_State* L) { // monster:isInSpawnRange([position]) Monster* monster = getUserdata(L, 1); if (monster) { pushBoolean(L, monster->isInSpawnRange(lua_gettop(L) >= 2 ? getPosition(L, 2) : monster->getPosition())); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterIsIdle(lua_State* L) { // monster:isIdle() Monster* monster = getUserdata(L, 1); if (monster) { pushBoolean(L, monster->getIdleStatus()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterSetIdle(lua_State* L) { // monster:setIdle(idle) Monster* monster = getUserdata(L, 1); if (!monster) { lua_pushnil(L); return 1; } monster->setIdle(getBoolean(L, 2)); pushBoolean(L, true); return 1; } int LuaScriptInterface::luaMonsterIsTarget(lua_State* L) { // monster:isTarget(creature) Monster* monster = getUserdata(L, 1); if (monster) { const Creature* creature = getCreature(L, 2); pushBoolean(L, monster->isTarget(creature)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterIsOpponent(lua_State* L) { // monster:isOpponent(creature) Monster* monster = getUserdata(L, 1); if (monster) { const Creature* creature = getCreature(L, 2); pushBoolean(L, monster->isOpponent(creature)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterIsFriend(lua_State* L) { // monster:isFriend(creature) Monster* monster = getUserdata(L, 1); if (monster) { const Creature* creature = getCreature(L, 2); pushBoolean(L, monster->isFriend(creature)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterAddFriend(lua_State* L) { // monster:addFriend(creature) Monster* monster = getUserdata(L, 1); if (monster) { Creature* creature = getCreature(L, 2); monster->addFriend(creature); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterRemoveFriend(lua_State* L) { // monster:removeFriend(creature) Monster* monster = getUserdata(L, 1); if (monster) { Creature* creature = getCreature(L, 2); monster->removeFriend(creature); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterGetFriendList(lua_State* L) { // monster:getFriendList() Monster* monster = getUserdata(L, 1); if (!monster) { lua_pushnil(L); return 1; } const auto& friendList = monster->getFriendList(); lua_createtable(L, friendList.size(), 0); int index = 0; for (Creature* creature : friendList) { pushUserdata(L, creature); setCreatureMetatable(L, -1, creature); lua_rawseti(L, -2, ++index); } return 1; } int LuaScriptInterface::luaMonsterGetFriendCount(lua_State* L) { // monster:getFriendCount() Monster* monster = getUserdata(L, 1); if (monster) { lua_pushnumber(L, monster->getFriendList().size()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterAddTarget(lua_State* L) { // monster:addTarget(creature[, pushFront = false]) Monster* monster = getUserdata(L, 1); if (!monster) { lua_pushnil(L); return 1; } Creature* creature = getCreature(L, 2); bool pushFront = getBoolean(L, 3, false); monster->addTarget(creature, pushFront); pushBoolean(L, true); return 1; } int LuaScriptInterface::luaMonsterRemoveTarget(lua_State* L) { // monster:removeTarget(creature) Monster* monster = getUserdata(L, 1); if (!monster) { lua_pushnil(L); return 1; } monster->removeTarget(getCreature(L, 2)); pushBoolean(L, true); return 1; } int LuaScriptInterface::luaMonsterGetTargetList(lua_State* L) { // monster:getTargetList() Monster* monster = getUserdata(L, 1); if (!monster) { lua_pushnil(L); return 1; } const auto& targetList = monster->getTargetList(); lua_createtable(L, targetList.size(), 0); int index = 0; for (Creature* creature : targetList) { pushUserdata(L, creature); setCreatureMetatable(L, -1, creature); lua_rawseti(L, -2, ++index); } return 1; } int LuaScriptInterface::luaMonsterGetTargetCount(lua_State* L) { // monster:getTargetCount() Monster* monster = getUserdata(L, 1); if (monster) { lua_pushnumber(L, monster->getTargetList().size()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterSelectTarget(lua_State* L) { // monster:selectTarget(creature) Monster* monster = getUserdata(L, 1); if (monster) { Creature* creature = getCreature(L, 2); pushBoolean(L, monster->selectTarget(creature)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterSearchTarget(lua_State* L) { // monster:searchTarget([searchType = TARGETSEARCH_ANY]) Monster* monster = getUserdata(L, 1); if (monster) { TargetSearchType_t searchType = getNumber(L, 2, TARGETSEARCH_ANY); pushBoolean(L, monster->searchTarget(searchType)); } else { lua_pushnil(L); } return 1; } // Npc int LuaScriptInterface::luaNpcCreate(lua_State* L) { // Npc([id or name or userdata]) Npc* npc; if (lua_gettop(L) >= 2) { if (isNumber(L, 2)) { npc = g_game.getNpcByID(getNumber(L, 2)); } else if (isString(L, 2)) { npc = g_game.getNpcByName(getString(L, 2)); } else if (isUserdata(L, 2)) { if (getUserdataType(L, 2) != LuaData_Npc) { lua_pushnil(L); return 1; } npc = getUserdata(L, 2); } else { npc = nullptr; } } else { npc = getScriptEnv()->getNpc(); } if (npc) { pushUserdata(L, npc); setMetatable(L, -1, "Npc"); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaNpcIsNpc(lua_State* L) { // npc:isNpc() pushBoolean(L, getUserdata(L, 1) != nullptr); return 1; } int LuaScriptInterface::luaNpcSetMasterPos(lua_State* L) { // npc:setMasterPos(pos[, radius]) Npc* npc = getUserdata(L, 1); if (!npc) { lua_pushnil(L); return 1; } const Position& pos = getPosition(L, 2); int32_t radius = getNumber(L, 3, 1); npc->setMasterPos(pos, radius); pushBoolean(L, true); return 1; } // Guild int LuaScriptInterface::luaGuildCreate(lua_State* L) { // Guild(id) uint32_t id = getNumber(L, 2); Guild* guild = g_game.getGuild(id); if (guild) { pushUserdata(L, guild); setMetatable(L, -1, "Guild"); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaGuildGetId(lua_State* L) { // guild:getId() Guild* guild = getUserdata(L, 1); if (guild) { lua_pushnumber(L, guild->getId()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaGuildGetName(lua_State* L) { // guild:getName() Guild* guild = getUserdata(L, 1); if (guild) { pushString(L, guild->getName()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaGuildGetMembersOnline(lua_State* L) { // guild:getMembersOnline() const Guild* guild = getUserdata(L, 1); if (!guild) { lua_pushnil(L); return 1; } const auto& members = guild->getMembersOnline(); lua_createtable(L, members.size(), 0); int index = 0; for (Player* player : members) { pushUserdata(L, player); setMetatable(L, -1, "Player"); lua_rawseti(L, -2, ++index); } return 1; } int LuaScriptInterface::luaGuildAddRank(lua_State* L) { // guild:addRank(id, name, level) Guild* guild = getUserdata(L, 1); if (guild) { uint32_t id = getNumber(L, 2); const std::string& name = getString(L, 3); uint8_t level = getNumber(L, 4); guild->addRank(id, name, level); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaGuildGetRankById(lua_State* L) { // guild:getRankById(id) Guild* guild = getUserdata(L, 1); if (!guild) { lua_pushnil(L); return 1; } uint32_t id = getNumber(L, 2); GuildRank* rank = guild->getRankById(id); if (rank) { lua_createtable(L, 0, 3); setField(L, "id", rank->id); setField(L, "name", rank->name); setField(L, "level", rank->level); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaGuildGetRankByLevel(lua_State* L) { // guild:getRankByLevel(level) const Guild* guild = getUserdata(L, 1); if (!guild) { lua_pushnil(L); return 1; } uint8_t level = getNumber(L, 2); const GuildRank* rank = guild->getRankByLevel(level); if (rank) { lua_createtable(L, 0, 3); setField(L, "id", rank->id); setField(L, "name", rank->name); setField(L, "level", rank->level); } else { lua_pushnil(L); } return 1; } // Group int LuaScriptInterface::luaGroupCreate(lua_State* L) { // Group(id) uint32_t id = getNumber(L, 2); Group* group = g_game.groups.getGroup(id); if (group) { pushUserdata(L, group); setMetatable(L, -1, "Group"); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaGroupGetId(lua_State* L) { // group:getId() Group* group = getUserdata(L, 1); if (group) { lua_pushnumber(L, group->id); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaGroupGetName(lua_State* L) { // group:getName() Group* group = getUserdata(L, 1); if (group) { pushString(L, group->name); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaGroupGetFlags(lua_State* L) { // group:getFlags() Group* group = getUserdata(L, 1); if (group) { lua_pushnumber(L, group->flags); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaGroupGetAccess(lua_State* L) { // group:getAccess() Group* group = getUserdata(L, 1); if (group) { pushBoolean(L, group->access); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaGroupGetMaxDepotItems(lua_State* L) { // group:getMaxDepotItems() Group* group = getUserdata(L, 1); if (group) { lua_pushnumber(L, group->maxDepotItems); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaGroupGetMaxVipEntries(lua_State* L) { // group:getMaxVipEntries() Group* group = getUserdata(L, 1); if (group) { lua_pushnumber(L, group->maxVipEntries); } else { lua_pushnil(L); } return 1; } // Vocation int LuaScriptInterface::luaVocationCreate(lua_State* L) { // Vocation(id or name) uint32_t id; if (isNumber(L, 2)) { id = getNumber(L, 2); } else { id = g_vocations.getVocationId(getString(L, 2)); } Vocation* vocation = g_vocations.getVocation(id); if (vocation) { pushUserdata(L, vocation); setMetatable(L, -1, "Vocation"); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaVocationGetId(lua_State* L) { // vocation:getId() Vocation* vocation = getUserdata(L, 1); if (vocation) { lua_pushnumber(L, vocation->getId()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaVocationGetName(lua_State* L) { // vocation:getName() Vocation* vocation = getUserdata(L, 1); if (vocation) { pushString(L, vocation->getVocName()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaVocationGetDescription(lua_State* L) { // vocation:getDescription() Vocation* vocation = getUserdata(L, 1); if (vocation) { pushString(L, vocation->getVocDescription()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaVocationGetRequiredSkillTries(lua_State* L) { // vocation:getRequiredSkillTries(skillType, skillLevel) Vocation* vocation = getUserdata(L, 1); if (vocation) { skills_t skillType = getNumber(L, 2); uint16_t skillLevel = getNumber(L, 3); lua_pushnumber(L, vocation->getReqSkillTries(skillType, skillLevel)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaVocationGetRequiredManaSpent(lua_State* L) { // vocation:getRequiredManaSpent(magicLevel) Vocation* vocation = getUserdata(L, 1); if (vocation) { uint32_t magicLevel = getNumber(L, 2); lua_pushnumber(L, vocation->getReqMana(magicLevel)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaVocationGetCapacityGain(lua_State* L) { // vocation:getCapacityGain() Vocation* vocation = getUserdata(L, 1); if (vocation) { lua_pushnumber(L, vocation->getCapGain()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaVocationGetHealthGain(lua_State* L) { // vocation:getHealthGain() Vocation* vocation = getUserdata(L, 1); if (vocation) { lua_pushnumber(L, vocation->getHPGain()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaVocationGetHealthGainTicks(lua_State* L) { // vocation:getHealthGainTicks() Vocation* vocation = getUserdata(L, 1); if (vocation) { lua_pushnumber(L, vocation->getHealthGainTicks()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaVocationGetHealthGainAmount(lua_State* L) { // vocation:getHealthGainAmount() Vocation* vocation = getUserdata(L, 1); if (vocation) { lua_pushnumber(L, vocation->getHealthGainAmount()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaVocationGetManaGain(lua_State* L) { // vocation:getManaGain() Vocation* vocation = getUserdata(L, 1); if (vocation) { lua_pushnumber(L, vocation->getManaGain()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaVocationGetManaGainTicks(lua_State* L) { // vocation:getManaGainTicks() Vocation* vocation = getUserdata(L, 1); if (vocation) { lua_pushnumber(L, vocation->getManaGainTicks()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaVocationGetManaGainAmount(lua_State* L) { // vocation:getManaGainAmount() Vocation* vocation = getUserdata(L, 1); if (vocation) { lua_pushnumber(L, vocation->getManaGainAmount()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaVocationGetMaxSoul(lua_State* L) { // vocation:getMaxSoul() Vocation* vocation = getUserdata(L, 1); if (vocation) { lua_pushnumber(L, vocation->getSoulMax()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaVocationGetSoulGainTicks(lua_State* L) { // vocation:getSoulGainTicks() Vocation* vocation = getUserdata(L, 1); if (vocation) { lua_pushnumber(L, vocation->getSoulGainTicks()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaVocationGetAttackSpeed(lua_State* L) { // vocation:getAttackSpeed() Vocation* vocation = getUserdata(L, 1); if (vocation) { lua_pushnumber(L, vocation->getAttackSpeed()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaVocationGetBaseSpeed(lua_State* L) { // vocation:getBaseSpeed() Vocation* vocation = getUserdata(L, 1); if (vocation) { lua_pushnumber(L, vocation->getBaseSpeed()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaVocationGetDemotion(lua_State* L) { // vocation:getDemotion() Vocation* vocation = getUserdata(L, 1); if (!vocation) { lua_pushnil(L); return 1; } uint16_t fromId = vocation->getFromVocation(); if (fromId == VOCATION_NONE) { lua_pushnil(L); return 1; } Vocation* demotedVocation = g_vocations.getVocation(fromId); if (demotedVocation && demotedVocation != vocation) { pushUserdata(L, demotedVocation); setMetatable(L, -1, "Vocation"); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaVocationGetPromotion(lua_State* L) { // vocation:getPromotion() Vocation* vocation = getUserdata(L, 1); if (!vocation) { lua_pushnil(L); return 1; } uint16_t promotedId = g_vocations.getPromotedVocation(vocation->getId()); if (promotedId == VOCATION_NONE) { lua_pushnil(L); return 1; } Vocation* promotedVocation = g_vocations.getVocation(promotedId); if (promotedVocation && promotedVocation != vocation) { pushUserdata(L, promotedVocation); setMetatable(L, -1, "Vocation"); } else { lua_pushnil(L); } return 1; } // Town int LuaScriptInterface::luaTownCreate(lua_State* L) { // Town(id or name) Town* town; if (isNumber(L, 2)) { town = g_game.map.towns.getTown(getNumber(L, 2)); } else if (isString(L, 2)) { town = g_game.map.towns.getTown(getString(L, 2)); } else { town = nullptr; } if (town) { pushUserdata(L, town); setMetatable(L, -1, "Town"); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaTownGetId(lua_State* L) { // town:getId() Town* town = getUserdata(L, 1); if (town) { lua_pushnumber(L, town->getID()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaTownGetName(lua_State* L) { // town:getName() Town* town = getUserdata(L, 1); if (town) { pushString(L, town->getName()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaTownGetTemplePosition(lua_State* L) { // town:getTemplePosition() Town* town = getUserdata(L, 1); if (town) { pushPosition(L, town->getTemplePosition()); } else { lua_pushnil(L); } return 1; } // House int LuaScriptInterface::luaHouseCreate(lua_State* L) { // House(id) House* house = g_game.map.houses.getHouse(getNumber(L, 2)); if (house) { pushUserdata(L, house); setMetatable(L, -1, "House"); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaHouseGetId(lua_State* L) { // house:getId() House* house = getUserdata(L, 1); if (house) { lua_pushnumber(L, house->getId()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaHouseGetName(lua_State* L) { // house:getName() House* house = getUserdata(L, 1); if (house) { pushString(L, house->getName()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaHouseGetTown(lua_State* L) { // house:getTown() House* house = getUserdata(L, 1); if (!house) { lua_pushnil(L); return 1; } Town* town = g_game.map.towns.getTown(house->getTownId()); if (town) { pushUserdata(L, town); setMetatable(L, -1, "Town"); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaHouseGetExitPosition(lua_State* L) { // house:getExitPosition() House* house = getUserdata(L, 1); if (house) { pushPosition(L, house->getEntryPosition()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaHouseGetRent(lua_State* L) { // house:getRent() House* house = getUserdata(L, 1); if (house) { lua_pushnumber(L, house->getRent()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaHouseGetOwnerGuid(lua_State* L) { // house:getOwnerGuid() House* house = getUserdata(L, 1); if (house) { lua_pushnumber(L, house->getOwner()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaHouseSetOwnerGuid(lua_State* L) { // house:setOwnerGuid(guid[, updateDatabase = true]) House* house = getUserdata(L, 1); if (house) { uint32_t guid = getNumber(L, 2); bool updateDatabase = getBoolean(L, 3, true); house->setOwner(guid, updateDatabase); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaHouseStartTrade(lua_State* L) { // house:startTrade(player, tradePartner) House* house = getUserdata(L, 1); Player* player = getUserdata(L, 2); Player* tradePartner = getUserdata(L, 3); if (!player || !tradePartner || !house) { lua_pushnil(L); return 1; } if (!Position::areInRange<2, 2, 0>(tradePartner->getPosition(), player->getPosition())) { lua_pushnumber(L, RETURNVALUE_TRADEPLAYERFARAWAY); return 1; } if (house->getOwner() != player->getGUID()) { lua_pushnumber(L, RETURNVALUE_YOUDONTOWNTHISHOUSE); return 1; } if (g_game.map.houses.getHouseByPlayerId(tradePartner->getGUID())) { lua_pushnumber(L, RETURNVALUE_TRADEPLAYERALREADYOWNSAHOUSE); return 1; } if (IOLoginData::hasBiddedOnHouse(tradePartner->getGUID())) { lua_pushnumber(L, RETURNVALUE_TRADEPLAYERHIGHESTBIDDER); return 1; } Item* transferItem = house->getTransferItem(); if (!transferItem) { lua_pushnumber(L, RETURNVALUE_YOUCANNOTTRADETHISHOUSE); return 1; } transferItem->getParent()->setParent(player); if (!g_game.internalStartTrade(player, tradePartner, transferItem)) { house->resetTransferItem(); } lua_pushnumber(L, RETURNVALUE_NOERROR); return 1; } int LuaScriptInterface::luaHouseGetBeds(lua_State* L) { // house:getBeds() House* house = getUserdata(L, 1); if (!house) { lua_pushnil(L); return 1; } const auto& beds = house->getBeds(); lua_createtable(L, beds.size(), 0); int index = 0; for (BedItem* bedItem : beds) { pushUserdata(L, bedItem); setItemMetatable(L, -1, bedItem); lua_rawseti(L, -2, ++index); } return 1; } int LuaScriptInterface::luaHouseGetBedCount(lua_State* L) { // house:getBedCount() House* house = getUserdata(L, 1); if (house) { lua_pushnumber(L, house->getBedCount()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaHouseGetDoors(lua_State* L) { // house:getDoors() House* house = getUserdata(L, 1); if (!house) { lua_pushnil(L); return 1; } const auto& doors = house->getDoors(); lua_createtable(L, doors.size(), 0); int index = 0; for (Door* door : doors) { pushUserdata(L, door); setItemMetatable(L, -1, door); lua_rawseti(L, -2, ++index); } return 1; } int LuaScriptInterface::luaHouseGetDoorCount(lua_State* L) { // house:getDoorCount() House* house = getUserdata(L, 1); if (house) { lua_pushnumber(L, house->getDoors().size()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaHouseGetTiles(lua_State* L) { // house:getTiles() House* house = getUserdata(L, 1); if (!house) { lua_pushnil(L); return 1; } const auto& tiles = house->getTiles(); lua_createtable(L, tiles.size(), 0); int index = 0; for (Tile* tile : tiles) { pushUserdata(L, tile); setMetatable(L, -1, "Tile"); lua_rawseti(L, -2, ++index); } return 1; } int LuaScriptInterface::luaHouseGetTileCount(lua_State* L) { // house:getTileCount() House* house = getUserdata(L, 1); if (house) { lua_pushnumber(L, house->getTiles().size()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaHouseGetAccessList(lua_State* L) { // house:getAccessList(listId) House* house = getUserdata(L, 1); if (!house) { lua_pushnil(L); return 1; } std::string list; uint32_t listId = getNumber(L, 2); if (house->getAccessList(listId, list)) { pushString(L, list); } else { pushBoolean(L, false); } return 1; } int LuaScriptInterface::luaHouseSetAccessList(lua_State* L) { // house:setAccessList(listId, list) House* house = getUserdata(L, 1); if (!house) { lua_pushnil(L); return 1; } uint32_t listId = getNumber(L, 2); const std::string& list = getString(L, 3); house->setAccessList(listId, list); pushBoolean(L, true); return 1; } // ItemType int LuaScriptInterface::luaItemTypeCreate(lua_State* L) { // ItemType(id or name) uint32_t id; if (isNumber(L, 2)) { id = getNumber(L, 2); } else { id = Item::items.getItemIdByName(getString(L, 2)); } const ItemType& itemType = Item::items[id]; pushUserdata(L, &itemType); setMetatable(L, -1, "ItemType"); return 1; } int LuaScriptInterface::luaItemTypeIsCorpse(lua_State* L) { // itemType:isCorpse() const ItemType* itemType = getUserdata(L, 1); if (itemType) { pushBoolean(L, itemType->corpse); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeIsDoor(lua_State* L) { // itemType:isDoor() const ItemType* itemType = getUserdata(L, 1); if (itemType) { pushBoolean(L, itemType->isDoor()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeIsContainer(lua_State* L) { // itemType:isContainer() const ItemType* itemType = getUserdata(L, 1); if (itemType) { pushBoolean(L, itemType->isContainer()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeIsChest(lua_State * L) { // itemType:isChest() const ItemType* itemType = getUserdata(L, 1); if (itemType) { pushBoolean(L, itemType->isChest()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeIsFluidContainer(lua_State* L) { // itemType:isFluidContainer() const ItemType* itemType = getUserdata(L, 1); if (itemType) { pushBoolean(L, itemType->isFluidContainer()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeIsMovable(lua_State* L) { // itemType:isMovable() const ItemType* itemType = getUserdata(L, 1); if (itemType) { pushBoolean(L, itemType->moveable); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeIsRune(lua_State* L) { // itemType:isRune() const ItemType* itemType = getUserdata(L, 1); if (itemType) { pushBoolean(L, itemType->isRune()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeIsStackable(lua_State* L) { // itemType:isStackable() const ItemType* itemType = getUserdata(L, 1); if (itemType) { pushBoolean(L, itemType->stackable); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeIsReadable(lua_State* L) { // itemType:isReadable() const ItemType* itemType = getUserdata(L, 1); if (itemType) { pushBoolean(L, itemType->canReadText); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeIsWritable(lua_State* L) { // itemType:isWritable() const ItemType* itemType = getUserdata(L, 1); if (itemType) { pushBoolean(L, itemType->canWriteText); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeIsMagicField(lua_State* L) { // itemType:isMagicField() const ItemType* itemType = getUserdata(L, 1); if (itemType) { pushBoolean(L, itemType->isMagicField()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeIsSplash(lua_State* L) { // itemType:isSplash() const ItemType* itemType = getUserdata(L, 1); if (itemType) { pushBoolean(L, itemType->isSplash()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeIsKey(lua_State* L) { // itemType:isKey() const ItemType* itemType = getUserdata(L, 1); if (itemType) { pushBoolean(L, itemType->isKey()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeIsDisguised(lua_State* L) { // itemType:isDisguised() const ItemType* itemType = getUserdata(L, 1); if (itemType) { pushBoolean(L, itemType->disguise); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeIsDestroyable(lua_State * L) { // itemType:isDestroyable() const ItemType* itemType = getUserdata(L, 1); if (itemType) { pushBoolean(L, itemType->destroy); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeIsGroundTile(lua_State * L) { // itemType:isGroundTile() const ItemType* itemType = getUserdata(L, 1); if (itemType) { pushBoolean(L, itemType->group == ITEM_GROUP_GROUND); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeGetType(lua_State* L) { // itemType:getType() const ItemType* itemType = getUserdata(L, 1); if (itemType) { lua_pushnumber(L, itemType->type); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeGetId(lua_State* L) { // itemType:getId() const ItemType* itemType = getUserdata(L, 1); if (itemType) { lua_pushnumber(L, itemType->id); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeGetDisguiseId(lua_State * L) { // itemType:getDisguiseId() const ItemType* itemType = getUserdata(L, 1); if (itemType) { lua_pushnumber(L, itemType->disguiseId); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeGetName(lua_State* L) { // itemType:getName() const ItemType* itemType = getUserdata(L, 1); if (itemType) { pushString(L, itemType->name); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeGetPluralName(lua_State* L) { // itemType:getPluralName() const ItemType* itemType = getUserdata(L, 1); if (itemType) { pushString(L, itemType->getPluralName()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeGetArticle(lua_State* L) { // itemType:getArticle() const ItemType* itemType = getUserdata(L, 1); if (itemType) { pushString(L, itemType->article); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeGetDescription(lua_State* L) { // itemType:getDescription() const ItemType* itemType = getUserdata(L, 1); if (itemType) { pushString(L, itemType->description); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeGetSlotPosition(lua_State *L) { // itemType:getSlotPosition() const ItemType* itemType = getUserdata(L, 1); if (itemType) { lua_pushnumber(L, itemType->slotPosition); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeGetDestroyTarget(lua_State * L) { // itemType:getDestroyTarget() const ItemType* itemType = getUserdata(L, 1); if (itemType) { lua_pushnumber(L, itemType->destroyTarget); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeGetCharges(lua_State* L) { // itemType:getCharges() const ItemType* itemType = getUserdata(L, 1); if (itemType) { lua_pushnumber(L, itemType->charges); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeGetFluidSource(lua_State* L) { // itemType:getFluidSource() const ItemType* itemType = getUserdata(L, 1); if (itemType) { lua_pushnumber(L, itemType->fluidSource); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeGetCapacity(lua_State* L) { // itemType:getCapacity() const ItemType* itemType = getUserdata(L, 1); if (itemType) { lua_pushnumber(L, itemType->maxItems); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeGetWeight(lua_State* L) { // itemType:getWeight([count = 1]) uint16_t count = getNumber(L, 2, 1); const ItemType* itemType = getUserdata(L, 1); if (!itemType) { lua_pushnil(L); return 1; } uint64_t weight = static_cast(itemType->weight) * std::max(1, count); lua_pushnumber(L, weight); return 1; } int LuaScriptInterface::luaItemTypeGetShootRange(lua_State* L) { // itemType:getShootRange() const ItemType* itemType = getUserdata(L, 1); if (itemType) { lua_pushnumber(L, itemType->shootRange); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeGetAttack(lua_State* L) { // itemType:getAttack() const ItemType* itemType = getUserdata(L, 1); if (itemType) { lua_pushnumber(L, itemType->attack); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeGetDefense(lua_State* L) { // itemType:getDefense() const ItemType* itemType = getUserdata(L, 1); if (itemType) { lua_pushnumber(L, itemType->defense); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeGetArmor(lua_State* L) { // itemType:getArmor() const ItemType* itemType = getUserdata(L, 1); if (itemType) { lua_pushnumber(L, itemType->armor); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeGetWeaponType(lua_State* L) { // itemType:getWeaponType() const ItemType* itemType = getUserdata(L, 1); if (itemType) { lua_pushnumber(L, itemType->weaponType); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeGetTransformEquipId(lua_State* L) { // itemType:getTransformEquipId() const ItemType* itemType = getUserdata(L, 1); if (itemType) { lua_pushnumber(L, itemType->transformEquipTo); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeGetTransformDeEquipId(lua_State* L) { // itemType:getTransformDeEquipId() const ItemType* itemType = getUserdata(L, 1); if (itemType) { lua_pushnumber(L, itemType->transformDeEquipTo); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeGetDecayId(lua_State* L) { // itemType:getDecayId() const ItemType* itemType = getUserdata(L, 1); if (itemType) { lua_pushnumber(L, itemType->decayTo); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeGetNutrition(lua_State* L) { // itemType:getNutrition() const ItemType* itemType = getUserdata(L, 1); if (itemType) { lua_pushnumber(L, itemType->nutrition); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeGetRequiredLevel(lua_State* L) { // itemType:getRequiredLevel() const ItemType* itemType = getUserdata(L, 1); if (itemType) { lua_pushnumber(L, itemType->minReqLevel); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaItemTypeHasSubType(lua_State* L) { // itemType:hasSubType() const ItemType* itemType = getUserdata(L, 1); if (itemType) { pushBoolean(L, itemType->hasSubType()); } else { lua_pushnil(L); } return 1; } // Combat int LuaScriptInterface::luaCombatCreate(lua_State* L) { // Combat() pushUserdata(L, g_luaEnvironment.createCombatObject(getScriptEnv()->getScriptInterface())); setMetatable(L, -1, "Combat"); return 1; } int LuaScriptInterface::luaCombatSetParameter(lua_State* L) { // combat:setParameter(key, value) Combat* combat = getUserdata(L, 1); if (!combat) { lua_pushnil(L); return 1; } CombatParam_t key = getNumber(L, 2); uint32_t value; if (isBoolean(L, 3)) { value = getBoolean(L, 3) ? 1 : 0; } else { value = getNumber(L, 3); } combat->setParam(key, value); pushBoolean(L, true); return 1; } int LuaScriptInterface::luaCombatSetFormula(lua_State* L) { // combat:setFormula(type, mina, minb, maxa, maxb) Combat* combat = getUserdata(L, 1); if (!combat) { lua_pushnil(L); return 1; } formulaType_t type = getNumber(L, 2); double mina = getNumber(L, 3); double minb = getNumber(L, 4); double maxa = getNumber(L, 5); double maxb = getNumber(L, 6); combat->setPlayerCombatValues(type, mina, minb, maxa, maxb); pushBoolean(L, true); return 1; } int LuaScriptInterface::luaCombatSetArea(lua_State* L) { // combat:setArea(area) if (getScriptEnv()->getScriptId() != EVENT_ID_LOADING) { reportErrorFunc("This function can only be used while loading the script."); lua_pushnil(L); return 1; } const AreaCombat* area = g_luaEnvironment.getAreaObject(getNumber(L, 2)); if (!area) { reportErrorFunc(getErrorDesc(LUA_ERROR_AREA_NOT_FOUND)); lua_pushnil(L); return 1; } Combat* combat = getUserdata(L, 1); if (combat) { combat->setArea(new AreaCombat(*area)); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCombatSetCondition(lua_State* L) { // combat:setCondition(condition) Condition* condition = getUserdata(L, 2); Combat* combat = getUserdata(L, 1); if (combat && condition) { combat->setCondition(condition->clone()); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCombatSetCallback(lua_State* L) { // combat:setCallback(key, function) Combat* combat = getUserdata(L, 1); if (!combat) { lua_pushnil(L); return 1; } CallBackParam_t key = getNumber(L, 2); if (!combat->setCallback(key)) { lua_pushnil(L); return 1; } CallBack* callback = combat->getCallback(key); if (!callback) { lua_pushnil(L); return 1; } const std::string& function = getString(L, 3); pushBoolean(L, callback->loadCallBack(getScriptEnv()->getScriptInterface(), function)); return 1; } int LuaScriptInterface::luaCombatSetOrigin(lua_State* L) { // combat:setOrigin(origin) Combat* combat = getUserdata(L, 1); if (combat) { combat->setOrigin(getNumber(L, 2)); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaCombatExecute(lua_State* L) { // combat:execute(creature, variant) Combat* combat = getUserdata(L, 1); if (!combat) { pushBoolean(L, false); return 1; } Creature* creature = getCreature(L, 2); const LuaVariant& variant = getVariant(L, 3); switch (variant.type) { case VARIANT_NUMBER: { Creature* target = g_game.getCreatureByID(variant.number); if (!target) { pushBoolean(L, false); return 1; } if (combat->hasArea()) { combat->doCombat(creature, target->getPosition()); } else { combat->doCombat(creature, target); } break; } case VARIANT_POSITION: { combat->doCombat(creature, variant.pos); break; } case VARIANT_TARGETPOSITION: { if (combat->hasArea()) { combat->doCombat(creature, variant.pos); } else { combat->postCombatEffects(creature, variant.pos); g_game.addMagicEffect(variant.pos, CONST_ME_POFF); } break; } case VARIANT_STRING: { Player* target = g_game.getPlayerByName(variant.text); if (!target) { pushBoolean(L, false); return 1; } combat->doCombat(creature, target); break; } case VARIANT_NONE: { reportErrorFunc(getErrorDesc(LUA_ERROR_VARIANT_NOT_FOUND)); pushBoolean(L, false); return 1; } default: { break; } } pushBoolean(L, true); return 1; } // Condition int LuaScriptInterface::luaConditionCreate(lua_State* L) { // Condition(conditionType[, conditionId = CONDITIONID_COMBAT]) ConditionType_t conditionType = getNumber(L, 2); ConditionId_t conditionId = getNumber(L, 3, CONDITIONID_COMBAT); Condition* condition = Condition::createCondition(conditionId, conditionType, 0, 0); if (condition) { pushUserdata(L, condition); setMetatable(L, -1, "Condition"); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaConditionDelete(lua_State* L) { // condition:delete() Condition** conditionPtr = getRawUserdata(L, 1); if (conditionPtr && *conditionPtr) { delete *conditionPtr; *conditionPtr = nullptr; } return 0; } int LuaScriptInterface::luaConditionGetId(lua_State* L) { // condition:getId() Condition* condition = getUserdata(L, 1); if (condition) { lua_pushnumber(L, condition->getId()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaConditionGetSubId(lua_State* L) { // condition:getSubId() Condition* condition = getUserdata(L, 1); if (condition) { lua_pushnumber(L, condition->getSubId()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaConditionGetType(lua_State* L) { // condition:getType() Condition* condition = getUserdata(L, 1); if (condition) { lua_pushnumber(L, condition->getType()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaConditionGetIcons(lua_State* L) { // condition:getIcons() Condition* condition = getUserdata(L, 1); if (condition) { lua_pushnumber(L, condition->getIcons()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaConditionGetEndTime(lua_State* L) { // condition:getEndTime() Condition* condition = getUserdata(L, 1); if (condition) { lua_pushnumber(L, condition->getEndTime()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaConditionClone(lua_State* L) { // condition:clone() Condition* condition = getUserdata(L, 1); if (condition) { pushUserdata(L, condition->clone()); setMetatable(L, -1, "Condition"); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaConditionGetTicks(lua_State* L) { // condition:getTicks() Condition* condition = getUserdata(L, 1); if (condition) { lua_pushnumber(L, condition->getTicks()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaConditionSetTicks(lua_State* L) { // condition:setTicks(ticks) int32_t ticks = getNumber(L, 2); Condition* condition = getUserdata(L, 1); if (condition) { condition->setTicks(ticks); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaConditionSetParameter(lua_State* L) { // condition:setParameter(key, value) Condition* condition = getUserdata(L, 1); if (!condition) { lua_pushnil(L); return 1; } ConditionParam_t key = getNumber(L, 2); int32_t value; if (isBoolean(L, 3)) { value = getBoolean(L, 3) ? 1 : 0; } else { value = getNumber(L, 3); } condition->setParam(key, value); pushBoolean(L, true); return 1; } int LuaScriptInterface::luaConditionSetSpeedDelta(lua_State* L) { // condition:setSpeedDelta(speedDelta) int32_t speedDelta = getNumber(L, 2); ConditionSpeed* condition = dynamic_cast(getUserdata(L, 1)); if (condition) { condition->setSpeedDelta(speedDelta); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaConditionSetOutfit(lua_State* L) { // condition:setOutfit(outfit) // condition:setOutfit(lookTypeEx, lookType, lookHead, lookBody, lookLegs, lookFeet[, lookAddons]) Outfit_t outfit; if (isTable(L, 2)) { outfit = getOutfit(L, 2); } else { outfit.lookAddons = getNumber(L, 8, outfit.lookAddons); outfit.lookFeet = getNumber(L, 7); outfit.lookLegs = getNumber(L, 6); outfit.lookBody = getNumber(L, 5); outfit.lookHead = getNumber(L, 4); outfit.lookType = getNumber(L, 3); outfit.lookTypeEx = getNumber(L, 2); } ConditionOutfit* condition = dynamic_cast(getUserdata(L, 1)); if (condition) { condition->setOutfit(outfit); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaConditionSetTiming(lua_State* L) { // condition:setTiming(count) int32_t count = getNumber(L, 2); ConditionDamage* condition = dynamic_cast(getUserdata(L, 1)); if (condition) { if (condition->getType() == CONDITION_POISON) { condition->setParam(CONDITION_PARAM_COUNT, 3); condition->setParam(CONDITION_PARAM_MAX_COUNT, 3); } else if (condition->getType() == CONDITION_FIRE) { condition->setParam(CONDITION_PARAM_COUNT, 8); condition->setParam(CONDITION_PARAM_MAX_COUNT, 8); count /= 10; } else if (condition->getType() == CONDITION_ENERGY) { condition->setParam(CONDITION_PARAM_COUNT, 10); condition->setParam(CONDITION_PARAM_MAX_COUNT, 10); count /= 20; } condition->setParam(CONDITION_PARAM_CYCLE, count); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } // MonsterType int LuaScriptInterface::luaMonsterTypeCreate(lua_State* L) { // MonsterType(name) MonsterType* monsterType = g_monsters.getMonsterType(getString(L, 2)); if (monsterType) { pushUserdata(L, monsterType); setMetatable(L, -1, "MonsterType"); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterTypeIsAttackable(lua_State* L) { // monsterType:isAttackable() MonsterType* monsterType = getUserdata(L, 1); if (monsterType) { pushBoolean(L, monsterType->info.isAttackable); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterTypeIsConvinceable(lua_State* L) { // monsterType:isConvinceable() MonsterType* monsterType = getUserdata(L, 1); if (monsterType) { pushBoolean(L, monsterType->info.isConvinceable); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterTypeIsSummonable(lua_State* L) { // monsterType:isSummonable() MonsterType* monsterType = getUserdata(L, 1); if (monsterType) { pushBoolean(L, monsterType->info.isSummonable); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterTypeIsIllusionable(lua_State* L) { // monsterType:isIllusionable() MonsterType* monsterType = getUserdata(L, 1); if (monsterType) { pushBoolean(L, monsterType->info.isIllusionable); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterTypeIsHostile(lua_State* L) { // monsterType:isHostile() MonsterType* monsterType = getUserdata(L, 1); if (monsterType) { pushBoolean(L, monsterType->info.isHostile); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterTypeIsPushable(lua_State* L) { // monsterType:isPushable() MonsterType* monsterType = getUserdata(L, 1); if (monsterType) { pushBoolean(L, monsterType->info.pushable); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterTypeIsHealthShown(lua_State* L) { // monsterType:isHealthShown() MonsterType* monsterType = getUserdata(L, 1); if (monsterType) { pushBoolean(L, !monsterType->info.hiddenHealth); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterTypeCanPushItems(lua_State* L) { // monsterType:canPushItems() MonsterType* monsterType = getUserdata(L, 1); if (monsterType) { pushBoolean(L, monsterType->info.canPushItems); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterTypeCanPushCreatures(lua_State* L) { // monsterType:canPushCreatures() MonsterType* monsterType = getUserdata(L, 1); if (monsterType) { pushBoolean(L, monsterType->info.canPushCreatures); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterTypeGetName(lua_State* L) { // monsterType:getName() MonsterType* monsterType = getUserdata(L, 1); if (monsterType) { pushString(L, monsterType->name); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterTypeGetNameDescription(lua_State* L) { // monsterType:getNameDescription() MonsterType* monsterType = getUserdata(L, 1); if (monsterType) { pushString(L, monsterType->nameDescription); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterTypeGetHealth(lua_State* L) { // monsterType:getHealth() MonsterType* monsterType = getUserdata(L, 1); if (monsterType) { lua_pushnumber(L, monsterType->info.health); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterTypeGetMaxHealth(lua_State* L) { // monsterType:getMaxHealth() MonsterType* monsterType = getUserdata(L, 1); if (monsterType) { lua_pushnumber(L, monsterType->info.healthMax); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterTypeGetRunHealth(lua_State* L) { // monsterType:getRunHealth() MonsterType* monsterType = getUserdata(L, 1); if (monsterType) { lua_pushnumber(L, monsterType->info.runAwayHealth); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterTypeGetExperience(lua_State* L) { // monsterType:getExperience() MonsterType* monsterType = getUserdata(L, 1); if (monsterType) { lua_pushnumber(L, monsterType->info.experience); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterTypeGetCombatImmunities(lua_State* L) { // monsterType:getCombatImmunities() MonsterType* monsterType = getUserdata(L, 1); if (monsterType) { lua_pushnumber(L, monsterType->info.damageImmunities); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterTypeGetConditionImmunities(lua_State* L) { // monsterType:getConditionImmunities() MonsterType* monsterType = getUserdata(L, 1); if (monsterType) { lua_pushnumber(L, monsterType->info.conditionImmunities); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterTypeGetAttackList(lua_State* L) { // monsterType:getAttackList() MonsterType* monsterType = getUserdata(L, 1); if (!monsterType) { lua_pushnil(L); return 1; } lua_createtable(L, monsterType->info.attackSpells.size(), 0); int index = 0; for (const auto& spellBlock : monsterType->info.attackSpells) { lua_createtable(L, 0, 8); setField(L, "chance", spellBlock.chance); setField(L, "isCombatSpell", spellBlock.combatSpell ? 1 : 0); setField(L, "minCombatValue", spellBlock.minCombatValue); setField(L, "maxCombatValue", spellBlock.maxCombatValue); setField(L, "range", spellBlock.range); pushUserdata(L, static_cast(spellBlock.spell)); lua_setfield(L, -2, "spell"); lua_rawseti(L, -2, ++index); } return 1; } int LuaScriptInterface::luaMonsterTypeGetDefenseList(lua_State* L) { // monsterType:getDefenseList() MonsterType* monsterType = getUserdata(L, 1); if (!monsterType) { lua_pushnil(L); return 1; } lua_createtable(L, monsterType->info.defenseSpells.size(), 0); int index = 0; for (const auto& spellBlock : monsterType->info.defenseSpells) { lua_createtable(L, 0, 8); setField(L, "chance", spellBlock.chance); setField(L, "isCombatSpell", spellBlock.combatSpell ? 1 : 0); setField(L, "minCombatValue", spellBlock.minCombatValue); setField(L, "maxCombatValue", spellBlock.maxCombatValue); setField(L, "range", spellBlock.range); pushUserdata(L, static_cast(spellBlock.spell)); lua_setfield(L, -2, "spell"); lua_rawseti(L, -2, ++index); } return 1; } int LuaScriptInterface::luaMonsterTypeGetElementList(lua_State* L) { // monsterType:getElementList() MonsterType* monsterType = getUserdata(L, 1); if (!monsterType) { lua_pushnil(L); return 1; } lua_createtable(L, monsterType->info.elementMap.size(), 0); for (const auto& elementEntry : monsterType->info.elementMap) { lua_pushnumber(L, elementEntry.second); lua_rawseti(L, -2, elementEntry.first); } return 1; } int LuaScriptInterface::luaMonsterTypeGetVoices(lua_State* L) { // monsterType:getVoices() MonsterType* monsterType = getUserdata(L, 1); if (!monsterType) { lua_pushnil(L); return 1; } int index = 0; lua_createtable(L, monsterType->info.voiceVector.size(), 0); for (const auto& voiceBlock : monsterType->info.voiceVector) { lua_createtable(L, 0, 2); setField(L, "text", voiceBlock.text); setField(L, "yellText", voiceBlock.yellText); lua_rawseti(L, -2, ++index); } return 1; } int LuaScriptInterface::luaMonsterTypeGetLoot(lua_State* L) { // monsterType:getLoot() MonsterType* monsterType = getUserdata(L, 1); if (!monsterType) { lua_pushnil(L); return 1; } static const std::function&)> parseLoot = [&](const std::vector& lootList) { lua_createtable(L, lootList.size(), 0); int index = 0; for (const auto& lootBlock : lootList) { lua_createtable(L, 0, 7); setField(L, "itemId", lootBlock.id); setField(L, "chance", lootBlock.chance); setField(L, "subType", lootBlock.subType); setField(L, "maxCount", lootBlock.countmax); setField(L, "actionId", lootBlock.actionId); setField(L, "text", lootBlock.text); parseLoot(lootBlock.childLoot); lua_setfield(L, -2, "childLoot"); lua_rawseti(L, -2, ++index); } }; parseLoot(monsterType->info.lootItems); return 1; } int LuaScriptInterface::luaMonsterTypeGetCreatureEvents(lua_State* L) { // monsterType:getCreatureEvents() MonsterType* monsterType = getUserdata(L, 1); if (!monsterType) { lua_pushnil(L); return 1; } int index = 0; lua_createtable(L, monsterType->info.scripts.size(), 0); for (const std::string& creatureEvent : monsterType->info.scripts) { pushString(L, creatureEvent); lua_rawseti(L, -2, ++index); } return 1; } int LuaScriptInterface::luaMonsterTypeGetSummonList(lua_State* L) { // monsterType:getSummonList() MonsterType* monsterType = getUserdata(L, 1); if (!monsterType) { lua_pushnil(L); return 1; } int index = 0; lua_createtable(L, monsterType->info.summons.size(), 0); for (const auto& summonBlock : monsterType->info.summons) { lua_createtable(L, 0, 3); setField(L, "name", summonBlock.name); setField(L, "chance", summonBlock.chance); lua_rawseti(L, -2, ++index); } return 1; } int LuaScriptInterface::luaMonsterTypeGetMaxSummons(lua_State* L) { // monsterType:getMaxSummons() MonsterType* monsterType = getUserdata(L, 1); if (monsterType) { lua_pushnumber(L, monsterType->info.maxSummons); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterTypeGetArmor(lua_State* L) { // monsterType:getArmor() MonsterType* monsterType = getUserdata(L, 1); if (monsterType) { lua_pushnumber(L, monsterType->info.armor); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterTypeGetDefense(lua_State* L) { // monsterType:getDefense() MonsterType* monsterType = getUserdata(L, 1); if (monsterType) { lua_pushnumber(L, monsterType->info.defense); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterTypeGetOutfit(lua_State* L) { // monsterType:getOutfit() MonsterType* monsterType = getUserdata(L, 1); if (monsterType) { pushOutfit(L, monsterType->info.outfit); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterTypeGetRace(lua_State* L) { // monsterType:getRace() MonsterType* monsterType = getUserdata(L, 1); if (monsterType) { lua_pushnumber(L, monsterType->info.race); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterTypeGetCorpseId(lua_State* L) { // monsterType:getCorpseId() MonsterType* monsterType = getUserdata(L, 1); if (monsterType) { lua_pushnumber(L, monsterType->info.lookcorpse); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterTypeGetManaCost(lua_State* L) { // monsterType:getManaCost() MonsterType* monsterType = getUserdata(L, 1); if (monsterType) { lua_pushnumber(L, monsterType->info.manaCost); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterTypeGetBaseSpeed(lua_State* L) { // monsterType:getBaseSpeed() MonsterType* monsterType = getUserdata(L, 1); if (monsterType) { lua_pushnumber(L, monsterType->info.baseSpeed); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterTypeGetLight(lua_State* L) { // monsterType:getLight() MonsterType* monsterType = getUserdata(L, 1); if (!monsterType) { lua_pushnil(L); return 1; } lua_pushnumber(L, monsterType->info.light.level); lua_pushnumber(L, monsterType->info.light.color); return 2; } int LuaScriptInterface::luaMonsterTypeGetTargetDistance(lua_State* L) { // monsterType:getTargetDistance() MonsterType* monsterType = getUserdata(L, 1); if (monsterType) { lua_pushnumber(L, monsterType->info.targetDistance); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterTypeGetChangeTargetChance(lua_State* L) { // monsterType:getChangeTargetChance() MonsterType* monsterType = getUserdata(L, 1); if (monsterType) { lua_pushnumber(L, monsterType->info.changeTargetChance); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaMonsterTypeGetChangeTargetSpeed(lua_State* L) { // monsterType:getChangeTargetSpeed() MonsterType* monsterType = getUserdata(L, 1); if (monsterType) { lua_pushnumber(L, monsterType->info.changeTargetSpeed); } else { lua_pushnil(L); } return 1; } // Party int LuaScriptInterface::luaPartyDisband(lua_State* L) { // party:disband() Party** partyPtr = getRawUserdata(L, 1); if (partyPtr && *partyPtr) { Party*& party = *partyPtr; party->disband(); party = nullptr; pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPartyGetLeader(lua_State* L) { // party:getLeader() Party* party = getUserdata(L, 1); if (!party) { lua_pushnil(L); return 1; } Player* leader = party->getLeader(); if (leader) { pushUserdata(L, leader); setMetatable(L, -1, "Player"); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPartySetLeader(lua_State* L) { // party:setLeader(player) Player* player = getPlayer(L, 2); Party* party = getUserdata(L, 1); if (party && player) { pushBoolean(L, party->passPartyLeadership(player)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPartyGetMembers(lua_State* L) { // party:getMembers() Party* party = getUserdata(L, 1); if (!party) { lua_pushnil(L); return 1; } int index = 0; lua_createtable(L, party->getMemberCount(), 0); for (Player* player : party->getMembers()) { pushUserdata(L, player); setMetatable(L, -1, "Player"); lua_rawseti(L, -2, ++index); } return 1; } int LuaScriptInterface::luaPartyGetMemberCount(lua_State* L) { // party:getMemberCount() Party* party = getUserdata(L, 1); if (party) { lua_pushnumber(L, party->getMemberCount()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPartyGetInvitees(lua_State* L) { // party:getInvitees() Party* party = getUserdata(L, 1); if (party) { lua_createtable(L, party->getInvitationCount(), 0); int index = 0; for (Player* player : party->getInvitees()) { pushUserdata(L, player); setMetatable(L, -1, "Player"); lua_rawseti(L, -2, ++index); } } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPartyGetInviteeCount(lua_State* L) { // party:getInviteeCount() Party* party = getUserdata(L, 1); if (party) { lua_pushnumber(L, party->getInvitationCount()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPartyAddInvite(lua_State* L) { // party:addInvite(player) Player* player = getPlayer(L, 2); Party* party = getUserdata(L, 1); if (party && player) { pushBoolean(L, party->invitePlayer(*player)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPartyRemoveInvite(lua_State* L) { // party:removeInvite(player) Player* player = getPlayer(L, 2); Party* party = getUserdata(L, 1); if (party && player) { pushBoolean(L, party->removeInvite(*player)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPartyAddMember(lua_State* L) { // party:addMember(player) Player* player = getPlayer(L, 2); Party* party = getUserdata(L, 1); if (party && player) { pushBoolean(L, party->joinParty(*player)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPartyRemoveMember(lua_State* L) { // party:removeMember(player) Player* player = getPlayer(L, 2); Party* party = getUserdata(L, 1); if (party && player) { pushBoolean(L, party->leaveParty(player)); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPartyIsSharedExperienceActive(lua_State* L) { // party:isSharedExperienceActive() Party* party = getUserdata(L, 1); if (party) { pushBoolean(L, party->isSharedExperienceActive()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPartyIsSharedExperienceEnabled(lua_State* L) { // party:isSharedExperienceEnabled() Party* party = getUserdata(L, 1); if (party) { pushBoolean(L, party->isSharedExperienceEnabled()); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPartyShareExperience(lua_State* L) { // party:shareExperience(experience) uint64_t experience = getNumber(L, 2); Party* party = getUserdata(L, 1); if (party) { party->shareExperience(experience, nullptr); pushBoolean(L, true); } else { lua_pushnil(L); } return 1; } int LuaScriptInterface::luaPartySetSharedExperience(lua_State* L) { // party:setSharedExperience(active) bool active = getBoolean(L, 2); Party* party = getUserdata(L, 1); if (party) { pushBoolean(L, party->setSharedExperience(party->getLeader(), active)); } else { lua_pushnil(L); } return 1; } // LuaEnvironment::LuaEnvironment() : LuaScriptInterface("Main Interface") {} LuaEnvironment::~LuaEnvironment() { delete testInterface; closeState(); } bool LuaEnvironment::initState() { luaState = luaL_newstate(); if (!luaState) { return false; } luaL_openlibs(luaState); registerFunctions(); runningEventId = EVENT_ID_USER; return true; } bool LuaEnvironment::reInitState() { // TODO: get children, reload children closeState(); return initState(); } bool LuaEnvironment::closeState() { if (!luaState) { return false; } for (const auto& combatEntry : combatIdMap) { clearCombatObjects(combatEntry.first); } for (const auto& areaEntry : areaIdMap) { clearAreaObjects(areaEntry.first); } for (auto& timerEntry : timerEvents) { LuaTimerEventDesc timerEventDesc = std::move(timerEntry.second); for (int32_t parameter : timerEventDesc.parameters) { luaL_unref(luaState, LUA_REGISTRYINDEX, parameter); } luaL_unref(luaState, LUA_REGISTRYINDEX, timerEventDesc.function); } combatIdMap.clear(); areaIdMap.clear(); timerEvents.clear(); cacheFiles.clear(); lua_close(luaState); luaState = nullptr; return true; } LuaScriptInterface* LuaEnvironment::getTestInterface() { if (!testInterface) { testInterface = new LuaScriptInterface("Test Interface"); testInterface->initState(); } return testInterface; } Combat* LuaEnvironment::getCombatObject(uint32_t id) const { auto it = combatMap.find(id); if (it == combatMap.end()) { return nullptr; } return it->second; } Combat* LuaEnvironment::createCombatObject(LuaScriptInterface* interface) { Combat* combat = new Combat; combatMap[++lastCombatId] = combat; combatIdMap[interface].push_back(lastCombatId); return combat; } void LuaEnvironment::clearCombatObjects(LuaScriptInterface* interface) { auto it = combatIdMap.find(interface); if (it == combatIdMap.end()) { return; } for (uint32_t id : it->second) { auto itt = combatMap.find(id); if (itt != combatMap.end()) { delete itt->second; combatMap.erase(itt); } } it->second.clear(); } AreaCombat* LuaEnvironment::getAreaObject(uint32_t id) const { auto it = areaMap.find(id); if (it == areaMap.end()) { return nullptr; } return it->second; } uint32_t LuaEnvironment::createAreaObject(LuaScriptInterface* interface) { areaMap[++lastAreaId] = new AreaCombat; areaIdMap[interface].push_back(lastAreaId); return lastAreaId; } void LuaEnvironment::clearAreaObjects(LuaScriptInterface* interface) { auto it = areaIdMap.find(interface); if (it == areaIdMap.end()) { return; } for (uint32_t id : it->second) { auto itt = areaMap.find(id); if (itt != areaMap.end()) { delete itt->second; areaMap.erase(itt); } } it->second.clear(); } void LuaEnvironment::executeTimerEvent(uint32_t eventIndex) { auto it = timerEvents.find(eventIndex); if (it == timerEvents.end()) { return; } LuaTimerEventDesc timerEventDesc = std::move(it->second); timerEvents.erase(it); //push function lua_rawgeti(luaState, LUA_REGISTRYINDEX, timerEventDesc.function); //push parameters for (auto parameter : boost::adaptors::reverse(timerEventDesc.parameters)) { lua_rawgeti(luaState, LUA_REGISTRYINDEX, parameter); } //call the function if (reserveScriptEnv()) { ScriptEnvironment* env = getScriptEnv(); env->setTimerEvent(); env->setScriptId(timerEventDesc.scriptId, this); callFunction(timerEventDesc.parameters.size()); } else { std::cout << "[Error - LuaScriptInterface::executeTimerEvent] Call stack overflow" << std::endl; } //free resources luaL_unref(luaState, LUA_REGISTRYINDEX, timerEventDesc.function); for (auto parameter : timerEventDesc.parameters) { luaL_unref(luaState, LUA_REGISTRYINDEX, parameter); } }