# Lua State Persistence / Save Game System ## Overview The Wherigo Player can save and restore the Lua state to preserve game progress. ## How It Works ### Automatic Save Locations Game saves are automatically stored at: - **macOS**: `~/Library/Application Support/wxWherigo/.save` - **Windows**: `%APPDATA%\wxWherigo\.save` - **Linux**: `~/.wxWherigo/.save` ### What is Saved? Persistence saves: - ✅ **All Wherigo Objects**: ZCartridge, Zone, ZItem, ZCharacter, ZTask, ZTimer, ZInput, ZMedia - ✅ **Object Properties**: Name, Description, Active, Visible, Container, etc. - ✅ **Global Variables**: All simple variables (Strings, Numbers, Booleans) - ✅ **Player Object**: Position, inventory, etc. - ✅ **Nested Tables**: Recursive serialization (up to depth 10) ### What is NOT Saved? - ❌ **Functions**: Lua functions cannot be serialized - ❌ **Userdata**: C objects remain in original state - ❌ **Threads/Coroutines**: Saved as `nil` - ❌ **Metatables**: Not persisted ## Usage in Code ### Save Game State ```cpp // Automatic path (recommended) wxGetApp().saveGameState(""); // Custom path wxGetApp().saveGameState("/path/to/save.lua"); ``` ### Load Game State ```cpp // Automatic path wxGetApp().loadGameState(""); // Custom path wxGetApp().loadGameState("/path/to/save.lua"); ``` ### In-Game - **Menu → Save Game** (Ctrl+S) - **Menu → Load Game** (Ctrl+L) ## Save File Format The save file is a readable Lua file: ```lua -- Wherigo Save State return { ["Player"] = { ["ClassName"] = "Player", ["Name"] = "Player", ["ObjectLocation"] = { ["latitude"] = 51.5074, ["longitude"] = -0.1278, ["altitude"] = 0 } }, ["zitemLetter"] = { ["ClassName"] = "ZItem", ["Name"] = "Letter from Professor", ["Active"] = true, ["Visible"] = true, ["Container"] = }, -- ... more objects } ``` ## Technical Details ### Serialization The implementation uses: 1. **Recursive traversal** of Lua tables 2. **Type detection** for different Lua types 3. **Escaping** of special characters in strings 4. **Reference handling** by Lua itself when loading ### Deserialization 1. Save file is loaded as Lua code (`luaL_loadstring`) 2. Execution returns a table (`lua_pcall`) 3. Table entries are restored as globals 4. UI is updated via `notifyStateChanged()` ## Performance - **Saving**: ~10-100ms for typical cartridges - **Loading**: ~20-200ms (including Lua parsing) - **File size**: ~10-500KB (depends on cartridge complexity) ## Extensions ### Custom Filters ```cpp // Save only specific globals std::vector myGlobals = {"Player", "zitemKey", "ztaskMain"}; wherigo::LuaPersistence::saveGlobals(L, "custom.save", myGlobals); ``` ### Auto-Save on Exit ```cpp // In cGame::OnClose() wxGetApp().saveGameState(""); // Auto-save ``` ### Multiple Save Slots ```cpp std::string slot1 = wxGetApp().getAutoSavePath() + ".slot1"; std::string slot2 = wxGetApp().getAutoSavePath() + ".slot2"; std::string slot3 = wxGetApp().getAutoSavePath() + ".slot3"; ``` ## Known Limitations 1. **Function Callbacks** are not saved (OnClick, OnEnter, etc.) - These remain defined in cartridge code 2. **Circular References** are cut off during recursion - Max depth: 10 levels 3. **Metatables** are lost - May need to be reset after loading 4. **Timer Status** is saved, but `Remaining` may need recalculation ## Debugging Enable logging to trace save/load: ```cpp wxLogDebug("Saved %zu globals to %s", globals.size(), filePath); wxLogDebug("Restored %d globals from %s", count, filePath); ``` ## Future Enhancements Possible improvements: - [ ] Compression of save files (zlib) - [ ] Encryption (prevent cheating) - [ ] Delta saves (only save changes) - [ ] Cloud sync integration - [ ] Automatic backups (keep 3 most recent saves)