mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 13:33:27 -04:00
252 lines
8.6 KiB
Lua
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
|