/** * \brief __newindex function of the environment of the savegame file. * * This special __newindex function catches declaration of global variables * to store them into the savegame. * * \param l The Lua context that is calling this function. * \return Number of values to return to Lua. */ int Savegame::l_newindex(lua_State* l) { return LuaTools::exception_boundary_handle(l, [&] { lua_getfield(l, LUA_REGISTRYINDEX, "savegame"); Savegame* savegame = static_cast<Savegame*>(lua_touserdata(l, -1)); lua_pop(l, 1); const std::string& key = LuaTools::check_string(l, 2); switch (lua_type(l, 3)) { case LUA_TBOOLEAN: savegame->set_boolean(key, lua_toboolean(l, 3)); break; case LUA_TNUMBER: savegame->set_integer(key, (int) lua_tointeger(l, 3)); break; case LUA_TSTRING: savegame->set_string(key, lua_tostring(l, 3)); break; default: LuaTools::type_error(l, 3, "string, number or boolean"); } return 0; }); }
/** * \brief __newindex function of the environment of the savegame file. * * This special __newindex function catches declaration of global variables * to store them into the savegame. * * \param l The Lua context that is calling this function. * \return Number of values to return to Lua. */ int Savegame::l_newindex(lua_State* l) { lua_getfield(l, LUA_REGISTRYINDEX, "savegame"); Savegame* savegame = static_cast<Savegame*>(lua_touserdata(l, -1)); lua_pop(l, 1); const std::string& key = luaL_checkstring(l, 2); switch (lua_type(l, 3)) { case LUA_TBOOLEAN: savegame->set_boolean(key, lua_toboolean(l, 3)); break; case LUA_TNUMBER: savegame->set_integer(key, int(lua_tointeger(l, 3))); break; case LUA_TSTRING: savegame->set_string(key, lua_tostring(l, 3)); break; default: luaL_typerror(l, 3, "string, number or boolean"); } return 0; }
/** * \brief Converts this savegame v1 into a savegame v2. * \param savegame_v2 The savegame to fill. */ void SavegameConverterV1::convert_to_v2(Savegame& savegame_v2) { // 1. Built-in values. savegame_v2.set_string(Savegame::KEY_STARTING_POINT, get_string(STARTING_POINT)); if (!get_string(STARTING_MAP).empty()) { savegame_v2.set_string(Savegame::KEY_STARTING_MAP, get_string(STARTING_MAP)); } else { // Older v1 savegames used integers to identify maps. std::ostringstream oss; oss << get_integer(STARTING_MAP_INT); savegame_v2.set_string(Savegame::KEY_STARTING_MAP, oss.str()); } savegame_v2.set_integer(Savegame::KEY_CURRENT_LIFE, get_integer(CURRENT_LIFE)); savegame_v2.set_integer(Savegame::KEY_CURRENT_MONEY, get_integer(CURRENT_MONEY)); savegame_v2.set_integer(Savegame::KEY_CURRENT_MAGIC, get_integer(CURRENT_MAGIC)); savegame_v2.set_integer(Savegame::KEY_MAX_LIFE, get_integer(MAX_LIFE)); savegame_v2.set_integer(Savegame::KEY_MAX_MONEY, get_integer(MAX_MONEY)); savegame_v2.set_integer(Savegame::KEY_MAX_MAGIC, get_integer(MAX_MAGIC)); savegame_v2.set_string(Savegame::KEY_ITEM_SLOT_1, get_string(ITEM_SLOT_0)); savegame_v2.set_string(Savegame::KEY_ITEM_SLOT_2, get_string(ITEM_SLOT_1)); savegame_v2.set_string(Savegame::KEY_KEYBOARD_ACTION, InputEvent::get_keyboard_key_name( InputEvent::KeyboardKey(get_integer(KEYBOARD_ACTION_KEY)))); savegame_v2.set_string(Savegame::KEY_KEYBOARD_ATTACK, InputEvent::get_keyboard_key_name( InputEvent::KeyboardKey(get_integer(KEYBOARD_SWORD_KEY)))); savegame_v2.set_string(Savegame::KEY_KEYBOARD_ITEM_1, InputEvent::get_keyboard_key_name( InputEvent::KeyboardKey(get_integer(KEYBOARD_ITEM_1_KEY)))); savegame_v2.set_string(Savegame::KEY_KEYBOARD_ITEM_2, InputEvent::get_keyboard_key_name( InputEvent::KeyboardKey(get_integer(KEYBOARD_ITEM_2_KEY)))); savegame_v2.set_string(Savegame::KEY_KEYBOARD_PAUSE, InputEvent::get_keyboard_key_name( InputEvent::KeyboardKey(get_integer(KEYBOARD_PAUSE_KEY)))); savegame_v2.set_string(Savegame::KEY_KEYBOARD_RIGHT, InputEvent::get_keyboard_key_name( InputEvent::KeyboardKey(get_integer(KEYBOARD_RIGHT_KEY)))); savegame_v2.set_string(Savegame::KEY_KEYBOARD_UP, InputEvent::get_keyboard_key_name( InputEvent::KeyboardKey(get_integer(KEYBOARD_UP_KEY)))); savegame_v2.set_string(Savegame::KEY_KEYBOARD_LEFT, InputEvent::get_keyboard_key_name( InputEvent::KeyboardKey(get_integer(KEYBOARD_LEFT_KEY)))); savegame_v2.set_string(Savegame::KEY_KEYBOARD_DOWN, InputEvent::get_keyboard_key_name( InputEvent::KeyboardKey(get_integer(KEYBOARD_DOWN_KEY)))); savegame_v2.set_string(Savegame::KEY_JOYPAD_ACTION, get_string(JOYPAD_ACTION_KEY)); savegame_v2.set_string(Savegame::KEY_JOYPAD_ATTACK, get_string(JOYPAD_SWORD_KEY)); savegame_v2.set_string(Savegame::KEY_JOYPAD_ITEM_1, get_string(JOYPAD_ITEM_1_KEY)); savegame_v2.set_string(Savegame::KEY_JOYPAD_ITEM_2, get_string(JOYPAD_ITEM_2_KEY)); savegame_v2.set_string(Savegame::KEY_JOYPAD_PAUSE, get_string(JOYPAD_PAUSE_KEY)); savegame_v2.set_string(Savegame::KEY_JOYPAD_RIGHT, get_string(JOYPAD_RIGHT_KEY)); savegame_v2.set_string(Savegame::KEY_JOYPAD_UP, get_string(JOYPAD_UP_KEY)); savegame_v2.set_string(Savegame::KEY_JOYPAD_LEFT, get_string(JOYPAD_LEFT_KEY)); savegame_v2.set_string(Savegame::KEY_JOYPAD_DOWN, get_string(JOYPAD_DOWN_KEY)); savegame_v2.set_integer(Savegame::KEY_ABILITY_RESISTANCE, get_integer(ABILITY_TUNIC)); savegame_v2.set_integer(Savegame::KEY_ABILITY_SWORD, get_integer(ABILITY_SWORD)); savegame_v2.set_integer(Savegame::KEY_ABILITY_SHIELD, get_integer(ABILITY_SHIELD)); savegame_v2.set_integer(Savegame::KEY_ABILITY_LIFT, get_integer(ABILITY_LIFT)); savegame_v2.set_integer(Savegame::KEY_ABILITY_SWIM, get_integer(ABILITY_SWIM)); savegame_v2.set_integer(Savegame::KEY_ABILITY_SWORD_KNOWLEDGE, get_integer(ABILITY_SWORD_KNOWLEDGE)); savegame_v2.set_integer(Savegame::KEY_ABILITY_DETECT_WEAK_WALLS, get_integer(ABILITY_DETECT_WEAK_WALLS)); savegame_v2.set_integer(Savegame::KEY_ABILITY_GET_BACK_FROM_DEATH, get_integer(ABILITY_GET_BACK_FROM_DEATH)); savegame_v2.set_integer(Savegame::KEY_ABILITY_RUN, get_integer(ABILITY_RUN)); // 2. Values that used to be built-in in v1 and become pure data in v2. savegame_v2.set_string("player_name", get_string(PLAYER_NAME)); savegame_v2.set_integer("pause_last_submenu", get_integer(PAUSE_LAST_SUBMENU) + 1); savegame_v2.set_integer("pause_inventory_last_item_index", get_integer(INVENTORY_LAST_ITEM_INDEX) + 1); for (int i = 0; i < 40; i++) { int index = 200 + i * 10; std::ostringstream oss; oss << "dungeon_" << (i + 1); const std::string& dungeon_number = oss.str(); // Dungeon finished (integer replaced by a boolean). if (get_integer(index) > 0) { savegame_v2.set_boolean(dungeon_number + "_finished", true); } // Got the map? (integer replaced by a boolean). ++index; if (get_integer(index) > 0) { savegame_v2.set_boolean(dungeon_number + "_map", true); } // Got the compass? (integer replaced by a boolean). ++index; if (get_integer(index) > 0) { savegame_v2.set_boolean(dungeon_number + "_compass", true); } // Got the big key? (integer replaced by a boolean). ++index; if (get_integer(index) > 0) { savegame_v2.set_boolean(dungeon_number + "_big_key", true); } // Got the boss key? (integer replaced by a boolean). ++index; if (get_integer(index) > 0) { savegame_v2.set_boolean(dungeon_number + "_boss_key", true); } // Number of small keys. ++index; int nb_small_keys = get_integer(index); if (nb_small_keys > 0) { savegame_v2.set_integer(dungeon_number + "_small_keys", nb_small_keys); } } // 3. Custom values. int i; for (i = 32; i < 64; i++) { const std::string& value = get_string(i); if (!value.empty()) { std::ostringstream oss; oss << "s" << i; savegame_v2.set_string(oss.str(), value); } } for (i = 1024; i < 2048; i++) { int value = get_integer(i); if (value != 0) { std::ostringstream oss; oss << "i" << i; savegame_v2.set_integer(oss.str(), value); } } for (i = 0; i < 32768; i++) { bool value = get_boolean(i); if (value) { std::ostringstream oss; oss << "b" << i; savegame_v2.set_boolean(oss.str(), value); } } }