Files
gen1recomp/tests/drivers/game3_forced_elevation_s4.lua
bryanthaboi 72a17b27dd CLOSES #2444
2026-09-24 08:39:43 -04:00

238 lines
8.8 KiB
Lua

local U = require("tests.drivers.util")
local DIR = os.getenv("POKEPORT_SHOT_DIR") or "/tmp/game3_forced_elevation_s4"
local failures = 0
local function result(ok, label, detail)
print((ok and "PASS " or "FAIL ") .. label .. (detail and (" " .. detail) or ""))
if not ok then failures = failures + 1 end
return ok
end
local function finish()
if failures == 0 then
print("PASS forced_elevation_s4")
love.event.quit(0)
else
print("FAIL forced_elevation_s4 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 Player = require("src.core.game3.player")
local Collision = require("src.core.game3.collision")
local Objects = require("src.core.game3.objects")
local Space = require("src.core.game3.scripting.space")
local Message = require("src.ui.game3.message")
local ForcedMovement = require("src.core.game3.forced_movement")
local TrainerSight = require("src.core.game3.trainer_sight")
local session = Runtime.getSession()
if not result(session ~= nil, "new_game_reached_field") then return finish() end
session.repelSteps = 5000
local function busy()
return (Space.vm and Space.vm:isRunning()) or (Message.isOpen and Message.isOpen())
end
local function settle(limit)
for _ = 1, (limit or 240) do
if not busy() then return true end
if Message.isOpen and Message.isOpen() then U.tap(game, "a") end
U.wait(4)
end
return false
end
local function place(x, y, facing, surfing)
Player.cellX, Player.cellY = x, y
Player.px, Player.py = x * 16, y * 16
Player.targetX, Player.targetY = x, y
Player.moving = false
Player.progress = 0
Player.facing = facing or "down"
Player.surfing = surfing and true or false
Player.dismounting = false
if game.session then
game.session.x, game.session.y, game.session.facing = x, y, facing or "down"
end
end
local function goTo(mapId, x, y, facing, surfing)
Map.load(nil, game, mapId, { x = x, y = y, facing = facing or "down" })
place(x, y, facing, surfing)
U.wait(60)
settle(600)
place(x, y, facing, surfing)
U.wait(10)
end
local function step(dir)
local fromX, fromY = Player.cellX, Player.cellY
for _ = 1, 3 do
U.hold(game, dir, 4)
for _ = 1, 60 do
U.wait(1)
if not Player.moving then break end
end
if Player.cellX ~= fromX or Player.cellY ~= fromY then break end
end
settle(200)
end
local function at(x, y) return Player.cellX == x and Player.cellY == y end
local function pos()
return string.format("at (%d,%d) cur=%s surf=%s", Player.cellX, Player.cellY,
tostring(Player.currentElevation), tostring(Player.surfing))
end
local function firstObject()
for _, lid in ipairs(Objects._order) do
local eo = Objects._byId[lid]
if eo and eo.visible and not eo.hidden and not eo.passable then return eo end
end
end
print("[driver] 1. constructed trainer on Safari Zone East sand, player on the rock stairs")
local E = "FR_SAFARI_ZONE_EAST"
goTo(E, 40, 18, "down")
local Field = require("src.core.game3.field")
for _ = 1, 600 do
if not Field.locked and not busy() then break end
U.wait(1)
end
result(not Field.locked, "field_unlocked_before_walking")
goTo(E, 40, 18, "down")
local stand = firstObject()
if stand then
Objects.setObjectXY(stand.localId, 40, 21)
stand.frozen = true
stand.facing = "up"
local def = {}
for k, v in pairs(stand.def or {}) do def[k] = v end
def.graphics, def.graphicsId, def.graphicsVar = 39, 39, nil
stand.def = def
stand.graphicsId = 39
stand.sprite = require("src.core.game3.scripting.gfx_ids").spriteFor(39) or stand.sprite
require("src.core.game3.field_view")._nativeDirty = true
end
result(stand ~= nil and stand.cellX == 40 and stand.cellY == 21 and stand.currentElevation == 3,
"safari_watcher_drawn_on_elev3_sand", stand and ("elev=" .. tostring(stand.currentElevation)) or "none")
local watcher = { localId = stand and stand.localId or 250, cellX = 40, cellY = 21, facing = "up", sight = 3,
currentElevation = 3, visible = true, hidden = false, moving = false }
result(Player.currentElevation == 4
and TrainerSight.checkLineOfSight(watcher, Player, game) == false,
"safari_elev3_trainer_misses_elev4_plateau", pos())
step("down")
local seen, dist = TrainerSight.checkLineOfSight(watcher, Player, game)
result(at(40, 19) and Player.currentElevation == 0 and seen == true and dist == 2,
"safari_elev3_trainer_sees_player_on_elev0_stair", pos() .. " dist=" .. tostring(dist))
local Popup = require("src.ui.game3.map_name_popup")
for _ = 1, 900 do
if not Popup.isActive() then break end
U.wait(1)
end
U.wait(2)
result(not Popup.isActive() and at(40, 19), "safari_map_name_popup_closed_before_shot", pos())
U.still(game, DIR .. "/s4_safari_player_on_stair_in_sight_line.png")
print("[driver] 2. an object on the Safari Zone East plateau still blocks the plateau walker")
local obj = firstObject()
if result(obj ~= nil, "safari_object_found") then
goTo(E, 38, 18, "right")
obj = Objects.find(obj.localId)
Objects.setObjectXY(obj.localId, 39, 18)
obj.frozen = true
U.wait(4)
step("right")
result(at(38, 18) and obj.currentElevation == 4 and Player.currentElevation == 4,
"plateau_object_same_elev_blocks", pos() .. " obj=" .. tostring(obj.currentElevation))
U.still(game, DIR .. "/s4_safari_bump_into_elev4_object.png")
end
print("[driver] 3. a ledge jump lands on an occupied cell")
local LM, lx, ly, npc
for _, m in ipairs({ "FR_ROUTE_1", "FR_ROUTE_3", "FR_ROUTE_4", "FR_ROUTE_22" }) do
goTo(m, 0, 0, "down")
lx, ly = nil, nil
for y = 0, Collision._heightCells - 3 do
for x = 0, Collision._widthCells - 1 do
if not lx and Collision.isWalkable(x, y) and Collision.elevationAt(x, y) == 3
and Collision.ledgeLanding(game, x, y, "down") and not Objects.blocks(x, y) then
lx, ly = x, y
end
end
end
npc = firstObject()
if lx and npc then LM = m break end
end
if result(LM ~= nil, "ledge_and_object_found",
tostring(LM) .. " " .. tostring(lx) .. "," .. tostring(ly)) then
goTo(LM, lx, ly, "down")
npc = Objects.find(npc.localId)
Objects.setObjectXY(npc.localId, lx, ly + 2)
npc.frozen = true
U.wait(2)
local sawJump = false
U.hold(game, "down", 4)
local shotMid = false
for i = 1, 80 do
if Player.jumping then
sawJump = true
if not shotMid and i >= 8 then
shotMid = U.still(game, DIR .. "/s4_ledge_midjump_toward_object_below_ledge.png")
end
end
U.wait(1)
if not Player.moving then break end
end
result(sawJump and shotMid and at(lx, ly + 2) and npc.cellX == lx and npc.cellY == ly + 2,
"ledge_jump_lands_on_object_cell", pos())
local ok = Collision.canEnter(game, lx, ly + 1, { fromX = lx, fromY = ly, dir = "down",
elevation = Player.currentElevation })
result(ok == false, "ledge_cell_itself_still_impassable")
end
print("[driver] 4. Seafoam B3F southward current against the elev 4 ledge")
local B3F = "FR_SEAFOAM_ISLANDS_B3F"
goTo(B3F, 16, 6, "down", true)
result(Collision.behavior(16, 6) == 0x53, "b3f_current_cell_is_southward",
"beh=" .. tostring(Collision.behavior(16, 6)))
result(Collision.elevationAt(16, 7) == 4, "b3f_cell_below_is_elev4",
"elev=" .. tostring(Collision.elevationAt(16, 7)))
for _ = 1, 90 do U.wait(1) end
result(at(16, 6) and Player.surfing and not Player.dismounting,
"b3f_current_holds_surfer_at_ledge", pos())
result(ForcedMovement.forced == false, "b3f_forced_flag_cleared")
U.still(game, DIR .. "/s4_seafoam_b3f_current_held_below_elev4_ledge.png")
print("[driver] 5. Route 12 fisher does not see a surfer below him")
local R12 = "FR_ROUTE_12"
goTo(R12, 17, 33, "up", true)
local fisher
for _, lid in ipairs(Objects._order) do
local eo = Objects._byId[lid]
if eo and eo.cellX == 17 and eo.cellY == 32 then fisher = eo end
end
if result(fisher ~= nil and (tonumber(fisher.sight) or 0) >= 1, "r12_fisher_found",
fisher and ("sight=" .. tostring(fisher.sight) .. " elev=" .. tostring(fisher.currentElevation))) then
fisher.facing = "down"
local seen = TrainerSight.checkLineOfSight(fisher, Player, game)
result(seen == false and Player.currentElevation == 1, "r12_fisher_misses_surfer", pos())
for _ = 1, 120 do U.wait(1) end
result(not busy() and at(17, 33) and Player.surfing, "r12_no_battle_after_wait", pos())
U.still(game, DIR .. "/s4_route12_surfer_below_fisher_unseen.png")
end
finish()
end