mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-15 07:41:21 +02:00
feat(mod-api): add trainer battle party scope
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
-- 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()
|
||||
|
||||
T.finish("trainer_before_battle")
|
||||
Reference in New Issue
Block a user