mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-12 08:21:02 +02:00
Delay evolution until trainer text ends
This commit is contained in:
+12
-1
@@ -265,7 +265,18 @@ function Commands.start_battle(ctx, kind, a, b)
|
||||
ctx.lastBattleResult = result
|
||||
ctx.lastCheck = result == "win"
|
||||
if ctx.overworld then
|
||||
ctx.overworld:afterBattle(result, battle)
|
||||
-- A map script often follows a trainer battle with its own text.
|
||||
-- Keep a level evolution behind that text: otherwise afterBattle
|
||||
-- pushes the evolution screen, then this runner resumes and pushes
|
||||
-- the trainer's text on top of it.
|
||||
if result == "win" then
|
||||
ctx.afterScript = ctx.afterScript or {}
|
||||
table.insert(ctx.afterScript, function()
|
||||
ctx.overworld:afterBattle(result, battle)
|
||||
end)
|
||||
else
|
||||
ctx.overworld:afterBattle(result, battle)
|
||||
end
|
||||
end
|
||||
runner:resume()
|
||||
end
|
||||
|
||||
@@ -125,6 +125,10 @@ function ScriptRunner:run(script, extra)
|
||||
end
|
||||
self.co = coroutine.create(function()
|
||||
self:exec(script, ctx)
|
||||
-- Commands can defer a game action until the script's own dialogue is
|
||||
-- done. start_battle uses this for win-path evolutions, which must not
|
||||
-- be covered by post-battle trainer text.
|
||||
for _, callback in ipairs(ctx.afterScript or {}) do callback() end
|
||||
if ctx.onDone then ctx.onDone() end
|
||||
if Runtime.wants("script.ended") then
|
||||
Runtime.emit("script.ended", { ctx = ctx, completed = true })
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
-- A trainer script's post-battle text must finish before a level evolution.
|
||||
-- Its start_battle row resumes the script after OverworldState:afterBattle,
|
||||
-- so this covers the same handoff used by trainer and Rocket encounters.
|
||||
|
||||
package.path = "./?.lua;./?/init.lua;" .. package.path
|
||||
if not _G.love then _G.love = require("tests.love_stub") end
|
||||
|
||||
local Data = require("src.core.Data")
|
||||
if not Data.maps then Data:load() end
|
||||
local S = require("tests.harness").suite("parity trainer evolution order")
|
||||
local check = S.check
|
||||
|
||||
local Game = require("src.core.Game")
|
||||
local SaveData = require("src.core.SaveData")
|
||||
local StateStack = require("src.core.StateStack")
|
||||
local ScriptRunner = require("src.script.ScriptRunner")
|
||||
local OverworldState = require("src.world.OverworldController")
|
||||
local Pokemon = require("src.pokemon.Pokemon")
|
||||
require("src.render.Font").load(Data)
|
||||
|
||||
Game.data = Data
|
||||
Game.save = SaveData.newGame()
|
||||
Game.stack = StateStack; StateStack:init()
|
||||
Game.renderer = { worldViewSize = function() return 160, 144 end }
|
||||
|
||||
local caterpie = Pokemon.new(Data, "CATERPIE", 7)
|
||||
Game.save.party = { caterpie }
|
||||
|
||||
local fakeBattle
|
||||
local originalBattleState = package.loaded["src.battle.BattleState"]
|
||||
package.loaded["src.battle.BattleState"] = {
|
||||
newTrainer = function()
|
||||
fakeBattle = { leveledUp = { [caterpie] = true } }
|
||||
return fakeBattle
|
||||
end,
|
||||
}
|
||||
|
||||
local overworld = setmetatable({}, { __index = OverworldState })
|
||||
overworld:enter("ROUTE_1", 5, 5, "down")
|
||||
local runner = ScriptRunner.new(Game, overworld)
|
||||
runner:run({
|
||||
{ "start_battle", "trainer", "OPP_YOUNGSTER", 1 },
|
||||
{ "show_text", "THE TRAINER TALKS AFTER THE FIGHT" },
|
||||
{ "show_text", "THE TRAINER HAS MORE TO SAY" },
|
||||
})
|
||||
|
||||
check(fakeBattle ~= nil, "trainer battle starts and yields the script")
|
||||
Game.stack:pop()
|
||||
fakeBattle.onFinish("win")
|
||||
|
||||
package.loaded["src.battle.BattleState"] = originalBattleState
|
||||
|
||||
local function stateHas(state, text)
|
||||
for _, page in ipairs(state.pages or {}) do
|
||||
for _, line in ipairs(page) do
|
||||
if type(line) == "string" and line:find(text, 1, true) then return true end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local afterText = Game.stack:top()
|
||||
check(stateHas(afterText, "THE TRAINER TALKS"),
|
||||
"the trainer's after-battle text is shown first")
|
||||
check(#Game.stack.states == 1,
|
||||
"the evolution screen waits until trainer after-text closes")
|
||||
|
||||
Game.stack:pop()
|
||||
afterText.onDone()
|
||||
|
||||
local moreText = Game.stack:top()
|
||||
check(stateHas(moreText, "MORE TO SAY"),
|
||||
"all trainer after-text finishes before evolution")
|
||||
check(#Game.stack.states == 1,
|
||||
"the evolution still waits for the last trainer text")
|
||||
|
||||
Game.stack:pop()
|
||||
moreText.onDone()
|
||||
|
||||
local evolutionText = Game.stack:top()
|
||||
check(stateHas(evolutionText, "evolving"),
|
||||
"the level evolution starts after trainer after-text closes")
|
||||
|
||||
S.finish()
|
||||
@@ -3279,6 +3279,7 @@ runSuites(orderedGlob("tests/parity_*.lua", {
|
||||
"tests/parity_hof.lua", "tests/parity_trade_gift.lua",
|
||||
"tests/parity_yellow_trades.lua",
|
||||
"tests/parity_yellow_bills_pikachu.lua",
|
||||
"tests/parity_trainer_evolution_order.lua",
|
||||
"tests/parity_intro.lua", "tests/parity_tilt.lua",
|
||||
"tests/parity_gbcfx.lua",
|
||||
}))
|
||||
|
||||
Reference in New Issue
Block a user