• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Lua Problem to get a Lua Table in LuaScript C++ Function.

darkshin

New old member
Joined
Dec 14, 2010
Messages
231
Reaction score
22
Hello Guys!!

I am having a trouble trying to get a Lua table at a C++ Function, in luascript.cpp.
Here is the code:

Lua file
Code:
function onUse(player, item, fromPosition, target, toPosition, isHotkey)

    local recipe = Recipe()

    local items = {
    item1 = {2157},
    valor1 = {50},
    item2 = {0},
    valor2 = {0},
    item3 = {0},
    valor3 = {0},
    item4 = {0},
    valor4 = {0},
    item5 = {0},
    valor5 = {0}
    }
   
    recipe:setRecipeItem(items)

end

C++ Function
Code:
int LuaScriptInterface::luaRecipeSetRecipeItem(lua_State* L)
{
    RecipeHandler* recipe = getUserdata<RecipeHandler>(L, 1);
    uint32_t items[5][2] = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } };

    lua_getglobal(L, "items");

    for (uint8_t i = 1; i < 5; ++i) {

        if (getField<uint32_t>(L, 2, "item" + std::to_string(i)) == 0 || getField<uint32_t>(L, 2, "valor" + std::to_string(i)) == 0) {
            std::cout << "[Error - LuaScriptInterface::SetRecipeItem] Null filed at: " << std::to_string(i) << std::endl;
            break;
        }
        else {
            items[i][1] = getField<uint32_t>(L, 2, "item" + std::to_string(i));
            items[i][2] = getField<uint32_t>(L, 2, "valor" + std::to_string(i));
        }
    }

    if (!isTable(L, 2)) {
        pushBoolean(L, false);
        return 1;
    }
    else {
   
        if (recipe) {
            std::cout << "[LuaScriptInterface::SetRecipeItem] Sending Values: " << std::to_string(items[1][1]) << std::endl;
            recipe->setRecipeItem(items);
        }
        else {
            lua_pushnil(L);
        }

    }

    return 1;
}

I am getting 0 at every"getField", so I assume that I am doing it wrong. Can anyone help me make it workout?
 
Try this:

Code:
int LuaScriptInterface::luaRecipeSetRecipeItem(lua_State* L)
{
    RecipeHandler* recipe = getUserdata<RecipeHandler>(L, 1);
    if (!recipe) {
        lua_pushnil(L);
        return 1;
    }

    std::map<uint16_t, uint16_t> items;

    //push first key for next()
    lua_pushnil(L);
    while (lua_next(L, 2) != 0) {
        //right now -2 is key, -1 is value
        lua_rawgeti(L, -1, 1); //push itemid onto the stack
        lua_rawgeti(L, -2, 2); //push price onto the stack       
        uint16_t itemid = static_cast<uint16_t>(lua_tonumber(L, -2));
        uint16_t price = static_cast<uint16_t>(lua_tonumber(L, -1));
        items[itemid] = price;
        lua_pop(L, 3); // pop value, itemid and price, but leave the last key for next()
    }   

    recipe->setRecipeItem(items);
    // P.S: modify your function to receive a std::map<uint16_t, uint16_t> and then you can iterate over the items like this:
    /*
        for (const auto& it: items) {
            // it.first is the itemid
            // it.second is the price
        }
    */    
    return 0;
}

I have left some comments so you can grasp what is going on. You can then call your function like this:

Code:
function onUse(player, item, fromPosition, target, toPosition, isHotkey)

    local recipe = Recipe()

   
    local items = {
        {2157, 50},
        {2158, 100},
        {1988, 20}
    }
  
    recipe:setRecipeItem(items)
end

I hope it helps.
 
Try this:

Code:
int LuaScriptInterface::luaRecipeSetRecipeItem(lua_State* L)
{
    RecipeHandler* recipe = getUserdata<RecipeHandler>(L, 1);
    if (!recipe) {
        lua_pushnil(L);
        return 1;
    }

    std::map<uint16_t, uint16_t> items;

    //push first key for next()
    lua_pushnil(L);
    while (lua_next(L, 2) != 0) {
        //right now -2 is key, -1 is value
        lua_rawgeti(L, -1, 1); //push itemid onto the stack
        lua_rawgeti(L, -2, 2); //push price onto the stack     
        uint16_t itemid = static_cast<uint16_t>(lua_tonumber(L, -2));
        uint16_t price = static_cast<uint16_t>(lua_tonumber(L, -1));
        items[itemid] = price;
        lua_pop(L, 3); // pop value, itemid and price, but leave the last key for next()
    } 

    recipe->setRecipeItem(items);
    // P.S: modify your function to receive a std::map<uint16_t, uint16_t> and then you can iterate over the items like this:
    /*
        for (const auto& it: items) {
            // it.first is the itemid
            // it.second is the price
        }
    */  
    return 0;
}

I hope it helps.

Hey @Non Sequitur ! It helped me alot with that function. However, I tried to use that code for a new function, but something is going wrong. Could you help me at this last one?

lua file:
Code:
local classItems = {
[2376] = {2144, 10}      
}

function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    
    local recipe = Recipe()
    local tile = Tile(toPosition)
    local position = target:getPosition()

if tile then
           local items = tile:getItems()
           local finalItem = nil
           local itemArray = {}
           
           for key,valor in ipairs(items) do
              local id = valor:getId() 
             if classItems[id] then
                finalItem = id
                itemArray = classItems[id]
             end
           end
           
           if finalItem then

           for key,valor in ipairs(itemArray) do
           print(key, valor)
           end

           recipe:setRecipeClassItems(itemArray, finalItem, player, position)
           end
end
end

c++ function
Code:
RecipeHandler* recipe = getUserdata<RecipeHandler>(L, 1);

    if (!recipe) {
        lua_pushnil(L);
        return 1;
    }

    std::map<uint16_t, uint16_t> items;

    //push first key for next()
    lua_pushnil(L);
    while (lua_next(L, 2) != 0) {
        //right now -2 is key, -1 is value
        lua_rawgeti(L, -1, 1);
        lua_rawgeti(L, -2, 2); // ERROR AT THIS LINE..  ACCESS VIOLATING READING LOCATION 0x0...18
        uint16_t itemid = static_cast<uint16_t>(lua_tonumber(L, -2));
        uint16_t amount = static_cast<uint16_t>(lua_tonumber(L, -1));
        items[itemid] = amount;
        lua_pop(L, 3); // pop value, itemid and price, but leave the last key for next()
    }

    uint16_t itemID = getNumber<uint16_t>(L, 3);
    Position position = getPosition(L, 4);
    Player* player = getPlayer(L, 5);

    if (player) {
        recipe->setRecipeClasses(itemID, position, player, items);
    }

    return 1;

Does the error at the c++ functions means that the field is empty/nil ?
 
You're passing this table to the function:
Code:
{2144, 10}

When it expects a table of tables, like this:
Code:
{
    {2144, 10}
}

You should take a better look at the example in my last post.
 
You're passing this table to the function:
Code:
{2144, 10}

When it expects a table of tables, like this:
Code:
{
    {2144, 10}
}

You should take a better look at the example in my last post.

Thank you! That's why it was returning null at the the second statement XD
 
Back
Top