mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-15 07:41:21 +02:00
93 lines
3.2 KiB
Lua
93 lines
3.2 KiB
Lua
-- A sandboxed mod can defer an ordinary trainer engagement and later resume
|
|
-- it with a battle-local player-party scope, using only public mod surfaces.
|
|
|
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
love = love or require("tests.love_stub")
|
|
|
|
local T = require("tests.modkit")
|
|
local OW = require("src.world.OverworldController")
|
|
|
|
local FIXTURE = {
|
|
["mods/scope_probe/manifest.json"] = [[{
|
|
"id": "scope_probe",
|
|
"name": "Scope Probe",
|
|
"version": "1.0.0",
|
|
"entry": "main.lua",
|
|
"api": 2
|
|
}]],
|
|
["mods/scope_probe/main.lua"] = [[
|
|
local mod = ...
|
|
mod.hooks:wrap("trainer.before_battle", function(next, game, context, continue)
|
|
mod.exports.game = game
|
|
mod.exports.context = context
|
|
mod.exports.continue = continue
|
|
return true
|
|
end)
|
|
]],
|
|
}
|
|
|
|
local vanilla = T.sdk.loadNone({})
|
|
local vanillaCalls, vanillaOptions = 0
|
|
OW.prepareTrainerBattle({ id = "game" }, {
|
|
trainerClass = "OPP_FIX_YOUNGSTER", partyIndex = 1,
|
|
mapId = "FIX_ROUTE", npcId = "TRAINER_1",
|
|
}, function(options)
|
|
vanillaCalls, vanillaOptions = vanillaCalls + 1, options
|
|
end)
|
|
T.eq(vanillaCalls, 1, "no mod starts the trainer battle exactly once")
|
|
T.eq(vanillaOptions, nil, "no mod supplies no battle-local party scope")
|
|
vanilla.release()
|
|
|
|
local run = T.sdk.loadMods({ "mods/scope_probe" }, {
|
|
fs = T.sdk.memfs(FIXTURE),
|
|
})
|
|
T.eq(#run.errors, 0,
|
|
"the public preparation probe loads clean (" .. tostring(run.errors[1]) .. ")")
|
|
local game = { id = "live-game" }
|
|
local calls, options = 0
|
|
OW.prepareTrainerBattle(game, {
|
|
trainerClass = "OPP_FIX_YOUNGSTER", partyIndex = 2,
|
|
mapId = "FIX_ROUTE", npcId = "TRAINER_7",
|
|
}, function(value)
|
|
calls, options = calls + 1, value
|
|
end)
|
|
T.eq(calls, 0, "a claiming public hook defers battle construction")
|
|
local out = run.loader.exports.scope_probe or {}
|
|
T.check(out.game == game, "the hook receives the live game")
|
|
T.same(out.context, {
|
|
trainerClass = "OPP_FIX_YOUNGSTER", partyIndex = 2,
|
|
mapId = "FIX_ROUTE", npcId = "TRAINER_7",
|
|
}, "the hook receives data-only trainer identity context")
|
|
T.eq(out.continue({ playerPartyIndices = { 2, 4 } }), true,
|
|
"the retained continuation resumes the deferred battle")
|
|
T.eq(calls, 1, "resume constructs the battle exactly once")
|
|
T.same(options, { playerPartyIndices = { 2, 4 } },
|
|
"ordered eligible indices cross the public seam unchanged")
|
|
T.eq(out.continue({ playerPartyIndices = { 1 } }), false,
|
|
"the continuation refuses a second invocation")
|
|
T.eq(calls, 1, "a duplicate resume cannot start a second battle")
|
|
run.release()
|
|
|
|
local cancelRun = T.sdk.loadMods({ "mods/scope_probe" }, {
|
|
fs = T.sdk.memfs(FIXTURE),
|
|
})
|
|
local starts, cancels = 0, 0
|
|
OW.prepareTrainerBattle(game, {
|
|
trainerClass = "OPP_FIX_YOUNGSTER", partyIndex = 2,
|
|
mapId = "FIX_ROUTE", npcId = "TRAINER_7",
|
|
}, function()
|
|
starts = starts + 1
|
|
end, function()
|
|
cancels = cancels + 1
|
|
end)
|
|
local cancelOut = cancelRun.loader.exports.scope_probe or {}
|
|
T.eq(cancelOut.continue({ cancel = true }), true,
|
|
"the retained continuation can cancel a deferred encounter")
|
|
T.eq(starts, 0, "cancelling never constructs a trainer battle")
|
|
T.eq(cancels, 1, "cancelling invokes the encounter's completion callback")
|
|
T.eq(cancelOut.continue(), false,
|
|
"a cancelled continuation remains one-shot")
|
|
cancelRun.release()
|
|
|
|
T.finish("trainer_before_battle")
|