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

150 lines
5.3 KiB
Lua

#!/usr/bin/env luajit
-- pokefirered/src/battle_script_commands.c:9617
package.path = "./?.lua;./?/init.lua;" .. package.path
require("tests.game3_cache").mountOrSkip("game3_stitchbattle_catch_headless_test")
require("tests.fixture_data.game3_items").install()
local failed = 0
local function check(cond, msg)
if cond then
print("[ok] " .. msg)
else
failed = failed + 1
print("[FAIL] " .. msg)
end
end
local function eq(a, b, msg)
check(a == b, string.format("%s (%s == %s)", msg, tostring(a), tostring(b)))
end
require("src.core.GameVersion").set("firered")
local gfx = setmetatable({}, { __index = function() return function() end end })
gfx.newQuad = function() return {} end
gfx.newImage = function()
return { setFilter = function() end, getDimensions = function() return 8, 8 end }
end
_G.love = { graphics = gfx }
local Storage = require("src.core.game3.storage")
local Flags = require("src.core.game3.scripting.flags")
local Dex = require("src.core.game3.dex")
local Runtime = require("src.core.game3.runtime")
local CatchSeq = require("src.core.game3.battle.catch_seq")
local romTextReal = package.loaded["src.core.game3.rom_text"]
local ROM_TEXT = { gText_PkmnsNickname = "'s nickname?", gText_YourName = "YOUR NAME?" }
local function romTextKey(n, i, j) return j and (n .. "[" .. i .. "][" .. j .. "]") or (n .. "[" .. i .. "]") end
local function romTextPlain(key, ctx) return ((ROM_TEXT[key] or key):gsub("{PLAYER}", ctx and ctx.playerName or "")) end
package.loaded["src.core.game3.rom_text"] = {
plain = romTextPlain, box = romTextPlain, ascii = romTextPlain, has = function() return true end,
key = romTextKey, at = function(n, i, j, ctx) return romTextPlain(romTextKey(n, i, j), ctx) end,
count = function() return 0 end, list = function() return {} end,
lazy = function(map) return setmetatable({}, { __index = function(_, k) return map[k] end }) end,
}
local Naming = require("src.ui.game3.naming")
package.loaded["src.core.game3.rom_text"] = romTextReal
-- pokefirered/include/constants/vars.h:105
local VAR_PC_BOX_TO_SEND_MON = 0x4037
local function mon(species, name)
return {
species = species, speciesId = species, name = name or "RATTATA",
level = 5, hp = 20, maxHp = 20, nickname = "",
}
end
local function new_session(partyCount)
local session = { name = "RED", party = {}, store = Flags.newStore(), dex = Dex.new() }
for _ = 1, partyCount do session.party[#session.party + 1] = mon(19) end
Storage.ensure(session)
session.storage.currentBox = 1
Flags.setVar(session.store, nil, VAR_PC_BOX_TO_SEND_MON, 0)
Runtime.session = session
return session
end
local function headless_catch(session)
local caught = mon(129, "MAGIKARP")
local st = {
wild = true,
enemy = { species = 129, level = 5, hp = 10, maxHp = 10, mon = caught },
player = { mon = session.party[1] },
playerName = "RED",
}
local msgs = {}
-- pokefirered/src/battle_script_commands.c:9617
local done = CatchSeq.begin(st, 4, true, 4, {
session = session,
headless = true,
pushMsg = function(text) msgs[#msgs + 1] = tostring(text) end,
})
return done, msgs
end
print("[test] 1. a headless catch with a full party records the PC transfer")
local s1 = new_session(6)
local done1, msgs1 = headless_catch(s1)
check(done1 == true, "the headless arm finished the sequence in one call")
local res1 = CatchSeq.catchResult()
check(res1 ~= nil, "CatchSeq.catchResult() is set after a headless catch")
eq(res1 and res1.location, "pc", "and it says the mon went to the PC")
check(table.concat(msgs1, " | "):find("transferred to", 1, true) ~= nil,
"the transfer line was pushed too (" .. table.concat(msgs1, " | ") .. ")")
print("[test] 2. the naming screen's fallback can now read it (naming_screen.c:696)")
Naming.open({
template = "CAUGHT_MON",
maxLen = 10,
species = 129,
seed = "MAGIKARP",
onDone = function() end,
})
Naming._state.name = "HEADLESS"
local key = nil
local input = { wasPressed = function(_, k) return key == k end }
local function press(k)
key = k
-- src/naming_screen.c:559-572
Naming.handleInput(input)
Naming.update(1 / 60)
key = nil
end
press("start")
press("a")
check(Naming._state ~= nil and Naming._state.pcPages ~= nil,
"the screen found the headless catch result and printed the transfer line")
press("a")
press("a")
check(not Naming.isOpen(), "and it closed after the message")
print("[test] 3. a headless catch with room keeps the mon in the party")
local s2 = new_session(3)
local done2 = headless_catch(s2)
check(done2 == true, "the headless arm finished again")
local res2 = CatchSeq.catchResult()
check(res2 ~= nil, "a party catch records a result as well")
eq(res2 and res2.location, "party", "and it says the mon joined the party")
eq(#s2.party, 4, "the party grew by one")
print("[test] 4. a headless miss records no catch at all")
local s3 = new_session(3)
local caught = mon(129, "MAGIKARP")
CatchSeq.begin({
wild = true,
enemy = { species = 129, level = 5, hp = 10, maxHp = 10, mon = caught },
player = { mon = s3.party[1] },
playerName = "RED",
}, 4, false, 2, { session = s3, headless = true, pushMsg = function() end })
eq(CatchSeq.catchResult(), nil, "a broken-free ball leaves catchResult() nil")
eq(#s3.party, 3, "and the party is unchanged")
if failed > 0 then
print("[test] FAILED " .. failed)
os.exit(1)
end
print("[test] all passed")
os.exit(0)