Files
gen1recomp/tests/drivers/boulder_dust_bug2263.lua

151 lines
4.9 KiB
Lua

-- engine/overworld/dust_smoke.asm:1
-- POKEPORT_DRIVER=tests/drivers/boulder_dust_bug2263.lua POKEPORT_IDENTITY=red-sep04 POKEPORT_TOUCH=0 POKEPORT_VERSION=red love .
return function(game)
local U = dofile("tests/drivers/util.lua")
local DIR = os.getenv("POKEPORT_SHOT_DIR") or os.getenv("SHOT_DIR") or "/tmp/shots"
local MAP = "SEAFOAM_ISLANDS_1F"
local DIRS = { "right", "left", "down", "up" }
local STEP = { down = { 0, 1 }, up = { 0, -1 }, left = { -1, 0 }, right = { 1, 0 } }
local ok = true
local function check(label, pass)
U.log(pass and "PASS" or "FAIL", label)
if not pass then ok = false end
return pass
end
local function finish()
for _, d in ipairs(DIRS) do game.input.state[d] = false end
U.log(ok and "PASS boulder_dust_2263" or "FAIL boulder_dust_2263")
love.event.quit(ok and 0 or 1)
while true do coroutine.yield() end
end
U.teleport(game, MAP, 17, 10, "right")
U.wait(10)
local ow = game.overworld
game.data.encounters[MAP] = nil
local rock = ow and ow:npcAtCell(18, 10)
if not check("boulder present at (18,10) on " .. MAP,
rock ~= nil and rock.def.sprite == "SPRITE_BOULDER") then
finish()
end
ow.strengthActive = true
local function free(x, y)
if not (ow.map:inBounds(x, y) and ow.map:isWalkableCell(x, y)) then return false end
local n = ow:npcAtCell(x, y)
return n == nil or n == rock
end
local cx, cy
for y = 9, 40 do
for x = 0, 60 do
if not cx and free(x, y) then
local all = true
for _, d in ipairs(DIRS) do
local s = STEP[d]
if not (free(x + s[1], y + s[2]) and free(x + 2 * s[1], y + 2 * s[2])) then
all = false
end
end
if all then cx, cy = x, y end
end
end
end
if not check("found an open cross for pushes in all four directions", cx ~= nil) then
finish()
end
U.log("push center", cx, cy)
local function setup(dir)
for _, d in ipairs(DIRS) do game.input.state[d] = false end
ow.dustAnim = nil
ow.boulderTried = nil
local s = STEP[dir]
rock.cellX, rock.cellY = cx + s[1], cy + s[2]
rock.px, rock.py = rock.cellX * 16, rock.cellY * 16
rock.moving, rock.targetX, rock.targetY = false, nil, nil
local p = ow.player
p.cellX, p.cellY = cx, cy
p.px, p.py = cx * 16, cy * 16
p.moving, p.targetX, p.targetY = false, nil, nil
p.facing = dir
U.wait(8)
end
local function pushUntilDust(dir)
local first = true
for _ = 1, 300 do
if ow.dustAnim and ow.dustAnim.boulder then return ow.dustAnim end
if first then table.insert(game.input.pressQueue, dir); first = false end
game.input.state[dir] = true
U.wait(1)
end
return nil
end
local marks = {}
for _, dir in ipairs(DIRS) do
setup(dir)
local s = STEP[dir]
local da = pushUntilDust(dir)
if check(dir .. ": boulder dust starts after the push", da ~= nil) then
check(dir .. ": dust anchored on the boulder's new cell",
da.x == cx + 2 * s[1] and da.y == cy + 2 * s[2])
check(dir .. ": first step already 1px toward the player, faded",
da.ox == -s[1] and da.oy == -s[2] and da.faded == true)
local n, lockHeld, maxStep, order = 0, true, 0, true
local m = {}
while ow.dustAnim == da and n < 120 do
local k = math.abs(da.ox) + math.abs(da.oy)
if k < maxStep then order = false end
maxStep = math.max(maxStep, k)
if not m[k] then m[k] = n end
if ow.player.moving or ow.player.cellX ~= cx or ow.player.cellY ~= cy then
lockHeld = false
end
game.input.state[dir] = true
n = n + 1
U.wait(1)
end
game.input.state[dir] = false
marks[dir] = m
U.log(dir, "dust frames", n)
check(dir .. ": dust lasts 24 frames (8 x Delay3)", n == 24)
check(dir .. ": dust slides 1px per step, 8px total", order and maxStep == 8)
check(dir .. ": player cannot step while the dust plays", lockHeld)
end
U.wait(20)
end
for _, dir in ipairs(DIRS) do
local m = marks[dir]
if m then
setup(dir)
local da = pushUntilDust(dir)
if da then
local t0 = U.frame()
U.shot(game, ("%s/2263_%s_01_dust_step1_under_boulder.png"):format(DIR, dir))
while ow.dustAnim == da and U.frame() - t0 < (m[4] or 9) do
game.input.state[dir] = true
U.wait(1)
end
U.shot(game, ("%s/2263_%s_02_dust_mid_slide.png"):format(DIR, dir))
while ow.dustAnim == da and U.frame() - t0 < (m[8] or 21) do
game.input.state[dir] = true
U.wait(1)
end
U.shot(game, ("%s/2263_%s_03_dust_half_over_old_cell.png"):format(DIR, dir))
game.input.state[dir] = false
end
U.wait(40)
end
end
ow:startDustAnim(cx, cy, nil)
check("cut puff keeps its static 32-frame timing",
ow.dustAnim.frames == 32 and ow.dustAnim.ox == nil and not ow.dustAnim.boulder)
ow.dustAnim = nil
finish()
end