SabrehavenServer/src/luascript.cpp
2019-12-12 17:41:44 +02:00

11729 lines
300 KiB
C++

/**
* Tibia GIMUD Server - a free and open-source MMORPG server emulator
* Copyright (C) 2019 Sabrehaven and Mark Samman <mark.samman@gmail.com>
*
* 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 <boost/range/adaptor/reversed.hpp>
#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*, Item*> 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<Item>(L, item);
setItemMetatable(L, -1, item);
} else if (Creature* creature = thing->getCreature()) {
pushUserdata<Creature>(L, creature);
setCreatureMetatable(L, -1, creature);
} else {
lua_pushnil(L);
}
}
void LuaScriptInterface::pushCylinder(lua_State* L, Cylinder* cylinder)
{
if (Creature* creature = cylinder->getCreature()) {
pushUserdata<Creature>(L, creature);
setCreatureMetatable(L, -1, creature);
} else if (Item* parentItem = cylinder->getItem()) {
pushUserdata<Item>(L, parentItem);
setItemMetatable(L, -1, parentItem);
} else if (Tile* tile = cylinder->getTile()) {
pushUserdata<Tile>(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<std::string> 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<std::string> 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<int> 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<int32_t>(L, -4);
damage.type = getNumber<CombatType_t>(L, -3);
damage.min = getNumber<int32_t>(L, -2);
damage.max = getNumber<CombatType_t>(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<uint16_t>(L, arg, "x");
position.y = getField<uint16_t>(L, arg, "y");
position.z = getField<uint8_t>(L, arg, "z");
lua_getfield(L, arg, "stackpos");
if (lua_isnil(L, -1) == 1) {
stackpos = 0;
} else {
stackpos = getNumber<int32_t>(L, -1);
}
lua_pop(L, 4);
return position;
}
Position LuaScriptInterface::getPosition(lua_State* L, int32_t arg)
{
Position position;
position.x = getField<uint16_t>(L, arg, "x");
position.y = getField<uint16_t>(L, arg, "y");
position.z = getField<uint8_t>(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<uint8_t>(L, arg, "lookAddons");
outfit.lookFeet = getField<uint8_t>(L, arg, "lookFeet");
outfit.lookLegs = getField<uint8_t>(L, arg, "lookLegs");
outfit.lookBody = getField<uint8_t>(L, arg, "lookBody");
outfit.lookHead = getField<uint8_t>(L, arg, "lookHead");
outfit.lookTypeEx = getField<uint8_t>(L, arg, "lookTypeEx");
outfit.lookType = getField<uint8_t>(L, arg, "lookType");
lua_pop(L, 6);
return outfit;
}
LuaVariant LuaScriptInterface::getVariant(lua_State* L, int32_t arg)
{
LuaVariant var;
switch (var.type = getField<LuaVariantType_t>(L, arg, "type")) {
case VARIANT_NUMBER: {
var.number = getField<uint32_t>(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<uint32_t>(L, -1)) {
case LuaData_Item:
thing = getUserdata<Item>(L, arg);
break;
case LuaData_Container:
thing = getUserdata<Container>(L, arg);
break;
case LuaData_Teleport:
thing = getUserdata<Teleport>(L, arg);
break;
case LuaData_Player:
thing = getUserdata<Player>(L, arg);
break;
case LuaData_Monster:
thing = getUserdata<Monster>(L, arg);
break;
case LuaData_Npc:
thing = getUserdata<Npc>(L, arg);
break;
default:
thing = nullptr;
break;
}
lua_pop(L, 2);
} else {
thing = getScriptEnv()->getThingByUID(getNumber<uint32_t>(L, arg));
}
return thing;
}
Creature* LuaScriptInterface::getCreature(lua_State* L, int32_t arg)
{
if (isUserdata(L, arg)) {
return getUserdata<Creature>(L, arg);
}
return g_game.getCreatureByID(getNumber<uint32_t>(L, arg));
}
Player* LuaScriptInterface::getPlayer(lua_State* L, int32_t arg)
{
if (isUserdata(L, arg)) {
return getUserdata<Player>(L, arg);
}
return g_game.getPlayerByID(getNumber<uint32_t>(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<LuaDataType>(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, <optional: default: 1> count/subtype)
//doPlayerAddItem(cid, itemid, <optional: default: 1> count, <optional: default: 1> canDropOnMap, <optional: default: 1>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, <optional> 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, <optional> 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}, <optional> {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_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_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::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)
// 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<uint32_t>(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<std::string>()(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<PlayerFlags>(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<uint32_t>(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, <optional: default: 1> count/subtype, <optional: default: 1> canDropOnMap)
//doPlayerAddItem(cid, itemid, <optional: default: 1> count, <optional: default: 1> canDropOnMap, <optional: default: 1>subtype)
Player* player = getPlayer(L, 1);
if (!player) {
reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND));
pushBoolean(L, false);
return 1;
}
uint16_t itemId = getNumber<uint16_t>(L, 2);
int32_t count = getNumber<int32_t>(L, 3, 1);
bool canDropOnMap = getBoolean(L, 4, true);
uint16_t subType = getNumber<uint16_t>(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<int32_t>(1, count);
} else if (it.hasSubType()) {
if (it.stackable) {
itemCount = static_cast<int32_t>(std::ceil(static_cast<float>(count) / 100));
} else {
itemCount = 1;
}
subType = count;
} else {
itemCount = std::max<int32_t>(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<uint32_t>(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, <optional> 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<uint16_t>(L, 1);
uint32_t count = getNumber<uint32_t>(L, 2, 1);
const ItemType& it = Item::items[itemId];
if (it.hasSubType()) {
if (it.stackable) {
itemCount = static_cast<int32_t>(std::ceil(static_cast<float>(count) / 100));
}
subType = count;
} else {
itemCount = std::max<int32_t>(1, count);
}
while (itemCount > 0) {
int32_t stackCount = std::min<int32_t>(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, <optional> count/subtype)
//Returns uid of the created item
uint16_t itemId = getNumber<uint16_t>(L, 1);
uint32_t count = getNumber<uint32_t>(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(lightInfo);
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<uint32_t>& 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<uint32_t>(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}, <optional> {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<uint32_t> 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<uint32_t> 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<uint32_t>(L, 1) != 0)) {
reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND));
pushBoolean(L, false);
return 1;
}
uint32_t areaId = getNumber<uint32_t>(L, 4);
const AreaCombat* area = g_luaEnvironment.getAreaObject(areaId);
if (area || areaId == 0) {
CombatType_t combatType = getNumber<CombatType_t>(L, 2);
CombatParams params;
params.combatType = combatType;
params.impactEffect = getNumber<uint8_t>(L, 7);
CombatDamage damage;
damage.origin = getNumber<CombatOrigin>(L, 8, ORIGIN_SPELL);
damage.type = combatType;
damage.value = normal_random(getNumber<int32_t>(L, 6), getNumber<int32_t>(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<uint32_t>(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<CombatType_t>(L, 3);
CombatParams params;
params.combatType = combatType;
params.impactEffect = getNumber<uint8_t>(L, 6);
CombatDamage damage;
damage.origin = getNumber<CombatOrigin>(L, 7, ORIGIN_SPELL);
damage.type = combatType;
damage.value = normal_random(getNumber<int32_t>(L, 4), getNumber<int32_t>(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<uint32_t>(L, 1) != 0)) {
reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND));
pushBoolean(L, false);
return 1;
}
uint32_t areaId = getNumber<uint32_t>(L, 3);
const AreaCombat* area = g_luaEnvironment.getAreaObject(areaId);
if (area || areaId == 0) {
CombatParams params;
params.impactEffect = getNumber<uint8_t>(L, 6);
CombatDamage damage;
damage.origin = getNumber<CombatOrigin>(L, 7, ORIGIN_SPELL);
damage.type = COMBAT_MANADRAIN;
damage.value = normal_random(getNumber<int32_t>(L, 4), getNumber<int32_t>(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<uint32_t>(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<uint8_t>(L, 5);
CombatDamage damage;
damage.origin = getNumber<CombatOrigin>(L, 6, ORIGIN_SPELL);
damage.type = COMBAT_MANADRAIN;
damage.value = normal_random(getNumber<int32_t>(L, 3), getNumber<int32_t>(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<uint32_t>(L, 1) != 0)) {
reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND));
pushBoolean(L, false);
return 1;
}
const Condition* condition = getUserdata<Condition>(L, 4);
if (!condition) {
reportErrorFunc(getErrorDesc(LUA_ERROR_CONDITION_NOT_FOUND));
pushBoolean(L, false);
return 1;
}
uint32_t areaId = getNumber<uint32_t>(L, 3);
const AreaCombat* area = g_luaEnvironment.getAreaObject(areaId);
if (area || areaId == 0) {
CombatParams params;
params.impactEffect = getNumber<uint8_t>(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<uint32_t>(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<Condition>(L, 3);
if (!condition) {
reportErrorFunc(getErrorDesc(LUA_ERROR_CONDITION_NOT_FOUND));
pushBoolean(L, false);
return 1;
}
CombatParams params;
params.impactEffect = getNumber<uint8_t>(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<uint32_t>(L, 1) != 0)) {
reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND));
pushBoolean(L, false);
return 1;
}
uint32_t areaId = getNumber<uint32_t>(L, 3);
const AreaCombat* area = g_luaEnvironment.getAreaObject(areaId);
if (area || areaId == 0) {
CombatParams params;
params.impactEffect = getNumber<uint8_t>(L, 5);
params.dispelType = getNumber<ConditionType_t>(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<uint32_t>(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<ConditionType_t>(L, 3);
params.impactEffect = getNumber<uint8_t>(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<int32_t>(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<int32_t>(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<uint32_t>(L, 2);
int32_t time = getNumber<int32_t>(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<Direction>(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<uint32_t>(L, -1)) != nullptr);
return 1;
}
int LuaScriptInterface::luaIsDepot(lua_State* L)
{
//isDepot(uid)
Container* container = getScriptEnv()->getContainerByUID(getNumber<uint32_t>(L, -1));
pushBoolean(L, container && container->getDepotLocker());
return 1;
}
int LuaScriptInterface::luaIsMoveable(lua_State* L)
{
//isMoveable(uid)
//isMovable(uid)
Thing* thing = getScriptEnv()->getThingByUID(getNumber<uint32_t>(L, -1));
pushBoolean(L, thing && thing->isPushable());
return 1;
}
int LuaScriptInterface::luaDoAddContainerItem(lua_State* L)
{
//doAddContainerItem(uid, itemid, <optional> count/subtype)
uint32_t uid = getNumber<uint32_t>(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<uint16_t>(L, 2);
const ItemType& it = Item::items[itemId];
int32_t itemCount = 1;
int32_t subType = 1;
uint32_t count = getNumber<uint32_t>(L, 3, 1);
if (it.hasSubType()) {
if (it.stackable) {
itemCount = static_cast<int32_t>(std::ceil(static_cast<float>(count) / 100));
}
subType = count;
} else {
itemCount = std::max<int32_t>(1, count);
}
while (itemCount > 0) {
int32_t stackCount = std::min<int32_t>(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<uint32_t>(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<uint16_t>(L, 2);
uint16_t color = getNumber<uint16_t>(L, 3);
uint32_t time = getNumber<uint32_t>(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<std::pair<int32_t, LuaDataType>> indexes;
for (int i = 3; i <= parameters; ++i) {
if (lua_getmetatable(globalState, i) == 0) {
continue;
}
lua_rawgeti(L, -1, 't');
LuaDataType type = getNumber<LuaDataType>(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<uint32_t>(100, getNumber<uint32_t>(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<uint32_t>(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<ConditionType_t>(L, 2);
uint32_t subId = getNumber<uint32_t>(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<uint32_t>(L, -1));
return 1;
}
#define MULTIOP(name, op) \
int LuaScriptInterface::luaBit##name(lua_State* L) \
{ \
int n = lua_gettop(L); \
uint32_t w = getNumber<uint32_t>(L, -1); \
for (int i = 1; i < n; ++i) \
w op getNumber<uint32_t>(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<uint32_t>(L, 1), n2 = getNumber<uint32_t>(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<ConfigManager::string_config_t>(L, -1)));
return 1;
}
int LuaScriptInterface::luaConfigManagerGetNumber(lua_State* L)
{
lua_pushnumber(L, g_config.getNumber(getNumber<ConfigManager::integer_config_t>(L, -1)));
return 1;
}
int LuaScriptInterface::luaConfigManagerGetBoolean(lua_State* L)
{
pushBoolean(L, g_config.getBoolean(getNumber<ConfigManager::boolean_config_t>(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<void(DBResult_ptr, bool)> 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<void(DBResult_ptr, bool)> 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<uint32_t>(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<uint32_t>(L, 1));
if (!res) {
pushBoolean(L, false);
return 1;
}
const std::string& s = getString(L, 2);
lua_pushnumber(L, res->getNumber<int64_t>(s));
return 1;
}
int LuaScriptInterface::luaResultGetString(lua_State* L)
{
DBResult_ptr res = ScriptEnvironment::getResultByID(getNumber<uint32_t>(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<uint32_t>(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<uint32_t>(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<uint32_t>(L, -1)));
return 1;
}
// Userdata
int LuaScriptInterface::luaUserdataCompare(lua_State* L)
{
// userdataA == userdataB
pushBoolean(L, getUserdata<void>(L, 1) == getUserdata<void>(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<uint_fast8_t>(L, 1);
lua_rawgeti(L, -3, 'h');
size_t hashB = getNumber<size_t>(L, 1);
lua_rawgeti(L, -3, 'p');
uint_fast8_t parentsA = getNumber<uint_fast8_t>(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<size_t>(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<int32_t>(L, 1), getNumber<int32_t>(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<int32_t>(L, 4, 0);
int32_t maxRangeX = getNumber<int32_t>(L, 5, 0);
int32_t minRangeY = getNumber<int32_t>(L, 6, 0);
int32_t maxRangeY = getNumber<int32_t>(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<Creature>(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<Player>(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<uint32_t>(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<Town>(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<House>(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<GameState_t>(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<WorldType_t>(L, 1);
g_game.setWorldType(type);
pushBoolean(L, true);
return 1;
}
int LuaScriptInterface::luaGameGetReturnMessage(lua_State* L)
{
// Game.getReturnMessage(value)
ReturnValue value = getNumber<ReturnValue>(L, 1);
pushString(L, getReturnMessage(value));
return 1;
}
int LuaScriptInterface::luaGameCreateItem(lua_State* L)
{
// Game.createItem(itemId[, count[, position]])
uint16_t count = getNumber<uint16_t>(L, 2, 1);
uint16_t id;
if (isNumber(L, 1)) {
id = getNumber<uint16_t>(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<uint16_t>(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<Item>(L, item);
setItemMetatable(L, -1, item);
return 1;
}
int LuaScriptInterface::luaGameCreateContainer(lua_State* L)
{
// Game.createContainer(itemId, size[, position])
uint16_t size = getNumber<uint16_t>(L, 2);
uint16_t id;
if (isNumber(L, 1)) {
id = getNumber<uint16_t>(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<Container>(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<Monster>(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<Npc>(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<uint16_t>(L, 1);
position.y = getNumber<uint16_t>(L, 2);
position.z = getNumber<uint16_t>(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<ReloadTypes_t>(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<uint32_t>(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<uint16_t>(L, 2, 0);
uint16_t y = getNumber<uint16_t>(L, 3, 0);
uint8_t z = getNumber<uint8_t>(L, 4, 0);
stackpos = getNumber<int32_t>(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<int32_t>(
std::max<int32_t>(
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<MagicEffectClasses>(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<ShootType_t>(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<uint8_t>(L, 4);
uint16_t y = getNumber<uint16_t>(L, 3);
uint16_t x = getNumber<uint16_t>(L, 2);
tile = g_game.map.getTile(x, y, z);
}
if (tile) {
pushUserdata<Tile>(L, tile);
setMetatable(L, -1, "Tile");
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaTileGetPosition(lua_State* L)
{
// tile:getPosition()
Tile* tile = getUserdata<Tile>(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<Tile>(L, 1);
if (tile && tile->getGround()) {
pushUserdata<Item>(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<int32_t>(L, 2);
Tile* tile = getUserdata<Tile>(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<Creature>(L, creature);
setCreatureMetatable(L, -1, creature);
} else if (Item* item = thing->getItem()) {
pushUserdata<Item>(L, item);
setItemMetatable(L, -1, item);
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaTileGetThingCount(lua_State* L)
{
// tile:getThingCount()
Tile* tile = getUserdata<Tile>(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<Tile>(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<Creature>(L, visibleCreature);
setCreatureMetatable(L, -1, visibleCreature);
} else if (Item* visibleItem = thing->getItem()) {
pushUserdata<Item>(L, visibleItem);
setItemMetatable(L, -1, visibleItem);
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaTileGetTopTopItem(lua_State* L)
{
// tile:getTopTopItem()
Tile* tile = getUserdata<Tile>(L, 1);
if (!tile) {
lua_pushnil(L);
return 1;
}
Item* item = tile->getTopTopItem();
if (item) {
pushUserdata<Item>(L, item);
setItemMetatable(L, -1, item);
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaTileGetTopDownItem(lua_State* L)
{
// tile:getTopDownItem()
Tile* tile = getUserdata<Tile>(L, 1);
if (!tile) {
lua_pushnil(L);
return 1;
}
Item* item = tile->getTopDownItem();
if (item) {
pushUserdata<Item>(L, item);
setItemMetatable(L, -1, item);
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaTileGetFieldItem(lua_State* L)
{
// tile:getFieldItem()
Tile* tile = getUserdata<Tile>(L, 1);
if (!tile) {
lua_pushnil(L);
return 1;
}
Item* item = tile->getFieldItem();
if (item) {
pushUserdata<Item>(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<Tile>(L, 1);
if (!tile) {
lua_pushnil(L);
return 1;
}
uint16_t itemId;
if (isNumber(L, 2)) {
itemId = getNumber<uint16_t>(L, 2);
} else {
itemId = Item::items.getItemIdByName(getString(L, 2));
if (itemId == 0) {
lua_pushnil(L);
return 1;
}
}
int32_t subType = getNumber<int32_t>(L, 3, -1);
Item* item = g_game.findItemOfType(tile, itemId, false, subType);
if (item) {
pushUserdata<Item>(L, item);
setItemMetatable(L, -1, item);
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaTileGetItemByType(lua_State* L)
{
// tile:getItemByType(itemType)
Tile* tile = getUserdata<Tile>(L, 1);
if (!tile) {
lua_pushnil(L);
return 1;
}
bool found;
ItemTypes_t itemType = getNumber<ItemTypes_t>(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<Item>(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<Item>(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<Tile>(L, 1);
if (!tile) {
lua_pushnil(L);
return 1;
}
int32_t topOrder = getNumber<int32_t>(L, 2);
Item* item = tile->getItemByTopOrder(topOrder);
if (!item) {
lua_pushnil(L);
return 1;
}
pushUserdata<Item>(L, item);
setItemMetatable(L, -1, item);
return 1;
}
int LuaScriptInterface::luaTileGetItemCountById(lua_State* L)
{
// tile:getItemCountById(itemId[, subType = -1])
Tile* tile = getUserdata<Tile>(L, 1);
if (!tile) {
lua_pushnil(L);
return 1;
}
int32_t subType = getNumber<int32_t>(L, 3, -1);
uint16_t itemId;
if (isNumber(L, 2)) {
itemId = getNumber<uint16_t>(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<Tile>(L, 1);
if (!tile) {
lua_pushnil(L);
return 1;
}
const Creature* creature = tile->getBottomCreature();
if (!creature) {
lua_pushnil(L);
return 1;
}
pushUserdata<const Creature>(L, creature);
setCreatureMetatable(L, -1, creature);
return 1;
}
int LuaScriptInterface::luaTileGetTopCreature(lua_State* L)
{
// tile:getTopCreature()
Tile* tile = getUserdata<Tile>(L, 1);
if (!tile) {
lua_pushnil(L);
return 1;
}
Creature* creature = tile->getTopCreature();
if (!creature) {
lua_pushnil(L);
return 1;
}
pushUserdata<Creature>(L, creature);
setCreatureMetatable(L, -1, creature);
return 1;
}
int LuaScriptInterface::luaTileGetBottomVisibleCreature(lua_State* L)
{
// tile:getBottomVisibleCreature(creature)
Tile* tile = getUserdata<Tile>(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<const Creature>(L, visibleCreature);
setCreatureMetatable(L, -1, visibleCreature);
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaTileGetTopVisibleCreature(lua_State* L)
{
// tile:getTopVisibleCreature(creature)
Tile* tile = getUserdata<Tile>(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<Creature>(L, visibleCreature);
setCreatureMetatable(L, -1, visibleCreature);
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaTileGetItems(lua_State* L)
{
// tile:getItems()
Tile* tile = getUserdata<Tile>(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<Item>(L, item);
setItemMetatable(L, -1, item);
lua_rawseti(L, -2, ++index);
}
return 1;
}
int LuaScriptInterface::luaTileGetItemCount(lua_State* L)
{
// tile:getItemCount()
Tile* tile = getUserdata<Tile>(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<Tile>(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<Tile>(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<Tile>(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<Creature>(L, creature);
setCreatureMetatable(L, -1, creature);
lua_rawseti(L, -2, ++index);
}
return 1;
}
int LuaScriptInterface::luaTileGetCreatureCount(lua_State* L)
{
// tile:getCreatureCount()
Tile* tile = getUserdata<Tile>(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<Tile>(L, 1);
if (!tile) {
lua_pushnil(L);
return 1;
}
Item* item;
if (lua_gettop(L) >= 3) {
item = getUserdata<Item>(L, 3);
} else {
item = nullptr;
}
ITEMPROPERTY property = getNumber<ITEMPROPERTY>(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<Tile>(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<Tile>(L, 1);
if (tile) {
tileflags_t flag = getNumber<tileflags_t>(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<Tile>(L, 1);
if (!tile) {
lua_pushnil(L);
return 1;
}
Thing* thing = getThing(L, 2);
if (thing) {
uint32_t flags = getNumber<uint32_t>(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<Tile>(L, 1);
if (!tile) {
lua_pushnil(L);
return 1;
}
if (HouseTile* houseTile = dynamic_cast<HouseTile*>(tile)) {
pushUserdata<House>(L, houseTile->getHouse());
setMetatable(L, -1, "House");
} else {
lua_pushnil(L);
}
return 1;
}
// NetworkMessage
int LuaScriptInterface::luaNetworkMessageCreate(lua_State* L)
{
// NetworkMessage()
pushUserdata<NetworkMessage>(L, new NetworkMessage);
setMetatable(L, -1, "NetworkMessage");
return 1;
}
int LuaScriptInterface::luaNetworkMessageDelete(lua_State* L)
{
NetworkMessage** messagePtr = getRawUserdata<NetworkMessage>(L, 1);
if (messagePtr && *messagePtr) {
delete *messagePtr;
*messagePtr = nullptr;
}
return 0;
}
int LuaScriptInterface::luaNetworkMessageGetByte(lua_State* L)
{
// networkMessage:getByte()
NetworkMessage* message = getUserdata<NetworkMessage>(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<NetworkMessage>(L, 1);
if (message) {
lua_pushnumber(L, message->get<uint16_t>());
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaNetworkMessageGetU32(lua_State* L)
{
// networkMessage:getU32()
NetworkMessage* message = getUserdata<NetworkMessage>(L, 1);
if (message) {
lua_pushnumber(L, message->get<uint32_t>());
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaNetworkMessageGetU64(lua_State* L)
{
// networkMessage:getU64()
NetworkMessage* message = getUserdata<NetworkMessage>(L, 1);
if (message) {
lua_pushnumber(L, message->get<uint64_t>());
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaNetworkMessageGetString(lua_State* L)
{
// networkMessage:getString()
NetworkMessage* message = getUserdata<NetworkMessage>(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<NetworkMessage>(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<uint8_t>(L, 2);
NetworkMessage* message = getUserdata<NetworkMessage>(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<uint16_t>(L, 2);
NetworkMessage* message = getUserdata<NetworkMessage>(L, 1);
if (message) {
message->add<uint16_t>(number);
pushBoolean(L, true);
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaNetworkMessageAddU32(lua_State* L)
{
// networkMessage:addU32(number)
uint32_t number = getNumber<uint32_t>(L, 2);
NetworkMessage* message = getUserdata<NetworkMessage>(L, 1);
if (message) {
message->add<uint32_t>(number);
pushBoolean(L, true);
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaNetworkMessageAddU64(lua_State* L)
{
// networkMessage:addU64(number)
uint64_t number = getNumber<uint64_t>(L, 2);
NetworkMessage* message = getUserdata<NetworkMessage>(L, 1);
if (message) {
message->add<uint64_t>(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<NetworkMessage>(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<NetworkMessage>(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<double>(L, 2);
NetworkMessage* message = getUserdata<NetworkMessage>(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<Item>(L, 2);
if (!item) {
reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND));
lua_pushnil(L);
return 1;
}
NetworkMessage* message = getUserdata<NetworkMessage>(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<NetworkMessage>(L, 1);
if (!message) {
lua_pushnil(L);
return 1;
}
uint16_t itemId;
if (isNumber(L, 2)) {
itemId = getNumber<uint16_t>(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<NetworkMessage>(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<int16_t>(L, 2);
NetworkMessage* message = getUserdata<NetworkMessage>(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<NetworkMessage>(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<uint32_t>(L, 2);
Item* item = getScriptEnv()->getItemByUID(id);
if (item) {
pushUserdata<Item>(L, item);
setItemMetatable(L, -1, item);
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaItemIsItem(lua_State* L)
{
// item:isItem()
pushBoolean(L, getUserdata<const Item>(L, 1) != nullptr);
return 1;
}
int LuaScriptInterface::luaItemGetParent(lua_State* L)
{
// item:getParent()
Item* item = getUserdata<Item>(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<Item>(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<Item>(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<Item>(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<Item>(L, clone);
setItemMetatable(L, -1, clone);
return 1;
}
int LuaScriptInterface::luaItemSplit(lua_State* L)
{
// item:split([count = 1])
Item** itemPtr = getRawUserdata<Item>(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<uint16_t>(getNumber<uint16_t>(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<Item>(L, splitItem);
setItemMetatable(L, -1, splitItem);
return 1;
}
int LuaScriptInterface::luaItemRemove(lua_State* L)
{
// item:remove([count = -1])
Item* item = getUserdata<Item>(L, 1);
if (item) {
int32_t count = getNumber<int32_t>(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<Item>(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<Item>(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<uint16_t>(L, 2);
Item* item = getUserdata<Item>(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<uint16_t>(L, 2);
Item* item = getUserdata<Item>(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<Item>(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<Item>(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<Item>(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<Item>(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<Item>(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<Item>(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<Item>(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<Item>(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<Item>(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<Item>(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<Item>(L, 1);
if (!item) {
lua_pushnil(L);
return 1;
}
Tile* tile = item->getTile();
if (tile) {
pushUserdata<Tile>(L, tile);
setMetatable(L, -1, "Tile");
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaItemHasAttribute(lua_State* L)
{
// item:hasAttribute(key)
Item* item = getUserdata<Item>(L, 1);
if (!item) {
lua_pushnil(L);
return 1;
}
itemAttrTypes attribute;
if (isNumber(L, 2)) {
attribute = getNumber<itemAttrTypes>(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<Item>(L, 1);
if (!item) {
lua_pushnil(L);
return 1;
}
itemAttrTypes attribute;
if (isNumber(L, 2)) {
attribute = getNumber<itemAttrTypes>(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<Item>(L, 1);
if (!item) {
lua_pushnil(L);
return 1;
}
itemAttrTypes attribute;
if (isNumber(L, 2)) {
attribute = getNumber<itemAttrTypes>(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<int32_t>(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<Item>(L, 1);
if (!item) {
lua_pushnil(L);
return 1;
}
itemAttrTypes attribute;
if (isNumber(L, 2)) {
attribute = getNumber<itemAttrTypes>(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<Item>(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<Container>(L, 2);
break;
case LuaData_Player:
toCylinder = getUserdata<Player>(L, 2);
break;
case LuaData_Tile:
toCylinder = getUserdata<Tile>(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<Item>(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<uint16_t>(L, 2);
} else {
itemId = Item::items.getItemIdByName(getString(L, 2));
if (itemId == 0) {
lua_pushnil(L);
return 1;
}
}
int32_t subType = getNumber<int32_t>(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<int32_t>(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<Item>(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<Item>(L, 1);
if (item) {
int32_t distance = getNumber<int32_t>(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<Item>(L, 1);
if (item) {
ITEMPROPERTY property = getNumber<ITEMPROPERTY>(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<uint32_t>(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<Container>(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<Container>(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<Container>(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<Container>(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<Container>(L, 1);
if (!container) {
lua_pushnil(L);
return 1;
}
uint32_t index = getNumber<uint32_t>(L, 2);
Item* item = container->getItemByIndex(index);
if (item) {
pushUserdata<Item>(L, item);
setItemMetatable(L, -1, item);
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaContainerHasItem(lua_State* L)
{
// container:hasItem(item)
Item* item = getUserdata<Item>(L, 2);
Container* container = getUserdata<Container>(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<Container>(L, 1);
if (!container) {
lua_pushnil(L);
return 1;
}
uint16_t itemId;
if (isNumber(L, 2)) {
itemId = getNumber<uint16_t>(L, 2);
} else {
itemId = Item::items.getItemIdByName(getString(L, 2));
if (itemId == 0) {
lua_pushnil(L);
return 1;
}
}
uint32_t subType = getNumber<uint32_t>(L, 3, 1);
Item* item = Item::CreateItem(itemId, std::min<uint32_t>(subType, 100));
if (!item) {
lua_pushnil(L);
return 1;
}
int32_t index = getNumber<int32_t>(L, 4, INDEX_WHEREEVER);
uint32_t flags = getNumber<uint32_t>(L, 5, 0);
ReturnValue ret = g_game.internalAddItem(container, item, index, flags);
if (ret == RETURNVALUE_NOERROR) {
pushUserdata<Item>(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<Item>(L, 2);
if (!item) {
lua_pushnil(L);
return 1;
}
Container* container = getUserdata<Container>(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<int32_t>(L, 3, INDEX_WHEREEVER);
uint32_t flags = getNumber<uint32_t>(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<Container>(L, 1);
if (!container) {
lua_pushnil(L);
return 1;
}
uint16_t itemId;
if (isNumber(L, 2)) {
itemId = getNumber<uint16_t>(L, 2);
} else {
itemId = Item::items.getItemIdByName(getString(L, 2));
if (itemId == 0) {
lua_pushnil(L);
return 1;
}
}
int32_t subType = getNumber<int32_t>(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<uint32_t>(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<Teleport>(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<Teleport>(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<uint32_t>(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<Creature>(L, 2);
} else {
creature = nullptr;
}
if (creature) {
pushUserdata<Creature>(L, creature);
setCreatureMetatable(L, -1, creature);
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaCreatureGetEvents(lua_State* L)
{
// creature:getEvents(type)
Creature* creature = getUserdata<Creature>(L, 1);
if (!creature) {
lua_pushnil(L);
return 1;
}
CreatureEventType_t eventType = getNumber<CreatureEventType_t>(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<Creature>(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<Creature>(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<const Creature>(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<const Creature>(L, 1) != nullptr);
return 1;
}
int LuaScriptInterface::luaCreatureIsInGhostMode(lua_State* L)
{
// creature:isInGhostMode()
const Creature* creature = getUserdata<const Creature>(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<const Creature>(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<const Creature>(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<Creature>(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<const Creature>(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<const Creature>(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<Creature>(L, 1);
if (!creature) {
lua_pushnil(L);
return 1;
}
Creature* target = creature->getAttackedCreature();
if (target) {
pushUserdata<Creature>(L, target);
setCreatureMetatable(L, -1, target);
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaCreatureSetTarget(lua_State* L)
{
// creature:setTarget(target)
Creature* creature = getUserdata<Creature>(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<Creature>(L, 1);
if (!creature) {
lua_pushnil(L);
return 1;
}
Creature* followCreature = creature->getFollowCreature();
if (followCreature) {
pushUserdata<Creature>(L, followCreature);
setCreatureMetatable(L, -1, followCreature);
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaCreatureSetFollowCreature(lua_State* L)
{
// creature:setFollowCreature(followedCreature)
Creature* creature = getUserdata<Creature>(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<Creature>(L, 1);
if (!creature) {
lua_pushnil(L);
return 1;
}
Creature* master = creature->getMaster();
if (!master) {
lua_pushnil(L);
return 1;
}
pushUserdata<Creature>(L, master);
setCreatureMetatable(L, -1, master);
return 1;
}
int LuaScriptInterface::luaCreatureSetMaster(lua_State* L)
{
// creature:setMaster(master)
Creature* creature = getUserdata<Creature>(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<const Creature>(L, 1);
if (!creature) {
lua_pushnil(L);
return 1;
}
LightInfo light;
creature->getCreatureLight(light);
lua_pushnumber(L, light.level);
lua_pushnumber(L, light.color);
return 2;
}
int LuaScriptInterface::luaCreatureSetLight(lua_State* L)
{
// creature:setLight(color, level)
Creature* creature = getUserdata<Creature>(L, 1);
if (!creature) {
lua_pushnil(L);
return 1;
}
LightInfo light;
light.color = getNumber<uint8_t>(L, 2);
light.level = getNumber<uint8_t>(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<const Creature>(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<const Creature>(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<int32_t>(L, 2);
g_game.changeSpeed(creature, delta);
pushBoolean(L, true);
return 1;
}
int LuaScriptInterface::luaCreatureSetDropLoot(lua_State* L)
{
// creature:setDropLoot(doDrop)
Creature* creature = getUserdata<Creature>(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<const Creature>(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<Creature>(L, 1);
if (!creature) {
lua_pushnil(L);
return 1;
}
Tile* tile = creature->getTile();
if (tile) {
pushUserdata<Tile>(L, tile);
setMetatable(L, -1, "Tile");
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaCreatureGetDirection(lua_State* L)
{
// creature:getDirection()
const Creature* creature = getUserdata<const Creature>(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<Creature>(L, 1);
if (creature) {
pushBoolean(L, g_game.internalCreatureTurn(creature, getNumber<Direction>(L, 2)));
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaCreatureGetHealth(lua_State* L)
{
// creature:getHealth()
const Creature* creature = getUserdata<const Creature>(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<Creature>(L, 1);
if (!creature) {
lua_pushnil(L);
return 1;
}
CombatDamage damage;
damage.value = getNumber<int32_t>(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<const Creature>(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<Creature>(L, 1);
if (!creature) {
lua_pushnil(L);
return 1;
}
creature->healthMax = getNumber<uint32_t>(L, 2);
creature->health = std::min<int32_t>(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<Creature>(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<Creature>(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<Creature>(L, 1);
if (creature) {
creature->setSkull(getNumber<Skulls_t>(L, 2));
pushBoolean(L, true);
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaCreatureGetOutfit(lua_State* L)
{
// creature:getOutfit()
const Creature* creature = getUserdata<const Creature>(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<Creature>(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<Creature>(L, 1);
if (!creature) {
lua_pushnil(L);
return 1;
}
ConditionType_t conditionType = getNumber<ConditionType_t>(L, 2);
ConditionId_t conditionId = getNumber<ConditionId_t>(L, 3, CONDITIONID_COMBAT);
uint32_t subId = getNumber<uint32_t>(L, 4, 0);
Condition* condition = creature->getCondition(conditionType, conditionId, subId);
if (condition) {
pushUserdata<Condition>(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<Creature>(L, 1);
Condition* condition = getUserdata<Condition>(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<Creature>(L, 1);
if (!creature) {
lua_pushnil(L);
return 1;
}
ConditionType_t conditionType = getNumber<ConditionType_t>(L, 2);
ConditionId_t conditionId = getNumber<ConditionId_t>(L, 3, CONDITIONID_COMBAT);
uint32_t subId = getNumber<uint32_t>(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<Creature>(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<Creature>(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<SpeakClasses>(L, 3);
const std::string& text = getString(L, 2);
Creature* creature = getUserdata<Creature>(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<Creature>(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<Creature>(L, 1);
if (!creature) {
lua_pushnil(L);
return 1;
}
lua_createtable(L, creature->getSummonCount(), 0);
int index = 0;
for (Creature* summon : creature->getSummons()) {
pushUserdata<Creature>(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<int32_t>(L, 2);
Creature* creature = getUserdata<Creature>(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<Creature>(L, 1);
if (!creature) {
lua_pushnil(L);
return 1;
}
const Position& position = getPosition(L, 2);
FindPathParams fpp;
fpp.minTargetDist = getNumber<int32_t>(L, 3, 0);
fpp.maxTargetDist = getNumber<int32_t>(L, 4, 1);
fpp.fullPathSearch = getBoolean(L, 5, fpp.fullPathSearch);
fpp.clearSight = getBoolean(L, 6, fpp.clearSight);
fpp.maxSearchDist = getNumber<int32_t>(L, 7, fpp.maxSearchDist);
std::forward_list<Direction> 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<uint32_t>(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<Player>(L, 2);
} else {
player = nullptr;
}
if (player) {
pushUserdata<Player>(L, player);
setMetatable(L, -1, "Player");
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaPlayerIsPlayer(lua_State* L)
{
// player:isPlayer()
pushBoolean(L, getUserdata<const Player>(L, 1) != nullptr);
return 1;
}
int LuaScriptInterface::luaPlayerGetGuid(lua_State* L)
{
// player:getGuid()
Player* player = getUserdata<Player>(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<Player>(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<Player>(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<Player>(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<Player>(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<Player>(L, 1);
if (player) {
PlayerFlags flag = getNumber<PlayerFlags>(L, 2);
pushBoolean(L, player->hasFlag(flag));
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaPlayerGetAccountType(lua_State* L)
{
// player:getAccountType()
Player* player = getUserdata<Player>(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<Player>(L, 1);
if (player) {
player->accountType = getNumber<AccountType_t>(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<Player>(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<Player>(L, 1);
if (player) {
player->capacity = getNumber<uint32_t>(L, 2);
player->sendStats();
pushBoolean(L, true);
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaPlayerGetFreeCapacity(lua_State* L)
{
// player:getFreeCapacity()
Player* player = getUserdata<Player>(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<Player>(L, 1);
if (!player) {
lua_pushnil(L);
return 1;
}
uint32_t depotId = getNumber<uint32_t>(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<Item>(L, depotLocker);
setItemMetatable(L, -1, depotLocker);
} else {
pushBoolean(L, false);
}
return 1;
}
int LuaScriptInterface::luaPlayerGetMurderTimestamps(lua_State * L)
{
// player:getMurderTimestamps()
Player* player = getUserdata<Player>(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<int64_t>(currentMurderTimestamp));
lua_rawseti(L, -2, ++i);
}
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaPlayerGetPlayerKillerEnd(lua_State* L)
{
// player:getPlayerKillerEnd()
Player* player = getUserdata<Player>(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<Player>(L, 1);
if (player) {
player->setPlayerKillerEnd(getNumber<time_t>(L, 2));
pushBoolean(L, true);
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaPlayerGetDeathPenalty(lua_State* L)
{
// player:getDeathPenalty()
Player* player = getUserdata<Player>(L, 1);
if (player) {
lua_pushnumber(L, static_cast<uint32_t>(player->getLostPercent() * 100));
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaPlayerGetExperience(lua_State* L)
{
// player:getExperience()
Player* player = getUserdata<Player>(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<Player>(L, 1);
if (player) {
int64_t experience = getNumber<int64_t>(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<Player>(L, 1);
if (player) {
int64_t experience = getNumber<int64_t>(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<Player>(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<Player>(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<Player>(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<const Player>(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<Player>(L, 1);
if (!player) {
lua_pushnil(L);
return 1;
}
int32_t manaChange = getNumber<int32_t>(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<const Player>(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<int32_t>(L, 2);
player->mana = std::min<int32_t>(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<Player>(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<Player>(L, 1);
if (player) {
player->addManaSpent(getNumber<uint64_t>(L, 2));
pushBoolean(L, true);
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaPlayerGetBaseMaxHealth(lua_State* L)
{
// player:getBaseMaxHealth()
Player* player = getUserdata<Player>(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<Player>(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<skills_t>(L, 2);
Player* player = getUserdata<Player>(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<skills_t>(L, 2);
Player* player = getUserdata<Player>(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<skills_t>(L, 2);
Player* player = getUserdata<Player>(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<skills_t>(L, 2);
Player* player = getUserdata<Player>(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<Player>(L, 1);
if (player) {
skills_t skillType = getNumber<skills_t>(L, 2);
uint64_t tries = getNumber<uint64_t>(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<Player>(L, 1);
if (!player) {
lua_pushnil(L);
return 1;
}
uint16_t itemId;
if (isNumber(L, 2)) {
itemId = getNumber<uint16_t>(L, 2);
} else {
itemId = Item::items.getItemIdByName(getString(L, 2));
if (itemId == 0) {
lua_pushnil(L);
return 1;
}
}
int32_t subType = getNumber<int32_t>(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<Player>(L, 1);
if (!player) {
lua_pushnil(L);
return 1;
}
uint16_t itemId;
if (isNumber(L, 2)) {
itemId = getNumber<uint16_t>(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<int32_t>(L, 4, -1);
Item* item = g_game.findItemOfType(player, itemId, deepSearch, subType);
if (item) {
pushUserdata<Item>(L, item);
setItemMetatable(L, -1, item);
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaPlayerGetVocation(lua_State* L)
{
// player:getVocation()
Player* player = getUserdata<Player>(L, 1);
if (player) {
pushUserdata<Vocation>(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<Player>(L, 1);
if (!player) {
lua_pushnil(L);
return 1;
}
Vocation* vocation;
if (isNumber(L, 2)) {
vocation = g_vocations.getVocation(getNumber<uint16_t>(L, 2));
} else if (isString(L, 2)) {
vocation = g_vocations.getVocation(g_vocations.getVocationId(getString(L, 2)));
} else if (isUserdata(L, 2)) {
vocation = getUserdata<Vocation>(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<Player>(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<Player>(L, 1);
if (player) {
PlayerSex_t newSex = getNumber<PlayerSex_t>(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<Player>(L, 1);
if (player) {
pushUserdata<Town>(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<Town>(L, 2);
if (!town) {
pushBoolean(L, false);
return 1;
}
Player* player = getUserdata<Player>(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<Player>(L, 1);
if (!player) {
lua_pushnil(L);
return 1;
}
Guild* guild = player->getGuild();
if (!guild) {
lua_pushnil(L);
return 1;
}
pushUserdata<Guild>(L, guild);
setMetatable(L, -1, "Guild");
return 1;
}
int LuaScriptInterface::luaPlayerSetGuild(lua_State* L)
{
// player:setGuild(guild)
Player* player = getUserdata<Player>(L, 1);
if (!player) {
lua_pushnil(L);
return 1;
}
player->setGuild(getUserdata<Guild>(L, 2));
pushBoolean(L, true);
return 1;
}
int LuaScriptInterface::luaPlayerGetGuildLevel(lua_State* L)
{
// player:getGuildLevel()
Player* player = getUserdata<Player>(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<uint8_t>(L, 2);
Player* player = getUserdata<Player>(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<Player>(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<Player>(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<Player>(L, 1);
if (player) {
pushUserdata<Group>(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<Group>(L, 2);
if (!group) {
pushBoolean(L, false);
return 1;
}
Player* player = getUserdata<Player>(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<Player>(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<uint16_t>(L, 2);
Player* player = getUserdata<Player>(L, 1);
if (player) {
player->staminaMinutes = std::min<uint16_t>(3360, stamina);
player->sendStats();
pushBoolean(L, true);
}
else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaPlayerGetSoul(lua_State* L)
{
// player:getSoul()
Player* player = getUserdata<Player>(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<int32_t>(L, 2);
Player* player = getUserdata<Player>(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<Player>(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<Player>(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<Player>(L, 1);
if (!player) {
lua_pushnil(L);
return 1;
}
int64_t balance = getNumber<int64_t>(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<Player>(L, 1);
if (!player) {
lua_pushnil(L);
return 1;
}
uint32_t key = getNumber<uint32_t>(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<int32_t>(L, 3);
uint32_t key = getNumber<uint32_t>(L, 2);
Player* player = getUserdata<Player>(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<Player>(L, 1);
if (!player) {
pushBoolean(L, false);
return 1;
}
uint16_t itemId;
if (isNumber(L, 2)) {
itemId = getNumber<uint16_t>(L, 2);
} else {
itemId = Item::items.getItemIdByName(getString(L, 2));
if (itemId == 0) {
lua_pushnil(L);
return 1;
}
}
int32_t count = getNumber<int32_t>(L, 3, 1);
int32_t subType = getNumber<int32_t>(L, 5, 1);
const ItemType& it = Item::items[itemId];
int32_t itemCount = 1;
int parameters = lua_gettop(L);
if (parameters >= 4) {
itemCount = std::max<int32_t>(1, count);
} else if (it.hasSubType()) {
if (it.stackable) {
itemCount = std::ceil(count / 100.f);
}
subType = count;
} else {
itemCount = std::max<int32_t>(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<slots_t>(L, 6, CONST_SLOT_WHEREEVER);
for (int32_t i = 1; i <= itemCount; ++i) {
int32_t stackCount = subType;
if (it.stackable) {
stackCount = std::min<int32_t>(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<Item>(L, item);
setItemMetatable(L, -1, item);
lua_settable(L, -3);
} else {
pushUserdata<Item>(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<Item>(L, 2);
if (!item) {
reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND));
pushBoolean(L, false);
return 1;
}
Player* player = getUserdata<Player>(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<slots_t>(L, 4, CONST_SLOT_WHEREEVER);
returnValue = g_game.internalPlayerAddItem(player, item, true, slot);
} else {
int32_t index = getNumber<int32_t>(L, 4, INDEX_WHEREEVER);
uint32_t flags = getNumber<uint32_t>(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<Player>(L, 1);
if (!player) {
lua_pushnil(L);
return 1;
}
uint16_t itemId;
if (isNumber(L, 2)) {
itemId = getNumber<uint16_t>(L, 2);
} else {
itemId = Item::items.getItemIdByName(getString(L, 2));
if (itemId == 0) {
lua_pushnil(L);
return 1;
}
}
uint32_t count = getNumber<uint32_t>(L, 3);
int32_t subType = getNumber<int32_t>(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<Player>(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<uint64_t>(L, 2);
Player* player = getUserdata<Player>(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<Player>(L, 1);
if (player) {
uint64_t money = getNumber<uint64_t>(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<Player>(L, 1);
if (!player) {
lua_pushnil(L);
return 1;
}
int32_t length = getNumber<int32_t>(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<uint16_t>(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<int32_t>(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<MessageClasses>(L, 2), getString(L, 3));
Player* player = getUserdata<Player>(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<Player>(L, 1);
if (!player) {
lua_pushnil(L);
return 1;
}
const Player* speaker = getUserdata<const Player>(L, 2);
const std::string& text = getString(L, 3);
SpeakClasses type = getNumber<SpeakClasses>(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<Player>(L, 1);
if (!player) {
lua_pushnil(L);
return 1;
}
Creature* speaker = getCreature(L, 2);
SpeakClasses type = getNumber<SpeakClasses>(L, 3);
const std::string& text = getString(L, 4);
uint16_t channelId = getNumber<uint16_t>(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<uint16_t>(L, 2);
Player* player = getUserdata<Player>(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<const Player>(L, 1);
if (!player) {
lua_pushnil(L);
return 1;
}
uint32_t slot = getNumber<uint32_t>(L, 2);
Thing* thing = player->getThing(slot);
if (!thing) {
lua_pushnil(L);
return 1;
}
Item* item = thing->getItem();
if (item) {
pushUserdata<Item>(L, item);
setItemMetatable(L, -1, item);
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaPlayerGetParty(lua_State* L)
{
// player:getParty()
const Player* player = getUserdata<const Player>(L, 1);
if (!player) {
lua_pushnil(L);
return 1;
}
Party* party = player->getParty();
if (party) {
pushUserdata<Party>(L, party);
setMetatable(L, -1, "Party");
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaPlayerAddOutfit(lua_State* L)
{
// player:addOutfit(lookType)
Player* player = getUserdata<Player>(L, 1);
if (player) {
player->addOutfit(getNumber<uint16_t>(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<Player>(L, 1);
if (player) {
uint16_t lookType = getNumber<uint16_t>(L, 2);
uint8_t addon = getNumber<uint8_t>(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<Player>(L, 1);
if (player) {
uint16_t lookType = getNumber<uint16_t>(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<Player>(L, 1);
if (player) {
uint16_t lookType = getNumber<uint16_t>(L, 2);
uint8_t addon = getNumber<uint8_t>(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<Player>(L, 1);
if (player) {
uint16_t lookType = getNumber<uint16_t>(L, 2);
uint8_t addon = getNumber<uint8_t>(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<Player>(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<Player>(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<Player>(L, 1);
if (!player) {
lua_pushnil(L);
return 1;
}
if (player->premiumDays != std::numeric_limits<uint16_t>::max()) {
uint16_t days = getNumber<uint16_t>(L, 2);
int32_t addDays = std::min<int32_t>(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<Player>(L, 1);
if (!player) {
lua_pushnil(L);
return 1;
}
if (player->premiumDays != std::numeric_limits<uint16_t>::max()) {
uint16_t days = getNumber<uint16_t>(L, 2);
int32_t removeDays = std::min<int32_t>(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<uint8_t>(L, 2) - 1;
Player* player = getUserdata<Player>(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<Player>(L, 1);
if (!player) {
lua_pushnil(L);
return 1;
}
uint8_t blessing = getNumber<uint8_t>(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<Player>(L, 1);
if (!player) {
lua_pushnil(L);
return 1;
}
uint8_t blessing = getNumber<uint8_t>(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<const Player>(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<Player>(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<Player>(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<Player>(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<Player>(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<Player>(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<Player>(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<Player>(L, 1);
if (!player) {
lua_pushnil(L);
return 1;
}
House* house = g_game.map.houses.getHouseByPlayerId(player->getGUID());
if (house) {
pushUserdata<House>(L, house);
setMetatable(L, -1, "House");
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaPlayerSetGhostMode(lua_State* L)
{
// player:setGhostMode(enabled)
Player* player = getUserdata<Player>(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<Player>(L, 1);
if (!player) {
lua_pushnil(L);
return 1;
}
Container* container = getUserdata<Container>(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<Player>(L, 1);
if (!player) {
lua_pushnil(L);
return 1;
}
Container* container = player->getContainerByID(getNumber<uint8_t>(L, 2));
if (container) {
pushUserdata<Container>(L, container);
setMetatable(L, -1, "Container");
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaPlayerGetContainerIndex(lua_State* L)
{
// player:getContainerIndex(id)
Player* player = getUserdata<Player>(L, 1);
if (player) {
lua_pushnumber(L, player->getContainerIndex(getNumber<uint8_t>(L, 2)));
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaPlayerGetTotalDamage(lua_State * L)
{
// player:getTotalDamage(attackSkill, attackValue, fightMode)
Player* player = getUserdata<Player>(L, 1);
if (player) {
uint32_t attackSkill = getNumber<uint32_t>(L, 2);
uint32_t attackValue = getNumber<uint32_t>(L, 3);
fightMode_t fightMode = static_cast<fightMode_t>(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<uint32_t>(L, 2));
} else if (isUserdata(L, 2)) {
if (getUserdataType(L, 2) != LuaData_Monster) {
lua_pushnil(L);
return 1;
}
monster = getUserdata<Monster>(L, 2);
} else {
monster = nullptr;
}
if (monster) {
pushUserdata<Monster>(L, monster);
setMetatable(L, -1, "Monster");
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaMonsterIsMonster(lua_State* L)
{
// monster:isMonster()
pushBoolean(L, getUserdata<const Monster>(L, 1) != nullptr);
return 1;
}
int LuaScriptInterface::luaMonsterGetType(lua_State* L)
{
// monster:getType()
const Monster* monster = getUserdata<const Monster>(L, 1);
if (monster) {
pushUserdata<MonsterType>(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<const Monster>(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<Monster>(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<Monster>(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<Monster>(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<Monster>(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<Monster>(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<Monster>(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<Monster>(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<Monster>(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<Monster>(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<Creature>(L, creature);
setCreatureMetatable(L, -1, creature);
lua_rawseti(L, -2, ++index);
}
return 1;
}
int LuaScriptInterface::luaMonsterGetFriendCount(lua_State* L)
{
// monster:getFriendCount()
Monster* monster = getUserdata<Monster>(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<Monster>(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<Monster>(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<Monster>(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<Creature>(L, creature);
setCreatureMetatable(L, -1, creature);
lua_rawseti(L, -2, ++index);
}
return 1;
}
int LuaScriptInterface::luaMonsterGetTargetCount(lua_State* L)
{
// monster:getTargetCount()
Monster* monster = getUserdata<Monster>(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<Monster>(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<Monster>(L, 1);
if (monster) {
TargetSearchType_t searchType = getNumber<TargetSearchType_t>(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<uint32_t>(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<Npc>(L, 2);
} else {
npc = nullptr;
}
} else {
npc = getScriptEnv()->getNpc();
}
if (npc) {
pushUserdata<Npc>(L, npc);
setMetatable(L, -1, "Npc");
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaNpcIsNpc(lua_State* L)
{
// npc:isNpc()
pushBoolean(L, getUserdata<const Npc>(L, 1) != nullptr);
return 1;
}
int LuaScriptInterface::luaNpcSetMasterPos(lua_State* L)
{
// npc:setMasterPos(pos[, radius])
Npc* npc = getUserdata<Npc>(L, 1);
if (!npc) {
lua_pushnil(L);
return 1;
}
const Position& pos = getPosition(L, 2);
int32_t radius = getNumber<int32_t>(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<uint32_t>(L, 2);
Guild* guild = g_game.getGuild(id);
if (guild) {
pushUserdata<Guild>(L, guild);
setMetatable(L, -1, "Guild");
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaGuildGetId(lua_State* L)
{
// guild:getId()
Guild* guild = getUserdata<Guild>(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<Guild>(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<const Guild>(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<Player>(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<Guild>(L, 1);
if (guild) {
uint32_t id = getNumber<uint32_t>(L, 2);
const std::string& name = getString(L, 3);
uint8_t level = getNumber<uint8_t>(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<Guild>(L, 1);
if (!guild) {
lua_pushnil(L);
return 1;
}
uint32_t id = getNumber<uint32_t>(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<const Guild>(L, 1);
if (!guild) {
lua_pushnil(L);
return 1;
}
uint8_t level = getNumber<uint8_t>(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<uint32_t>(L, 2);
Group* group = g_game.groups.getGroup(id);
if (group) {
pushUserdata<Group>(L, group);
setMetatable(L, -1, "Group");
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaGroupGetId(lua_State* L)
{
// group:getId()
Group* group = getUserdata<Group>(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<Group>(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<Group>(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<Group>(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<Group>(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<Group>(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<uint32_t>(L, 2);
} else {
id = g_vocations.getVocationId(getString(L, 2));
}
Vocation* vocation = g_vocations.getVocation(id);
if (vocation) {
pushUserdata<Vocation>(L, vocation);
setMetatable(L, -1, "Vocation");
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaVocationGetId(lua_State* L)
{
// vocation:getId()
Vocation* vocation = getUserdata<Vocation>(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<Vocation>(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<Vocation>(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<Vocation>(L, 1);
if (vocation) {
skills_t skillType = getNumber<skills_t>(L, 2);
uint16_t skillLevel = getNumber<uint16_t>(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<Vocation>(L, 1);
if (vocation) {
uint32_t magicLevel = getNumber<uint32_t>(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<Vocation>(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<Vocation>(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<Vocation>(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<Vocation>(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<Vocation>(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<Vocation>(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<Vocation>(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<Vocation>(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<Vocation>(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<Vocation>(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<Vocation>(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<Vocation>(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<Vocation>(L, demotedVocation);
setMetatable(L, -1, "Vocation");
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaVocationGetPromotion(lua_State* L)
{
// vocation:getPromotion()
Vocation* vocation = getUserdata<Vocation>(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<Vocation>(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<uint32_t>(L, 2));
} else if (isString(L, 2)) {
town = g_game.map.towns.getTown(getString(L, 2));
} else {
town = nullptr;
}
if (town) {
pushUserdata<Town>(L, town);
setMetatable(L, -1, "Town");
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaTownGetId(lua_State* L)
{
// town:getId()
Town* town = getUserdata<Town>(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<Town>(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<Town>(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<uint32_t>(L, 2));
if (house) {
pushUserdata<House>(L, house);
setMetatable(L, -1, "House");
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaHouseGetId(lua_State* L)
{
// house:getId()
House* house = getUserdata<House>(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<House>(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<House>(L, 1);
if (!house) {
lua_pushnil(L);
return 1;
}
Town* town = g_game.map.towns.getTown(house->getTownId());
if (town) {
pushUserdata<Town>(L, town);
setMetatable(L, -1, "Town");
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaHouseGetExitPosition(lua_State* L)
{
// house:getExitPosition()
House* house = getUserdata<House>(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<House>(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<House>(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<House>(L, 1);
if (house) {
uint32_t guid = getNumber<uint32_t>(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<House>(L, 1);
Player* player = getUserdata<Player>(L, 2);
Player* tradePartner = getUserdata<Player>(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<House>(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<Item>(L, bedItem);
setItemMetatable(L, -1, bedItem);
lua_rawseti(L, -2, ++index);
}
return 1;
}
int LuaScriptInterface::luaHouseGetBedCount(lua_State* L)
{
// house:getBedCount()
House* house = getUserdata<House>(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<House>(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<Item>(L, door);
setItemMetatable(L, -1, door);
lua_rawseti(L, -2, ++index);
}
return 1;
}
int LuaScriptInterface::luaHouseGetDoorCount(lua_State* L)
{
// house:getDoorCount()
House* house = getUserdata<House>(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<House>(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<Tile>(L, tile);
setMetatable(L, -1, "Tile");
lua_rawseti(L, -2, ++index);
}
return 1;
}
int LuaScriptInterface::luaHouseGetTileCount(lua_State* L)
{
// house:getTileCount()
House* house = getUserdata<House>(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<House>(L, 1);
if (!house) {
lua_pushnil(L);
return 1;
}
std::string list;
uint32_t listId = getNumber<uint32_t>(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<House>(L, 1);
if (!house) {
lua_pushnil(L);
return 1;
}
uint32_t listId = getNumber<uint32_t>(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<uint32_t>(L, 2);
} else {
id = Item::items.getItemIdByName(getString(L, 2));
}
const ItemType& itemType = Item::items[id];
pushUserdata<const ItemType>(L, &itemType);
setMetatable(L, -1, "ItemType");
return 1;
}
int LuaScriptInterface::luaItemTypeIsCorpse(lua_State* L)
{
// itemType:isCorpse()
const ItemType* itemType = getUserdata<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<uint16_t>(L, 2, 1);
const ItemType* itemType = getUserdata<const ItemType>(L, 1);
if (!itemType) {
lua_pushnil(L);
return 1;
}
uint64_t weight = static_cast<uint64_t>(itemType->weight) * std::max<int32_t>(1, count);
lua_pushnumber(L, weight);
return 1;
}
int LuaScriptInterface::luaItemTypeGetShootRange(lua_State* L)
{
// itemType:getShootRange()
const ItemType* itemType = getUserdata<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(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<const ItemType>(L, 1);
if (itemType) {
pushBoolean(L, itemType->hasSubType());
} else {
lua_pushnil(L);
}
return 1;
}
// Combat
int LuaScriptInterface::luaCombatCreate(lua_State* L)
{
// Combat()
pushUserdata<Combat>(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<Combat>(L, 1);
if (!combat) {
lua_pushnil(L);
return 1;
}
CombatParam_t key = getNumber<CombatParam_t>(L, 2);
uint32_t value;
if (isBoolean(L, 3)) {
value = getBoolean(L, 3) ? 1 : 0;
} else {
value = getNumber<uint32_t>(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<Combat>(L, 1);
if (!combat) {
lua_pushnil(L);
return 1;
}
formulaType_t type = getNumber<formulaType_t>(L, 2);
double mina = getNumber<double>(L, 3);
double minb = getNumber<double>(L, 4);
double maxa = getNumber<double>(L, 5);
double maxb = getNumber<double>(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<uint32_t>(L, 2));
if (!area) {
reportErrorFunc(getErrorDesc(LUA_ERROR_AREA_NOT_FOUND));
lua_pushnil(L);
return 1;
}
Combat* combat = getUserdata<Combat>(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<Condition>(L, 2);
Combat* combat = getUserdata<Combat>(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<Combat>(L, 1);
if (!combat) {
lua_pushnil(L);
return 1;
}
CallBackParam_t key = getNumber<CallBackParam_t>(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<Combat>(L, 1);
if (combat) {
combat->setOrigin(getNumber<CombatOrigin>(L, 2));
pushBoolean(L, true);
}
else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaCombatExecute(lua_State* L)
{
// combat:execute(creature, variant)
Combat* combat = getUserdata<Combat>(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<ConditionType_t>(L, 2);
ConditionId_t conditionId = getNumber<ConditionId_t>(L, 3, CONDITIONID_COMBAT);
Condition* condition = Condition::createCondition(conditionId, conditionType, 0, 0);
if (condition) {
pushUserdata<Condition>(L, condition);
setMetatable(L, -1, "Condition");
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaConditionDelete(lua_State* L)
{
// condition:delete()
Condition** conditionPtr = getRawUserdata<Condition>(L, 1);
if (conditionPtr && *conditionPtr) {
delete *conditionPtr;
*conditionPtr = nullptr;
}
return 0;
}
int LuaScriptInterface::luaConditionGetId(lua_State* L)
{
// condition:getId()
Condition* condition = getUserdata<Condition>(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<Condition>(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<Condition>(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<Condition>(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<Condition>(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<Condition>(L, 1);
if (condition) {
pushUserdata<Condition>(L, condition->clone());
setMetatable(L, -1, "Condition");
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaConditionGetTicks(lua_State* L)
{
// condition:getTicks()
Condition* condition = getUserdata<Condition>(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<int32_t>(L, 2);
Condition* condition = getUserdata<Condition>(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<Condition>(L, 1);
if (!condition) {
lua_pushnil(L);
return 1;
}
ConditionParam_t key = getNumber<ConditionParam_t>(L, 2);
int32_t value;
if (isBoolean(L, 3)) {
value = getBoolean(L, 3) ? 1 : 0;
} else {
value = getNumber<int32_t>(L, 3);
}
condition->setParam(key, value);
pushBoolean(L, true);
return 1;
}
int LuaScriptInterface::luaConditionSetSpeedDelta(lua_State* L)
{
// condition:setSpeedDelta(speedDelta)
int32_t speedDelta = getNumber<int32_t>(L, 2);
ConditionSpeed* condition = dynamic_cast<ConditionSpeed*>(getUserdata<Condition>(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<uint8_t>(L, 8, outfit.lookAddons);
outfit.lookFeet = getNumber<uint8_t>(L, 7);
outfit.lookLegs = getNumber<uint8_t>(L, 6);
outfit.lookBody = getNumber<uint8_t>(L, 5);
outfit.lookHead = getNumber<uint8_t>(L, 4);
outfit.lookType = getNumber<uint8_t>(L, 3);
outfit.lookTypeEx = getNumber<uint8_t>(L, 2);
}
ConditionOutfit* condition = dynamic_cast<ConditionOutfit*>(getUserdata<Condition>(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<int32_t>(L, 2);
ConditionDamage* condition = dynamic_cast<ConditionDamage*>(getUserdata<Condition>(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<MonsterType>(L, monsterType);
setMetatable(L, -1, "MonsterType");
} else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaMonsterTypeIsAttackable(lua_State* L)
{
// monsterType:isAttackable()
MonsterType* monsterType = getUserdata<MonsterType>(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<MonsterType>(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<MonsterType>(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<MonsterType>(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<MonsterType>(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<MonsterType>(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<MonsterType>(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<MonsterType>(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<MonsterType>(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<MonsterType>(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<MonsterType>(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<MonsterType>(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<MonsterType>(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<MonsterType>(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<MonsterType>(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<MonsterType>(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<MonsterType>(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<MonsterType>(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<CombatSpell>(L, static_cast<CombatSpell*>(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<MonsterType>(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<CombatSpell>(L, static_cast<CombatSpell*>(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<MonsterType>(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<MonsterType>(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<MonsterType>(L, 1);
if (!monsterType) {
lua_pushnil(L);
return 1;
}
static const std::function<void(const std::vector<LootBlock>&)> parseLoot = [&](const std::vector<LootBlock>& 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<MonsterType>(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<MonsterType>(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<MonsterType>(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<MonsterType>(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<MonsterType>(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<MonsterType>(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<MonsterType>(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<MonsterType>(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<MonsterType>(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<MonsterType>(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<MonsterType>(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<MonsterType>(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<MonsterType>(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<MonsterType>(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<Party>(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<Party>(L, 1);
if (!party) {
lua_pushnil(L);
return 1;
}
Player* leader = party->getLeader();
if (leader) {
pushUserdata<Player>(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<Party>(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<Party>(L, 1);
if (!party) {
lua_pushnil(L);
return 1;
}
int index = 0;
lua_createtable(L, party->getMemberCount(), 0);
for (Player* player : party->getMembers()) {
pushUserdata<Player>(L, player);
setMetatable(L, -1, "Player");
lua_rawseti(L, -2, ++index);
}
return 1;
}
int LuaScriptInterface::luaPartyGetMemberCount(lua_State* L)
{
// party:getMemberCount()
Party* party = getUserdata<Party>(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<Party>(L, 1);
if (party) {
lua_createtable(L, party->getInvitationCount(), 0);
int index = 0;
for (Player* player : party->getInvitees()) {
pushUserdata<Player>(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<Party>(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<Party>(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<Party>(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<Party>(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<Party>(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<Party>(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<Party>(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<uint64_t>(L, 2);
Party* party = getUserdata<Party>(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<Party>(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);
}
}