Per-category GAME SPEED: overworld/battle/menu + core.logic_speed hook (RFC 0007)

GameSpeed is a single fast-forward multiplier applied uniformly to the
whole logic clock -- overworld walking, menu navigation and battle turns
all scale together. A player who wants 4X battles but 1X overworld (so a
cutscene or NPC dialogue doesn't blur past) has no way to get both.

Splits save.options.speed into speedOverworld/speedBattle/speedMenu, each
cycling independently, with an automatic migration so an existing save's
speed choice carries over. Game.speedCategoryInStack resolves which
category is active by walking the state stack (the same idiom
wideBattleInStack/fillScaleInStack already use), so a menu opened mid-
battle inherits battle speed rather than resetting to whatever "menu"
defaults to. Adds a new core.logic_speed hook so a mod can read or
override the resolved multiplier for the current frame regardless of
which category produced it, sitting after the link-play and run-argument
overrides so neither is a seam a mod can defeat.

RFC 0007 status: Proposed.
This commit is contained in:
david
2026-08-09 20:13:21 -07:00
parent 943ba5dcbf
commit 3c71afb9fa
14 changed files with 602 additions and 34 deletions
+15
View File
@@ -51,4 +51,19 @@ function GameSpeed.cycle(v, dir)
return levels[nextIdx]
end
-- Per-category speed (RFC 0007): overworld walking, battle turns and menu
-- navigation each cycle their own multiplier instead of one global "speed"
-- value. This list is the single source of truth for which categories
-- exist and the order the Options rows/save.options keys follow;
-- Game.lua's stack-walk (Game.speedCategoryInStack) decides WHICH category
-- is active on a given frame, this module only knows the category names.
GameSpeed.CATEGORIES = { "overworld", "battle", "menu" }
-- the save.options field name a category's multiplier lives under, e.g.
-- "overworld" -> "speedOverworld". Centralized so Game.lua, OptionsMenu.lua,
-- LauncherSettings.lua and the SaveData migration never hand-spell the key.
function GameSpeed.optionKey(category)
return "speed" .. category:sub(1, 1):upper() .. category:sub(2)
end
return GameSpeed