int lua_mapgen(map * m, std::string terrain_type, mapgendata md, int t, float d, const std::string & scr) { lua_State* L = lua_state; { map** map_userdata = (map**) lua_newuserdata(L, sizeof(map*)); *map_userdata = m; luah_setmetatable(L, "map_metatable"); luah_setglobal(L, "map", -1); } int err = luaL_loadstring(L, scr.c_str() ); if(err) { // Error handling. const char* error = lua_tostring(L, -1); debugmsg("Error loading lua mapgen: %s", error); return err; } // int function_index = luaL_ref(L, LUA_REGISTRYINDEX); // todo; make use of this // lua_rawgeti(L, LUA_REGISTRYINDEX, function_index); lua_pushstring(L, terrain_type.c_str()); lua_setglobal(L, "tertype"); lua_pushinteger(L, t); lua_setglobal(L, "turn"); err=lua_pcall(L, 0 , LUA_MULTRET, 0); if(err) { // Error handling. const char* error = lua_tostring(L, -1); debugmsg("Error running lua mapgen: %s", error); } // luah_remove_from_registry(L, function_index); // todo: make use of this return err; }
// Lua monster movement override int lua_monster_move(monster* m) { lua_State *L = lua_state; update_globals(L); lua_getglobal(L, "monster_move"); lua_getfield(L, -1, m->type->name.c_str()); // OK our function should now be at the top. if(lua_isnil(L, -1)) { lua_settop(L, 0); return 0; } // Push the monster on top of the stack. monster** monster_userdata = (monster**) lua_newuserdata(L, sizeof(monster*)); *monster_userdata = m; // Set the metatable for the monster. luah_setmetatable(L, "monster_metatable"); // Call the function int err = lua_pcall(lua_state, 1, 0, 0); if(err) { // Error handling. const char* error = lua_tostring(L, -1); debugmsg("Error in lua monster move function: %s", error); } lua_settop(L, 0); return 1; }
// items = game.items_at(x, y) static int game_items_at(lua_State *L) { int x = lua_tointeger(L, 1); int y = lua_tointeger(L, 2); std::vector<item>& items = g->m.i_at(x, y); lua_createtable(L, items.size(), 0); // Preallocate enough space for all our items. // Iterate over the monster list and insert each monster into our returned table. for(int i=0; i < items.size(); i++) { // The stack will look like this: // 1 - t, table containing item // 2 - k, index at which the next item will be inserted // 3 - v, next item to insert // // lua_rawset then does t[k] = v and pops v and k from the stack lua_pushnumber(L, i + 1); item** item_userdata = (item**) lua_newuserdata(L, sizeof(item*)); *item_userdata = &(items[i]); luah_setmetatable(L, "item_metatable"); lua_rawset(L, -3); } return 1; // 1 return values }
int lua_mapgen(map *m, std::string terrain_type, mapgendata, int t, float, const std::string &scr) { if( lua_state == nullptr ) { return 0; } lua_State *L = lua_state; { map **map_userdata = (map **) lua_newuserdata(L, sizeof(map *)); *map_userdata = m; luah_setmetatable(L, "map_metatable"); luah_setglobal(L, "map", -1); } int err = luaL_loadstring(L, scr.c_str() ); if( lua_report_error( L, err, scr.c_str() ) ) { return err; } // int function_index = luaL_ref(L, LUA_REGISTRYINDEX); // todo; make use of this // lua_rawgeti(L, LUA_REGISTRYINDEX, function_index); lua_pushstring(L, terrain_type.c_str()); lua_setglobal(L, "tertype"); lua_pushinteger(L, t); lua_setglobal(L, "turn"); err = lua_pcall(L, 0 , LUA_MULTRET, 0); lua_report_error( L, err, scr.c_str() ); // luah_remove_from_registry(L, function_index); // todo: make use of this return err; }
// monstergroups = game.monstergroups(overmap) static int game_monstergroups(lua_State *L) { overmap **userdata = (overmap**) lua_touserdata(L, 1); std::vector<mongroup>& mongroups = (*userdata)->zg; lua_createtable(L, mongroups.size(), 0); // Preallocate enough space for all our monster groups. // Iterate over the monster group list and insert each monster group into our returned table. for( size_t i = 0; i < mongroups.size(); ++i ) { // The stack will look like this: // 1 - t, table containing group // 2 - k, index at which the next group will be inserted // 3 - v, next group to insert // // lua_rawset then does t[k] = v and pops v and k from the stack lua_pushnumber(L, i + 1); mongroup** mongroup_userdata = (mongroup**) lua_newuserdata(L, sizeof(mongroup*)); *mongroup_userdata = &(mongroups[i]); luah_setmetatable(L, "mongroup_metatable"); lua_rawset(L, -3); } return 1; // 1 return values }
// mtype = game.monster_type(name) static int game_monster_type(lua_State *L) { const char* parameter1 = (const char*) lua_tostring(L, 1); mtype** monster_type = (mtype**) lua_newuserdata(L, sizeof(mtype*)); *monster_type = GetMType(parameter1); luah_setmetatable(L, "mtype_metatable"); return 1; // 1 return values }
// monster = game.monster_at(x, y) static int game_monster_at(lua_State *L) { int parameter1 = (int) lua_tonumber(L, 1); int parameter2 = (int) lua_tonumber(L, 2); int monster_idx = g->mon_at(parameter1, parameter2); monster& mon_ref = g->zombie(monster_idx); monster** monster_userdata = (monster**) lua_newuserdata(L, sizeof(monster*)); *monster_userdata = &mon_ref; luah_setmetatable(L, "monster_metatable"); return 1; // 1 return values }
void update_globals(lua_State *L) { // Make sure the player reference is up to date. { player** player_userdata = (player**) lua_newuserdata(L, sizeof(player*)); *player_userdata = &g->u; // Set the metatable for the player. luah_setmetatable(L, "player_metatable"); luah_setglobal(L, "player", -1); } // Make sure the map reference is up to date. { map** map_userdata = (map**) lua_newuserdata(L, sizeof(map*)); *map_userdata = &g->m; // Set the metatable for the player. luah_setmetatable(L, "map_metatable"); luah_setglobal(L, "map", -1); } }
// If we're not using lua, need to define Use_function in a way to always call the C++ function int use_function::call(player* player_instance, item* item_instance, bool active) { if(function_type == USE_FUNCTION_CPP) { // If it's a C++ function, simply call it with the given arguments. iuse tmp; return (tmp.*cpp_function)(player_instance, item_instance, active); } else { #ifdef LUA // We'll be using lua_state a lot! lua_State* L = lua_state; // If it's a lua function, the arguments have to be wrapped in // lua userdata's and passed on the lua stack. // We will now call the function f(player, item, active) update_globals(L); // Push the lua function on top of the stack lua_rawgeti(L, LUA_REGISTRYINDEX, lua_function); // Push the item on top of the stack. int item_in_registry; { item** item_userdata = (item**) lua_newuserdata(L, sizeof(item*)); *item_userdata = item_instance; // Save a reference to the item in the registry so that we can deallocate it // when we're done. item_in_registry = luah_store_in_registry(L, -1); // Set the metatable for the item. luah_setmetatable(L, "item_metatable"); } // Push the "active" parameter on top of the stack. lua_pushboolean(L, active); // Call the iuse function int err = lua_pcall(L, 3, 1, 0); if(err) { // Error handling. const char* error = lua_tostring(L, -1); debugmsg("Error in lua iuse function: %s", error); } // Make sure the now outdated parameters we passed to lua aren't // being used anymore by setting a metatable that will error on // access. luah_remove_from_registry(L, item_in_registry); luah_setmetatable(L, "outdated_metatable"); return lua_tointeger(L, -1); #else // If LUA isn't defined and for some reason we registered a lua function, // simply do nothing. return 0; #endif } }
// If we're not using lua, need to define Use_function in a way to always call the C++ function int use_function::call(player *player_instance, item *item_instance, bool active, point pos) const { if (function_type == USE_FUNCTION_NONE) { if (player_instance != NULL && player_instance->is_player()) { add_msg(_("You can't do anything interesting with your %s."), item_instance->tname().c_str()); } } else if (function_type == USE_FUNCTION_CPP) { // If it's a C++ function, simply call it with the given arguments. iuse tmp; return (tmp.*cpp_function)(player_instance, item_instance, active, pos); } else if (function_type == USE_FUNCTION_ACTOR_PTR) { return actor_ptr->use(player_instance, item_instance, active, pos); } else { #ifdef LUA // We'll be using lua_state a lot! lua_State *L = lua_state; // If it's a lua function, the arguments have to be wrapped in // lua userdata's and passed on the lua stack. // We will now call the function f(player, item, active) update_globals(L); // Push the lua function on top of the stack lua_rawgeti(L, LUA_REGISTRYINDEX, lua_function); // TODO: also pass the player object, because of NPCs and all // I guess // Push the item on top of the stack. int item_in_registry; { item **item_userdata = (item **) lua_newuserdata(L, sizeof(item *)); *item_userdata = item_instance; // Save a reference to the item in the registry so that we can deallocate it // when we're done. item_in_registry = luah_store_in_registry(L, -1); // Set the metatable for the item. luah_setmetatable(L, "item_metatable"); } // Push the "active" parameter on top of the stack. lua_pushboolean(L, active); // Call the iuse function int err = lua_pcall(L, 2, 1, 0); lua_report_error( L, err, "iuse function" ); // Make sure the now outdated parameters we passed to lua aren't // being used anymore by setting a metatable that will error on // access. luah_remove_from_registry(L, item_in_registry); luah_setmetatable(L, "outdated_metatable"); return lua_tointeger(L, -1); #else // If LUA isn't defined and for some reason we registered a lua function, // simply do nothing. return 0; #endif } return 0; }