Files
gen1recomp/tests/drivers/nightshade_anim_bug1848_test.lua
T

123 lines
4.5 KiB
Lua

-- Eye check on NIGHT_SHADE's wavy screen (#1848). AnimationWavyScreen's
-- `ld c, $ff` counts outer passes and the inner loop exits twice a frame
-- (pokered engine/battle/animations.asm:1884-1903, 1916-1927), so the
-- wobble runs ~128 frames with a 16-line wave, not 255 with a 32-line one.
-- POKEPORT_DRIVER=tests/drivers/nightshade_anim_bug1848_test.lua POKEPORT_IDENTITY=bug1848 POKEPORT_TOUCH=0 love .
-- No POKEPORT_SPEED: fast-forward scales the logic clock only.
return function(game)
local U = dofile("tests/drivers/util.lua")
local Pokemon = require("src.pokemon.Pokemon")
local BattleState = require("src.battle.BattleState")
local AnimPlayer = require("src.battle.AnimPlayer")
local DIR = os.getenv("SHOT_DIR") or "/tmp/shots"
-- data/generated/maps.lua ROUTE_1: open path south of the first grass
-- patch; pokered data/maps/objects/Route1.asm parks its youngsters at
-- (5, 24) and (15, 13), so nobody is standing here or watching.
local MAP = "ROUTE_1"
local STAND = { x = 5, y = 5, facing = "down" }
local function check(label, ok)
U.log(ok and "PASS" or "FAIL", label)
return ok
end
local opts = game.save.options or {}
local sfxVol = opts.sfxVol or 7
if sfxVol == 0 then
U.log("FAIL sfx volume is 0, so the flash that opens the animation is")
U.log(" silent. Set SFX to 7 in OPTION first.")
end
check(("sfx volume %d"):format(sfxVol), sfxVol > 0)
if opts.animations == false then
U.log("FAIL OPTION has animations off, which skips every queued anim row.")
end
check("battle animations are on", opts.animations ~= false)
local anims = (game.data.battle_anims or {}).moveAnims or {}
check("NIGHT_SHADE has an animation", anims.NIGHT_SHADE ~= nil)
-- what the animation player budgets for the effect, ahead of the battle
local probe = AnimPlayer.new(game.data.battle_anims)
probe:start("NIGHT_SHADE", true)
local budget
for _, e in ipairs(probe.events) do
if e.effect == "SE_WAVY_SCREEN" then budget = e.dur end
end
check(("SE_WAVY_SCREEN is budgeted %s frames (want 128)"):format(tostring(budget)),
budget == 128)
local lead = Pokemon.new(game.data, "GASTLY", 25)
lead.moves = { { id = "NIGHT_SHADE", pp = 15 } }
game.save.party = { lead }
U.teleport(game, MAP, STAND.x, STAND.y, STAND.facing)
U.wait(15)
local ow = game.overworld
if not ow.map:isWalkableCell(STAND.x, STAND.y) then
for _, d in ipairs({ { 0, 1 }, { 0, -1 }, { 1, 0 }, { -1, 0 } }) do
local cx, cy = STAND.x + d[1], STAND.y + d[2]
if ow.map:isWalkableCell(cx, cy) and not ow:npcAtCell(cx, cy) then
U.log(("(%d, %d) is blocked, standing on"):format(STAND.x, STAND.y), cx, cy)
U.teleport(game, MAP, cx, cy, STAND.facing)
U.wait(15)
ow = game.overworld
break
end
end
end
check("standing on " .. MAP, ow.map.id == MAP)
local battle = BattleState.newWild(game, "PIDGEY", 6)
battle.onFinish = function() end
ow:pushBattle(battle)
local function waitPhase(phase, tries)
for _ = 1, tries do
if battle.phase == phase then return true end
U.tap(game, "a")
U.wait(6)
end
return battle.phase == phase
end
check("the battle reached the menu", waitPhase("menu", 60))
U.tap(game, "a")
check("NIGHT_SHADE is the move on the list", waitPhase("moveSelect", 20))
U.tap(game, "a")
-- ride the animation and time the wave from the fx layer itself
local started, frames, phases = false, 0, {}
local shots = { [4] = "start", [64] = "middle", [124] = "end" }
for _ = 1, 400 do
local wavy = battle.fx and battle.fx.wavy
if wavy then
started = true
frames = frames + 1
phases[#phases + 1] = wavy.phase
local tag = shots[frames]
if tag then
U.shot(game, ("%s/bug1848_wavy_%s.png"):format(DIR, tag))
end
elseif started then
break
end
U.wait(1)
end
check("the wave actually ran", started)
check(("the wave lasted %d frames (want 128)"):format(frames),
frames >= 120 and frames <= 136)
local step = (#phases >= 2) and (phases[2] - phases[1]) or 0
check(("the offset pointer advances %d entries a frame (want 2)"):format(step),
step == 2)
U.log("Three shots are in " .. DIR .. ": bug1848_wavy_start/middle/end.png.")
U.log("The screen should ripple with about nine full waves top to bottom,")
U.log("scrolling upward, and settle after roughly two seconds. The near-miss")
U.log("to watch for is half that many waves crawling for twice as long.")
while true do
coroutine.yield()
end
end