mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-28 23:00:21 -04:00
145 lines
6.3 KiB
Lua
145 lines
6.3 KiB
Lua
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
|
|
local T = require("tests.harness")
|
|
local check, eq = T.check, T.eq
|
|
|
|
local GameVersion = require("src.core.GameVersion")
|
|
local Profile = require("src.core.game3.profile")
|
|
Profile.reset()
|
|
GameVersion.set("emerald")
|
|
|
|
local Dataset = require("src.core.game3.dataset")
|
|
local cache = Dataset.cache()
|
|
local src = cache and cache:read("data/generated/gba/pokemon/battle_anims/pack.lua")
|
|
local manifest = cache and cache:read("data/generated/gba/pokemon/battle/manifest.lua")
|
|
if type(src) ~= "string" or type(manifest) ~= "string" or not manifest:find('layout = "rse"', 1, true) then
|
|
print("emerald_battle_anims_test: skipped (no Emerald cache; set POKEPORT_IDENTITY)")
|
|
os.exit(0)
|
|
end
|
|
local pack = assert(load(src, "@pack.lua", "t", {}))()
|
|
|
|
local Anim = require("src.core.game3.battle.anim")
|
|
local AnimVm = require("src.core.game3.battle.anim_vm")
|
|
local AnimTasks = require("src.core.game3.battle.anim_tasks")
|
|
local AnimSprites = require("src.core.game3.battle.anim_sprites")
|
|
local AnimCallbacks = require("src.core.game3.battle.anim_callbacks")
|
|
AnimTasks.init()
|
|
|
|
do
|
|
local coords = Anim.Coords
|
|
local vm = AnimVm.new()
|
|
local contestLabel = { { op = "delay", frames = 2 }, { op = "end" } }
|
|
vm:setPack({ labels = { CONTEST_ANIM = contestLabel } })
|
|
local positions = { [2] = { 112, 80, x = 112, y = 80 }, [3] = { 48, 40, x = 48, y = 40 } }
|
|
vm:launch({ { op = "jumpifcontest", label = "CONTEST_ANIM" }, { op = "end" } }, {
|
|
ctx = { isContest = true }, coordinateOverrides = positions, attackerId = 2, targetId = 3,
|
|
})
|
|
vm:update(1 / 60)
|
|
eq(vm.script[1].op, "delay", "jumpifcontest selects the contest animation body")
|
|
eq(coords.coords(nil, 2).x .. "/" .. coords.coords(nil, 3).x, "112/48", "contest coordinates are active during playback")
|
|
vm:tickFrames(5)
|
|
eq(vm.active, false, "contest animation VM finishes")
|
|
check(coords.coords(nil, 2) ~= positions[2], "animation end restores shared battler coordinates")
|
|
end
|
|
|
|
local moves = 0
|
|
for _ in pairs(pack.moves) do moves = moves + 1 end
|
|
eq(moves, 355, "Emerald gBattleAnims_Moves rows")
|
|
eq(pack.generalNames[4], "POKEBLOCK_THROW", "general anim 4")
|
|
eq(#pack.generalNames, 22, "23 general anims")
|
|
check(pack.tags.POKEBLOCK ~= nil and pack.tags.SAFARI_BAIT == nil, "tag 269 is POKEBLOCK on Emerald")
|
|
|
|
local function taskOk(name)
|
|
local key = tostring(name):gsub("^g", "")
|
|
return AnimTasks.REGISTRY[name] or AnimTasks.REGISTRY[key] or AnimTasks.REGISTRY["AnimTask_" .. key]
|
|
end
|
|
local function cbOk(name)
|
|
local clean = tostring(name):gsub("^Anim", "")
|
|
return AnimCallbacks[name] or AnimCallbacks[clean] or AnimCallbacks["Anim" .. clean]
|
|
end
|
|
local missing = {}
|
|
local function scan(script, where)
|
|
for _, op in ipairs(script or {}) do
|
|
if op.op == "createvisualtask" or op.op == "createsoundtask" then
|
|
if not taskOk(op.task) then missing[#missing + 1] = "task " .. tostring(op.task) .. " @" .. where end
|
|
elseif op.op == "createsprite" then
|
|
if op.callback and op.callback ~= "" and not cbOk(op.callback)
|
|
and not AnimTasks.REGISTRY["_noGfx_" .. op.callback] and not (op.noGfx and taskOk(op.callback)) then
|
|
missing[#missing + 1] = "callback " .. op.callback .. " @" .. where
|
|
end
|
|
if op.tag and not pack.tags[op.tag] then missing[#missing + 1] = "tag " .. op.tag .. " @" .. where end
|
|
elseif op.op == "loadspritegfx" and op.tag and not pack.tags[op.tag] then
|
|
missing[#missing + 1] = "tag " .. op.tag .. " @" .. where
|
|
end
|
|
end
|
|
end
|
|
for id, s in pairs(pack.moves) do scan(s, "move " .. id) end
|
|
for _, kind in ipairs({ "general", "special", "status" }) do
|
|
for i, s in pairs(pack[kind]) do scan(s, kind .. " " .. tostring(pack[kind .. "Names"][i])) end
|
|
end
|
|
for l, s in pairs(pack.labels) do scan(s, "label " .. l) end
|
|
for _, m in ipairs(missing) do print(" unresolved " .. m) end
|
|
eq(#missing, 0, "every task/callback/tag in the Emerald pack resolves")
|
|
check(taskOk("ThrowBall_StandingTrainer") ~= nil, "AnimTask_ThrowBall_StandingTrainer registered")
|
|
check(taskOk("IsBallBlockedByTrainer") ~= nil, "AnimTask_IsBallBlockedByTrainer registered")
|
|
|
|
local PicSizes = require("src.core.game3.battle.anim_port.g1_pic_sizes")
|
|
local pc = assert(load(cache:read("data/generated/gba/pokemon/pic_coords.lua"), "@pic_coords", "t", {}))()
|
|
eq(PicSizes.front[1], pc.front[1].width * 256 + pc.front[1].height, "Emerald front pic size from the pic_coords pack")
|
|
eq(PicSizes.back[25], pc.back[25].width * 256 + pc.back[25].height, "Emerald back pic size from the pic_coords pack")
|
|
check(PicSizes.front ~= PicSizes.FRLG.front, "Emerald does not read the FRLG pic size table")
|
|
eq(require("src.core.game3.battle.anim_port.g2_mon_sizes").front[1],
|
|
(pc.front[1].width / 8) * 16 + pc.front[1].height / 8, "g2 mon size shape from the pack")
|
|
|
|
local rp = print
|
|
local logs = {}
|
|
local errors, timeouts, ran = 0, 0, 0
|
|
local function run(label, script, side)
|
|
AnimTasks.reset()
|
|
AnimSprites.reset()
|
|
Anim.reset({ headless = true })
|
|
Anim.loadPack(pack)
|
|
local vm = AnimVm.new()
|
|
vm:setPack(pack)
|
|
print = function(...) logs[#logs + 1] = label .. ": " .. table.concat({ ... }, " ") end
|
|
local ok, err = pcall(function()
|
|
vm:launch(script, {
|
|
attackerSide = side, targetSide = side == "player" and "enemy" or "player", isReversed = side == "enemy",
|
|
attackerSpecies = 280, targetSpecies = 288,
|
|
})
|
|
local n = 0
|
|
while vm:busy() and n < 1500 do
|
|
n = n + 1
|
|
vm:update(1 / 60)
|
|
Anim.update(1 / 60)
|
|
end
|
|
end)
|
|
print = rp
|
|
ran = ran + 1
|
|
if not ok then
|
|
errors = errors + 1
|
|
rp(" " .. label .. ": " .. tostring(err))
|
|
elseif vm:busy() then
|
|
timeouts = timeouts + 1
|
|
rp(" " .. label .. ": timeout")
|
|
end
|
|
end
|
|
for id = 1, 354 do
|
|
run("move " .. id .. "/player", pack.moves[id], "player")
|
|
run("move " .. id .. "/enemy", pack.moves[id], "enemy")
|
|
end
|
|
for i = 0, #pack.generalNames do run("general " .. pack.generalNames[i], pack.general[i], "player") end
|
|
for i = 0, #pack.statusNames do run("status " .. pack.statusNames[i], pack.status[i], "enemy") end
|
|
local taskErrors = 0
|
|
for _, l in ipairs(logs) do
|
|
if l:find("[battle.anim]", 1, true) and not l:find("cap", 1, true) then
|
|
taskErrors = taskErrors + 1
|
|
rp(" " .. l)
|
|
end
|
|
end
|
|
eq(errors, 0, "no Lua error across " .. ran .. " Emerald anims")
|
|
eq(timeouts, 0, "every Emerald move/general/status anim ends")
|
|
eq(taskErrors, 0, "no task/sprite callback error logged")
|
|
|
|
T.finish()
|