Files
gen1recomp/tests/engine/status_screen_white_hold_2060.lua

168 lines
5.7 KiB
Lua

-- engine/menus/start_sub_menus.asm:97-104
-- engine/pokemon/status_screen.asm:82, home/pokemon.asm:186
-- luajit tests/engine/status_screen_white_hold_2060.lua
package.path = "./?.lua;./?/init.lua;" .. package.path
local T = require("tests.harness")
local rects = {}
local color = { 1, 1, 1, 1 }
love = love or {}
love.graphics = {
setColor = function(r, g, b, a) color = { r, g, b, a or 1 } end,
rectangle = function(_, x, y, w, h)
rects[#rects + 1] = { x = x, y = y, w = w, h = h, color = color }
end,
draw = function() end,
push = function() end, pop = function() end,
translate = function() end, scale = function() end,
}
package.loaded["src.render.Font"] = {
draw = function() end, drawCode = function() end, drawBox = function() end,
width = function() return 0 end,
}
package.loaded["src.render.HudTiles"] = {
statusTile = function() end, tile = function() end, drawHPBar = function() end,
}
package.loaded["src.render.PaletteFX"] = {
shader = function() return nil end,
pal = function() return nil end,
markTrueColor = function() end,
}
package.loaded["src.pokemon.Sprites"] = { path = function() return nil, false end }
local cries = {}
package.loaded["src.core.Sound"] = {
play = function() end,
playCry = function(_, species) cries[#cries + 1] = species end,
}
package.loaded["src.mods.Runtime"] = {
wants = function() return false end,
wantsHook = function() return false end,
emit = function() end,
call = function(_, fallback, ...) return fallback(...) end,
}
package.loaded["src.ui.Screens"] = {}
local Transition = require("src.render.Transition")
local SummaryMenu = assert(loadfile("src/ui/SummaryMenu.lua"))()
local function mkGame()
local stack = { states = {} }
function stack:push(s) self.states[#self.states + 1] = s end
function stack:pop() return table.remove(self.states) end
function stack:top() return self.states[#self.states] end
local input = { pressed = nil }
function input:wasPressed(b) return self.pressed == b end
return {
data = {
pokemon = { BULBASAUR = { name = "BULBASAUR", dex = 1, types = { "GRASS" } } },
moves = {},
statuses = nil,
},
save = { player = { id = 1, name = "RED" } },
stack = stack,
input = input,
}
end
local function mkMon()
return {
nickname = "SAUR", species = "BULBASAUR", level = 5, exp = 100,
hp = 10, stats = { hp = 10, attack = 5, defense = 5, speed = 5, special = 5 },
moves = {},
}
end
local game = mkGame()
local mon = mkMon()
local FRAMES = Transition.flashFrames(game)
T.check(type(FRAMES) == "number" and FRAMES > 0,
"Transition.flashFrames reports the white_flash record's frame count")
local function step(button)
game.input.pressed = button
local top = game.stack:top()
if top and top.update then top:update(1 / 60) end
game.input.pressed = nil
end
local function fullScreenRects()
rects = {}
local top = game.stack:top()
if top and top.draw then top:draw() end
local n = 0
for _, r in ipairs(rects) do
if r.x == 0 and r.y == 0 and r.w == 160 and r.h == 144 then n = n + 1 end
end
return n
end
-- engine/pokemon/status_screen.asm:82
local screen = SummaryMenu.new(game, mon)
game.stack:push(screen)
T.eq(screen.whiteHold, FRAMES, "SummaryMenu opens with a full white hold")
T.eq(#cries, 0, "and the cry has not played yet (status_screen.asm:168-172)")
T.eq(fullScreenRects(), 2,
"the held frame paints the page and then a white overlay on top")
for i = 1, FRAMES - 1 do
step("a")
T.eq(screen.whiteHold, FRAMES - i, "the hold burns one frame per update")
T.eq(screen.page, 1, "A pressed during the hold is eaten, not a page flip")
T.eq(#cries, 0, "the cry waits for GBPalNormal")
end
step()
T.eq(screen.whiteHold, 0, "the hold ends after its frame budget")
T.eq(#cries, 1, "PlayCry fires exactly once, at the end of the hold")
T.eq(cries[1], "BULBASAUR", "and it is this mon's cry")
T.eq(fullScreenRects(), 1, "after the hold the page draws with no overlay")
step("a")
T.eq(screen.page, 2, "A flips to page 2 once the hold is over")
T.eq(#game.stack.states, 1, "the page flip pushes nothing")
step("a")
T.eq(#game.stack.states, 2, "closing page 2 pushes the exit white-out")
local blink = game.stack:top()
T.check(blink ~= nil and blink.pages == nil and blink.isOpaque == true
and type(blink.frames) == "number",
"the pushed state is the opaque WhiteFlash, not a text box")
T.eq(blink.frames, FRAMES, "and it holds for the same white_flash budget")
T.eq(fullScreenRects(), 1, "the exit hold paints solid white over everything")
for i = 1, FRAMES - 1 do
step()
T.eq(#game.stack.states, 2,
"the status screen is still on the stack at hold frame " .. i)
end
step()
T.eq(#game.stack.states, 0,
"the flash and the status screen come off together (status_screen.asm:431)")
T.eq(#cries, 1, "closing does not replay the cry")
-- engine/pokemon/status_screen.asm:172
local zeroGame = mkGame()
zeroGame.data.transitions = { white_flash = { kind = "fade", frames = 0 } }
cries = {}
T.eq(Transition.flashFrames(zeroGame), 0,
"a mod can zero the white_flash record's frames")
local zeroScreen = SummaryMenu.new(zeroGame, mkMon())
zeroGame.stack:push(zeroScreen)
T.eq(zeroScreen.whiteHold, 0, "the status screen then opens with no hold")
T.eq(#cries, 1, "and the cry still plays, immediately on entry")
T.eq(cries[1], "BULBASAUR", "and it is this mon's cry")
zeroGame.input.pressed = nil
zeroScreen:update(1 / 60)
T.eq(#cries, 1, "the zero-frame hold does not replay the cry")
T.eq(zeroScreen.page, 1, "and an idle frame does not flip the page")
zeroGame.input.pressed = "a"
zeroScreen:update(1 / 60)
zeroGame.input.pressed = nil
T.eq(zeroScreen.page, 2, "input is live at once with no hold to burn")
T.finish("status_screen_white_hold_2060")