I have a lua function called from c, giving it a table as argument with some string fields and number values. I serialized some world state from my c program in this table. This is for a dialogue system. When I access the table in lua, i want to check whether or not some world state matches. This controls the output of the dialogue options (see example code below).
What I don´t want is to pre initialize all possible state.
I only want to ask in lua for example:
if(table.player.killedEnemys > 5) then
//calls a c-function that loads the given Text to display and the follow up function when clicked
PresentOption("Try to impress opponent.", "show_off_to_soldier")
end
It works fine. If a player field was setted in the table before calling the function with this table as argument, killedEnemys is 0 due to the metamethod __index and __newindex:
function newindex_metamethod(t,i, v)
rawset(t, i, v)
end
function index_metamethod(t,i)
t[i] = 0
end
But I encounter an error by the line of the if-condition, saying: attempt to index a nil value (field 'player') when player is also not existing in the table so far.
I thought the metamethods set the field "player" in the table before indexing this field further with "killedEnemys". But this seems to be wrong and I do not understand why.
In my imagination the table should looks like this:
table =
{
"player" = //set by the metamethods
{
"killedEnemys" = 0 //set by the metamethod
}
}
Questions: 1. Is it possible to use metamethods in lua like this, if more than one field in a nested table does not exist? 2. How does Lua operate on this nested table calls?
This is how I call it from C and the function being called in lua:
//IN C:
lua_getglobal(L, funcName); // where funcName represents a string for the function
//"small_talk" below
lua_table_serializer ser = {}; //serialization of the game state using the LBP-Method
ser.L = L; //it creates a table and pushes it to the stack where
Serialize(&ser, npc);
lua_newtable(L); // creating a table and set it as metatable of the
lua_pushstring(L, "__index"); // table with the serialized game state
lua_getglobal(L, "index_metamethod");
lua_rawset(L, -3);
lua_pushstring(L, "__newindex");
lua_getglobal(L, "newindex_metamethod");
lua_rawset(L, -3);
lua_setmetatable(L, -2);
lua_pcall(L, 1, 0, 0);
//IN LUA:
function small_talk(table)
PlayText("....")
PresentOption("...", "small_talk2")
if(table.player.killedEnemys > 5) then
PresentOption("Try to impress opponent.", "show_off_to_soldier")
end
end
There are no other global variables with the same name.
I also tried some variations for the metamethods like setting t[i] = {} and so on.
The metamethods are called for field player, but not killedEnemys (I printed the metamethod calls to check).
Anything works fine unless there are multiple levels of not existing fields.
I also saw this question which is similar. But with the solutions the syntacic sugar is lost. Also I want to know why the metamethod-solution does not the job.