local SAVE_GAME_BANK = 6 local SAVE_GAME_MAGIC_VALUE_ADDRESS = 0 local SAVE_GAME_MAGIC_VALUE = 0xCA local SAVE_GAME_CURRENT_SCREEN_ADDRESS = 6 -- Define a consistent order for screens for save/load operations local SCREEN_ID_ORDER = {"home", "toilet", "walking_to_office", "office", "walking_to_home"} --- Gets initial data for Context. -- @return table Initial context data. local function get_initial_data() return { active_window = WINDOW_SPLASH, intro = { y = Config.screen.height, speed = 0.5, text = [[Norman Reds’ everyday life seems ordinary: work, meetings, coffee, and endless notifications. But beneath him, or around him — something is constantly building, and it soon becomes clear that there is more going on than meets the eye.]] }, splash_timer = Config.timing.splash_duration, popup = { show = false, content = {} }, player = { sprite_id = Config.player.sprite_id }, ground = { x = 0, y = Config.screen.height, w = Config.screen.width, h = 8 }, menu_items = {}, selected_menu_item = 1, game_in_progress = false, minigame_ddr = Minigame.get_default_ddr(), minigame_button_mash = Minigame.get_default_button_mash(), minigame_rhythm = Minigame.get_default_rhythm(), meters = Meter.get_initial(), game = { current_screen = "home", current_situation = nil, } } end --- Global game context. Context = {} --- Resets game context to initial state. local function reset_context_to_initial_state() local initial_data = get_initial_data() for k in pairs(Context) do if type(Context[k]) ~= "function" then Context[k] = nil end end for k, v in pairs(initial_data) do Context[k] = v end end --- Starts a new game. function Context.new_game() reset_context_to_initial_state() Context.game_in_progress = true MenuWindow.refresh_menu_items() Screen.get_by_id(Context.game.current_screen).init() end --- Saves the current game state. function Context.save_game() if not Context.game_in_progress then return end mset(SAVE_GAME_MAGIC_VALUE, SAVE_GAME_MAGIC_VALUE_ADDRESS, SAVE_GAME_BANK) local screen_index_to_save for i, screen_id in ipairs(SCREEN_ID_ORDER) do if screen_id == Context.game.current_screen then screen_index_to_save = i break end end if screen_index_to_save then mset(screen_index_to_save, SAVE_GAME_CURRENT_SCREEN_ADDRESS, SAVE_GAME_BANK) else trace("Error: Current screen ID '" .. Context.game.current_screen .. "' not found in SCREEN_ID_ORDER for saving.") end end --- Loads a saved game state. function Context.load_game() if mget(SAVE_GAME_MAGIC_VALUE_ADDRESS, SAVE_GAME_BANK) ~= SAVE_GAME_MAGIC_VALUE then Context.new_game() return end reset_context_to_initial_state() local loaded_screen_index = mget(SAVE_GAME_CURRENT_SCREEN_ADDRESS, SAVE_GAME_BANK) if loaded_screen_index and SCREEN_ID_ORDER[loaded_screen_index] then Context.game.current_screen = SCREEN_ID_ORDER[loaded_screen_index] else trace("Error: Invalid screen index loaded: " .. tostring(loaded_screen_index) .. ". Defaulting to new game state.") Context.new_game() return end Context.game_in_progress = true MenuWindow.refresh_menu_items() Screen.get_by_id(Context.game.current_screen).init() end