mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-12 08:21:02 +02:00
131 lines
5.3 KiB
Lua
131 lines
5.3 KiB
Lua
-- Regression (#518): without a BICYCLE, the Route 16/18 gate guard must
|
|
-- still shove the player one tile aside after refusing them, not leave
|
|
-- them parked against the counter.
|
|
--
|
|
-- pokered's Route16Gate1FGuardScript / Route18Gate1FGuardScript (scripts/
|
|
-- Route16Gate1F.asm, Route18Gate1F.asm) print the refusal text, then
|
|
-- simulate one PAD_RIGHT step (StartSimulatingJoypadStates) and only clear
|
|
-- wJoyIgnore once that step lands. data/scripts/story5.lua's bikeGateGuard
|
|
-- walked the player up to the counter and stopped there -- the ported
|
|
-- refusal text played, but nothing ever moved the player off the doorway.
|
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
if not _G.love then _G.love = require("tests.love_stub") end
|
|
|
|
local Data = require("src.core.Data")
|
|
if not (Data.maps and Data.maps.ROUTE_16_GATE_1F) then Data:load() end
|
|
|
|
local Game = require("src.core.Game")
|
|
local Input = require("src.core.Input")
|
|
local MapLoader = require("src.world.MapLoader")
|
|
local Renderer = require("src.render.Renderer")
|
|
local SaveData = require("src.core.SaveData")
|
|
local StateStack = require("src.core.StateStack")
|
|
local OW = require("src.world.OverworldController")
|
|
local S = require("tests.harness").suite("parity bike gate shove (#518)")
|
|
local check, eq = S.check, S.eq
|
|
|
|
-- ground truth: data/generated/maps.lua ROUTE_16_GATE_1F.objects, the guard
|
|
-- sits at (4,5) behind a solid counter row (row 6); rows 7-10 south of it
|
|
-- are the open waiting area bikeGateGuard's coords cover.
|
|
local r16 = MapLoader.load(Data, "ROUTE_16_GATE_1F")
|
|
check(r16:isWalkableCell(4, 7), "the counter-adjacent stop cell (4,7) is walkable")
|
|
check(r16:isWalkableCell(5, 7), "the shove target (5,7) is walkable")
|
|
check(not r16:isWalkableCell(4, 6), "row 6 (the counter) blocks straight through")
|
|
|
|
Game.data = Data
|
|
Game.input = Input; Input:init()
|
|
Game.renderer = Renderer; Renderer:init()
|
|
Game.stack = StateStack; StateStack:init()
|
|
|
|
-- stub TextBox the way parity_A.lua drives gym leader text: a bare table
|
|
-- capturing (text, onDone) so the test can dismiss it without pagination.
|
|
local realTB = package.loaded["src.render.TextBox"]
|
|
package.loaded["src.render.TextBox"] = {
|
|
new = function(_, text, done) return { text = text, onDone = done } end,
|
|
}
|
|
|
|
local mapScripts = require("data.scripts.init")
|
|
local hooks = mapScripts.get("ROUTE_16_GATE_1F")
|
|
check(hooks and hooks.onStep, "ROUTE_16_GATE_1F has an onStep hook")
|
|
|
|
-- one 16-frame step per fixed update, same as parity_ledge_seam_hop.lua
|
|
local function runFrames(ow, n)
|
|
for _ = 1, n do
|
|
ow:updateScriptMoves()
|
|
ow.player:update()
|
|
end
|
|
end
|
|
|
|
-- dismiss the top stubbed box the way TextBox:update does: pop, then onDone
|
|
local function dismissTop()
|
|
local box = Game.stack:pop()
|
|
if box.onDone then box.onDone() end
|
|
return box
|
|
end
|
|
|
|
local function standNoBike(x, y, facing)
|
|
Game.save = SaveData.newGame()
|
|
Game.save.inventory.BICYCLE = nil
|
|
while Game.stack:top() do Game.stack:pop() end
|
|
Game.stack:push(OW, "ROUTE_16_GATE_1F", x, y, facing or "up")
|
|
local ow = Game.stack:top()
|
|
ow.player.moving = false
|
|
return ow
|
|
end
|
|
|
|
-- --- approaching from three tiles out: walk-up then shove -----------------
|
|
do
|
|
local ow = standNoBike(4, 10)
|
|
local handled = hooks.onStep(Game, ow, ow.player.cellX, ow.player.cellY)
|
|
check(handled, "onStep claims the coordinate trigger without a BICYCLE")
|
|
|
|
local box1 = Game.stack:top()
|
|
check(box1 ~= nil, "the wait-up refusal text box opened")
|
|
check(box1.text:find("Wait up", 1, true) ~= nil
|
|
or box1.text:find("Excuse me", 1, true) ~= nil,
|
|
"first box is the guard's stop line")
|
|
dismissTop()
|
|
|
|
local box2 = Game.stack:top()
|
|
check(box2 ~= nil, "the second (explanation) box opened")
|
|
eq(box2.text, Data.text._Route16Gate1FGuardNoPedestriansAllowedText,
|
|
"second box is the guard's no-pedestrians explanation, verbatim")
|
|
dismissTop()
|
|
|
|
check(#ow.scriptMoves > 0 or ow.player.moving,
|
|
"closing the explanation queues the walk-up-then-shove movement")
|
|
runFrames(ow, 200)
|
|
check(not ow.player.moving, "the scripted movement has settled")
|
|
eq(#ow.scriptMoves, 0, "no scripted move is left hanging")
|
|
eq(ow.player.cellX, 5, "the player ends one tile right of the counter (#518 shove)")
|
|
eq(ow.player.cellY, 7, "the player ends on the counter-adjacent row, not further")
|
|
end
|
|
|
|
-- --- already standing at the counter-adjacent row: shove with no walk-up --
|
|
do
|
|
local ow = standNoBike(4, 7)
|
|
local handled = hooks.onStep(Game, ow, ow.player.cellX, ow.player.cellY)
|
|
check(handled, "onStep still claims it when already adjacent to the counter")
|
|
dismissTop() -- wait-up
|
|
dismissTop() -- explanation
|
|
runFrames(ow, 200)
|
|
check(not ow.player.moving, "the shove-only movement has settled")
|
|
eq(#ow.scriptMoves, 0, "no scripted move is left hanging")
|
|
eq(ow.player.cellX, 5, "still ends one tile right (#518 shove with dist=0)")
|
|
eq(ow.player.cellY, 7, "y is unchanged since there was no walk-up needed")
|
|
end
|
|
|
|
-- --- control: a BICYCLE in the bag lets the trigger pass through untouched
|
|
do
|
|
local ow = standNoBike(4, 10)
|
|
ow.player.moving = false
|
|
Game.save.inventory.BICYCLE = true
|
|
local handled = hooks.onStep(Game, ow, ow.player.cellX, ow.player.cellY)
|
|
check(not handled, "with a BICYCLE, onStep does not intercept the step")
|
|
check(Game.stack:top() == ow, "no text box opened when riding a BICYCLE")
|
|
end
|
|
|
|
package.loaded["src.render.TextBox"] = realTB
|
|
|
|
S.finish()
|