mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-12 00:10:56 +02:00
124 lines
5.0 KiB
Lua
124 lines
5.0 KiB
Lua
-- Manual check that the exit mat you warp in on answers the first press of
|
|
-- DOWN (#378). The house door outside is a door tile, so it leaves
|
|
-- BIT_STANDING_ON_WARP set and ClearVariablesOnEnterMap never clears it
|
|
-- (home/overworld.asm:247, engine/overworld/player_state.asm:190).
|
|
-- POKEPORT_DRIVER=tests/drivers/exit_mat_bug378_test.lua POKEPORT_IDENTITY=bug378 POKEPORT_TOUCH=0 POKEPORT_VERSION=red love .
|
|
-- Do not set POKEPORT_SPEED: fast-forward desynchronizes the audio clock.
|
|
return function(game)
|
|
local U = dofile("tests/drivers/util.lua")
|
|
local Warp = require("src.world.Warp")
|
|
|
|
local HOUSE = "REDS_HOUSE_1F"
|
|
local TOWN = "PALLET_TOWN"
|
|
|
|
local fails = 0
|
|
local function expect(cond, ...)
|
|
if not cond then fails = fails + 1 end
|
|
U.log(cond and "PASS" or "FAIL", ...)
|
|
end
|
|
|
|
local ow
|
|
local function settle(mapId)
|
|
for _ = 1, 300 do
|
|
ow = game.overworld
|
|
if ow and ow.map.id == mapId and not ow.transitioning
|
|
and #ow.scriptMoves == 0 and not ow.player.moving then
|
|
break
|
|
end
|
|
U.wait(1)
|
|
end
|
|
U.wait(4)
|
|
ow = game.overworld
|
|
end
|
|
|
|
-- data/generated/maps.lua warps, extracted from pokered
|
|
-- data/maps/objects/PalletTown.asm and RedsHouse1F.asm: the town warp whose
|
|
-- destination is the house is the door tile, and the house's LAST_MAP warps
|
|
-- are the two mat cells on its bottom row.
|
|
local function warpTo(mapId, destMap)
|
|
for _, w in ipairs(game.data.maps[mapId].warps or {}) do
|
|
if w.destMap == destMap then return w end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
local door = warpTo(TOWN, HOUSE)
|
|
local mat = warpTo(HOUSE, "LAST_MAP")
|
|
expect(door ~= nil, "Pallet Town has a warp into " .. HOUSE)
|
|
expect(mat ~= nil, HOUSE .. " has a LAST_MAP exit warp")
|
|
if not (door and mat) then error("map data has no door/mat pair to test") end
|
|
U.log(("door at (%d, %d), mat at (%d, %d)"):format(door.x, door.y,
|
|
mat.x, mat.y))
|
|
|
|
-- Approach the door from the south, which is the only side the walk-in works
|
|
-- from; if a map edit blocked that cell, take any walkable neighbour.
|
|
U.teleport(game, TOWN, door.x, door.y + 1, "up")
|
|
settle(TOWN)
|
|
local stand = { x = door.x, y = door.y + 1, facing = "up" }
|
|
if not ow.map:isWalkableCell(stand.x, stand.y) then
|
|
local sides = {
|
|
{ 0, 1, "up" }, { 0, -1, "down" }, { 1, 0, "left" }, { -1, 0, "right" },
|
|
}
|
|
for _, s in ipairs(sides) do
|
|
local cx, cy = door.x + s[1], door.y + s[2]
|
|
if ow.map:isWalkableCell(cx, cy) then
|
|
U.log(("cell (%d, %d) is blocked, approaching from"):format(
|
|
stand.x, stand.y), cx, cy, "facing", s[3])
|
|
stand = { x = cx, y = cy, facing = s[3] }
|
|
U.teleport(game, TOWN, cx, cy, s[3])
|
|
settle(TOWN)
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Walk in for real: teleporting straight onto the mat would never set the
|
|
-- flag the door sets, so the bug could not show up. The direction is
|
|
-- released the instant the warp lands, because a still-held d-pad walks the
|
|
-- player off the mat and stepping back onto it is ExtraWarpCheck's own
|
|
-- trigger, which would exit the house before the human sees anything.
|
|
for _ = 1, 120 do
|
|
if game.overworld and game.overworld.map.id == HOUSE then break end
|
|
table.insert(game.input.pressQueue, stand.facing)
|
|
game.input.state[stand.facing] = true
|
|
coroutine.yield()
|
|
end
|
|
game.input.state[stand.facing] = false
|
|
settle(HOUSE)
|
|
expect(ow.map.id == HOUSE, "walked in through the door, map:", ow.map.id)
|
|
local p = ow.player
|
|
expect(p.cellX == mat.x and p.cellY == mat.y,
|
|
("landed on the mat (%d, %d), got:"):format(mat.x, mat.y),
|
|
p.cellX, p.cellY)
|
|
expect(ow.map:warpAtCell(p.cellX, p.cellY) ~= nil,
|
|
"the cell under the player carries a warp entry")
|
|
expect(not ow.map:isWarpTileCell(p.cellX, p.cellY),
|
|
("the mat tile ($%02X) is no warp-activating tile, so nothing cleared "
|
|
.. "the flag"):format(ow.map:cellTile(p.cellX, p.cellY)))
|
|
expect(ow:canCollisionWarp(),
|
|
"BIT_STANDING_ON_WARP survived the warp, so DOWN can exit (#378)")
|
|
expect(Warp.onEdge(ow.map, p.cellX, p.cellY, "down") ~= nil,
|
|
"and DOWN off the south edge resolves to the exit warp")
|
|
expect(ow.warpEntryCell ~= nil,
|
|
"the completed-step arrival record is set, as #265 wants it")
|
|
|
|
local vol = game.save.options and game.save.options.sfxVol
|
|
if vol == 0 then
|
|
U.log("sfxVol is 0: a wrong bonk would be SILENT, raise it in OPTION first")
|
|
else
|
|
U.log("sfxVol", tostring(vol), "-- there should be no collision thud at all")
|
|
end
|
|
|
|
U.log("You are on the mat inside the house, already facing down. Press DOWN.")
|
|
U.log("Right: it fades out on the first press and you are back in Pallet")
|
|
U.log("Town on the door, which auto-steps you one cell south. Wrong: a")
|
|
U.log("collision thud and Red walks in place until you step off the mat.")
|
|
U.log("The stairs at the top right must still bonk, not bounce floors (#230).")
|
|
|
|
if fails > 0 then U.log(fails .. " check(s) failed before the handoff") end
|
|
|
|
while true do
|
|
coroutine.yield()
|
|
end
|
|
end
|