mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-12 08:21:02 +02:00
142 lines
6.0 KiB
Lua
142 lines
6.0 KiB
Lua
-- Driver: forced-step shoves use the wrong primitive (issue #151).
|
|
--
|
|
-- Two related defects, both a scripted "push the player back one step" that
|
|
-- reaches for the wrong movement primitive:
|
|
--
|
|
-- A MUSEUM_1F ticket rope (data/scripts/story2.lua museumClerk onDecline):
|
|
-- declining the Y50 ticket must shove the player one cell SOUTH off the
|
|
-- exhibit rope (scripts/Museum1F.asm) -- the player crossed the rope
|
|
-- heading NORTH, so the shove is south. The bug shoved "right" onto the
|
|
-- counter tile (11,4)=tile 23, non-walkable, matching the report's "moved
|
|
-- onto the table". Correct landing is (10,5)=tile 1 (walkable floor).
|
|
--
|
|
-- B VIRIDIAN_CITY gym lock (data/scripts/story5.lua stepGate/viridianGym-
|
|
-- Lock): the tile below the Gym door (32,8)=tile 44 is a DOWN-ledge
|
|
-- (44 -> 55, data/tilesets/ledge_tiles.asm); Gen1 shoves the player with a
|
|
-- SIMULATED JOYPAD down-press that runs the normal step pipeline including
|
|
-- HandleLedges (engine/overworld/ledges.asm), so the shove HOPS the ledge
|
|
-- and lands on (32,10)=tile 57. The bug used a raw scriptMove that
|
|
-- ignores ledges, planting the player standing on the ledge tile (32,9).
|
|
--
|
|
-- Both cases assert the CORRECT Gen1 outcome, so this FAILS on the bug and
|
|
-- PASSES once the shove primitives are fixed.
|
|
--
|
|
-- Run:
|
|
-- POKEPORT_DRIVER=tests/drivers/decline_push_bug151_test.lua \
|
|
-- POKEPORT_IDENTITY=bug151 POKEPORT_TOUCH=0 love .
|
|
return function(game)
|
|
local U = dofile("tests/drivers/util.lua")
|
|
local shotDir = os.getenv("POKEPORT_SHOTDIR") or "."
|
|
local function shot(name) U.shot(game, shotDir .. "/" .. name) end
|
|
local TextBox = require("src.render.TextBox")
|
|
local ChoiceBox = require("src.ui.ChoiceBox")
|
|
|
|
-- a party + starter flag so the overworld is fully usable
|
|
game.save.flags = game.save.flags or {}
|
|
game.save.flags.EVENT_GOT_STARTER = true
|
|
local Pokemon = require("src.pokemon.Pokemon")
|
|
if #game.save.party == 0 then
|
|
table.insert(game.save.party, Pokemon.new(game.data, "CHARMANDER", 5))
|
|
end
|
|
|
|
local fails = 0
|
|
local function expect(cond, ...)
|
|
if not cond then fails = fails + 1 end
|
|
U.log(cond and "PASS" or "FAIL", ...)
|
|
end
|
|
|
|
-- Advance dialog until control returns to the overworld: tap A through
|
|
-- TextBoxes, tap B through a ChoiceBox (B always declines -- ChoiceBox:update
|
|
-- calls onChoose(false) on B). Bounded so a stuck box can't hang the run.
|
|
local function driveDialog(maxIters)
|
|
for _ = 1, (maxIters or 240) do
|
|
local top = game.stack:top()
|
|
if top == game.overworld then return true end
|
|
if getmetatable(top) == ChoiceBox then
|
|
U.tap(game, "b")
|
|
elseif getmetatable(top) == TextBox then
|
|
U.tap(game, "a")
|
|
else
|
|
-- unknown state: nudge with A so we never wedge
|
|
U.tap(game, "a")
|
|
end
|
|
U.wait(2)
|
|
end
|
|
return game.stack:top() == game.overworld
|
|
end
|
|
|
|
-- Drain queued scriptMoves + any in-flight step, sampling p.hopFrames each
|
|
-- frame (a hop arc is set only by checkLedgeHop). Returns whether a hop was
|
|
-- ever seen while draining.
|
|
local function drainMoves(p, maxFrames)
|
|
local hopSeen = (p.hopFrames or 0) > 0
|
|
for _ = 1, (maxFrames or 180) do
|
|
local ow = game.overworld
|
|
local pending = ow.scriptMoves and #ow.scriptMoves > 0
|
|
if not pending and not p.moving and (p.hopFrames or 0) == 0 then break end
|
|
if (p.hopFrames or 0) > 0 then hopSeen = true end
|
|
U.wait(1)
|
|
end
|
|
return hopSeen
|
|
end
|
|
|
|
-- ------------------------------------------------------------------
|
|
-- Case A: MUSEUM_1F ticket-rope decline must shove SOUTH, not RIGHT.
|
|
-- ------------------------------------------------------------------
|
|
do
|
|
game.save.flags.EVENT_BOUGHT_MUSEUM_TICKET = false
|
|
game.save.money = 1000 -- enough to buy, so declining is a real NO choice
|
|
U.teleport(game, "MUSEUM_1F", 10, 5, "up")
|
|
U.wait(6)
|
|
local p = game.overworld.player
|
|
shot("museum_decline_before.png")
|
|
-- step north onto the rope cell (10,4); the clerk stops us there
|
|
U.hold(game, "up", 24)
|
|
-- clerk dialog: advance the pitch, decline the YES/NO, clear "Come again!"
|
|
driveDialog(240)
|
|
drainMoves(p, 120)
|
|
shot("museum_decline_after.png")
|
|
expect(p.cellX == 10 and p.cellY == 5,
|
|
"A: declining shoves the player SOUTH to (10,5), got:", p.cellX, p.cellY)
|
|
end
|
|
|
|
-- ------------------------------------------------------------------
|
|
-- Case B: VIRIDIAN_CITY gym lock shove must HOP the down-ledge.
|
|
-- ------------------------------------------------------------------
|
|
do
|
|
-- fresh badge state: no non-Earth badges, so the gym stays locked
|
|
game.save.inventory = game.save.inventory or {}
|
|
for _, b in ipairs({ "BOULDERBADGE", "CASCADEBADGE", "THUNDERBADGE",
|
|
"RAINBOWBADGE", "SOULBADGE", "MARSHBADGE",
|
|
"VOLCANOBADGE" }) do
|
|
game.save.inventory[b] = nil
|
|
end
|
|
U.teleport(game, "VIRIDIAN_CITY", 31, 8, "right")
|
|
U.wait(6)
|
|
local p = game.overworld.player
|
|
shot("viridian_gymlock_before.png")
|
|
-- step east onto (32,8) directly below the locked Gym door
|
|
U.hold(game, "right", 24)
|
|
-- the "GYM's doors are locked..." box appears; clearing it fires the shove
|
|
local ow = game.overworld
|
|
local hopSeen = false
|
|
for _ = 1, 240 do
|
|
local top = game.stack:top()
|
|
if top == game.overworld then break end
|
|
if getmetatable(top) == TextBox then U.tap(game, "a") else U.tap(game, "a") end
|
|
if (p.hopFrames or 0) > 0 then hopSeen = true end
|
|
U.wait(2)
|
|
if (p.hopFrames or 0) > 0 then hopSeen = true end
|
|
end
|
|
if drainMoves(p, 180) then hopSeen = true end
|
|
shot("viridian_gymlock_after.png")
|
|
expect(hopSeen, "B: the gym-lock shove HOPS the ledge (hop arc seen)")
|
|
expect(p.cellX == 32 and p.cellY == 10,
|
|
"B: landed south of the ledge at (32,10), got:", p.cellX, p.cellY)
|
|
end
|
|
|
|
if fails > 0 then error(fails .. " check(s) failed") end
|
|
U.log("all checks passed -- #151 shoves are Gen1-correct "
|
|
.. "(museum decline goes south, Viridian gym lock hops the ledge)")
|
|
end
|