Files
gen1recomp/tests/drivers/game3_link_union_room.lua
2026-09-25 10:28:21 -04:00

146 lines
5.2 KiB
Lua

local U = require("tests.drivers.util")
local DIR = os.getenv("POKEPORT_SHOT_DIR") or "/tmp/game3_link_union_room"
local Plaza = require("src.core.game3.link.union_plaza_map")
local UNION_ROOM = Plaza.MAP_ID
local CENTER_2F = "FR_VIRIDIAN_CITY_POKEMON_CENTER_2F"
-- pokefirered/data/specials.inc:5 SetCableClubWarp
local SET_CABLE_CLUB_WARP = 0x01
-- pokefirered/include/constants/vars.h:163
local VAR_CABLE_CLUB_STATE = 0x406F
-- pokefirered/include/constants/vars.h:328
local VAR_RESULT = 0x800D
-- pokefirered/include/constants/flags.h:1375
local FLAG_SYS_POKEDEX_GET = 0x829
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 link_union_room")
love.event.quit(0)
else
print("FAIL link_union_room failures=" .. failures)
love.event.quit(1)
end
end
return function(game)
print("PASS driver_started")
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 Space = require("src.core.game3.scripting.space")
local Flags = require("src.core.game3.scripting.flags")
local Player = require("src.core.game3.player")
local Objects = require("src.core.game3.objects")
local Link = require("src.core.game3.link")
local Union = require("src.core.game3.link.union_room")
local Screen = require("src.ui.game3.union_room")
local Game3Link = require("src.link.Game3Link")
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 setVar(id, v) Flags.setVar(Space.store, ctx(), id, v) end
local function getVar(id) return tonumber(Flags.getVar(Space.store, ctx(), id)) or 0 end
local function place(x, y, facing)
Player.cellX, Player.cellY = x, y
Player.px, Player.py = x * 16, y * 16
Player.targetX, Player.targetY = x, y
Player.facing = facing
if game.session then
game.session.x, game.session.y, game.session.facing = x, y, facing
end
end
Flags.setFlag(Space.store, ctx(), FLAG_SYS_POKEDEX_GET, true)
-- pokefirered/data/scripts/cable_club.inc:776 CableClub_EventScript_EnterUnionRoom
Map.load(nil, game, CENTER_2F, { x = 5, y = 2, facing = "up" })
place(5, 2, "up")
U.wait(60)
Flags.setFlag(Space.store, ctx(), FLAG_SYS_POKEDEX_GET, true)
place(5, 1, "up")
U.wait(10)
local Natives = require("src.core.game3.scripting.natives")
Natives.special(ctx(), SET_CABLE_CLUB_WARP, Space.vm and Space.vm.adapters)
result(session.dynamicWarp ~= nil and session.dynamicWarp.map == CENTER_2F,
"SetCableClubWarp recorded the way back to the cable club counter")
setVar(VAR_CABLE_CLUB_STATE, 6)
local slotKey = require("src.import.gba.map_catalog").slotKeyFor("FR_UNION_ROOM") or ""
local group, num = slotKey:match("(%d+)%D+(%d+)")
-- pokefirered/data/scripts/cable_club.inc:797
Space.vm.adapters.warp(tonumber(group), tonumber(num), 0xFF, 7, 11, function() end, "warpspinenter")
U.wait(120)
result(Space.mapId == UNION_ROOM, "the player is in the Union Room")
result(Union.isActive(), "the Union Room ON_RESUME ran RunUnionRoom")
print("[driver] union state after entry: " .. tostring(Union.state))
U.shot(game, DIR .. "/union_room_01_empty.png")
result(Union.relay and Union.capacity() == Plaza.CAP, "offline, the Union Room is still the 40-player plaza")
result(Union.playerCount() == 0, "with nobody in it")
local waited = 0
-- pokefirered/src/field_fadetransition.c:578 DoUnionRoomWarp
waited = 0
while waited < 200 and Screen.isOpen() do
U.tap(game, "b")
U.wait(20)
waited = waited + 20
end
U.wait(30)
place(12, 22, "down")
U.wait(30)
local Message = require("src.ui.game3.message")
waited = 0
while waited < 200 and Message.isOpen() do
U.tap(game, "a")
U.wait(20)
waited = waited + 20
end
U.wait(20)
for _ = 1, 20 do
if Space.mapId ~= UNION_ROOM then break end
U.hold(game, "down", 8)
end
print("[driver] exit walk: p=" .. tostring(Player.cellX) .. "," .. tostring(Player.cellY)
.. " msg=" .. tostring(Message.isOpen()) .. " union=" .. tostring(Union.state))
waited = 0
while waited < 600 and Space.mapId == UNION_ROOM do
U.wait(15)
waited = waited + 15
end
U.wait(90)
print("[driver] after the pad: map=" .. tostring(Space.mapId) ..
" union=" .. tostring(Union.state) .. " cable=" .. tostring(getVar(VAR_CABLE_CLUB_STATE)))
result(Space.mapId == CENTER_2F, "the pad warped the player back to the cable club counter")
result(not Union.isActive(), "leaving the Union Room ended the session")
waited = 0
while waited < 600 and getVar(VAR_CABLE_CLUB_STATE) ~= 0 do
U.tap(game, "a")
U.wait(20)
waited = waited + 20
end
result(getVar(VAR_CABLE_CLUB_STATE) == 0,
"CableClub_EventScript_ExitUnionRoom cleared VAR_CABLE_CLUB_STATE")
U.shot(game, DIR .. "/union_room_06_back_at_counter.png")
Link.reset()
finish()
end