mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 05:32:07 -04:00
282 lines
10 KiB
Lua
282 lines
10 KiB
Lua
#!/usr/bin/env luajit
|
|
-- pokefirered/src/battle_script_commands.c:9617 Cmd_givecaughtmon
|
|
-- pokefirered/data/battle_scripts_2.s:87 trygivecaughtmonnick
|
|
|
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
require("tests.game3_cache").mountOrSkip("game3_stitchbattle_pc_transfer_test", "scripts/text.lua")
|
|
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 has(s, sub)
|
|
return type(s) == "string" and s:find(sub, 1, true) ~= nil
|
|
end
|
|
|
|
local function flat(s)
|
|
return tostring(s):gsub("\n", " "):gsub("\f", " | ")
|
|
end
|
|
|
|
package.loaded["src.ui.game3.stack"] = {
|
|
push = function() end,
|
|
pop = function() end,
|
|
busy = function() return false end,
|
|
drawOrder = function() return {} end,
|
|
}
|
|
|
|
local Flags = require("src.core.game3.scripting.flags")
|
|
local Storage = require("src.core.game3.storage")
|
|
local Dex = require("src.core.game3.dex")
|
|
local Runtime = require("src.core.game3.runtime")
|
|
local Catching = require("src.core.game3.battle.catching")
|
|
local CatchSeq = require("src.core.game3.battle.catch_seq")
|
|
local BattleItems = require("src.core.game3.battle.items")
|
|
local Bag = require("src.core.game3.bag")
|
|
|
|
local FLAG_SYS_NOT_SOMEONES_PC = 0x834
|
|
local FLAG_SHOWN_BOX_WAS_FULL_MESSAGE = 0x843
|
|
local VAR_PC_BOX_TO_SEND_MON = 0x4037
|
|
|
|
local function filler(sp)
|
|
return { species = sp, speciesId = sp, name = "RATTATA", level = 5, hp = 20, maxHp = 20, nickname = "" }
|
|
end
|
|
|
|
local function caterpie()
|
|
return { species = 10, speciesId = 10, name = "CATERPIE", level = 3, hp = 6, maxHp = 6, nickname = "" }
|
|
end
|
|
|
|
local function new_session(fillBox1)
|
|
local s = { name = "RED", store = Flags.newStore(), dex = Dex.new(), party = {} }
|
|
for i = 1, 6 do s.party[i] = filler(19) end
|
|
Storage.ensure(s)
|
|
s.storage.currentBox = 1
|
|
if fillBox1 then
|
|
for slot = 1, Storage.IN_BOX_COUNT do s.storage.boxes[1].mons[slot] = filler(19) end
|
|
end
|
|
Dex.registerCapture(s.dex, 10)
|
|
Runtime.session = s
|
|
Flags.setFlag(s.store, nil, FLAG_SHOWN_BOX_WAS_FULL_MESSAGE, false)
|
|
Flags.setFlag(s.store, nil, FLAG_SYS_NOT_SOMEONES_PC, false)
|
|
Flags.setVar(s.store, nil, VAR_PC_BOX_TO_SEND_MON, 0)
|
|
return s
|
|
end
|
|
|
|
local function foe_state(session)
|
|
local mon = caterpie()
|
|
local enemy = { species = 10, level = 3, hp = 6, maxHp = 6, mon = mon }
|
|
return { wild = true, enemy = enemy, player = { mon = session.party[1] }, playerName = "RED" }, enemy
|
|
end
|
|
|
|
local prevSession = Runtime.getSession and Runtime.getSession() or nil
|
|
|
|
print("[test] 1. the headless ball path prints pret's Someone's PC line, not the hand-written one")
|
|
local s1 = new_session(false)
|
|
local st1 = foe_state(s1)
|
|
local msgs1 = {}
|
|
CatchSeq.begin(st1, 4, true, 4, {
|
|
headless = true,
|
|
session = s1,
|
|
pushMsg = function(t) msgs1[#msgs1 + 1] = t end,
|
|
})
|
|
local line1
|
|
for _, m in ipairs(msgs1) do if has(m, "transferred") then line1 = m end end
|
|
check(line1 ~= nil, "a transfer line was printed")
|
|
check(not has(line1 or "", "to the PC."), "the hand-written 'was transferred to the PC.' string is gone")
|
|
check(has(line1 or "", "CATERPIE was transferred to\nSomeone's PC."),
|
|
"pret STRINGID_PKMNTRANSFERREDSOMEONESPC: " .. flat(line1))
|
|
check(has(line1 or "", "It was placed in \nBOX “BOX 1.”"), "and it names the box it was placed in")
|
|
|
|
print("[test] 2. FLAG_SYS_NOT_SOMEONES_PC swaps in BILL'S PC")
|
|
local s2 = new_session(false)
|
|
Flags.setFlag(s2.store, nil, FLAG_SYS_NOT_SOMEONES_PC, true)
|
|
local st2 = foe_state(s2)
|
|
local msgs2 = {}
|
|
CatchSeq.begin(st2, 4, true, 4, {
|
|
headless = true,
|
|
session = s2,
|
|
pushMsg = function(t) msgs2[#msgs2 + 1] = t end,
|
|
})
|
|
local line2
|
|
for _, m in ipairs(msgs2) do if has(m, "transferred") then line2 = m end end
|
|
check(has(line2 or "", "CATERPIE was transferred to\nBILL'S PC."),
|
|
"pret STRINGID_PKMNTRANSFERREDBILLSPC: " .. flat(line2))
|
|
Flags.setFlag(s2.store, nil, FLAG_SYS_NOT_SOMEONES_PC, false)
|
|
|
|
print("[test] 3. a spillover names the box that was full first")
|
|
local s3 = new_session(true)
|
|
local st3 = foe_state(s3)
|
|
local msgs3 = {}
|
|
CatchSeq.begin(st3, 4, true, 4, {
|
|
headless = true,
|
|
session = s3,
|
|
pushMsg = function(t) msgs3[#msgs3 + 1] = t end,
|
|
})
|
|
local line3
|
|
for _, m in ipairs(msgs3) do if has(m, "transferred") then line3 = m end end
|
|
check(has(line3 or "", "BOX “BOX 1” on\nSomeone's PC was full."),
|
|
"pret STRINGID_PKMNBOXSOMEONESPCFULL: " .. flat(line3))
|
|
check(has(line3 or "", "CATERPIE was transferred to\nBOX “BOX 2.”"),
|
|
"and the mon went to BOX 2")
|
|
check(s3.storage.boxes[2].mons[1] ~= nil, "the caught mon really is in box 2")
|
|
|
|
print("[test] 4. the bag-item ball path uses the same four strings")
|
|
local s4 = new_session(false)
|
|
local st4 = foe_state(s4)
|
|
s4.bag = Bag.new()
|
|
Bag.add(s4.bag, 1, 1)
|
|
local _, msgs4 = BattleItems.use(st4, nil, s4.bag, s4, 1, nil, nil)
|
|
local line4
|
|
for _, m in ipairs(msgs4 or {}) do if has(m, "transferred") then line4 = m end end
|
|
check(line4 ~= nil, "a transfer line was printed for the bag path")
|
|
check(not has(line4 or "", "to the PC."), "the hand-written string is gone from items.lua too")
|
|
check(has(line4 or "", "CATERPIE was transferred to\nSomeone's PC."),
|
|
"pret line from the bag path: " .. flat(line4))
|
|
|
|
print("[test] 5. an empty nickname never leaks into the caught line")
|
|
local s5 = new_session(false)
|
|
local st5 = foe_state(s5)
|
|
local msgs5 = {}
|
|
CatchSeq.begin(st5, 4, true, 4, {
|
|
headless = true,
|
|
session = s5,
|
|
pushMsg = function(t) msgs5[#msgs5 + 1] = t end,
|
|
})
|
|
local gotcha
|
|
for _, m in ipairs(msgs5) do if has(m, "Gotcha!") then gotcha = m end end
|
|
check(has(gotcha or "", "CATERPIE was caught!"), "Gotcha line names the species: " .. flat(gotcha))
|
|
|
|
local Battle = require("src.core.game3.battle")
|
|
local BattleUi = require("src.core.game3.battle.ui")
|
|
local Choice = require("src.ui.game3.choice")
|
|
local Message = require("src.ui.game3.message")
|
|
local Naming = require("src.ui.game3.naming")
|
|
|
|
local mockInput = {
|
|
_pressed = {},
|
|
press = function(self, key) self._pressed[key] = true end,
|
|
clear = function(self) self._pressed = {} end,
|
|
isDown = function(self, key) return self._pressed[key] == true end,
|
|
wasPressed = function(self, key)
|
|
if self._pressed[key] then
|
|
self._pressed[key] = false
|
|
return true
|
|
end
|
|
return false
|
|
end,
|
|
}
|
|
function mockInput:consume(key)
|
|
return self:wasPressed(key)
|
|
end
|
|
|
|
local function run_to_choice()
|
|
local guard = 0
|
|
while Message.isOpen() and not Choice.active and guard < 4000 do
|
|
Message.tick()
|
|
BattleUi.pump()
|
|
guard = guard + 1
|
|
end
|
|
end
|
|
|
|
local function log_after(mark)
|
|
local out = {}
|
|
for i = mark + 1, #(BattleUi._log or {}) do out[#out + 1] = BattleUi._log[i] end
|
|
return out
|
|
end
|
|
|
|
print("[test] 6. declining the nickname prints the pret line with the species name")
|
|
local s6 = new_session(true)
|
|
local st6, enemy6 = foe_state(s6)
|
|
Battle.start({
|
|
wild = true,
|
|
playerParty = s6.party,
|
|
foe = st6.enemy,
|
|
headless = false,
|
|
session = s6,
|
|
})
|
|
local catchRes6 = Catching.storeCaught(s6, enemy6, 4)
|
|
check(catchRes6 and catchRes6.location == "pc", "the catch really overflowed into the PC")
|
|
local mark6 = #(BattleUi._log or {})
|
|
Battle.startPostCatchFlow(catchRes6)
|
|
run_to_choice()
|
|
check(Choice.active == true, "the nickname Yes/No is up")
|
|
mockInput:clear()
|
|
mockInput:press("b")
|
|
Battle.update(1 / 60, { input = mockInput })
|
|
check(not Naming.isOpen(), "declining does not open the keyboard")
|
|
check(Battle._phase == "catch_pc_msg", "phase is catch_pc_msg (got " .. tostring(Battle._phase) .. ")")
|
|
local line6
|
|
for _, m in ipairs(log_after(mark6)) do if has(m, "transferred") then line6 = m end end
|
|
check(line6 ~= nil, "a transfer line reached the battle log")
|
|
check(not has(line6 or "", "to the PC."), "init.lua no longer hand-writes the line")
|
|
check(has(line6 or "", "BOX “BOX 1” on\nSomeone's PC was full."),
|
|
"the box-was-full page is pret's: " .. flat(line6))
|
|
check(has(line6 or "", "CATERPIE was transferred to\nBOX “BOX 2.”"), "and the species name is used")
|
|
|
|
print("[test] 7. naming the caught mon skips the line, as trygivecaughtmonnick does")
|
|
local s7 = new_session(true)
|
|
local st7, enemy7 = foe_state(s7)
|
|
Battle.start({
|
|
wild = true,
|
|
playerParty = s7.party,
|
|
foe = st7.enemy,
|
|
headless = false,
|
|
session = s7,
|
|
})
|
|
local catchRes7 = Catching.storeCaught(s7, enemy7, 4)
|
|
check(catchRes7 and catchRes7.location == "pc", "the second catch also overflowed into the PC")
|
|
local mark7 = #(BattleUi._log or {})
|
|
Battle.startPostCatchFlow(catchRes7)
|
|
run_to_choice()
|
|
mockInput:clear()
|
|
mockInput:press("a")
|
|
Battle.update(1 / 60, { input = mockInput })
|
|
check(Naming.isOpen(), "accepting opens the keyboard")
|
|
Naming.close("AAAAAAAAAA")
|
|
check(catchRes7.mon.nickname == "AAAAAAAAAA", "the typed nickname was applied to the boxed mon")
|
|
local leaked = nil
|
|
for _, m in ipairs(log_after(mark7)) do
|
|
if has(m, "transferred") then leaked = m end
|
|
end
|
|
check(leaked == nil, "no transfer line is printed on the nickname branch (got " .. flat(leaked) .. ")")
|
|
check(Battle._phase == "ending", "battle goes straight to ending (got " .. tostring(Battle._phase) .. ")")
|
|
|
|
print("[test] 8. the nickname branch still runs givecaughtmon's ShouldShowBoxWasFullMessage")
|
|
check(Flags.getFlag(s7.store, nil, FLAG_SHOWN_BOX_WAS_FULL_MESSAGE) and true or false,
|
|
"FLAG_SHOWN_BOX_WAS_FULL_MESSAGE is set after the nicknamed catch")
|
|
local st8, enemy8 = foe_state(s7)
|
|
Battle.start({
|
|
wild = true,
|
|
playerParty = s7.party,
|
|
foe = st8.enemy,
|
|
headless = false,
|
|
session = s7,
|
|
})
|
|
local catchRes8 = Catching.storeCaught(s7, enemy8, 4)
|
|
check(catchRes8 and catchRes8.location == "pc", "the next catch overflows into the PC too")
|
|
local mark8 = #(BattleUi._log or {})
|
|
Battle.startPostCatchFlow(catchRes8)
|
|
run_to_choice()
|
|
mockInput:clear()
|
|
mockInput:press("b")
|
|
Battle.update(1 / 60, { input = mockInput })
|
|
local line8
|
|
for _, m in ipairs(log_after(mark8)) do if has(m, "transferred") then line8 = m end end
|
|
check(has(line8 or "", "CATERPIE was transferred to\nSomeone's PC."),
|
|
"the declined catch after it gets the plain line: " .. flat(line8))
|
|
check(not has(line8 or "", "was full"), "and not a second box-was-full page")
|
|
|
|
Runtime.session = prevSession
|
|
|
|
if failed > 0 then
|
|
print(string.format("\n%d PC-transfer test(s) failed.", failed))
|
|
os.exit(1)
|
|
end
|
|
print("\nAll PC-transfer tests passed.")
|