mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-20 04:31:09 +02:00
G2 support
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
-- The end of the game, sampled: the Hall of Fame induction, the credits roll,
|
||||
-- and the roster the PC shows afterwards.
|
||||
--
|
||||
-- POKEPORT_GAME=gold POKEPORT_DRIVER=tests/drivers/gold_halloffame_shots.lua love .
|
||||
-- POKEPORT_SHOT_DIR=/tmp/gold-hof (default)
|
||||
--
|
||||
-- Everything here is a cinematic, which is exactly what no assertion can
|
||||
-- check: "does the backpic really sweep off to the left before the frontpic
|
||||
-- comes back", "does the banner change mon on each CREDITS_SCENE", "does THE
|
||||
-- END stay up after the last blank" are questions for eyes. So this stands
|
||||
-- the real screens up on the real stack, lets them run at their own 60 Hz, and
|
||||
-- lays each one out as a contact sheet.
|
||||
--
|
||||
-- Shots are named by the frame the screen has been running for and the phase
|
||||
-- (or credits scene) it is in, so a file is directly comparable against
|
||||
-- engine/events/halloffame.asm and engine/movie/credits.asm.
|
||||
local U = require("tests.drivers.util")
|
||||
|
||||
local Core = require("src.core.gen2.HallOfFame")
|
||||
local Credits = require("src.ui.gen2.Credits")
|
||||
local HallOfFame = require("src.ui.gen2.HallOfFame")
|
||||
local Mon = require("src.battle.gen2.Mon")
|
||||
|
||||
-- The induction is 292 frames a mon, so a six-mon party runs about 1900
|
||||
-- frames; the credits are about 4400. Half a second apiece keeps both
|
||||
-- readable without an unusable number of files.
|
||||
local INDUCT_INTERVAL = 20
|
||||
local CREDITS_INTERVAL = 60
|
||||
local LIMIT = 8000
|
||||
|
||||
return function(game)
|
||||
local out = os.getenv("POKEPORT_SHOT_DIR") or "/tmp/gold-hof"
|
||||
|
||||
U.wait(45)
|
||||
assert(game.world and game.world.map, "gold world did not boot")
|
||||
|
||||
local save = game.save
|
||||
local data = game.data
|
||||
|
||||
-- A champion's party. Mon.new is the ONE builder for a Gen 2 party member:
|
||||
-- anything routed through Gen 1's Pokemon.new comes back with no moves,
|
||||
-- because a Gen 2 moveset is levelMoves and Gen 1 reads level1Moves.
|
||||
local roster = {
|
||||
{ "TYPHLOSION", 50, "BLAZE" },
|
||||
{ "LANTURN", 46, "SPARK" },
|
||||
{ "AMPHAROS", 45, nil },
|
||||
{ "UMBREON", 44, "DUSK" },
|
||||
{ "SCIZOR", 43, nil },
|
||||
{ "GYARADOS", 47, "RAGE" },
|
||||
}
|
||||
save.party = {}
|
||||
for _, row in ipairs(roster) do
|
||||
local mon = Mon.new(data, row[1], row[2], { nickname = row[3] })
|
||||
if mon then
|
||||
mon.otId = save.player and save.player.id or 12345
|
||||
save.party[#save.party + 1] = mon
|
||||
end
|
||||
end
|
||||
assert(#save.party > 0, "no party could be built from this cache")
|
||||
save.player.name = save.player.name or "GOLD"
|
||||
save.playTime = { hours = 42, minutes = 7, seconds = 0, frames = 0 }
|
||||
|
||||
-- ---- the induction ------------------------------------------------------
|
||||
|
||||
-- What the `halloffame` opcode does to the save before the screen opens.
|
||||
-- `wasEntered` is the ALLOW_SKIPPING_CREDITS_F bit Credits wants: false the
|
||||
-- first time, which is why a first-time champion cannot hurry the roll.
|
||||
local entry, wasEntered = Core.induct(save, save.party)
|
||||
U.log(("inducted: %d mon(s), win count %d, spawn %s")
|
||||
:format(#entry.mons, entry.winCount, tostring(save.spawnAfterChampion)))
|
||||
|
||||
local inducted = false
|
||||
local induction = HallOfFame.new(game, {
|
||||
save = save, entry = entry,
|
||||
onDone = function() inducted = true end,
|
||||
})
|
||||
game.stack:clear()
|
||||
game.stack:push(induction)
|
||||
|
||||
local shots, phase = 0, nil
|
||||
while not inducted and induction.frames < LIMIT do
|
||||
U.wait(INDUCT_INTERVAL)
|
||||
if induction.phase ~= phase then
|
||||
phase = induction.phase
|
||||
U.log(("hof phase %s at frame %d (mon %d, scx=%02x scy=%02x)")
|
||||
:format(tostring(phase), induction.frames, induction.index,
|
||||
induction.scx, induction.scy))
|
||||
end
|
||||
U.shot(game, ("%s/hof-%04d-%s.png")
|
||||
:format(out, induction.frames, tostring(phase)))
|
||||
shots = shots + 1
|
||||
end
|
||||
assert(inducted, "the induction never reached HOF_AnimatePlayerPic's end")
|
||||
U.log(("%d induction shots over %d frames"):format(shots, induction.frames))
|
||||
game.stack:pop()
|
||||
|
||||
-- ---- the credits --------------------------------------------------------
|
||||
|
||||
local rolled = false
|
||||
local credits = Credits.new(game, {
|
||||
allowSkip = wasEntered,
|
||||
onDone = function() rolled = true end,
|
||||
})
|
||||
game.stack:clear()
|
||||
game.stack:push(credits)
|
||||
|
||||
shots = 0
|
||||
local scene = -1
|
||||
while not credits.exiting and credits.frames < LIMIT do
|
||||
U.wait(CREDITS_INTERVAL)
|
||||
if credits.scene ~= scene then
|
||||
scene = credits.scene
|
||||
U.log(("credits scene %d at frame %d (pass %d, pos %d)")
|
||||
:format(scene, credits.frames, credits.passes, credits.pos))
|
||||
end
|
||||
U.shot(game, ("%s/credits-%04d-scene%d.png")
|
||||
:format(out, credits.frames, scene))
|
||||
shots = shots + 1
|
||||
end
|
||||
assert(credits.exiting, "the credits script never reached CREDITS_END")
|
||||
-- CREDITS_END only sets the exit flag; the screen waits on A, so the last
|
||||
-- shot is THE END sitting there exactly as the player sees it.
|
||||
U.wait(30)
|
||||
U.shot(game, ("%s/credits-%04d-theend.png"):format(out, credits.frames))
|
||||
U.log(("%d credits shots over %d frames, %d passes")
|
||||
:format(shots + 1, credits.frames, credits.passes))
|
||||
U.tap(game, "a")
|
||||
U.wait(10)
|
||||
assert(rolled, "A did not leave the credits once the exit flag was up")
|
||||
game.stack:clear()
|
||||
|
||||
-- ---- the roster, as the PC shows it -------------------------------------
|
||||
|
||||
-- _HallOfFamePC over the row that was just written: A walks the team, and
|
||||
-- the header is "-Time Famer" rather than "New Hall of Famer!".
|
||||
local viewer = HallOfFame.new(game, {
|
||||
mode = "view", save = save, onDone = function() end,
|
||||
})
|
||||
game.stack:push(viewer)
|
||||
for index = 1, #entry.mons do
|
||||
U.wait(10)
|
||||
U.shot(game, ("%s/pc-%02d-%s.png")
|
||||
:format(out, index, tostring((viewer:currentMon() or {}).species)))
|
||||
U.tap(game, "a")
|
||||
end
|
||||
U.log("roster viewer shot for " .. #entry.mons .. " mon(s) in " .. out)
|
||||
end
|
||||
Reference in New Issue
Block a user