mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-10-01 23:42:25 -04:00
further fixes
This commit is contained in:
@@ -476,6 +476,8 @@ function Battle.start(opts)
|
||||
if #playerParty == 0 then
|
||||
return nil, "empty party"
|
||||
end
|
||||
local okStay, StayMessage = pcall(require, "src.ui.game3.message")
|
||||
if okStay and StayMessage and StayMessage.closeStay then StayMessage.closeStay() end
|
||||
local linkBattle = (opts.link or (type(opts.foe) == "table" and opts.foe.link)) and true or false
|
||||
local Guard = require("src.core.game3.battle.link_guard")
|
||||
if linkBattle then Guard.arm() else Guard.disarm() end
|
||||
|
||||
@@ -600,6 +600,11 @@ function BattleBridge.start(mod, game, foe, opts)
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
local StayMessage = package.loaded["src.ui.game3.message"]
|
||||
if StayMessage and StayMessage.closeStay then StayMessage.closeStay() end
|
||||
end
|
||||
|
||||
local function doStart()
|
||||
local ok, err = Battle.start(startOpts)
|
||||
if not ok then
|
||||
|
||||
@@ -350,6 +350,10 @@ function Map.load(mod, game, mapId, opts)
|
||||
if not MapIds.isGame3Map(mapId) then
|
||||
return nil, "not a game3 map"
|
||||
end
|
||||
if not opts.seamless then
|
||||
local StayMessage = package.loaded["src.ui.game3.message"]
|
||||
if StayMessage and StayMessage.closeStay then StayMessage.closeStay() end
|
||||
end
|
||||
-- pret RestartWildEncounterImmunitySteps on LoadMap / LoadMapFromWarp: every
|
||||
-- map entry restarts the wild encounter grace period. Unconditional, so the
|
||||
-- seamless connection crossing between two routes resets it too.
|
||||
|
||||
@@ -55,7 +55,13 @@ function Vm:halt(aborted)
|
||||
a.unfreezeLocal(lid, snap)
|
||||
end
|
||||
end
|
||||
local wasLocked = ctx.lockKind ~= nil and not aborted
|
||||
Ctx.haltCleanup(self.ctx)
|
||||
if wasLocked then
|
||||
-- pokeemerald/src/script.c:233
|
||||
local Field = package.loaded["src.core.game3.field"]
|
||||
if Field and Field.unlock then Field.unlock() end
|
||||
end
|
||||
self:_scriptEnded(not aborted)
|
||||
end
|
||||
|
||||
|
||||
@@ -57,6 +57,10 @@ end
|
||||
|
||||
-- src/fldeff_flash.c:475
|
||||
function CaveTransition.start(kind, done, skipFirstTask)
|
||||
do
|
||||
local StayMessage = package.loaded["src.ui.game3.message"]
|
||||
if StayMessage and StayMessage.closeStay then StayMessage.closeStay() end
|
||||
end
|
||||
local run = newRun(kind, done)
|
||||
if skipFirstTask then run.task = "1" else run.defer = true end
|
||||
CaveTransition._run = run
|
||||
|
||||
@@ -288,6 +288,13 @@ function Message.close()
|
||||
if done then done() end
|
||||
end
|
||||
|
||||
function Message.closeStay()
|
||||
if not (Message.open and Message._stay) then return false end
|
||||
Message._done = nil
|
||||
Message.close()
|
||||
return true
|
||||
end
|
||||
|
||||
-- pokefirered/src/main.c:480
|
||||
function Message.reset()
|
||||
Message._done = nil
|
||||
|
||||
@@ -451,6 +451,10 @@ end
|
||||
|
||||
function Naming.open(opts)
|
||||
opts = opts or {}
|
||||
do
|
||||
local StayMessage = package.loaded["src.ui.game3.message"]
|
||||
if StayMessage and StayMessage.closeStay then StayMessage.closeStay() end
|
||||
end
|
||||
local man = cacheManifest()
|
||||
local tpl = Naming.templateFromManifest(man, opts.template or "PLAYER")
|
||||
local okF, Fade = pcall(require, "src.ui.game3.fade")
|
||||
|
||||
@@ -28,6 +28,10 @@ end
|
||||
|
||||
function ReleaseSeq.start(opts)
|
||||
opts = opts or {}
|
||||
do
|
||||
local StayMessage = package.loaded["src.ui.game3.message"]
|
||||
if StayMessage and StayMessage.closeStay then StayMessage.closeStay() end
|
||||
end
|
||||
ReleaseSeq.active = true
|
||||
ReleaseSeq.state = "confirm"
|
||||
ReleaseSeq.session = opts.session
|
||||
|
||||
@@ -123,6 +123,10 @@ local function loadAssets()
|
||||
end
|
||||
|
||||
function Seagallop.start(originId, destId, onWarp, onDone)
|
||||
do
|
||||
local StayMessage = package.loaded["src.ui.game3.message"]
|
||||
if StayMessage and StayMessage.closeStay then StayMessage.closeStay() end
|
||||
end
|
||||
local dir = Seagallop.directionOfTravel(originId, destId)
|
||||
local run = {
|
||||
origin = originId,
|
||||
|
||||
@@ -24,6 +24,10 @@ end
|
||||
-- opts.drawUnder: if true, still draw layers below this one.
|
||||
function Stack.push(id, mod, opts)
|
||||
opts = opts or {}
|
||||
if opts.hideBelow ~= false then
|
||||
local Message = package.loaded["src.ui.game3.message"]
|
||||
if Message and Message.closeStay then Message.closeStay() end
|
||||
end
|
||||
-- Replace existing same-id layer (re-open).
|
||||
for i = #Stack._layers, 1, -1 do
|
||||
if Stack._layers[i].id == id then
|
||||
|
||||
@@ -0,0 +1,222 @@
|
||||
local U = require("tests.drivers.util")
|
||||
local L = require("tests.drivers.em_battle_loop")
|
||||
|
||||
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()
|
||||
print((failures == 0 and "PASS" or "FAIL") .. " em_stay_box_handoffs failures=" .. failures)
|
||||
love.event.quit(failures == 0 and 0 or 1)
|
||||
U.wait(10)
|
||||
end
|
||||
|
||||
return function(game)
|
||||
io.stdout:setvbuf("line")
|
||||
for _ = 1, 900 do
|
||||
if game.phase == "boot" and game.boot then break end
|
||||
U.wait(1)
|
||||
end
|
||||
game:_handleBootAction({ action = "new_game", name = "BRENDAN", gender = 0 })
|
||||
U.wait(240)
|
||||
|
||||
local Runtime = require("src.core.game3.runtime")
|
||||
local Map = require("src.core.game3.map")
|
||||
local Party = require("src.core.game3.party")
|
||||
local Space = require("src.core.game3.scripting.space")
|
||||
local Message = require("src.ui.game3.message")
|
||||
local Choice = require("src.ui.game3.choice")
|
||||
local Stack = require("src.ui.game3.stack")
|
||||
local Field = require("src.core.game3.field")
|
||||
local Battle = require("src.core.game3.battle")
|
||||
local Safari = require("src.core.game3.safari")
|
||||
local Encounters = require("src.core.game3.encounters")
|
||||
local C = require("src.core.game3.constants").of("emerald")
|
||||
local session = Runtime.getSession()
|
||||
if not result(session ~= nil, "field session exists") then return finish() end
|
||||
Encounters.onStep = function() return nil end
|
||||
session.party = {}
|
||||
Party.giveMon(session, C.species.byName.SPECIES_SWAMPERT, 40, "")
|
||||
|
||||
local function running() return Space.vm and Space.vm:isRunning() end
|
||||
local function untilTrue(fn, frames, step)
|
||||
for _ = 1, frames do
|
||||
if fn() then return true end
|
||||
U.wait(step or 2)
|
||||
end
|
||||
return fn() and true or false
|
||||
end
|
||||
local function answerYes()
|
||||
local opened = untilTrue(function()
|
||||
if Choice.isOpen and Choice.isOpen() then return true end
|
||||
if Message.isOpen() and Message.isWaiting() then U.tap(game, "a") end
|
||||
return false
|
||||
end, 900, 4)
|
||||
if opened then U.wait(6); U.tap(game, "a") end
|
||||
return opened
|
||||
end
|
||||
local function idle()
|
||||
return not running() and not Message.isOpen() and not (Choice.isOpen and Choice.isOpen())
|
||||
end
|
||||
local function settle(label)
|
||||
local ok = untilTrue(function()
|
||||
if Message.isOpen() and not Choice.isOpen() then U.tap(game, "a") end
|
||||
return not running()
|
||||
end, 900, 4)
|
||||
result(ok, label .. ": script finished")
|
||||
U.wait(30)
|
||||
end
|
||||
local function load(id, x, y, facing)
|
||||
local ok, err = pcall(function() Map.load(nil, game, id, { x = x, y = y, facing = facing }) end)
|
||||
result(ok, "load " .. id .. " " .. tostring(err or ""))
|
||||
session.map = id
|
||||
U.wait(60)
|
||||
end
|
||||
local function start(label, localId)
|
||||
local key = Space.scriptKey(label)
|
||||
local ok = key and Space.startScript(key, localId)
|
||||
return result(ok and true or false, label .. " starts")
|
||||
end
|
||||
|
||||
-- pokeemerald/data/scripts/safari_zone.inc:19 warp after MSGBOX_YESNO
|
||||
Safari.enter(session)
|
||||
load("EM_SAFARI_ZONE_SOUTH", 10, 20, "up")
|
||||
if start("SafariZone_EventScript_RetirePrompt") and answerYes() then
|
||||
local warped = untilTrue(function()
|
||||
return Map.current == "EM_ROUTE121_SAFARI_ZONE_ENTRANCE" and not running()
|
||||
end, 1500, 4)
|
||||
result(warped, "safari retire: warped to entrance (" .. tostring(Map.current) .. ")")
|
||||
untilTrue(function() return not Field.locked end, 300, 2)
|
||||
result(not Message.isOpen(), "safari retire: stay box closed after warp")
|
||||
result(not Field.locked, "safari retire: field unlocked after warp")
|
||||
else
|
||||
result(false, "safari retire: prompt opened")
|
||||
end
|
||||
Safari.exit(session)
|
||||
|
||||
-- pokeemerald/data/scripts/safari_zone.inc:41 fadescreen + special OpenPokeblockCaseOnFeeder
|
||||
Safari.enter(session)
|
||||
load("EM_SAFARI_ZONE_SOUTH", 10, 20, "up")
|
||||
if start("EventScript_PokeBlockFeeder") and answerYes() then
|
||||
local screen = untilTrue(function() return Stack.depth() > 0 or not running() end, 900, 4)
|
||||
result(screen, "pokeblock feeder: reached a screen or finished")
|
||||
result(not Message.isOpen(), "pokeblock feeder: stay box closed at screen hand-off")
|
||||
for _ = 1, 4 do
|
||||
if Stack.depth() > 0 then U.tap(game, "b"); U.wait(20) end
|
||||
end
|
||||
settle("pokeblock feeder")
|
||||
result(idle(), "pokeblock feeder: idle afterwards")
|
||||
result(not Field.locked, "pokeblock feeder: field unlocked after cancel")
|
||||
result(not Field.isLocked(), "pokeblock feeder: no field lock tags remain")
|
||||
else
|
||||
result(false, "pokeblock feeder: prompt opened")
|
||||
end
|
||||
Safari.exit(session)
|
||||
|
||||
-- pokeemerald/data/maps/RustboroCity_House1/scripts.inc:12 special ChoosePartyMon
|
||||
load("EM_RUSTBORO_CITY_HOUSE1", 4, 6, "up")
|
||||
if start("RustboroCity_House1_EventScript_Trader", 1) and answerYes() then
|
||||
local party = untilTrue(function() return Stack.has("party") or not running() end, 900, 4)
|
||||
result(party and Stack.has("party"), "rustboro trade: party menu opened")
|
||||
result(not Message.isOpen(), "rustboro trade: stay box closed at party menu")
|
||||
U.tap(game, "b"); U.wait(20)
|
||||
settle("rustboro trade")
|
||||
result(idle(), "rustboro trade: idle afterwards")
|
||||
result(not Field.locked, "rustboro trade: field unlocked")
|
||||
else
|
||||
result(false, "rustboro trade: prompt opened")
|
||||
end
|
||||
|
||||
-- stayed box straight into dowildbattle (synthetic chain over real ops)
|
||||
load("EM_ROUTE104", 10, 10, "down")
|
||||
local key = "synthetic_stay_wild"
|
||||
Space.vm.scripts[key] = {
|
||||
{ op = "lockall" },
|
||||
{ op = "message", ptr = "SafariZone_Text_WouldYouLikeToExit" },
|
||||
{ op = "setwildbattle", C.species.byName.SPECIES_ZIGZAGOON, 3 },
|
||||
{ op = "dowildbattle" },
|
||||
{ op = "releaseall" },
|
||||
{ op = "end" },
|
||||
}
|
||||
result(Space.startScript(key) and true or false, "synthetic stay+wild battle starts")
|
||||
local inBattle = untilTrue(function() return Battle.isActive() end, 1500, 2)
|
||||
result(inBattle, "wild battle started")
|
||||
if inBattle then
|
||||
result(not Message.isOpen(), "stay+wild: stay box closed once battle is up")
|
||||
local over = L.run(game, { turnCap = 60, guard = 60000 })
|
||||
result(over, "wild battle ended turn=" .. tostring(Battle._st and Battle._st.turn) .. " phase=" .. tostring(Battle._phase))
|
||||
U.wait(60)
|
||||
settle("stay+wild")
|
||||
end
|
||||
result(not Message.isOpen(), "stay+wild: stay box closed after battle")
|
||||
result(not Field.locked, "stay+wild: field unlocked")
|
||||
|
||||
-- pokeemerald/data/maps/Route104/scripts.inc:832 trainerbattle_single behind a stayed box
|
||||
load("EM_ROUTE104", 10, 10, "down")
|
||||
local ivanKey = Space.scriptKey("Route104_EventScript_Ivan")
|
||||
local ivan = ivanKey and Space.vm.scripts[ivanKey]
|
||||
result(type(ivan) == "table", "ivan script resolves")
|
||||
if type(ivan) == "table" then
|
||||
local chain = { { op = "lockall" }, { op = "message", ptr = "SafariZone_Text_WouldYouLikeToExit", stay = true } }
|
||||
for _, row in ipairs(ivan) do chain[#chain + 1] = row end
|
||||
Space.vm.scripts["synthetic_stay_trainer"] = chain
|
||||
result(Space.startScript("synthetic_stay_trainer") and true or false, "synthetic stay+trainer starts")
|
||||
local sawStay = untilTrue(function() return Message.isOpen() end, 300, 1)
|
||||
result(sawStay, "stay+trainer: stay box opened first")
|
||||
local tb = untilTrue(function()
|
||||
if Message.isOpen() and Message.isWaiting() and not Battle.isActive() then U.tap(game, "a") end
|
||||
return Battle.isActive()
|
||||
end, 3000, 2)
|
||||
result(tb, "stay+trainer: trainer battle started")
|
||||
if tb then
|
||||
result(not Message.isOpen(), "stay+trainer: stay box closed once battle is up")
|
||||
local over = L.run(game, { turnCap = 60, guard = 60000 })
|
||||
result(over, "trainer battle ended")
|
||||
U.wait(60)
|
||||
settle("stay+trainer")
|
||||
end
|
||||
result(not Message.isOpen(), "stay+trainer: stay box closed after battle")
|
||||
result(not Field.locked, "stay+trainer: field unlocked")
|
||||
end
|
||||
|
||||
-- pokeemerald/data/maps/LavaridgeTown_HerbShop/scripts.inc:7 message then pokemart
|
||||
load("EM_LAVARIDGE_TOWN_HERB_SHOP", 3, 4, "up")
|
||||
if start("LavaridgeTown_HerbShop_EventScript_Clerk", 1) then
|
||||
local ShopMenu = require("src.ui.game3.shop_menu")
|
||||
local shop = untilTrue(function()
|
||||
if Message.isOpen() and Message.isWaiting() and not ShopMenu.isOpen() then U.tap(game, "a") end
|
||||
return ShopMenu.isOpen()
|
||||
end, 1500, 2)
|
||||
result(shop, "herb shop: shop menu opened")
|
||||
result(not Message.isOpen(), "herb shop: stay box closed at shop")
|
||||
for _ = 1, 6 do
|
||||
if ShopMenu.isOpen() then U.tap(game, "b"); U.wait(20) end
|
||||
end
|
||||
settle("herb shop")
|
||||
result(not Field.locked, "herb shop: field unlocked")
|
||||
end
|
||||
|
||||
-- pokeemerald/data/maps/Route112_CableCarStation/scripts.inc:50 stayed box then special CableCar
|
||||
load("EM_ROUTE112_CABLE_CAR_STATION", 6, 8, "up")
|
||||
Space.vm.scripts["synthetic_stay_cablecar"] = {
|
||||
{ op = "lockall" },
|
||||
{ op = "message", ptr = "SafariZone_Text_WouldYouLikeToExit", stay = true },
|
||||
{ op = "special", id = 155 },
|
||||
{ op = "releaseall" },
|
||||
{ op = "end" },
|
||||
}
|
||||
result(Space.startScript("synthetic_stay_cablecar") and true or false, "synthetic stay+cable car starts")
|
||||
local cc = untilTrue(function()
|
||||
if Message.isOpen() and Message.isWaiting() and Stack.depth() == 0 then U.tap(game, "a") end
|
||||
return Stack.has("cable_car")
|
||||
end, 900, 2)
|
||||
result(cc, "stay+cable car: scene opened")
|
||||
result(not Message.isOpen(), "stay+cable car: stay box closed at scene")
|
||||
while Stack.depth() > 0 do Stack.pop() end
|
||||
U.wait(10)
|
||||
|
||||
finish()
|
||||
end
|
||||
@@ -0,0 +1,112 @@
|
||||
local U = require("tests.drivers.util")
|
||||
local L = require("tests.drivers.em_battle_loop")
|
||||
|
||||
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()
|
||||
print((failures == 0 and "PASS" or "FAIL") .. " fr_stay_box_handoffs failures=" .. failures)
|
||||
love.event.quit(failures == 0 and 0 or 1)
|
||||
U.wait(10)
|
||||
end
|
||||
|
||||
return function(game)
|
||||
io.stdout:setvbuf("line")
|
||||
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 Party = require("src.core.game3.party")
|
||||
local Space = require("src.core.game3.scripting.space")
|
||||
local Message = require("src.ui.game3.message")
|
||||
local Choice = require("src.ui.game3.choice")
|
||||
local Field = require("src.core.game3.field")
|
||||
local Battle = require("src.core.game3.battle")
|
||||
local Encounters = require("src.core.game3.encounters")
|
||||
local C = require("src.core.game3.constants").of("firered")
|
||||
local session = Runtime.getSession()
|
||||
if not result(session ~= nil, "field session exists") then return finish() end
|
||||
Encounters.onStep = function() return nil end
|
||||
session.party = {}
|
||||
Party.giveMon(session, C.species.byName.SPECIES_BLASTOISE, 40, "")
|
||||
|
||||
local function running() return Space.vm and Space.vm:isRunning() end
|
||||
local function untilTrue(fn, frames, step)
|
||||
for _ = 1, frames do
|
||||
if fn() then return true end
|
||||
U.wait(step or 2)
|
||||
end
|
||||
return fn() and true or false
|
||||
end
|
||||
local function answerYes()
|
||||
local opened = untilTrue(function()
|
||||
if Choice.isOpen and Choice.isOpen() then return true end
|
||||
if Message.isOpen() and Message.isWaiting() then U.tap(game, "a") end
|
||||
return false
|
||||
end, 900, 4)
|
||||
if opened then U.wait(6); U.tap(game, "a") end
|
||||
return opened
|
||||
end
|
||||
local function load(id, x, y, facing)
|
||||
local ok, err = pcall(function() Map.load(nil, game, id, { x = x, y = y, facing = facing }) end)
|
||||
result(ok, "load " .. id .. " " .. tostring(err or ""))
|
||||
session.map = id
|
||||
U.wait(60)
|
||||
end
|
||||
|
||||
-- pokefirered/data/maps/CinnabarIsland_PokemonLab_Lounge/scripts.inc:52 special ChoosePartyMon
|
||||
local Stack = require("src.ui.game3.stack")
|
||||
load("FR_CINNABAR_ISLAND_POKEMON_LAB_LOUNGE", 6, 6, "up")
|
||||
local key = Space.scriptKey("g3:0816e33e") or Space.scriptKey("g3:0816e3b6")
|
||||
result(key and Space.startScript(key, 1) and true or false, "Norma trade script starts")
|
||||
if answerYes() then
|
||||
local party = untilTrue(function() return Stack.has("party") or not running() end, 900, 4)
|
||||
result(party and Stack.has("party"), "trade: party menu opened")
|
||||
result(not Message.isOpen(), "trade: stay box closed at party menu")
|
||||
U.tap(game, "b"); U.wait(20)
|
||||
untilTrue(function()
|
||||
if Message.isOpen() and not Choice.isOpen() then U.tap(game, "a") end
|
||||
return not running()
|
||||
end, 900, 4)
|
||||
result(not running() and not Message.isOpen(), "trade: idle afterwards")
|
||||
result(not Field.locked, "trade: field unlocked")
|
||||
else
|
||||
result(false, "trade: prompt opened")
|
||||
end
|
||||
|
||||
load("FR_ROUTE1", 10, 10, "down")
|
||||
local synth = "synthetic_stay_wild"
|
||||
Space.vm.scripts[synth] = {
|
||||
{ op = "lockall" },
|
||||
{ op = "message", ptr = "SafariZone_Text_WouldYouLikeToExit" },
|
||||
{ op = "setwildbattle", C.species.byName.SPECIES_RATTATA, 3 },
|
||||
{ op = "dowildbattle" },
|
||||
{ op = "releaseall" },
|
||||
{ op = "end" },
|
||||
}
|
||||
result(Space.startScript(synth) and true or false, "synthetic stay+wild battle starts")
|
||||
local inBattle = untilTrue(function() return Battle.isActive() end, 1500, 2)
|
||||
result(inBattle, "wild battle started")
|
||||
if inBattle then
|
||||
result(not Message.isOpen(), "stay+wild: stay box closed once battle is up")
|
||||
local over = L.run(game, { turnCap = 60, guard = 60000 })
|
||||
result(over, "wild battle ended")
|
||||
U.wait(60)
|
||||
untilTrue(function()
|
||||
if Message.isOpen() then U.tap(game, "a") end
|
||||
return not running()
|
||||
end, 900, 4)
|
||||
end
|
||||
result(not Message.isOpen(), "stay+wild: stay box closed after battle")
|
||||
result(not Field.locked, "stay+wild: field unlocked")
|
||||
finish()
|
||||
end
|
||||
Reference in New Issue
Block a user