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