mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 13:33:27 -04:00
203 lines
7.3 KiB
Lua
203 lines
7.3 KiB
Lua
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
if not _G.love then _G.love = require("tests.love_stub") end
|
|
|
|
local T = require("tests.harness")
|
|
local check, eq = T.check, T.eq
|
|
|
|
local FixedStep = require("src.core.FixedStep")
|
|
local GameSpeed = require("src.core.GameSpeed")
|
|
local Hooks = require("src.mods.Hooks")
|
|
local Runtime = require("src.mods.Runtime")
|
|
local Game = require("src.core.Game")
|
|
local Game2 = require("src.core.Game2")
|
|
local Game3 = require("src.core.Game3")
|
|
|
|
local function stack(...) return { states = { ... } } end
|
|
local unpack = table.unpack or unpack
|
|
|
|
local battle = { isBattle = true }
|
|
local overworld = { isOverworld = true }
|
|
|
|
local function gen1(states, opts)
|
|
return setmetatable({
|
|
save = { options = opts or { speedOverworld = 200, speedBattle = 200, speedMenu = 200 } },
|
|
stack = stack(unpack(states)),
|
|
writeOptions = function() end,
|
|
}, { __index = Game })
|
|
end
|
|
|
|
do
|
|
local g = gen1({ overworld })
|
|
eq(g:logicSpeed(), 200, "gen1 overworld runs the saved 200X")
|
|
check(not g:speedLocked(), "gen1 overworld is not locked")
|
|
g = gen1({ overworld, battle })
|
|
eq(g:logicSpeed(), 200, "gen1 local battle runs BATTLE SPEED")
|
|
g.linkSession = true
|
|
eq(g:logicSpeed(), 1, "gen1 link battle is 1X at speedBattle 200")
|
|
g.speedOverride = 200
|
|
eq(g:logicSpeed(), 1, "gen1 link battle ignores speedOverride (--speed, skin FF hold)")
|
|
local bus = Hooks.new()
|
|
local saved = Runtime.hooks
|
|
Runtime.hooks = bus
|
|
local ran = false
|
|
local unsub = bus:wrap("core.logic_speed", function() ran = true; return 200 end)
|
|
g.speedOverride = nil
|
|
eq(g:logicSpeed(), 1, "gen1 link battle ignores a core.logic_speed hook returning 200")
|
|
check(not ran, "the hook is never called while locked")
|
|
local ow = gen1({ overworld })
|
|
eq(ow:logicSpeed(), 200, "outside battle the hook still runs")
|
|
check(ran, "...and was called")
|
|
unsub()
|
|
Runtime.hooks = saved
|
|
end
|
|
|
|
do
|
|
GameSpeed.setAllowed({ 2, 4 })
|
|
local g = gen1({ overworld, battle })
|
|
g.linkSession = true
|
|
eq(g:logicSpeed(), 1, "a cart ladder without 1 still locks to a literal 1")
|
|
eq(gen1({ overworld }, { speedOverworld = 4 }):logicSpeed(), 4,
|
|
"and outside battle the ladder applies")
|
|
GameSpeed.setAllowed(nil)
|
|
end
|
|
|
|
do
|
|
local g = gen1({ overworld, battle },
|
|
{ speedOverworld = 1, speedBattle = 1, speedMenu = 1 })
|
|
g.linkSession = true
|
|
g:_cycleSpeed(1)
|
|
g:_cycleSpeed(-1)
|
|
g:_cycleSpeed(1)
|
|
eq(g.save.options.speedBattle, 1, "gen1 speed presses in a link battle leave speedBattle")
|
|
eq(g.save.options.speedOverworld, 1, "and speedOverworld")
|
|
g:touchSkinHotkey("fast_forward_toggle", true)
|
|
eq(g.save.options.speedBattle, 1, "gen1 skin FF toggle in a link battle is ignored")
|
|
g:touchSkinHotkey("fast_forward_hold", true)
|
|
eq(g:logicSpeed(), 1, "gen1 skin FF hold in a link battle stays 1X")
|
|
g:touchSkinHotkey("fast_forward_hold", false)
|
|
eq(g.speedOverride, nil, "and releasing restores the pre-hold override")
|
|
g.linkSession = nil
|
|
g:_cycleSpeed(1)
|
|
eq(g.save.options.speedBattle, 2, "gen1 speed press in a local battle cycles speedBattle")
|
|
end
|
|
|
|
do
|
|
local g = gen1({ overworld })
|
|
g.linkSession = true
|
|
eq(g:logicSpeed(), 1, "gen1 link session is 1X")
|
|
g.linkSession = nil
|
|
g.linkNet = { closed = false }
|
|
eq(g:logicSpeed(), 1, "gen1 open linkNet (arena, tournament, spectate) is 1X")
|
|
end
|
|
|
|
local function gen2(fields)
|
|
fields.persistOptions = fields.persistOptions or function() end
|
|
return setmetatable(fields, { __index = Game2 })
|
|
end
|
|
|
|
do
|
|
eq(gen2({ options = { speed = 200 }, stack = stack({}) }):logicSpeed(), 200,
|
|
"gen2 overworld runs GAME SPEED")
|
|
eq(gen2({ options = { speed = 200 }, stack = stack({}, battle) }):logicSpeed(), 200,
|
|
"gen2 local battle runs GAME SPEED")
|
|
eq(gen2({ options = { speed = 200 }, speedOverride = 200, linkNet = { closed = false },
|
|
stack = stack({}, battle) }):logicSpeed(), 1,
|
|
"gen2 link battle ignores speedOverride")
|
|
eq(gen2({ options = { speed = 200 }, linkNet = { closed = false } }):logicSpeed(), 1,
|
|
"gen2 online arena / LinkBattle2 linkNet is 1X")
|
|
eq(gen2({ options = { speed = 200 }, linkSession = true }):logicSpeed(), 1,
|
|
"gen2 tournament / spectate linkSession is 1X")
|
|
local g = gen2({ options = { speed = 1 }, stack = stack({}, battle) })
|
|
g:_cycleSpeed(1)
|
|
eq(g.options.speed, 2, "gen2 pad speed press in a local battle cycles")
|
|
g.stack = stack({})
|
|
g.linkNet = { closed = false }
|
|
g:_cycleSpeed(1)
|
|
eq(g.options.speed, 2, "gen2 pad speed press over a link is ignored")
|
|
end
|
|
|
|
local battleActive, battleLink = false, false
|
|
package.loaded["src.core.game3.battle"] = {
|
|
isActive = function() return battleActive end,
|
|
getState = function() return { link = battleLink } end,
|
|
}
|
|
|
|
local function gen3()
|
|
return setmetatable({
|
|
phase = "field",
|
|
options = { speedOverworld = 200, speedBattle = 200, speedMenu = 200 },
|
|
writeOptions = function() end,
|
|
}, { __index = Game3 })
|
|
end
|
|
|
|
do
|
|
local g = gen3()
|
|
eq(g:logicSpeed(), 200, "gen3 field runs OVERWORLD SPEED")
|
|
battleActive = true
|
|
eq(g:logicSpeed(), 200, "gen3 local battle runs BATTLE SPEED")
|
|
battleLink = true
|
|
eq(g:logicSpeed(), 1, "gen3 link battle is 1X")
|
|
g.speedOverride = 200
|
|
eq(g:logicSpeed(), 1, "gen3 link battle ignores speedOverride")
|
|
g.speedOverride = nil
|
|
g:_cycleSpeed(1)
|
|
eq(g.options.speedBattle, 200, "gen3 speed press in a link battle is ignored")
|
|
battleActive, battleLink = false, false
|
|
package.loaded["src.core.game3.link.union_room"] = { isActive = function() return true end }
|
|
eq(g:logicSpeed(), 1, "gen3 Union Room is 1X")
|
|
package.loaded["src.core.game3.link.union_room"] = nil
|
|
package.loaded["src.core.game3.map"] = { current = "FR_UNION_ROOM" }
|
|
eq(g:logicSpeed(), 1, "gen3 Union Room map is 1X")
|
|
package.loaded["src.core.game3.map"] = nil
|
|
eq(g:logicSpeed(), 200, "and the field is back to 200X")
|
|
end
|
|
|
|
local function runFrame(g, lockAt)
|
|
local steps = 0
|
|
local savedInit = { accum = FixedStep.accum, callback = FixedStep.callback }
|
|
FixedStep.clock = function() return 0 end
|
|
FixedStep:init(function()
|
|
steps = steps + 1
|
|
if steps == lockAt then
|
|
battleActive, battleLink = true, true
|
|
g.linkSession = true
|
|
g.stack = stack(overworld, battle)
|
|
end
|
|
g:_speedLockEdge()
|
|
end)
|
|
local speed = g:logicSpeed()
|
|
g._frameSpeed = speed
|
|
FixedStep.maxAccum = FixedStep.catchupLimit(speed, FixedStep.STEP)
|
|
FixedStep:update(FixedStep.STEP, speed)
|
|
FixedStep.clock = nil
|
|
FixedStep.accum, FixedStep.callback = savedInit.accum, savedInit.callback
|
|
return steps, speed
|
|
end
|
|
|
|
do
|
|
battleActive = false
|
|
local g = gen3()
|
|
local steps, speed = runFrame(g, 3)
|
|
eq(speed, 200, "the frame started unlocked at 200X")
|
|
eq(steps, 3, "gen3: a link battle starting mid-frame ends the frame on that step")
|
|
battleActive, battleLink = false, false
|
|
|
|
local g1 = gen1({ overworld })
|
|
steps = runFrame(g1, 5)
|
|
eq(steps, 5, "gen1: a link battle push mid-frame ends the frame on that step")
|
|
eq(g1:logicSpeed(), 1, "and the next frame samples 1X")
|
|
|
|
local g2 = gen2({ options = { speed = 200 }, stack = stack({}) })
|
|
steps = runFrame(g2, 2)
|
|
eq(steps, 2, "gen2: a link battle push mid-frame ends the frame on that step")
|
|
battleActive, battleLink = false, false
|
|
|
|
local plain = gen1({ overworld })
|
|
steps = runFrame(plain, -1)
|
|
check(steps > 100, "without a lock flip the 200X frame runs its steps")
|
|
end
|
|
|
|
package.loaded["src.core.game3.battle"] = nil
|
|
|
|
T.finish("speed lock")
|