Add 3X game speed and R2/L2 shoulder button speed hotkeys

Add 3X as a speed option between 2X and 4X in GameSpeed.LEVELS (#677).

Add controller hotkeys: rightshoulder (R2) cycles speed up through the
level list, leftshoulder (L2) cycles speed down. Keyboard equivalent
is hotkey 1 (cycles up). All hotkeys are gated during transitions,
scripted cutscenes, and link play (same guards as the color hotkey
at key 2).

The _cycleSpeed helper wraps the save-options update with the same
busy/overworld guard used by the existing color-cycle hotkey.

Fixes #677
This commit is contained in:
Shane McGovern
2026-08-02 23:10:06 +01:00
parent 4e7eda65ed
commit 3f88d1c49a
2 changed files with 33 additions and 1 deletions
+32
View File
@@ -509,6 +509,24 @@ function Game:wheelmoved(_, dy)
end
end
function Game:_cycleSpeed(dir)
if not (self.save and self.save.options) then return end
local busy
local ow = self.overworld
if ow then
local top = self.stack:top()
busy = ow.transitioning
or (top == ow and (
(ow.runner and ow.runner.isRunning and ow.runner:isRunning())
or (ow.scriptMoves and #ow.scriptMoves > 0)
or ow.engaging or ow.emote))
end
if busy then return end
local GameSpeed = require("src.core.GameSpeed")
self.save.options.speed = GameSpeed.cycle(self.save.options.speed, dir)
self:writeOptions()
end
function Game:keypressed(key)
if self.stack and self.stack:top() and self.stack:top().onKeyPressed then
self.stack:top():onKeyPressed(key)
@@ -546,6 +564,11 @@ function Game:keypressed(key)
elseif key == "=" then
self:zoomStep(1)
return
elseif key == "1" then
-- cycle GAME SPEED (0.25X → 200X, logic only; audio unaffected);
-- R2/L2 on gamepad do the same (see gamepadpressed)
self:_cycleSpeed(1)
return
elseif key == "2" then
-- cycle COLORS (GBC / OG / OG INV / GBC INV / CLASSIC); the pack change
-- forces Game.overworld:reloadMap, which rebuilds the live NPC array, so
@@ -626,6 +649,15 @@ function Game:gamepadpressed(joystick, button)
-- a controller is being used: the touch overlay steps aside until the
-- next screen touch (mobile only; a no-op elsewhere)
TouchControls:noteGamepad()
-- shoulder buttons cycle GAME SPEED (R2/rightshoulder = faster,
-- L2/leftshoulder = slower; same as keyboard hotkey 1)
if button == "rightshoulder" then
self:_cycleSpeed(1)
return
elseif button == "leftshoulder" then
self:_cycleSpeed(-1)
return
end
-- BindingsMenu's pad capture rides the same top-state routing as keys
local top = self.stack and self.stack:top()
if top and top.onGamepadPressed then
+1 -1
View File
@@ -18,7 +18,7 @@ local GameSpeed = {}
-- attempt is long enough that the iteration loop, not the engine, is the
-- bottleneck. Vsync caps how much a real frame can do, so past 10X the
-- multiplier is increasingly a ceiling rather than a rate.
GameSpeed.LEVELS = { 1, 2, 4, 10, 20, 30, 50, 75, 100,200 }
GameSpeed.LEVELS = { 1, 2, 3, 4, 10, 20, 30, 50, 75, 100, 200 }
GameSpeed.DEFAULT = 1
function GameSpeed.levelLabel(v)