Files
gen1recomp/tests/drivers/game3_stitchuif_boxsend.lua
bryanthaboi dee935a4ea CLOSES #2430
2026-09-23 11:58:32 -04:00

252 lines
8.6 KiB
Lua

local U = require("tests.drivers.util")
local DIR = os.getenv("POKEPORT_SHOT_DIR") or "/tmp/game3_stitchuif_boxsend"
local CENTER = "FR_VIRIDIAN_CITY_POKEMON_CENTER_1F"
-- pokefirered/include/constants/metatile_behaviors.h:135
local MB_PC = 0x83
-- pokefirered/include/constants/vars.h:105
local VAR_PC_BOX_TO_SEND_MON = 0x4037
-- pokefirered/include/constants/flags.h:1401
local FLAG_SHOWN_BOX_WAS_FULL_MESSAGE = 0x843
local CHARMANDER, MAGIKARP, PIDGEY = 4, 129, 16
local ITEM_MASTER_BALL = 1
local failures = 0
local function result(ok, label)
print((ok and "PASS " or "FAIL ") .. label)
if not ok then failures = failures + 1 end
return ok
end
local function finish()
if failures == 0 then
print("PASS stitchuif_boxsend")
love.event.quit(0)
else
print("FAIL stitchuif_boxsend failures=" .. failures)
love.event.quit(1)
end
end
return function(game)
for _ = 1, 900 do
if game.phase == "boot" and game.boot then break end
U.wait(1)
end
game:_handleBootAction({ action = "new_game", name = "RED" })
U.wait(240)
local Runtime = require("src.core.game3.runtime")
local Map = require("src.core.game3.map")
local Player = require("src.core.game3.player")
local Party = require("src.core.game3.party")
local Storage = require("src.core.game3.storage")
local Bag = require("src.core.game3.bag")
local Flags = require("src.core.game3.scripting.flags")
local Space = require("src.core.game3.scripting.space")
local Collision = require("src.core.game3.collision")
local PcMenu = require("src.ui.game3.pc_menu")
local BoxStorageUI = require("src.ui.game3.box_storage_ui")
local BattleBridge = require("src.core.game3.battle_bridge")
local Battle = require("src.core.game3.battle")
local Anim = require("src.core.game3.battle.anim")
local Ui = require("src.core.game3.battle.ui")
local Message = require("src.ui.game3.message")
local BagMenu = require("src.ui.game3.bag_menu")
local session = Runtime.getSession()
if not result(session ~= nil, "new game reached the game3 field") then return finish() end
local function ctx() return Space.vm and Space.vm.ctx end
local function getVar(id) return Flags.getVar(Space.store, ctx(), id) end
local function getFlag(id) return Flags.getFlag(Space.store, ctx(), id) and true or false end
session.party = {}
for _ = 1, 6 do Party.giveMon(session, CHARMANDER, 8) end
local storage = Storage.ensure(session)
storage.currentBox = 2
for _ = 1, Storage.IN_BOX_COUNT do
if Party.giveMonToPlayer(session, PIDGEY, 3) ~= Party.MON_GIVEN_TO_PC then break end
end
storage.currentBox = 1
if not result(Storage.countBoxMons(storage, 2) == Storage.IN_BOX_COUNT,
"BOX 2 is full (" .. Storage.countBoxMons(storage, 2) .. "/" .. Storage.IN_BOX_COUNT .. ")") then
return finish()
end
Flags.setVar(Space.store, ctx(), VAR_PC_BOX_TO_SEND_MON, 0)
Flags.setFlag(Space.store, ctx(), FLAG_SHOWN_BOX_WAS_FULL_MESSAGE, true)
Map.load(nil, game, CENTER, { x = 3, y = 4, facing = "down" })
session.x, session.y, session.facing = 3, 4, "down"
Player.cellX, Player.cellY = 3, 4
Player.px, Player.py = 3 * 16, 4 * 16
Player.targetX, Player.targetY = 3, 4
U.wait(120)
local px, py
local def = Map.currentDef and Map.currentDef()
local layout = def and def.midLayout
for cy = 0, (layout and layout.height or 0) - 1 do
for cx = 0, (layout and layout.width or 0) - 1 do
if Collision.behavior(cx, cy) == MB_PC then px, py = cx, cy end
end
end
if not result(px ~= nil, "the Pokemon Center has an MB_PC tile") then return finish() end
U.log(string.format("[driver] PC tile at (%d,%d)", px, py))
Player.cellX, Player.cellY = px, py + 1
Player.px, Player.py = px * 16, (py + 1) * 16
Player.targetX, Player.targetY = px, py + 1
Player.facing = "up"
session.x, session.y, session.facing = px, py + 1, "up"
U.wait(60)
local opened = false
for _ = 1, 14 do
U.tap(game, "a")
U.wait(30)
if PcMenu.isOpen and PcMenu.isOpen() then opened = true break end
end
if not result(opened, "talking to the PC opened the PC menu") then return finish() end
local Audio = require("src.core.game3.audio")
for _ = 1, 4000 do
if not Audio.isSePlaying() and not Message.isOpen() then break end
if Message.isOpen() and not Audio.isSePlaying() then U.tap(game, "a") end
U.wait(4)
end
U.wait(20)
U.shot(game, DIR .. "/stitchuif_boxsend_01_pc_menu.png")
-- pokefirered/src/pokemon_storage_system_tasks.c:426
U.tap(game, "a")
for _ = 1, 4000 do
if PcMenu.isOpen() and PcMenu.mode == "storage_menu" then break end
if Message.isOpen() and not Audio.isSePlaying() then U.tap(game, "a") end
U.wait(4)
end
U.wait(30)
result(PcMenu.mode == "storage_menu", "SOMEONE'S PC opened the storage menu")
for _ = 1, 2 do
U.tap(game, "down")
U.wait(12)
end
U.tap(game, "a")
U.wait(40)
if not result(BoxStorageUI.isOpen(), "the box screen opened") then return finish() end
result(storage.currentBox == 1, "the box screen opened on BOX 1")
U.tap(game, "up")
U.wait(24)
result(BoxStorageUI.cursorSlot == 0, "the cursor reached the box title header")
U.tap(game, "right")
U.wait(30)
result(storage.currentBox == 2, "the header arrow scrolled to the full BOX 2")
result(getVar(VAR_PC_BOX_TO_SEND_MON) == 0,
"the send target is still BOX 1 while the screen is up")
U.shot(game, DIR .. "/stitchuif_boxsend_02_box2_full.png")
U.tap(game, "b")
U.wait(40)
result(not BoxStorageUI.isOpen(), "B left the box screen")
result(getVar(VAR_PC_BOX_TO_SEND_MON) == 1,
"leaving on BOX 2 moved the send target (got " .. getVar(VAR_PC_BOX_TO_SEND_MON) .. ")")
result(getFlag(FLAG_SHOWN_BOX_WAS_FULL_MESSAGE) == false,
"and cleared FLAG_SHOWN_BOX_WAS_FULL_MESSAGE")
local idle = 0
for _ = 1, 120 do
local busy = (PcMenu.isOpen and PcMenu.isOpen()) or Message.isOpen()
or (Space.vm and Space.vm:isRunning())
if not busy then
idle = idle + 1
if idle >= 30 then break end
U.wait(1)
else
idle = 0
if PcMenu.isOpen and PcMenu.isOpen() then
U.tap(game, "b")
elseif Message.isOpen() then
U.tap(game, "a")
end
U.wait(20)
end
end
if not result(idle >= 30, "the PC logged off and its script ended before the battle") then return finish() end
local ok = BattleBridge.startWild(Runtime._mod, game, { species = MAGIKARP, level = 5 },
{ fade = false })
if not result(ok == true, "a wild MAGIKARP battle started") then return finish() end
local function at_command()
return Battle.isActive() and Battle._phase == "command" and Ui._mode == "menu"
end
local function throw_master_ball()
Bag.add(session.bag, ITEM_MASTER_BALL, 1)
U.tap(game, "right")
U.wait(20)
U.tap(game, "a")
U.wait(90)
for _ = 1, 6 do
if BagMenu.currentPocket() == "POKE_BALLS" then break end
U.tap(game, "right")
U.wait(40)
end
U.tap(game, "a")
U.wait(40)
U.tap(game, "a")
U.wait(40)
end
local wanted = { match = "was full", done = false }
local seen = {}
local thrown, lastTap, f = false, 0, 0
for _ = 1, 12000 do
f = f + 1
if not Battle.isActive() then break end
if at_command() and not thrown then
thrown = true
throw_master_ball()
lastTap = f
elseif Anim.vm() and Anim.vm():busy() then
U.wait(1)
else
if Message.isOpen() and not Message.isTyping() then
local page = Message.currentPage() or ""
if page ~= "" then
seen[#seen + 1] = page
if not wanted.done and page:find(wanted.match, 1, true) then
wanted.done = true
U.shot(game, DIR .. "/stitchuif_boxsend_03_box2_was_full.png")
result(page:find("BOX 2", 1, true) ~= nil,
"the full box named on screen is BOX 2 (" .. page .. ")")
result(page:find("BOX 1", 1, true) == nil,
"the empty BOX 1 is not blamed")
end
end
end
if f - lastTap >= 24 then
lastTap = f
U.tap(game, Battle._phase == "catch_nickname_prompt" and "b" or "a")
else
U.wait(1)
end
end
end
result(wanted.done, "the catch printed a box-was-full page")
local placed = nil
for _, p in ipairs(seen) do
if p:find("transferred to", 1, true) then placed = p end
end
result(placed ~= nil and placed:find("BOX 3", 1, true) ~= nil,
"the MAGIKARP is announced into BOX 3 (" .. tostring(placed) .. ")")
local boxed = storage.boxes[3] and storage.boxes[3].mons[1]
result(boxed ~= nil and tonumber(boxed.species or boxed.speciesId) == MAGIKARP,
"and it really landed in BOX 3 slot 1")
U.wait(90)
finish()
end