Files
bryanthaboi 96d23ab93b battle stuff
2026-09-18 13:11:33 -04:00

256 lines
9.5 KiB
Lua

local U = require("tests.drivers.util")
local DIR = os.getenv("POKEPORT_SHOT_DIR") or "/tmp/game3_battle_gaps"
return function(game)
local fails = 0
local function result(ok, label)
print((ok and "PASS " or "FAIL ") .. label)
if not ok then fails = fails + 1 end
end
for _ = 1, 600 do
if game.phase == "boot" and game.boot then break end
U.wait(1)
end
game:_handleBootAction({ action = "new_game", name = "RED" })
U.wait(180)
local Runtime = require("src.core.game3.runtime")
local Party = require("src.core.game3.party")
local BattleBridge = require("src.core.game3.battle_bridge")
local Battle = require("src.core.game3.battle")
local Anim = require("src.core.game3.battle.anim")
local AnimSeq = require("src.core.game3.battle.anim_seq")
local IntroSeq = require("src.core.game3.battle.intro_seq")
local Ui = require("src.core.game3.battle.ui")
local PartyMenu = require("src.ui.game3.party_menu")
local Message = require("src.ui.game3.message")
local session = Runtime.getSession()
local f, lastTap = 0, 0
local function pump_text()
if Ui.dialogPending and Ui.dialogPending() and f - lastTap >= 14 then
lastTap = f
U.tap(game, "a")
return true
end
return false
end
local function at_command()
return Battle.isActive() and Battle._phase == "command" and Ui._mode == "menu"
end
local function cur_step()
return AnimSeq._steps and AnimSeq._steps[AnimSeq._i]
end
local function vm_busy()
return Anim.vm() and Anim.vm():busy()
end
local function page()
return Message.isOpen() and tostring(Message.currentPage()) or ""
end
local function run_until(pred, shots, limit, choose)
shots = shots or {}
local counts = {}
local menuFrames = 0
for _ = 1, limit or 4000 do
f = f + 1
local holding = false
for _, sh in ipairs(shots) do
if not sh.taken and sh.match() then
holding = true
counts[sh] = (counts[sh] or 0) + 1
if counts[sh] >= (sh.delay or 1) then
sh.taken = U.shot(game, DIR .. "/" .. sh.file)
print("shot " .. sh.file .. " text=" .. page():gsub("\n", " "))
end
end
end
if pred() then return true end
if PartyMenu.isOpen() and choose then
menuFrames = menuFrames + 1
if menuFrames > 45 then
menuFrames = 0
choose()
else
U.wait(1)
end
elseif holding then
U.wait(1)
else
local s = cur_step()
if vm_busy() or (s and s.kind ~= "msg") or IntroSeq._waitingGen then
U.wait(1)
elseif not pump_text() then
U.wait(1)
end
end
end
return false
end
local function report(shots)
for _, sh in ipairs(shots) do result(sh.taken == true, "shot " .. sh.file) end
end
local function finish_battle()
Battle.abort("run")
for _ = 1, 120 do
if not Battle.isActive() then break end
U.wait(1)
end
U.wait(30)
end
local function command(cmd)
Ui._pendingCommand = cmd
Ui._mode = "none"
end
local function log_tail(from)
local log = Ui.log()
for i = from + 1, #log do print(" log: " .. tostring(log[i]):gsub("\n", " ")) end
return #log
end
session.party = {}
Party.giveMon(session, 6, 50)
Party.giveMon(session, 25, 40)
do
local ok = BattleBridge.startWild(Runtime._mod, game, { species = 92, level = 20, ghost = true }, { fade = false })
result(ok == true, "ghost battle started")
local shots = {
{ match = function() return page():find("can't be ID'd", 1, true) ~= nil end, delay = 40, file = "gap_01_ghost_intro.png" },
}
run_until(at_command, shots, 3000)
report(shots)
result(at_command(), "ghost battle command menu")
local st = Battle.getState()
result(st and st.ghostBattle and not st.ghostUnveiled, "ghost battle flag")
local li = log_tail(0)
local turnShots = {
{ match = function() local s = cur_step() return s and s.kind == "anim" and s.data.name == "MON_SCARED" and vm_busy() end,
delay = 24, file = "gap_02_too_scared.png" },
{ match = function() local s = cur_step() return s and s.kind == "anim" and s.data.name == "GHOST_GET_OUT" and vm_busy() end,
delay = 60, file = "gap_03_get_out.png" },
}
command({ kind = "move", move = st.player.mon.moves[1], slot = 1, user = "player" })
run_until(function() return f > 10 and at_command() end, turnShots, 4000)
report(turnShots)
li = log_tail(li)
result(st.enemy.mon.hp == st.enemy.mon.maxHp, "ghost untouched")
local Bag = require("src.core.game3.bag")
Bag.add(session.bag, 4, 3)
local ballShots = {
{ match = function() return page():find("dodged", 1, true) ~= nil end, delay = 20, file = "gap_04_ball_dodge.png" },
}
command({ kind = "bag", itemId = 4, user = "player" })
run_until(function() return f > 10 and at_command() end, ballShots, 4000)
report(ballShots)
li = log_tail(li)
command({ kind = "run", user = "player" })
run_until(function() return not Battle.isActive() end, {}, 2000)
log_tail(li)
result(not Battle.isActive(), "ran from the ghost")
U.wait(30)
end
do
local ok = BattleBridge.startWild(Runtime._mod, game,
{ species = 105, level = 30, ghost = true, ghostUnveiled = true }, { fade = false })
result(ok == true, "marowak battle started")
local shots = {
{ match = function() return page():find("unveiled", 1, true) ~= nil and not vm_busy() end, delay = 10, file = "gap_05_scope_text.png" },
{ match = function() local p = Anim.present("enemy") return vm_busy() and (p.mosaic or 0) >= 6 end, delay = 1, file = "gap_06_scope_mosaic.png" },
{ match = function() return page():find("MAROWAK", 1, true) ~= nil end, delay = 30, file = "gap_07_ghost_was_marowak.png" },
}
run_until(at_command, shots, 4000)
report(shots)
local st = Battle.getState()
result(Anim.present("enemy").ghostUnveiled == true and st.enemy.mon.nickname == nil, "marowak unveiled")
log_tail(0)
finish_battle()
end
do
local ok = BattleBridge.start(Runtime._mod, game,
{ trainerId = 326, party = { { species = 58, level = 30, ability = "INTIMIDATE" }, { species = 1, level = 30 } } },
{ wild = false, trainerId = 326, fade = false })
result(ok == true, "trainer battle started")
local sawGo = false
local shots = {
{ match = function()
local s = cur_step()
local hit = Battle._phase == "startfx" and s and s.kind == "anim" and s.data.name == "STATS_CHANGE" and vm_busy()
if hit and page():find("Go!", 1, true) then sawGo = true end
return hit
end, delay = 16, file = "gap_08_intimidate_go_text.png" },
}
run_until(at_command, shots, 4000)
report(shots)
result(sawGo, "Go! text on screen during the intimidate stat drop")
local st = Battle.getState()
Party.giveMon(session, 12, 30)
st.playerParty[3] = st.playerParty[3] or session.party[3]
for _, m in ipairs(st.foeParty or {}) do
m.moves = { 150, 0, 0, 0 }
m.pp = { 40, 0, 0, 0 }
end
st.enemy.mon.moves = { 150, 0, 0, 0 }
st.player.mon.moves[1] = 226
st.player.mon.pp[1] = 10
st.player.stages.attack = 2
local chose = false
local bpShots = {
{ match = function() return PartyMenu.isOpen() end, delay = 30, file = "gap_09_baton_pass_party_menu.png" },
{ match = function() return chose and page():find("Go!", 1, true) ~= nil end, delay = 10, file = "gap_10_baton_pass_go.png" },
}
local target = #st.playerParty
command({ kind = "move", move = 226, slot = 1, user = "player" })
run_until(function() return f > 10 and at_command() end, bpShots, 5000, function()
PartyMenu.cursor = target
U.tap(game, "a")
U.wait(12)
U.tap(game, "a")
U.wait(12)
chose = true
end)
report(bpShots)
result(st.player.partyIndex == target and st.player.stages.attack == 2, "baton pass to the chosen slot kept +2 ATK")
log_tail(0)
finish_battle()
end
do
session.party = {}
Party.giveMon(session, 385, 40)
local ok = BattleBridge.startWild(Runtime._mod, game,
{ species = 385, level = 40, moves = { 240, 0, 0, 0 }, pp = { 5, 0, 0, 0 } }, { fade = false })
result(ok == true, "castform battle started")
run_until(at_command, {}, 3000)
local st = Battle.getState()
st.player.mon.moves[1] = 241
st.player.mon.pp[1] = 5
st.player.mon.speed, st.enemy.mon.speed = 200, 10
U.shot(game, DIR .. "/gap_11_castform_normal.png")
local shots = {
{ match = function() local s = cur_step() return s and s.kind == "anim" and s.data.name == "CASTFORM_CHANGE"
and (Anim.present(s.data.attacker).mosaic or 0) >= 10 end, delay = 1, file = "gap_12_castform_mosaic.png" },
{ match = function() return Anim.present("player").castformForm == 1 and Anim.present("enemy").castformForm == 1
and page():find("transformed", 1, true) ~= nil end, delay = 20, file = "gap_13_castform_both_sunny.png" },
{ match = function() return Anim.present("player").castformForm == 2 end, delay = 40, file = "gap_14_castform_rainy.png" },
}
command({ kind = "move", move = 241, slot = 1, user = "player" })
run_until(function() return f > 10 and at_command() end, shots, 6000)
report(shots)
result(Anim.present("player").castformForm == 2, "player castform ended in RAIN form")
log_tail(0)
finish_battle()
end
print(string.format("battle gaps driver: %d failure(s)", fails))
love.event.quit(fails == 0 and 0 or 1)
end