mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 13:33:27 -04:00
268 lines
8.9 KiB
Lua
268 lines
8.9 KiB
Lua
local U = require("tests.drivers.util")
|
|
local DIR = os.getenv("POKEPORT_SHOT_DIR") or "/tmp/game3_safari_start_menu"
|
|
|
|
local ENTRANCE = "FR_FUCHSIA_CITY_SAFARI_ZONE_ENTRANCE"
|
|
local CENTER = "FR_SAFARI_ZONE_CENTER"
|
|
|
|
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 safari_start_menu")
|
|
love.event.quit(0)
|
|
else
|
|
print("FAIL safari_start_menu 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 Player = require("src.core.game3.player")
|
|
local Safari = require("src.core.game3.safari")
|
|
local Message = require("src.ui.game3.message")
|
|
local Choice = require("src.ui.game3.choice")
|
|
local StartMenu = require("src.ui.game3.start_menu")
|
|
local Party = require("src.core.game3.party")
|
|
local Collision = require("src.core.game3.collision")
|
|
local Encounters = require("src.core.game3.encounters")
|
|
local Battle = require("src.core.game3.battle")
|
|
local Ui = require("src.core.game3.battle.ui")
|
|
local Rng = require("src.core.game3.rng")
|
|
local Flags = require("src.core.game3.scripting.flags")
|
|
local Bridge = require("src.core.game3.bridge")
|
|
local SaveData = require("src.core.SaveData")
|
|
|
|
local session = Runtime.getSession()
|
|
if not result(session ~= nil, "new game reached the game3 field") then return finish() end
|
|
session.party = {}
|
|
Party.giveMon(session, 6, 40)
|
|
session.money = 5000
|
|
local secret = session.secretId
|
|
|
|
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
|
|
|
|
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
|
|
end
|
|
for _ = 1, 90 do
|
|
if not Player.moving then break end
|
|
U.wait(1)
|
|
end
|
|
U.wait(2)
|
|
return Player.cellX ~= sx or Player.cellY ~= sy
|
|
end
|
|
|
|
local function mashA(n)
|
|
for _ = 1, n or 40 do
|
|
U.tap(game, "a")
|
|
U.wait(6)
|
|
if not (Space.vm and Space.vm:isRunning()) and not Message.isOpen() then break end
|
|
end
|
|
end
|
|
|
|
local function ids()
|
|
local t = {}
|
|
for _, e in ipairs(StartMenu.ENTRIES or {}) do t[#t + 1] = e.id end
|
|
return table.concat(t, ",")
|
|
end
|
|
|
|
-- pokefirered/data/maps/FuchsiaCity_SafariZone_Entrance/scripts.inc:114
|
|
goTo(ENTRANCE, 4, 6, "up")
|
|
walk("up")
|
|
walk("up")
|
|
walk("up")
|
|
mashA(60)
|
|
for _ = 1, 60 do
|
|
U.wait(4)
|
|
if Space.mapId == CENTER then break end
|
|
if Space.vm and Space.vm:isRunning() then mashA(20) end
|
|
end
|
|
if not result(Space.mapId == CENTER,
|
|
"paid at the gate and entered the zone, map=" .. tostring(Space.mapId)) then return finish() end
|
|
result(Safari.isActive(session) == true, "EnterSafariMode armed safari mode")
|
|
result(Safari.balls(session) == 30, "30 SAFARI BALLS (" .. Safari.balls(session) .. ")")
|
|
walk("up")
|
|
U.wait(60)
|
|
|
|
for _ = 1, 40 do
|
|
if StartMenu.isOpen() then break end
|
|
if (Space.vm and Space.vm:isRunning()) or Message.isOpen() then mashA(4) end
|
|
U.tap(game, "start")
|
|
for _ = 1, 30 do
|
|
if StartMenu.isOpen() then break end
|
|
U.wait(1)
|
|
end
|
|
end
|
|
if not result(StartMenu.isOpen(), "start menu opened in the zone") then return finish() end
|
|
-- pokefirered/src/start_menu.c:226
|
|
result(ids() == "retire,pokedex,pokemon,bag,trainer,option,exit",
|
|
"safari start menu list (" .. ids() .. ")")
|
|
result(not ids():find("save", 1, true), "no SAVE in the zone")
|
|
result(StartMenu._safariStats == true, "steps/balls window is up")
|
|
U.shot(game, DIR .. "/2422_safari_start_menu_retire_stats.png")
|
|
U.tap(game, "b")
|
|
U.wait(20)
|
|
|
|
local before = SaveData.load()
|
|
game:_hotkey("f1")
|
|
local after = SaveData.load()
|
|
result(not (after and after.map == CENTER) and (after and after.savedAt) == (before and before.savedAt),
|
|
"F1 quick-save refused in the zone")
|
|
result(game:saveOffered() == false, "mod saveGame gate refuses in the zone")
|
|
|
|
-- pokefirered/src/wild_encounter.c:712
|
|
local function grassy(cx, cy)
|
|
if Encounters.encounterTypeAt(cx, cy) ~= 1 then return false end
|
|
return Collision.isWalkable(cx, cy) and Collision.canEnter(game, cx, cy, {}) ~= false
|
|
end
|
|
local gx, gy
|
|
do
|
|
local layout = Map._def and Map._def.midLayout
|
|
local bestScore = -1
|
|
for cy = 3, (layout and layout.height or 0) - 4 do
|
|
for cx = 3, layout.width - 4 do
|
|
if grassy(cx, cy) then
|
|
local score = 0
|
|
for dy = -2, 2 do
|
|
for dx = -2, 2 do
|
|
if grassy(cx + dx, cy + dy) then score = score + 1 end
|
|
end
|
|
end
|
|
if score > bestScore then gx, gy, bestScore = cx, cy, score end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if not result(gx ~= nil, "found safari grass") then return finish() end
|
|
local dir = grassy(gx + 1, gy) and "right" or "down"
|
|
local back = dir == "right" and "left" or "up"
|
|
place(gx, gy, dir)
|
|
U.wait(20)
|
|
Rng.SeedRng(0x2468)
|
|
Rng.SeedWildEncounterRng(0x2468)
|
|
Encounters.resetRateModifiers()
|
|
local d = dir
|
|
for _ = 1, 300 do
|
|
if Battle.isActive and Battle.isActive() then break end
|
|
walk(d)
|
|
d = (d == dir) and back or dir
|
|
end
|
|
if not result(Battle.isActive and Battle.isActive(), "grass encounter started") then return finish() end
|
|
local st = Battle.getState()
|
|
result(st and st.safari == true, "the encounter is a Safari battle")
|
|
local atMenu = false
|
|
for _ = 1, 150 do
|
|
if Battle._phase == "command" and Ui._mode == "menu" then atMenu = true break end
|
|
U.tap(game, "a")
|
|
U.wait(6)
|
|
end
|
|
result(atMenu, "reached the BALL/BAIT/ROCK/RUN menu")
|
|
U.shot(game, DIR .. "/2422_safari_battle_menu.png")
|
|
for _ = 1, 400 do
|
|
if not (Battle.isActive and Battle.isActive()) then break end
|
|
if Battle._phase == "command" and Ui._mode == "menu" then
|
|
-- pokefirered/src/battle_controller_safari.c:162
|
|
U.tap(game, "right") U.wait(6)
|
|
U.tap(game, "down") U.wait(6)
|
|
U.tap(game, "a") U.wait(20)
|
|
else
|
|
U.tap(game, "a")
|
|
U.wait(8)
|
|
end
|
|
end
|
|
if not result(not (Battle.isActive and Battle.isActive()), "ran from the safari battle") then
|
|
return finish()
|
|
end
|
|
U.wait(90)
|
|
|
|
U.tap(game, "start")
|
|
U.wait(30)
|
|
StartMenu.cursor = 1
|
|
result(StartMenu.isOpen() and StartMenu.ENTRIES[1].id == "retire", "RETIRE is the first entry")
|
|
U.tap(game, "a")
|
|
for _ = 1, 60 do
|
|
if Choice.active then break end
|
|
U.tap(game, "a")
|
|
U.wait(8)
|
|
end
|
|
result(Choice.active and Choice.cursor == 1, "retire asks YES/NO")
|
|
U.tap(game, "a")
|
|
for _ = 1, 120 do
|
|
if Space.mapId == ENTRANCE then break end
|
|
U.wait(4)
|
|
end
|
|
result(Space.mapId == ENTRANCE, "RETIRE warped back to the gate, map=" .. tostring(Space.mapId))
|
|
result(Safari.isActive(session) == false, "safari mode is off after RETIRE")
|
|
mashA(60)
|
|
U.wait(60)
|
|
U.shot(game, DIR .. "/2422_retire_back_at_gate.png")
|
|
|
|
goTo(CENTER, 26, 30, "up")
|
|
result(Safari.isActive(session) == false, "stranded setup: in the zone with safari mode off")
|
|
Bridge.persistSessionOnly(Runtime._mod, game)
|
|
result(game:saveGame() ~= false, "wrote a save standing in the zone")
|
|
local raw = SaveData.load()
|
|
result(type(raw) == "table" and raw.map == CENTER, "the save holds map " .. tostring(raw and raw.map))
|
|
|
|
game:_handleBootAction({ action = "continue" })
|
|
U.wait(60)
|
|
for _ = 1, 400 do
|
|
if game.phase ~= "quest_log" then break end
|
|
U.tap(game, "a")
|
|
U.wait(6)
|
|
end
|
|
U.wait(120)
|
|
local loaded = Runtime.getSession()
|
|
if not result(loaded ~= nil, "Continue reached the field") then return finish() end
|
|
result(loaded.secretId == secret, "secret id came back off the save")
|
|
result(Space.mapId == ENTRANCE, "the stranded save resumes at the gate, map=" .. tostring(Space.mapId))
|
|
U.shot(game, DIR .. "/2422_stranded_continue_at_gate.png")
|
|
mashA(60)
|
|
for _ = 1, 60 do
|
|
if Flags.getVar(Space.store, nil, Safari.VAR_ENTRANCE_SCENE) == 0 then break end
|
|
mashA(10)
|
|
U.wait(4)
|
|
end
|
|
result(Flags.getVar(Space.store, nil, Safari.VAR_ENTRANCE_SCENE) == 0, "ExitWarpIn finished")
|
|
result(Safari.isActive(loaded) == false, "safari mode stays off")
|
|
U.wait(30)
|
|
local reload = SaveData.load()
|
|
result(reload and reload.map == CENTER, "the slot itself is untouched until the next save")
|
|
|
|
finish()
|
|
end
|