Files
gen1recomp/tests/drivers/oak_test.lua
T
2026-07-17 20:30:02 -04:00

109 lines
4.1 KiB
Lua

-- Driver: the full Pallet intro chain. Steps north to trigger Oak,
-- follows him to the lab, takes a starter, watches the rival
-- counter-pick, tries to leave (door gate + ambush battle).
return function(game)
local U = dofile("tests/drivers/util.lua")
local DIR = os.getenv("SHOT_DIR") or "/tmp/shots"
-- start two rows south: the trigger is the step ONTO row y=1
-- (PalletTownDefaultScript's wYCoord == 1 check)
U.teleport(game, "PALLET_TOWN", 10, 3, "up")
local ow = game.overworld
-- press A only when a dialog is open (mashing at the overworld would
-- re-interact with whatever the player faces)
local function mashUntil(cond, label, cap)
for _ = 1, cap or 400 do
if cond() then return true end
if game.stack:top() ~= ow then
U.tap(game, "a")
end
U.wait(4)
end
U.log("TIMEOUT waiting for " .. label)
return false
end
local function idle()
return game.stack:top() == ow and not ow.runner:isRunning()
and #ow.scriptMoves == 0 and not ow.transitioning
and not ow.emote -- cutscene DelayFrames/bubble holds
end
-- trigger Oak (two steps north onto row 1)
U.hold(game, "up", 40)
U.wait(30)
U.shot(game, DIR .. "/oak_1_heywait.png")
U.wait(90) -- auto-close + "!" bubble
U.shot(game, DIR .. "/oak_2_bubble.png")
U.wait(120) -- Oak's zigzag walk up from (8,5)
U.shot(game, DIR .. "/oak_3_follow.png")
-- dismiss "It's unsafe!" (multi-page), then catch the escort mid-walk
mashUntil(function() return game.stack:top() == ow end, "unsafe text", 200)
U.wait(130)
U.shot(game, DIR .. "/oak_3b_escort.png")
mashUntil(function() return ow.map.id == "OAKS_LAB" end, "lab entry", 900)
U.shot(game, DIR .. "/oak_4_arrived.png")
mashUntil(idle, "walk-in done", 600)
U.shot(game, DIR .. "/oak_5_at_desk.png")
U.log("in lab at:", ow.player.cellX, ow.player.cellY)
-- the walk-in ends at (5,3) below Oak; to the middle ball:
-- down to (5,4) -> right to (7,4) -> face up at SQUIRTLE's ball
U.hold(game, "down", 18)
U.wait(10)
U.hold(game, "right", 34)
U.wait(20) -- let the second step land before turning
U.tap(game, "up")
U.wait(10)
U.log("at ball:", ow.player.cellX, ow.player.cellY, ow.player.facing)
U.tap(game, "a")
U.wait(40)
U.shot(game, DIR .. "/oak_6_ball_prompt.png")
U.tap(game, "a") -- YES
mashUntil(function() return #game.save.party > 0 end, "starter", 200)
U.shot(game, DIR .. "/oak_7_got_starter.png")
-- step away from the ball first: A-mash while facing it re-opens
-- its dialog forever
U.hold(game, "down", 20)
mashUntil(idle, "rival pick done", 400)
U.shot(game, DIR .. "/oak_8_rival_picked.png")
U.log("party:", game.save.party[1] and game.save.party[1].species,
"pos:", ow.player.cellX, ow.player.cellY)
-- head for the door: rival ambush -> battle. Exact single steps
-- left to column 4 (column 3 runs into the lab table), then south.
for _ = 1, 3 do
U.hold(game, "left", 16)
U.wait(12)
end
U.hold(game, "down", 120)
U.wait(30)
U.shot(game, DIR .. "/oak_9_ambush.png")
local BattleSeen = false
for _ = 1, 200 do
if game.stack:top() ~= ow and game.stack:top() and game.stack:top().kind then
BattleSeen = true
break
end
U.tap(game, "a")
U.wait(4)
end
U.wait(60)
U.shot(game, DIR .. "/oak_10_battle.png")
mashUntil(idle, "battle over", 1500)
U.wait(30)
U.shot(game, DIR .. "/oak_11_after_battle.png")
U.log("final:", ow.map.id, ow.player.cellX, ow.player.cellY,
"battled:", tostring(game.save.flags.EVENT_BATTLED_RIVAL_IN_OAKS_LAB),
"battleSeen:", tostring(BattleSeen))
U.log("stuck-state: runner=", tostring(ow.runner:isRunning()),
"moves=", #ow.scriptMoves, "top=", tostring(game.stack:top() == ow),
"transitioning=", tostring(ow.transitioning),
"emote=", tostring(ow.emote ~= nil))
for i, mv in ipairs(ow.scriptMoves) do
U.log((" move %d: entity=%s dir=%s remaining=%d moving=%s"):format(
i, tostring(mv.entity.def and mv.entity.def.sprite or "PLAYER"),
tostring(mv.dir), mv.remaining, tostring(mv.entity.moving)))
end
end