Autosave used SDL_TICKS_PASSED in diablo.cpp, but that macro is not available in SDL3, which broke the Linux SDL3 CI build.
Switch the autosave timer state to the SDL_GetTicks return type and compare deadlines through a small local helper. The helper keeps SDL_TICKS_PASSED semantics on SDL1/SDL2 while using a direct comparison on SDL3, so this fixes the SDL3 compile error without broad timer refactoring in other code paths.
Split the save flow into explicit manual and auto save kinds and return a SaveResult instead of overloading gbValidSaveFile as the outcome of the last save attempt.
Redesign backup handling so the persistent backup slot represents the last manual save, while autosave uses its own temporary restore copy and no longer overwrites the manual backup.
Manual save UI now reports failure separately from preserved-save recovery, and autosave only reports success when the new save actually succeeds.
Sample the timestamp once after SaveGame and use it to set cooldown and next-timer values to avoid inconsistent timings from multiple SDL_GetTicks calls. Calculate the saved-game message duration based on elapsed time and clamp it to a minimum of 500ms so the confirmation is visible. Also change GetSaveGameMenuLabel to return std::string_view and return the saved label directly instead of a c_str(), simplifying lifetime handling.
- Add RequestAutoSave() wrapper function with centralized filter logic
- Add HasPendingAutoSave() helper for better code readability
- Replace direct QueueAutoSave() calls with RequestAutoSave()
- Consolidate multiplayer and enabled checks in one place
- Improve code maintainability and separation of concerns
Implement an autosave subsystem and safer save handling, plus related UI and hooks.
- Add autosave state and logic (diablo.cpp): periodic timer, pending queue, priorities (Timer, TownEntry, BossKill, UniquePickup), cooldowns, combat cooldowns, enemy proximity safety checks, and helper APIs (QueueAutoSave, AttemptAutoSave, IsAutoSaveSafe, etc.).
- Integrate autosave triggers: queue on town entry (loadsave), unique item pickup (inv.cpp), boss kills (monster.cpp), and mark combat activity from player actions and hits (player.cpp).
- Add gameplay options to enable autosave and set interval (options.h/.cpp) and display countdown/ready label in the game menu (gamemenu.cpp/gmenu.cpp). Menu text retrieval updated to show remaining seconds or "ready".
- Make SaveGame robust (loadsave.cpp): write hero and stash via new pfile_write_hero_with_backup() and pfile_write_stash_with_backup() that create backups and restore on failure. Add utilities to copy/restore unpacked save directories safely (pfile.cpp) and adjust stash path handling signature.
- Minor fixes and cleanups: restrict mouse-motion handling to KeyboardAndMouse path, small reordering in player sprite width switch, and a few safety/formatting tweaks.
Autosave only runs in single-player and when IsAutoSaveSafe() conditions are met. Backup save logic attempts to preserve the previous save on failure.
Also renames lua/lua.hpp to lua/lua_global.hpp.
The previous name broke version auto-detection in sol2, which involves
calling `__has_include(<lua/lua.hpp>)`.
Gets rid of `orig_palette`, we now always have only 2 palettes:
1. `logical_palette`
This palette has color cycling / swapping applied but no global
effects such as brightness / fade-in.
2. `system_palette`
This palette is the actual palette used for rendering.
It is usually `logical_palette` with the global brightness setting
and fade-in/out applied.
Additionally, we now keep the k-d tree around and use it to
update single colors.
The colors that are color-cycled / swapped are never included
in the k-d tree, so the tree does not need updating on color
cycles/swaps.
In C++, globals initialization order accross translation units is not
defined. Accessing a global via a function ensures that it is initialized.
This will be needed for #7638, which will statically initialize change
handlers after the Options object has been initialized.