int NpcScriptInterface::luagetDistanceTo(lua_State* L) { //getDistanceTo(uid) ScriptEnvironment* env = getScriptEnv(); Npc* npc = env->getNpc(); if (!npc) { reportErrorFunc(getErrorDesc(LUA_ERROR_THING_NOT_FOUND)); lua_pushnil(L); return 1; } uint32_t uid = getNumber<uint32_t>(L, -1); Thing* thing = env->getThingByUID(uid); if (!thing) { reportErrorFunc(getErrorDesc(LUA_ERROR_THING_NOT_FOUND)); lua_pushnil(L); return 1; } const Position& thingPos = thing->getPosition(); const Position& npcPos = npc->getPosition(); if (npcPos.z != thingPos.z) { lua_pushnumber(L, -1); } else { int32_t dist = std::max<int32_t>(Position::getDistanceX(npcPos, thingPos), Position::getDistanceY(npcPos, thingPos)); lua_pushnumber(L, dist); } return 1; }
int NpcScriptInterface::luagetDistanceTo(lua_State *L) { //getDistanceTo(uid) uint32_t uid = popNumber(L); ScriptEnviroment* env = getScriptEnv(); Npc* npc = env->getNpc(); Thing* thing = env->getThingByUID(uid); if(thing && npc){ Position thing_pos = thing->getPosition(); Position npc_pos = npc->getPosition(); if(npc_pos.z != thing_pos.z){ lua_pushnumber(L, -1); } else{ int32_t dist = std::max(std::abs(npc_pos.x - thing_pos.x), std::abs(npc_pos.y - thing_pos.y)); lua_pushnumber(L, dist); } } else{ reportErrorFunc(getErrorDesc(LUA_ERROR_THING_NOT_FOUND)); lua_pushnil(L); } return 1; }
int NpcScriptInterface::luaCloseShop(lua_State *L) { //closeShopWindow(cid) ScriptEnviroment* env = getScriptEnv(); Npc* npc = env->getNpc(); Player* player = env->getPlayerByUID(popNumber(L)); int32_t buyCallback; int32_t sellCallback; if(player == NULL) { reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); lua_pushnumber(L, LUA_ERROR); return 1; } player->sendCloseShop(); player->getShopOwner(buyCallback, sellCallback); if(buyCallback != -1) luaL_unref(L, LUA_REGISTRYINDEX, buyCallback); if(sellCallback != -1) luaL_unref(L, LUA_REGISTRYINDEX, sellCallback); player->setShopOwner(NULL, -1, -1); return 1; }
int NpcScriptInterface::luaCreatureGetPos(lua_State *L) { /*/ //creatureGetPosition(cid) popNumber(L); reportErrorFunc("Deprecated function. Use getCreaturePosition"); /*/ uint32_t uid = popNumber(L); ScriptEnviroment* env = getScriptEnv(); Creature* creature = env->getCreatureByUID(uid); if(creature){ Position pos = creature->getPosition(); lua_pushnumber(L, pos.x); lua_pushnumber(L, pos.y); lua_pushnumber(L, pos.z); } else{ reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); } return 3; }
int NpcScriptInterface::luaCreatureGetName(lua_State *L) { //creatureGetName(cid) popNumber(L); reportErrorFunc("Deprecated function. Use getCreatureName"); lua_pushstring(L, ""); return 1; }
int NpcScriptInterface::luaCreatureGetName2(lua_State *L) { //creatureGetName2(name) - returns creature id popString(L); reportErrorFunc("Deprecated function."); lua_pushnil(L); return 1; }
int32_t NpcScriptInterface::luaCloseShopWindow(lua_State* L) { //closeShopWindow(cid) ScriptEnvironment* env = getScriptEnv(); Player* player = g_game.getPlayerByID(popNumber(L)); if (!player) { reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); pushBoolean(L, false); return 1; } Npc* npc = env->getNpc(); if (!npc) { reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); pushBoolean(L, false); return 1; } int32_t buyCallback; int32_t sellCallback; Npc* merchant = player->getShopOwner(buyCallback, sellCallback); //Check if we actually have a shop window with this player. if (merchant == npc) { player->sendCloseShop(); if (buyCallback != -1) { luaL_unref(L, LUA_REGISTRYINDEX, buyCallback); } if (sellCallback != -1) { luaL_unref(L, LUA_REGISTRYINDEX, sellCallback); } player->setShopOwner(NULL, -1, -1); npc->removeShopPlayer(player); } pushBoolean(L, true); return 1; }
int NpcScriptInterface::luaCreatureGetPos(lua_State *L) { //creatureGetPosition(cid) popNumber(L); reportErrorFunc("Deprecated function. Use getCreaturePosition"); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); return 3; }
int NpcScriptInterface::luaNpcCloseShopWindow(lua_State* L) { // npc:closeShopWindow(player) Player* player = getPlayer(L, 2); if (!player) { reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); pushBoolean(L, false); return 1; } Npc* npc = getUserdata<Npc>(L, 1); if (!npc) { reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); pushBoolean(L, false); return 1; } int32_t buyCallback; int32_t sellCallback; Npc* merchant = player->getShopOwner(buyCallback, sellCallback); if (merchant == npc) { player->sendCloseShop(); if (buyCallback != -1) { luaL_unref(L, LUA_REGISTRYINDEX, buyCallback); } if (sellCallback != -1) { luaL_unref(L, LUA_REGISTRYINDEX, sellCallback); } player->setShopOwner(nullptr, -1, -1); npc->removeShopPlayer(player); } pushBoolean(L, true); return 1; }
int NpcScriptInterface::luaNpcOpenShopWindow(lua_State* L) { // npc:openShopWindow(cid, items, buyCallback, sellCallback) if (!isTable(L, 3)) { reportErrorFunc("item list is not a table."); pushBoolean(L, false); return 1; } Player* player = getPlayer(L, 2); if (!player) { reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); pushBoolean(L, false); return 1; } Npc* npc = getUserdata<Npc>(L, 1); if (!npc) { reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); pushBoolean(L, false); return 1; } int32_t sellCallback = -1; if (LuaScriptInterface::isFunction(L, 5)) { sellCallback = luaL_ref(L, LUA_REGISTRYINDEX); } int32_t buyCallback = -1; if (LuaScriptInterface::isFunction(L, 4)) { buyCallback = luaL_ref(L, LUA_REGISTRYINDEX); } std::list<ShopInfo> items; lua_pushnil(L); while (lua_next(L, 3) != 0) { const auto tableIndex = lua_gettop(L); ShopInfo item; item.itemId = getField<uint32_t>(L, tableIndex, "id"); item.subType = getField<int32_t>(L, tableIndex, "subType"); if (item.subType == 0) { item.subType = getField<int32_t>(L, tableIndex, "subtype"); lua_pop(L, 1); } item.buyPrice = getField<uint32_t>(L, tableIndex, "buy"); item.sellPrice = getField<uint32_t>(L, tableIndex, "sell"); item.realName = getFieldString(L, tableIndex, "name"); items.push_back(item); lua_pop(L, 6); } lua_pop(L, 1); player->closeShopWindow(false); npc->addShopPlayer(player); player->setShopOwner(npc, buyCallback, sellCallback); player->openShopWindow(npc, items); pushBoolean(L, true); return 1; }
int NpcScriptInterface::luaDoSellItem(lua_State* L) { //doSellItem(cid, itemid, amount, <optional> subtype, <optional> actionid, <optional: default: 1> canDropOnMap) Player* player = getPlayer(L, 1); if (!player) { reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); pushBoolean(L, false); return 1; } uint32_t sellCount = 0; uint32_t itemId = getNumber<uint32_t>(L, 2); uint32_t amount = getNumber<uint32_t>(L, 3); uint32_t subType; int32_t n = getNumber<int32_t>(L, 4, -1); if (n != -1) { subType = n; } else { subType = 1; } uint32_t actionId = getNumber<uint32_t>(L, 5, 0); bool canDropOnMap = getBoolean(L, 6, true); const ItemType& it = Item::items[itemId]; if (it.stackable) { while (amount > 0) { int32_t stackCount = std::min<int32_t>(100, amount); Item* item = Item::CreateItem(it.id, stackCount); if (item && actionId != 0) { item->setActionId(actionId); } if (g_game.internalPlayerAddItem(player, item, canDropOnMap) != RETURNVALUE_NOERROR) { delete item; lua_pushnumber(L, sellCount); return 1; } amount -= stackCount; sellCount += stackCount; } } else { for (uint32_t i = 0; i < amount; ++i) { Item* item = Item::CreateItem(it.id, subType); if (item && actionId != 0) { item->setActionId(actionId); } if (g_game.internalPlayerAddItem(player, item, canDropOnMap) != RETURNVALUE_NOERROR) { delete item; lua_pushnumber(L, sellCount); return 1; } ++sellCount; } } lua_pushnumber(L, sellCount); return 1; }
int NpcScriptInterface::luaOpenShopWindow(lua_State* L) { //openShopWindow(cid, items, onBuy callback, onSell callback) int32_t sellCallback; if (lua_isfunction(L, -1) == 0) { sellCallback = -1; lua_pop(L, 1); // skip it - use default value } else { sellCallback = popCallback(L); } int32_t buyCallback; if (lua_isfunction(L, -1) == 0) { buyCallback = -1; lua_pop(L, 1); // skip it - use default value } else { buyCallback = popCallback(L); } if (lua_istable(L, -1) == 0) { reportError(__FUNCTION__, "item list is not a table."); pushBoolean(L, false); return 1; } std::list<ShopInfo> items; lua_pushnil(L); while (lua_next(L, -2) != 0) { const auto tableIndex = lua_gettop(L); ShopInfo item; item.itemId = getField<uint32_t>(L, tableIndex, "id"); item.subType = getField<int32_t>(L, tableIndex, "subType"); if (item.subType == 0) { item.subType = getField<int32_t>(L, tableIndex, "subtype"); lua_pop(L, 1); } item.buyPrice = getField<uint32_t>(L, tableIndex, "buy"); item.sellPrice = getField<uint32_t>(L, tableIndex, "sell"); item.realName = getFieldString(L, tableIndex, "name"); items.push_back(item); lua_pop(L, 6); } lua_pop(L, 1); Player* player = getPlayer(L, -1); if (!player) { reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); pushBoolean(L, false); return 1; } //Close any eventual other shop window currently open. player->closeShopWindow(false); Npc* npc = getScriptEnv()->getNpc(); if (!npc) { reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); pushBoolean(L, false); return 1; } npc->addShopPlayer(player); player->setShopOwner(npc, buyCallback, sellCallback); player->openShopWindow(npc, items); pushBoolean(L, true); return 1; }
int32_t NpcScriptInterface::luaDoSellItem(lua_State* L) { //doSellItem(cid, itemid, amount, <optional> subtype, <optional> actionid, <optional: default: 1> canDropOnMap) int32_t parameters = lua_gettop(L); bool canDropOnMap; if (parameters > 5) { canDropOnMap = popBoolean(L); } else { canDropOnMap = true; } uint32_t actionId = 0; if (parameters > 4) { actionId = popNumber(L); } uint32_t subType = 1; if (parameters > 3) { int32_t n = popNumber(L); if (n != -1) { subType = n; } } uint32_t amount = popNumber(L); uint32_t itemId = popNumber(L); Player* player = g_game.getPlayerByID(popNumber(L)); if (!player) { reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); pushBoolean(L, false); return 1; } uint32_t sellCount = 0; const ItemType& it = Item::items[itemId]; if (it.stackable) { while (amount > 0) { int32_t stackCount = std::min<int32_t>(100, amount); Item* item = Item::CreateItem(it.id, stackCount); if (item && actionId != 0) { item->setActionId(actionId); } if (g_game.internalPlayerAddItem(player, item, canDropOnMap) != RET_NOERROR) { delete item; lua_pushnumber(L, sellCount); return 1; } amount = amount - stackCount; sellCount += stackCount; } } else { for (uint32_t i = 0; i < amount; ++i) { Item* item = Item::CreateItem(it.id, subType); if (item && actionId != 0) { item->setActionId(actionId); } if (g_game.internalPlayerAddItem(player, item, canDropOnMap) != RET_NOERROR) { delete item; lua_pushnumber(L, sellCount); return 1; } ++sellCount; } } lua_pushnumber(L, sellCount); return 1; }
// new: shop int NpcScriptInterface::luaSendShop(lua_State *L) { //sendShopWindow(cid, items, onBuy callback, onSell callback) int32_t buyCallback = -1; int32_t sellCallback = -1; std::list<ShopInfo> items; Player* player = NULL; ScriptEnviroment* env = getScriptEnv(); Npc* npc = env->getNpc(); if(lua_isfunction(L, -1) == 0) { lua_pop(L, 1); // skip it - use default value } else { sellCallback = popCallback(L); } if(lua_isfunction(L, -1) == 0) { lua_pop(L, 1); // skip it - use default value } else { buyCallback = popCallback(L); } if(lua_istable(L, -1) == 0) { reportError(__FUNCTION__, "item list is not a table."); lua_pushnumber(L, LUA_ERROR); return 1; } // first key lua_pushnil(L); while(lua_next(L, -2) != 0) { ShopInfo item; item.itemId = getField(L, "id"); item.itemCharges = getField(L, "charges"); item.buyPrice = getField(L, "buy"); item.salePrice = getField(L, "sell"); #ifdef __DEBUG_820__ std::cout << "Added Item " << item.itemId << " with charges " << item.itemCharges << " costs " << item.buyPrice << " and sells for " << item.salePrice << std::endl; #endif items.push_back(item); lua_pop(L, 1); } lua_pop(L, 1); player = env->getPlayerByUID(popNumber(L)); if(player == NULL) { reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); lua_pushnumber(L, LUA_ERROR); return 1; } player->setShopOwner(env->getNpc(), buyCallback, sellCallback); player->sendShop(items); player->sendCash(g_game.getMoney(player)); return 1; }