Files
bryanthaboi ae6cac89e1 G2 support
2026-08-11 11:53:30 -04:00

100 lines
3.6 KiB
Lua

-- GiveItemScript (engine/overworld/scripting.asm:441-449) is ONE MapTextbox.
--
-- POKEPORT_GAME=gold POKEPORT_DRIVER=tests/drivers/gold_giveitem_box.lua love .
--
-- `writetext .ReceivedItemText / iffalse .Full / waitsfx / specialsound /
-- waitbutton / itemnotify`: the received line and the "put it in the pocket"
-- line print into the SAME box, which the caller's `opentext` opened and the
-- caller's `closetext` closes. Nothing between them takes the box down.
--
-- This port draws a box per message, so the seam between them is where the
-- fidelity is: the second box has to go up inside the same frame the first
-- one pops. If a frame renders with an empty state stack in between, the box
-- visibly tears down and rebuilds AND Game2's play clock -- which only ticks
-- while the overworld is the top state (src/core/Game2.lua, wGameTimerPaused)
-- -- comes off pause for the length of the gap.
--
-- The run counts the bare-overworld frames between the two boxes and the
-- play-clock frames they cost, and shoots both pages.
local U = require("tests.drivers.util")
return function(game)
local out = os.getenv("POKEPORT_SHOT_DIR") or "/tmp/gold-giveitem"
local function tap(button)
game.input.pressQueue[#game.input.pressQueue + 1] = button
game.input.state[button] = true
U.wait(2)
game.input.state[button] = false
U.wait(2)
end
U.wait(45)
local world = game.world
assert(world and world.map, "gold world did not boot")
game.save.playTime = { hours = 0, minutes = 0, seconds = 0, frames = 0 }
local function clockFrames()
local t = game.save.playTime
return ((t.hours * 60 + t.minutes) * 60 + t.seconds) * 60 + t.frames
end
-- `opentext / verbosegiveitem POTION, 1 / closetext / end`, the shape every
-- NPC hand-over in the game uses.
world.vm:start({
{ op = "opentext" },
{ op = "verbosegiveitem", args = { "POTION", 1 } },
{ op = "closetext" },
{ op = "end" },
})
-- Sampled every frame, and the A press goes in every sixth: a sample taken
-- only on press frames would step straight over the seam being measured.
local bare, boxes, seenFirst = 0, 0, false
local clockAtFirstBox, clockAtLastBox = nil, nil
local shots, pressIn = 0, 8
for _ = 1, 900 do
if not world:busy() and seenFirst then break end
local top = game.stack:top()
if top then
if not seenFirst then
seenFirst = true
clockAtFirstBox = clockFrames()
end
clockAtLastBox = clockFrames()
if shots < 2 and boxes % 12 == 6 then
shots = shots + 1
U.shot(game, ("%s/%02d-page.png"):format(out, shots))
end
boxes = boxes + 1
elseif seenFirst then
bare = bare + 1
end
pressIn = pressIn - 1
if pressIn <= 0 then
pressIn = 6
game.input.pressQueue[#game.input.pressQueue + 1] = "a"
game.input.state.a = true
U.wait(1)
game.input.state.a = false
else
U.wait(1)
end
end
local spent = (clockAtLastBox or 0) - (clockAtFirstBox or 0)
print(("[driver] %d frames with a box up, %d bare frames between the pages")
:format(boxes, bare))
print(("[driver] the play clock advanced %d frames across the exchange")
:format(spent))
assert(seenFirst, "no text box ever went up for the item")
assert(bare == 0,
("the overworld drew bare for %d frames between the two pages of one "
.. "GiveItemScript textbox"):format(bare))
assert(spent == 0,
("the play clock ran for %d frames while an item was being handed over")
:format(spent))
print("[driver] PASS gold giveitem single box in " .. out)
love.event.quit()
end