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
+19 -2
View File
@@ -261,8 +261,12 @@ function SaveData.defaultOptions()
-- (the PIKACHU VOL row appears only on Yellow; see Sound.lua)
pikaVol = 7,
musicFilter = 0,
-- logic fast-forward multiplier; audio is unaffected (GameSpeed.lua)
speed = 1,
-- Per-category logic fast-forward multiplier (RFC 0007); audio is
-- unaffected (GameSpeed.lua). Superseded from a single "speed" field --
-- mergeOptions migrates an old save's value into all three below.
speedOverworld = 1,
speedBattle = 1,
speedMenu = 1,
-- port display options (OptionsMenu / hotkeys 2/3/4/5)
colors = "gbc",
tilt = 0,
@@ -339,6 +343,19 @@ function SaveData.mergeOptions(loaded)
for k, v in pairs(loaded) do
opts[k] = v
end
-- RFC 0007 migration: a save from before per-category GAME SPEED still
-- has a single "speed" and none of the three new fields, so seed all
-- three from it -- an existing player's fast-forward preference
-- carries over instead of two of the three categories silently
-- resetting to 1X. "speed" is dropped on the way out (not kept as a
-- stale alias), so a re-save never re-triggers this migration.
if loaded.speed ~= nil and loaded.speedOverworld == nil
and loaded.speedBattle == nil and loaded.speedMenu == nil then
opts.speedOverworld = loaded.speed
opts.speedBattle = loaded.speed
opts.speedMenu = loaded.speed
end
opts.speed = nil
end
return opts
end