mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-12 08:21:02 +02:00
165 lines
6.3 KiB
Lua
165 lines
6.3 KiB
Lua
-- Manual check that a warp arrival hides Pikachu under the player (#863):
|
|
-- pokeyellow spawns on the player's own coords and the follow buffer walks
|
|
-- it out, but before the fix it popped in already beside him.
|
|
-- Warp cells: pokered data/maps/objects/RedsHouse1F.asm / RedsHouse2F.asm.
|
|
-- POKEPORT_DRIVER=tests/drivers/pikachu_warp_spawn_bug863_test.lua POKEPORT_IDENTITY=bug863 POKEPORT_TOUCH=0 POKEPORT_VERSION=yellow love .
|
|
-- Never add POKEPORT_SPEED; the identity needs an imported Yellow cache.
|
|
return function(game)
|
|
local U = dofile("tests/drivers/util.lua")
|
|
local Pokemon = require("src.pokemon.Pokemon")
|
|
local GameVersion = require("src.core.GameVersion")
|
|
local PF = require("src.world.PikachuFollower")
|
|
local SHOT_DIR = os.getenv("SHOT_DIR") or "/tmp/shots"
|
|
|
|
local function check(label, ok)
|
|
U.log(ok and "PASS" or "FAIL", label)
|
|
return ok
|
|
end
|
|
|
|
check("running as Yellow (needs POKEPORT_VERSION=yellow)",
|
|
GameVersion.isYellow())
|
|
|
|
-- the follower only spawns behind EVENT_GOT_STARTER with a healthy
|
|
-- PIKACHU in the party (PikachuFollower shouldSpawn)
|
|
game.save.flags = game.save.flags or {}
|
|
game.save.flags.EVENT_GOT_STARTER = true
|
|
game.save.party = { Pokemon.new(game.data, "PIKACHU", 20) }
|
|
game.save.onBike = false
|
|
game.save.player.name = "bryan"
|
|
|
|
-- pokered RedsHouse1F.asm: warp_event 7, 1 -> REDS_HOUSE_2F, and
|
|
-- RedsHouse2F.asm: warp_event 7, 1 back down. Read the live map data
|
|
-- so a hack or mod that moved the stairs still points us at them.
|
|
local function warpTo(fromMap, destMap)
|
|
local def = game.data.maps[fromMap]
|
|
for _, w in ipairs(def and def.warps or {}) do
|
|
if w.destMap == destMap then return w.x, w.y end
|
|
end
|
|
return nil
|
|
end
|
|
local wx, wy = warpTo("REDS_HOUSE_1F", "REDS_HOUSE_2F")
|
|
check("REDS_HOUSE_1F has a warp to REDS_HOUSE_2F", wx ~= nil)
|
|
wx, wy = wx or 7, wy or 1
|
|
|
|
local follower = function() return PF.current(game.overworld) end
|
|
|
|
local function overlapsPlayer()
|
|
local npc = follower()
|
|
local p = game.overworld and game.overworld.player
|
|
return npc and p and npc.cellX == p.cellX and npc.cellY == p.cellY
|
|
end
|
|
|
|
-- press-and-hold dir until the map flips, releasing the instant it
|
|
-- does so no queued step drags the player off the arrival warp cell
|
|
local function walkUntilMap(dir, targetMap, maxFrames)
|
|
for _ = 1, maxFrames do
|
|
local ow = game.overworld
|
|
if ow and ow.map and ow.map.id == targetMap then break end
|
|
table.insert(game.input.pressQueue, dir)
|
|
game.input.state[dir] = true
|
|
coroutine.yield()
|
|
end
|
|
game.input.state[dir] = false
|
|
U.wait(45) -- warp fade + arrival settle
|
|
local ow = game.overworld
|
|
return ow and ow.map and ow.map.id == targetMap
|
|
end
|
|
|
|
-- stand two below the stairs facing up; fall back to any walkable cell
|
|
-- below the warp if a mod reshaped the room
|
|
local sx, sy = wx, wy + 2
|
|
U.teleport(game, "REDS_HOUSE_1F", sx, sy, "up")
|
|
U.wait(10)
|
|
local ow = game.overworld
|
|
if not ow.map:isWalkableCell(sx, sy) then
|
|
for dy = 1, 3 do
|
|
if ow.map:isWalkableCell(wx, wy + dy) then
|
|
sx, sy = wx, wy + dy
|
|
U.teleport(game, "REDS_HOUSE_1F", sx, sy, "up")
|
|
U.wait(10)
|
|
break
|
|
end
|
|
end
|
|
end
|
|
-- U.teleport is itself a fresh map load, so the fixed spawn already
|
|
-- parks Pikachu on the player's cell here
|
|
check("follower spawned on map load", follower() ~= nil)
|
|
check("map-load spawn is on the player's own cell", overlapsPlayer())
|
|
|
|
-- climb the stairs
|
|
check("walked up into REDS_HOUSE_2F",
|
|
walkUntilMap("up", "REDS_HOUSE_2F", 240))
|
|
check("warp arrival upstairs: Pikachu hidden under the player",
|
|
overlapsPlayer())
|
|
U.shot(game, SHOT_DIR .. "/bug863_2f_arrival.png")
|
|
|
|
-- the draw sort tie-break (#863): sharing the player's py must list the
|
|
-- follower first so he draws over it. The sort runs in draw, and the
|
|
-- shot above rendered a frame, so entities order is post-sort here.
|
|
do
|
|
local npc = follower()
|
|
local p = game.overworld.player
|
|
if npc and p and npc.py == p.py then
|
|
local ni, pi
|
|
for i, e in ipairs(game.overworld.entities) do
|
|
if e == npc then ni = i elseif e == p then pi = i end
|
|
end
|
|
check("draw sort puts the hidden follower under the player",
|
|
ni ~= nil and pi ~= nil and ni < pi)
|
|
end
|
|
end
|
|
|
|
-- walk off the stairs: the trail should pull Pikachu out one behind
|
|
U.hold(game, "down", 20)
|
|
U.wait(20)
|
|
U.hold(game, "down", 20)
|
|
U.wait(30)
|
|
do
|
|
local npc = follower()
|
|
local p = game.overworld.player
|
|
check("two steps later Pikachu trails one cell behind",
|
|
npc and p and npc.cellX == p.cellX and npc.cellY == p.cellY - 1)
|
|
check("and it faces down, walking out of the stairwell",
|
|
npc and npc.facing == "down")
|
|
end
|
|
U.shot(game, SHOT_DIR .. "/bug863_2f_trailing.png")
|
|
|
|
-- back down the same stairs: descent must hide it the same way
|
|
check("walked back down into REDS_HOUSE_1F",
|
|
walkUntilMap("up", "REDS_HOUSE_1F", 240))
|
|
check("warp arrival downstairs: Pikachu hidden under the player",
|
|
overlapsPlayer())
|
|
U.shot(game, SHOT_DIR .. "/bug863_1f_return.png")
|
|
|
|
-- regression: a connection seam is the keepPikachu path (#427), not a
|
|
-- respawn, so the follower must ride across it, not vanish or repark
|
|
U.teleport(game, "PALLET_TOWN", 10, 2, "up")
|
|
U.wait(10)
|
|
check("crossed the Pallet Town north seam into ROUTE_1",
|
|
walkUntilMap("up", "ROUTE_1", 300))
|
|
do
|
|
local npc = follower()
|
|
local p = game.overworld.player
|
|
check("follower survived the connection crossing", npc ~= nil)
|
|
check("and stayed within trailing range of the player",
|
|
npc and p and math.abs(npc.cellX - p.cellX)
|
|
+ math.abs(npc.cellY - p.cellY) <= 2)
|
|
end
|
|
U.shot(game, SHOT_DIR .. "/bug863_route1_seam.png")
|
|
|
|
local sfx = game.save.options and game.save.options.sfxVol
|
|
if sfx == 0 then
|
|
U.log("note: sfxVol is 0, Pikachu's steps and voice will be silent")
|
|
end
|
|
|
|
U.log("The shots above tell the story: on both stair arrivals only the")
|
|
U.log("player should be visible, Pikachu is tucked under him until he")
|
|
U.log("steps away, then it follows one cell behind facing his way.")
|
|
U.log("If a Pikachu sits beside him the moment a warp lands, that is")
|
|
U.log("the old bug. The pad is yours; warp around and watch spawns.")
|
|
|
|
while true do
|
|
coroutine.yield()
|
|
end
|
|
end
|