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

106 lines
4.7 KiB
Lua

#!/usr/bin/env luajit
package.path = "./?.lua;./?/init.lua;" .. package.path
require("tests.game3_cache").stubSpeciesNames()
package.loaded["src.core.game3.audio"] = setmetatable({}, {
__index = function() return function() end end,
})
local failed, passed = 0, 0
local function check(cond, msg)
if cond then
passed = passed + 1
print("[ok] " .. msg)
else
failed = failed + 1
print("[FAIL] " .. msg)
end
end
local Field = require("src.core.game3.field")
local root = require("src.import.gba.extract_island1").CACHE_ROOT
Field.installFlyDestinations({ fly_destinations = {
MAPSEC_PALLET_TOWN = { mapsec = 88, map = "FR_PALLET_TOWN", x = 6, y = 8, healLocation = 1 },
} }, root)
local Schema = require("src.core.game3.save_schema_firered")
local Natives = require("src.core.game3.scripting.natives")
local Std = require("src.core.game3.scripting.stdscripts")
local session = Schema.newGame({ gender = 0 })
session.map, session.x, session.y = "FR_POKEMON_LEAGUE_HALL_OF_FAME", 5, 4
session.playtime = { hours = 12, minutes = 34, seconds = 56 }
session.party = {
{ species = 6, level = 60, hp = 3, maxHp = 180, status = 1 },
{ species = 412, isEgg = true, level = 5, hp = 20, maxHp = 20 },
}
package.loaded["src.core.game3.runtime"] = { getSession = function() return session end }
local setFlags = {}
local hofOpened = false
local adapters = {
setFlag = function(id, v) setFlags[id] = v end,
hallOfFame = function(done) hofOpened = true done() end,
}
local handler = Natives.ALLOW["special:" .. Std.SPECIAL.EnterHallOfFame]
check(type(handler) == "function", "EnterHallOfFame native registered")
handler({}, adapters)
check(hofOpened, "HoF screen opened")
check(session.party[1].hp == 180 and session.party[1].status == nil, "party healed")
check(session.party[1].championRibbon == true, "champion ribbon given")
check(not session.party[2].championRibbon, "egg gets no champion ribbon")
check(setFlags[0x83B] == true, "FLAG_SYS_RIBBON_GET set")
check(tonumber(session.gameStats[42]) == 1, "GAME_STAT_RECEIVED_RIBBONS incremented")
check(tonumber(session.gameStats[1]) == 12 * 65536 + 34 * 256 + 56, "GAME_STAT_FIRST_HOF_PLAY_TIME stamped")
check(setFlags[0x82C] == true and session.game_cleared == true, "FLAG_SYS_GAME_CLEAR set")
local saved = Schema.toSaveTable(session)
check(saved.map == "FR_POKEMON_LEAGUE_HALL_OF_FAME", "save keeps the HoF room position")
check(saved.specialSaveWarpFlags == 1, "CONTINUE_GAME_WARP saved")
local cont = Schema.fromSaveTable(saved)
check(cont.map == "FR_PALLET_TOWN" and cont.x == 6 and cont.y == 8,
"continue lands at Pallet Town 6,8 (got " .. tostring(cont.map) .. " " .. tostring(cont.x) .. "," .. tostring(cont.y) .. ")")
check(cont.specialSaveWarpFlags == 0, "CONTINUE_GAME_WARP cleared on continue")
cont.map, cont.x, cont.y = "FR_VIRIDIAN_CITY", 20, 20
local cont2 = Schema.fromSaveTable(Schema.toSaveTable(cont))
check(cont2.map == "FR_VIRIDIAN_CITY" and cont2.x == 20 and cont2.y == 20, "normal save after continue keeps its position")
handler({}, adapters)
check(tonumber(session.gameStats[42]) == 1, "second induction gives no new ribbons")
check(tonumber(session.gameStats[1]) == 12 * 65536 + 34 * 256 + 56, "first HoF time not overwritten")
local stuck = Schema.toSaveTable(Schema.newGame({ gender = 0 }))
stuck.map, stuck.x, stuck.y = "FR_POKEMON_LEAGUE_HALL_OF_FAME", 5, 4
stuck.specialSaveWarpFlags = nil
stuck.continueGameWarp = nil
local freed = Schema.fromSaveTable(stuck)
check(freed.map == "FR_PALLET_TOWN" and freed.x == 6 and freed.y == 8, "save stuck in the HoF room continues in Pallet Town")
local Dataset = require("src.core.game3.dataset")
local realCache = Dataset.cache
Dataset.cache = function() return { read = function() return nil end } end
Field.invalidateFlyDestinations()
stuck.map, stuck.x, stuck.y = "FR_POKEMON_LEAGUE_HALL_OF_FAME", 5, 4
local okLoad, deferred = pcall(Schema.fromSaveTable, stuck)
check(okLoad, "a stuck save loads with no readable cache (" .. tostring(not okLoad and deferred or "ok") .. ")")
check(okLoad and deferred.map == "FR_POKEMON_LEAGUE_HALL_OF_FAME" and deferred._continueWarpDeferred == true,
"the repair waits for the cache")
check(okLoad and Schema.toSaveTable(deferred)._continueWarpDeferred == nil, "the deferral is not written to the save")
Dataset.cache = realCache
Field.installFlyDestinations({ fly_destinations = {
MAPSEC_PALLET_TOWN = { mapsec = 88, map = "FR_PALLET_TOWN", x = 6, y = 8, healLocation = 1 },
} }, root)
if okLoad then
Field.start(nil, nil, deferred)
check(deferred.map == "FR_PALLET_TOWN" and deferred.x == 6 and deferred.y == 8
and not deferred._continueWarpDeferred, "the deferred repair lands in Pallet Town once the field starts")
Field.stop()
end
print(string.format("%d passed, %d failed", passed, failed))
os.exit(failed == 0 and 0 or 1)