Files
gen1recomp/tests/drivers/game3_field_victory_road.lua
2026-09-23 16:34:15 -04:00

186 lines
6.2 KiB
Lua

local U = require("tests.drivers.util")
local DIR = os.getenv("POKEPORT_SHOT_DIR") or "/tmp/game3_field_victory_road"
-- pokefirered/include/constants/vars.h:152
local VAR_MAP_SCENE_VICTORY_ROAD_1F = 0x4064
local VR1F = "FR_VICTORY_ROAD_1F"
-- pokefirered/data/maps/Route23/scripts.inc:8
local VR2F = "FR_VICTORY_ROAD_2F"
-- pokefirered/data/maps/VictoryRoad_1F/scripts.inc:11
local BARRIER_X, BARRIER_TOP, BARRIER_BOTTOM = 12, 14, 15
local SWITCH_X, SWITCH_Y = 20, 16
local BOULDER_ID = 5
local PATH = {
"left", "left", "left", "left", "left", "up", "up", "right", "down", "left",
"down", "right", "right", "right", "right", "right", "down", "right", "up", "up",
"left", "up", "right", "right", "right", "right", "right", "right", "right", "down",
"right", "up", "up", "down", "left", "left", "up", "up", "right", "right",
"up", "right", "down",
}
local failures = 0
local function result(ok, label)
print((ok and "PASS " or "FAIL ") .. label)
if not ok then failures = failures + 1 end
return ok
end
local function finish()
if failures == 0 then
print("PASS field_victory_road")
love.event.quit(0)
else
print("FAIL field_victory_road failures=" .. failures)
love.event.quit(1)
end
end
return function(game)
for _ = 1, 900 do
if game.phase == "boot" and game.boot then break end
U.wait(1)
end
game:_handleBootAction({ action = "new_game", name = "RED" })
U.wait(240)
local Runtime = require("src.core.game3.runtime")
local Map = require("src.core.game3.map")
local Space = require("src.core.game3.scripting.space")
local Flags = require("src.core.game3.scripting.flags")
local Player = require("src.core.game3.player")
local Objects = require("src.core.game3.objects")
local Field = require("src.core.game3.field")
local Collision = require("src.core.game3.collision")
local FieldMoves = require("src.core.game3.field_moves")
local session = Runtime.getSession()
if not result(session ~= nil, "new game reached the game3 field") then return finish() end
local function ctx() return Space.vm and Space.vm.ctx end
local function getVar(id) return Flags.getVar(Space.store, ctx(), id) end
local function place(x, y, facing)
Player.moving = false
Player.progress = 0
Player.cellX, Player.cellY = x, y
Player.px, Player.py = x * 16, y * 16
Player.targetX, Player.targetY = x, y
Player.facing = facing
if game.session then
game.session.x, game.session.y, game.session.facing = x, y, facing
end
end
local function goTo(id, x, y, facing)
Map.load(nil, game, id, { x = x, y = y, facing = facing or "down" })
place(x, y, facing or "down")
U.wait(60)
end
-- pokefirered/include/constants/vars.h:47 VAR_REPEL_STEP_COUNT
local party = session.party
if type(party) == "table" and type(party[1]) == "table" then
party[1].level = 60
end
session.repelSteps = 250
local function armStrength()
Flags.setFlag(Space.store, ctx(), FieldMoves.SYS_FLAGS.USE_STRENGTH, true)
session.repelSteps = 250
end
local function barrierShut()
local o = Field.metatileOverrideAt(VR1F, BARRIER_X, BARRIER_TOP)
return o ~= nil and o.impassable == true
end
local function canPass()
return Collision.canEnter(game, BARRIER_X, BARRIER_BOTTOM,
{ fromX = BARRIER_X - 1, fromY = BARRIER_BOTTOM, dir = "right" }) == true
end
local function walk(dir)
local sx, sy = Player.cellX, Player.cellY
for _ = 1, 30 do
U.hold(game, dir, 1)
if Player.moving then break end
if Player.boulderPush then
for _ = 1, 40 do
if not Player.boulderPush then break end
U.hold(game, dir, 1)
end
end
end
for _ = 1, 48 do
if not Player.moving then break end
U.wait(1)
end
U.wait(1)
return Player.cellX ~= sx or Player.cellY ~= sy
end
local function runScript(secs)
local deadline = love.timer.getTime() + (secs or 8)
while love.timer.getTime() < deadline do
if not (Space.vm and Space.vm:isRunning()) then break end
U.wait(1)
end
end
goTo(VR1F, 11, 15, "right")
armStrength()
result(Space.mapId == VR1F, "stood on Victory Road 1F, map=" .. tostring(Space.mapId))
result(getVar(VAR_MAP_SCENE_VICTORY_ROAD_1F) == 0,
"VAR_MAP_SCENE_VICTORY_ROAD_1F starts at 0, got " ..
tostring(getVar(VAR_MAP_SCENE_VICTORY_ROAD_1F)))
result(barrierShut(), "ON_LOAD walled the rock barrier at (12,14)/(12,15)")
result(not canPass(), "the barrier blocks the way north")
U.shot(game, DIR .. "/field_victory_road_01_barrier_up.png")
goTo(VR1F, 11, 19, "up")
armStrength()
local boulder = Objects.find(BOULDER_ID)
result(boulder ~= nil and boulder.cellX == 7 and boulder.cellY == 18,
"the strength boulder sits at (7,18)")
local walked = 0
for i, dir in ipairs(PATH) do
if walk(dir) then
walked = walked + 1
else
U.log(string.format("step %d (%s) went nowhere at (%s,%s)", i, dir,
tostring(Player.cellX), tostring(Player.cellY)))
end
if Space.vm and Space.vm:isRunning() then runScript() end
end
U.log("walked " .. walked .. "/" .. #PATH .. " steps, player at (" ..
tostring(Player.cellX) .. "," .. tostring(Player.cellY) .. ")")
boulder = Objects.find(BOULDER_ID)
result(boulder ~= nil and boulder.cellX == SWITCH_X and boulder.cellY == SWITCH_Y,
"the boulder was pushed onto the floor switch, at (" ..
tostring(boulder and boulder.cellX) .. "," .. tostring(boulder and boulder.cellY) .. ")")
runScript()
U.wait(60)
result(getVar(VAR_MAP_SCENE_VICTORY_ROAD_1F) == 100,
"the floor-switch script ran, var=" .. tostring(getVar(VAR_MAP_SCENE_VICTORY_ROAD_1F)))
U.shot(game, DIR .. "/field_victory_road_02_switch_pressed.png")
result(not barrierShut(), "the rock barrier is gone")
result(canPass(), "the way north is walkable")
goTo(VR2F, 1, 10, "down")
U.wait(30)
goTo(VR1F, 11, 15, "right")
U.wait(30)
result(getVar(VAR_MAP_SCENE_VICTORY_ROAD_1F) == 100,
"the var survived the reload, var=" .. tostring(getVar(VAR_MAP_SCENE_VICTORY_ROAD_1F)))
result(not barrierShut(), "ON_LOAD did not re-wall the barrier")
result(canPass(), "the way north is still walkable after the reload")
U.shot(game, DIR .. "/field_victory_road_03_barrier_open_after_reload.png")
finish()
end