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
@@ -46,7 +46,9 @@ return function(game)
os.getenv("POKEPORT_DRIVER") == nil)
check("no fast-forward multiplier is set",
(tonumber(os.getenv("POKEPORT_SPEED")) or 1) == 1
and (game.save.options.speed or 1) == 1)
and (game.save.options.speedOverworld or 1) == 1
and (game.save.options.speedBattle or 1) == 1
and (game.save.options.speedMenu or 1) == 1)
check("a window is up to watch (this is a visual call)",
love.window ~= nil and love.window.isOpen and love.window.isOpen())
U.log("MAX FPS reads", FrameCap.label(game.save.options.fpsCap),