Files
gen1recomp/tests/drivers/game3_partial_trap.lua
T

182 lines
6.2 KiB
Lua

local U = require("tests.drivers.util")
local DIR = os.getenv("POKEPORT_SHOT_DIR") or "/tmp/game3_partial_trap"
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 Ui = require("src.core.game3.battle.ui")
local Rules = require("src.core.game3.battle.rules")
local session = Runtime.getSession()
session.party = {}
Party.giveMon(session, 6, 50)
local pm = session.party[1]
pm.moves = { 35, 150 }
pm.pp = { 20, 40 }
pm.maxPp = { 20, 40 }
local ok, err = BattleBridge.startWild(Runtime._mod, game, { species = 129, level = 60 }, { fade = false })
result(ok == true, "wild battle started " .. tostring(err or ""))
if not ok then love.event.quit(1) return end
local function cur_step()
return AnimSeq._steps and AnimSeq._steps[AnimSeq._i]
end
local function vm_active_for(animName)
return function()
local s = cur_step()
if not s or s.kind ~= "anim" or s.data.name ~= animName then return false end
return Anim.vm() and Anim.vm():busy()
end
end
local function msg_says(needle)
return function()
local s = cur_step()
if not s or s.kind ~= "msg" then return false end
local Message = package.loaded["src.ui.game3.message"]
if Message and Message.isTyping and Message.isTyping() then return false end
if not (Ui.dialogPending and Ui.dialogPending()) then return false end
return tostring(s.data.text or ""):find(needle, 1, true) ~= nil
end
end
local SHOTS = {
{ match = msg_says("was WRAPPED by"), delay = 2, file = "partial_trap_01_wrapped.png" },
{ match = vm_active_for("TURN_TRAP"), delay = 14, file = "partial_trap_02_turn_trap.png" },
{ match = msg_says("is hurt"), delay = 2, file = "partial_trap_03_chip.png" },
{ match = msg_says("was freed"), delay = 2, file = "partial_trap_04_freed.png" },
}
local counts = {}
local function at_command()
return Battle.isActive() and Battle._phase == "command" and Ui._mode == "menu"
end
local f, lastTap = 0, 0
local function pump()
f = f + 1
for si, sh in ipairs(SHOTS) do
if not sh.taken and sh.match() then
counts[si] = (counts[si] or 0) + 1
if counts[si] >= sh.delay then
sh.taken = true
U.shot(game, DIR .. "/" .. sh.file)
print("shot " .. sh.file)
end
end
end
if Ui.dialogPending and Ui.dialogPending() and f - lastTap >= 14 then
lastTap = f
U.tap(game, "a")
else
U.wait(1)
end
end
for _ = 1, 3000 do
if at_command() then break end
pump()
end
result(at_command(), "reached command menu")
local st = Battle.getState()
if not st then love.event.quit(1) return end
local logI = 0
local function turn(slot, label)
U.tap(game, "a")
for _ = 1, 120 do
if Ui._mode == "moves" then break end
U.wait(1)
end
if Ui._mode ~= "moves" then
result(false, "move menu opened for " .. label)
return
end
for _ = 1, 4 do
if Ui._moveIndex == slot then break end
U.tap(game, (Ui._moveIndex or 1) < slot and "right" or "left")
U.wait(4)
end
result(Ui._moveIndex == slot, "cursor on move slot " .. slot .. " for " .. label)
U.tap(game, "a")
for i = 1, 4000 do
if not Battle.isActive() then break end
if i > 20 and at_command() then break end
pump()
end
local log = Ui.log()
for li = logI + 1, #log do print(" log: " .. tostring(log[li]):gsub("\n", " ")) end
logI = #log
print(string.format(" turn %s ehp=%s/%s php=%s trap=%s", label, tostring(st.enemy.mon.hp),
tostring(st.enemy.mon.maxHp), tostring(st.player.mon.hp), tostring(st.enemy.expTrapTurns)))
end
-- pokefirered/src/battle_script_commands.c:2490
for _ = 1, 6 do
if (st.enemy.expTrapTurns or 0) > 0 or not Battle.isActive() then break end
turn(1, "wrap")
end
local rolled = st.enemy.expTrapTurns or 0
result(rolled >= 2 and rolled <= 5, "trap turns left after the first residual are 2..5, got " .. tostring(rolled))
local wrapText = false
for _, t in ipairs(Ui.log()) do
if t:find("WRAPPED by", 1, true) then wrapText = true end
end
result(wrapText, "gWrappedStringIds message for MOVE_WRAP printed")
-- pokefirered/src/battle_util.c:886
local chip = Rules.partialTrap.chipAmount(st.enemy.mon.maxHp)
local ticks, freed, freedText = 0, false, false
for _ = 1, 8 do
if not Battle.isActive() then break end
local left = st.enemy.expTrapTurns
if not left then freed = true break end
local before = st.enemy.mon.hp
local mark = #Ui.log()
turn(2, "splash while trapped")
local lost = before - st.enemy.mon.hp
for li = mark + 1, #Ui.log() do
if Ui.log()[li]:find("was freed", 1, true) then freedText = true end
end
if st.enemy.expTrapTurns then
ticks = ticks + 1
result(lost == chip, string.format("residual chip is exactly maxHP/16 (%d == %d)", lost, chip))
result(st.enemy.expTrapTurns == left - 1, "trap counter ticked down by one")
else
result(lost == 0, "release turn deals no chip (" .. tostring(lost) .. ")")
freed = true
end
end
result(freed and freedText, "trap released on its own with the freed message")
result(ticks == rolled - 1, string.format("chip turns (%d) == rolled remaining - 1 (%d)", ticks, rolled - 1))
result(st.enemy.expTrapTurns == nil, "expTrapTurns cleared on release")
result(Battle.isActive() and at_command(), "battle still live at the command menu after release")
for _, sh in ipairs(SHOTS) do
result(sh.taken == true, "shot " .. sh.file)
end
print((fails == 0) and "PARTIAL_TRAP DRIVER PASS" or ("PARTIAL_TRAP DRIVER FAIL " .. fails))
love.event.quit(fails == 0 and 0 or 1)
end