mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 13:33:27 -04:00
235 lines
9.4 KiB
Lua
235 lines
9.4 KiB
Lua
#!/usr/bin/env luajit
|
|
-- pokefirered/src/safari_zone.c:26 EnterSafariMode
|
|
-- pokefirered/src/safari_zone.c:41 SafariZoneTakeStep
|
|
-- pokefirered/data/scripts/safari_zone.inc:7 SafariZone_EventScript_Exit
|
|
-- pokefirered/src/field_control_avatar.c:677 TryStartStepCountScript
|
|
|
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
|
|
local failed = 0
|
|
local function check(cond, msg)
|
|
if cond then
|
|
print("[ok] " .. msg)
|
|
else
|
|
failed = failed + 1
|
|
print("[FAIL] " .. msg)
|
|
end
|
|
end
|
|
|
|
local function finish()
|
|
if failed > 0 then
|
|
print("[test] FAILED " .. failed)
|
|
os.exit(1)
|
|
end
|
|
print("[test] all passed")
|
|
os.exit(0)
|
|
end
|
|
|
|
local GameVersion = require("src.core.GameVersion")
|
|
GameVersion.set("firered")
|
|
|
|
local Safari = require("src.core.game3.safari")
|
|
local Rules = require("src.core.game3.battle.rules")
|
|
|
|
print("[test] 1. the constants are pret's")
|
|
check(Safari.BALLS == 30, "30 SAFARI BALLS")
|
|
check(Safari.STEPS == 600, "600 steps")
|
|
check(Safari.BALLS == Rules.safari.BALLS and Safari.STEPS == Rules.safari.STEPS,
|
|
"the overworld and the battle side agree")
|
|
check(Safari.FLAG_SYS_SAFARI_MODE == 0x800, "FLAG_SYS_SAFARI_MODE is 0x800")
|
|
check(Safari.VAR_ENTRANCE_SCENE == 0x406E,
|
|
"VAR_MAP_SCENE_FUCHSIA_CITY_SAFARI_ZONE_ENTRANCE is 0x406E")
|
|
check(Safari.EXIT_MAP == "FR_FUCHSIA_CITY_SAFARI_ZONE_ENTRANCE"
|
|
and Safari.EXIT_X == 4 and Safari.EXIT_Y == 1,
|
|
"the exit warp is the Fuchsia entrance at (4,1)")
|
|
|
|
local Cache = require("tests.game3_cache")
|
|
local cacheRoot = Cache.mount("scripts/events.lua", { native = true })
|
|
if not cacheRoot then
|
|
print("[skip] game3_field_safari_test (cache-backed sections): " .. tostring(Cache.reason))
|
|
finish()
|
|
end
|
|
print("[info] FireRed cache at " .. cacheRoot)
|
|
|
|
local Dataset = require("src.core.game3.dataset")
|
|
local Collision = require("src.core.game3.collision")
|
|
local Objects = require("src.core.game3.objects")
|
|
local Player = require("src.core.game3.player")
|
|
local Field = require("src.core.game3.field")
|
|
local Space = require("src.core.game3.scripting.space")
|
|
local Flags = require("src.core.game3.scripting.flags")
|
|
local StepEvents = require("src.core.game3.step_events")
|
|
local Warp = require("src.core.game3.warp")
|
|
local Runtime = require("src.core.game3.runtime")
|
|
|
|
local game = { data = {} }
|
|
Dataset.hydrate(game)
|
|
local session = { map = nil, flags = {}, vars = {}, party = {}, name = "RED" }
|
|
game.session = session
|
|
Runtime.session = session
|
|
|
|
local function enterMap(mapId)
|
|
local def = game.data.maps[mapId]
|
|
if not def then return nil end
|
|
Field._game = game
|
|
Field._session = session
|
|
session.map = mapId
|
|
Field.running = true
|
|
Field.locked = false
|
|
Space.activate(nil, mapId, game, nil)
|
|
Collision.bindMap(game, mapId, def)
|
|
Objects.loadMap(game, mapId, def)
|
|
return def
|
|
end
|
|
|
|
print("[test] 2. the Safari Zone maps and the entrance warp exist")
|
|
local center = enterMap("FR_SAFARI_ZONE_CENTER")
|
|
check(center ~= nil, "FR_SAFARI_ZONE_CENTER is in the cache")
|
|
local entrance = game.data.maps[Safari.EXIT_MAP]
|
|
check(entrance ~= nil, Safari.EXIT_MAP .. " is in the cache")
|
|
if not (center and entrance) then finish() end
|
|
|
|
print("[test] 3. EnterSafariMode arms the session")
|
|
check(Safari.isActive(session) == false, "safari mode starts off")
|
|
check(Safari.enter(session) == true, "EnterSafariMode")
|
|
check(Safari.isActive(session) == true, "FLAG_SYS_SAFARI_MODE is set")
|
|
check(Flags.getFlag(Space.store, nil, Safari.FLAG_SYS_SAFARI_MODE) == true,
|
|
"and the script store sees it")
|
|
check(Safari.balls(session) == 30, "30 balls on the session")
|
|
check(Safari.steps(session) == 600, "600 steps on the session")
|
|
check(session.safari.balls == 30, "the battle side reads session.safari.balls")
|
|
|
|
print("[test] 4. every step burns one of the 600")
|
|
session.party = { { species = 1, level = 10, hp = 20, maxHp = 20 } }
|
|
for _ = 1, 10 do StepEvents.onStepTaken(session, game) end
|
|
check(Safari.steps(session) == 590, "10 steps left 590 (" .. Safari.steps(session) .. ")")
|
|
|
|
print("[test] 5. a step outside safari mode burns nothing")
|
|
Safari.exit(session)
|
|
check(Safari.isActive(session) == false, "ExitSafariMode cleared the flag")
|
|
check(Safari.balls(session) == 0, "and zeroed the balls")
|
|
local before = Safari.steps(session)
|
|
StepEvents.onStepTaken(session, game)
|
|
check(Safari.steps(session) == before, "SafariZoneTakeStep is a no-op when off")
|
|
|
|
print("[test] 6. the last step ends the game and ejects to the entrance")
|
|
Safari.enter(session)
|
|
session.safari.steps = 2
|
|
Warp.clear()
|
|
StepEvents.onStepTaken(session, game)
|
|
check(Safari.steps(session) == 1, "599 of 600 gone, one step left")
|
|
check(Safari.isActive(session) == true, "still in the Safari Zone")
|
|
StepEvents.onStepTaken(session, game)
|
|
check(Safari.steps(session) == 0, "the counter hits zero")
|
|
check(Safari.isActive(session) == false, "the PA announcement ran ExitSafariMode")
|
|
check(session.vars[Safari.VAR_ENTRANCE_SCENE] == 1,
|
|
"VAR_MAP_SCENE_FUCHSIA_CITY_SAFARI_ZONE_ENTRANCE is 1 for the exit cutscene")
|
|
check(Flags.getVar(Space.store, nil, Safari.VAR_ENTRANCE_SCENE) == 1,
|
|
"the script store sees the same var")
|
|
local pending = Warp._pending
|
|
check((pending ~= nil and pending.mapId == Safari.EXIT_MAP and pending.x == 4 and pending.y == 1)
|
|
or session.map == Safari.EXIT_MAP,
|
|
"the player is on the way to the Fuchsia entrance at (4,1)")
|
|
Warp.clear()
|
|
|
|
print("[test] 7. retiring early ejects the same way")
|
|
enterMap("FR_SAFARI_ZONE_CENTER")
|
|
Safari.enter(session)
|
|
check(Safari.retirePrompt(session, game) == true, "the retire prompt ran")
|
|
check(Safari.isActive(session) == false, "retiring left safari mode")
|
|
check(session.vars[Safari.VAR_ENTRANCE_SCENE] == 1, "and set the entrance scene var")
|
|
Warp.clear()
|
|
|
|
print("[test] 8. out of balls ends it too")
|
|
enterMap("FR_SAFARI_ZONE_CENTER")
|
|
Safari.enter(session)
|
|
session.safari.balls = 0
|
|
check(Safari.outOfBalls(session, game) == true, "the out-of-balls announcement ran")
|
|
check(Safari.isActive(session) == false, "out of balls leaves safari mode")
|
|
Warp.clear()
|
|
|
|
print("[test] 9. Continue inside the zone does not eject on the first step")
|
|
local Schema = require("src.core.game3.save_schema_firered")
|
|
enterMap("FR_SAFARI_ZONE_CENTER")
|
|
Safari.enter(session)
|
|
session.safari.steps = 500
|
|
Space.persistSession(nil, game)
|
|
local save = Schema.toSaveTable(session)
|
|
check(save.safari == nil,
|
|
"gNumSafariBalls / gSafariZoneStepCounter are EWRAM, so no save block carries them")
|
|
check(save.flags[tostring(Safari.FLAG_SYS_SAFARI_MODE)] == true,
|
|
"but FLAG_SYS_SAFARI_MODE rides the saved flag store")
|
|
local loaded = Schema.fromSaveTable(save)
|
|
check(loaded.safari == nil, "the loaded session has no counters")
|
|
game.session = loaded
|
|
Runtime.session = loaded
|
|
Field._session = loaded
|
|
Space.deactivate(nil)
|
|
Space.activate(nil, "FR_SAFARI_ZONE_CENTER", game, nil)
|
|
-- pokefirered/src/overworld.c:1695 CB2_ContinueSavedGame
|
|
check(Safari.isActive(loaded) == false, "ResetSafariZoneFlag_ clears the flag on Continue")
|
|
check(Flags.getFlag(Space.store, nil, Safari.FLAG_SYS_SAFARI_MODE) == false,
|
|
"and the script store agrees")
|
|
loaded.party = { { species = 1, level = 10, hp = 20, maxHp = 20 } }
|
|
Warp.clear()
|
|
StepEvents.onStepTaken(loaded, game)
|
|
check(Warp._pending == nil, "the first step after Continue does not eject the player")
|
|
check((loaded.vars[Safari.VAR_ENTRANCE_SCENE] or 0) ~= 1, "and does not run the exit script")
|
|
game.session = session
|
|
Runtime.session = session
|
|
Field._session = session
|
|
session.flags[Safari.FLAG_SYS_SAFARI_MODE] = nil
|
|
session.safari = nil
|
|
Space.deactivate(nil)
|
|
Space.activate(nil, "FR_SAFARI_ZONE_CENTER", game, nil)
|
|
|
|
print("[test] 10. zero balls ejects on return to the field, with no step needed")
|
|
enterMap("FR_SAFARI_ZONE_CENTER")
|
|
Safari.enter(session)
|
|
check(Field.pollSafariBalls(game) == false, "with balls left the field poll does nothing")
|
|
session.safari.balls = 0
|
|
Warp.clear()
|
|
-- pokefirered/src/safari_zone.c:60 CB2_EndSafariBattle
|
|
check(Field.pollSafariBalls(game) == true, "at zero balls the poll runs the PA announcement")
|
|
check(Safari.isActive(session) == false, "which leaves safari mode")
|
|
check(session.vars[Safari.VAR_ENTRANCE_SCENE] == 1, "and sets the entrance scene var")
|
|
check(Warp._pending ~= nil and Warp._pending.mapId == Safari.EXIT_MAP,
|
|
"with a warp to the Fuchsia entrance")
|
|
Warp.clear()
|
|
|
|
print("[test] 11. a step at zero balls ejects too, before the step counter")
|
|
enterMap("FR_SAFARI_ZONE_CENTER")
|
|
Safari.enter(session)
|
|
session.safari.balls = 0
|
|
Warp.clear()
|
|
StepEvents.onStepTaken(session, game)
|
|
check(Safari.isActive(session) == false, "walking with an empty bag of balls ends the game")
|
|
check(Warp._pending ~= nil and Warp._pending.mapId == Safari.EXIT_MAP, "same eject")
|
|
Warp.clear()
|
|
|
|
print("[test] 12. RETIRE asks before it ejects")
|
|
enterMap("FR_SAFARI_ZONE_CENTER")
|
|
Safari.enter(session)
|
|
Warp.clear()
|
|
local asked, answer, closed = nil, false, false
|
|
Safari.presenter = {
|
|
message = function(text, onDone) asked = text; onDone() end,
|
|
yesNo = function(onPick) onPick(answer) end,
|
|
close = function() closed = true end,
|
|
}
|
|
check(Safari.retirePrompt(session, game) == true, "the retire prompt ran")
|
|
check(type(asked) == "string" and asked:find("exit the SAFARI", 1, true) ~= nil,
|
|
"it asks SafariZone_Text_WouldYouLikeToExit")
|
|
check(Safari.isActive(session) == true, "NO keeps the SAFARI GAME going")
|
|
check(closed == true, "and closes the box")
|
|
check(Warp._pending == nil, "warping nowhere")
|
|
answer = true
|
|
check(Safari.retirePrompt(session, game) == true, "asked again")
|
|
check(Safari.isActive(session) == false, "YES ends the SAFARI GAME")
|
|
check(Warp._pending ~= nil and Warp._pending.mapId == Safari.EXIT_MAP,
|
|
"and warps to the Fuchsia entrance")
|
|
Safari.presenter = nil
|
|
Warp.clear()
|
|
|
|
finish()
|