mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 13:33:27 -04:00
132 lines
5.1 KiB
Lua
132 lines
5.1 KiB
Lua
-- #2324: the level-up stat window gates the EXP sequence; it is never run past.
|
|
--
|
|
-- pokefirered draws the lvlup box from Cmd_drawlvlupbox and then *waits* for the
|
|
-- player (battle_script_commands.c: Cmd_drawlvlupbox ends the command, the
|
|
-- controller only returns after LvlUpBoxInput sees A/B). The FRLG rewrite
|
|
-- opened the box and kept pumping, so the box outlived its own step: it could
|
|
-- no longer be dismissed (input routing is phase-gated) and sat on screen over
|
|
-- the win/money text.
|
|
--
|
|
-- luajit tests/engine/battle_levelup_statwindow_bug2324.lua
|
|
|
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
|
|
local T = require("tests.modkit")
|
|
local check, eq = T.check, T.eq
|
|
require("tests.game3_cache").stubSpeciesNames()
|
|
|
|
local BattleText = require("src.core.game3.battle.battle_text")
|
|
BattleText.get = function(id) return tostring(id) end
|
|
|
|
local Experience = require("src.core.game3.battle.experience")
|
|
local ExpSeq = require("src.core.game3.battle.exp_seq")
|
|
local StatGrowth = require("src.ui.game3.stat_growth")
|
|
local Ui = require("src.core.game3.battle.ui")
|
|
local Anim = require("src.core.game3.battle.anim")
|
|
local Battle = require("src.core.game3.battle.init")
|
|
|
|
local A_PRESS = { wasPressed = function(_, key) return key == "a" end }
|
|
local NO_PRESS = { wasPressed = function() return false end }
|
|
|
|
-- A mon one award away from a level, so the sequence always grows stats.
|
|
local function levelUpMon()
|
|
return {
|
|
species = 1,
|
|
level = 5,
|
|
hp = 20,
|
|
maxHp = 20,
|
|
attack = 10,
|
|
defense = 10,
|
|
spAtk = 12,
|
|
spDef = 12,
|
|
speed = 9,
|
|
exp = Experience.expForLevel(3, 5),
|
|
growthRate = 3,
|
|
}
|
|
end
|
|
|
|
--- Runs the sequence up to the point the stat window opens.
|
|
--- Returns the pushMsg log and the ExpSeq step index at that moment.
|
|
local function pumpToStatWindow()
|
|
local mon = levelUpMon()
|
|
local res = Experience.apply(mon, 100)
|
|
local messages = {}
|
|
local awards = { { mon = mon, result = res, partyIndex = 1 } }
|
|
|
|
Ui.reset({ headless = false })
|
|
check(ExpSeq.begin(awards, function(t) messages[#messages + 1] = t end, nil,
|
|
{ headless = false }), "the level-up award starts an EXP sequence")
|
|
|
|
-- exp-gain text, then the bar, then the grew-to-LV text
|
|
for _ = 1, 4 do
|
|
ExpSeq.update()
|
|
Ui._showing = false
|
|
Ui._queue = {}
|
|
Anim.reset({ headless = false })
|
|
end
|
|
|
|
check(StatGrowth.isOpen(), "the stat window opened on level up")
|
|
eq(StatGrowth._page, 1, "the stat window starts on Page 1 (diffs)")
|
|
return messages, ExpSeq._i, mon, res
|
|
end
|
|
|
|
do
|
|
local messages, stepBefore = pumpToStatWindow()
|
|
local msgsBefore = #messages
|
|
|
|
-- The box waits for the player: idle pumps must not move the sequence.
|
|
for i = 1, 20 do
|
|
eq(ExpSeq.update(), false, "pump " .. i .. " reports busy while the box is open")
|
|
end
|
|
eq(ExpSeq._i, stepBefore, "idle pumps did not advance the sequence")
|
|
eq(#messages, msgsBefore, "idle pumps pushed no further battle text")
|
|
check(StatGrowth.isOpen(), "the box is still open after 20 idle pumps")
|
|
eq(StatGrowth._page, 1, "the box is still on Page 1 after 20 idle pumps")
|
|
|
|
-- Page 2 is still a wait.
|
|
check(StatGrowth.handleInput(A_PRESS), "A consumed on Page 1")
|
|
eq(StatGrowth._page, 2, "the box flipped to Page 2 (new values)")
|
|
check(StatGrowth.isOpen(), "the box is still open on Page 2")
|
|
for _ = 1, 20 do
|
|
eq(ExpSeq.update(), false, "pump reports busy while Page 2 is open")
|
|
end
|
|
eq(ExpSeq._i, stepBefore, "Page 2 idle pumps did not advance the sequence")
|
|
eq(#messages, msgsBefore, "Page 2 idle pumps pushed no further battle text")
|
|
|
|
-- The second A press is what releases the sequence.
|
|
check(StatGrowth.handleInput(A_PRESS), "A consumed on Page 2")
|
|
check(not StatGrowth.isOpen(), "the second A press closed the box")
|
|
eq(ExpSeq._i, stepBefore + 1, "the sequence advanced only once the box closed")
|
|
|
|
-- And it can be driven to the end from there without the box coming back.
|
|
local guard = 0
|
|
while not ExpSeq.update() and guard < 200 do
|
|
guard = guard + 1
|
|
Ui._showing = false
|
|
Ui._queue = {}
|
|
Anim.reset({ headless = false })
|
|
end
|
|
check(guard < 200, "the sequence finishes after the box is dismissed")
|
|
check(not StatGrowth.isOpen(), "no stat window survives the finished sequence")
|
|
check(ExpSeq.busy() == false, "ExpSeq.busy() is false once the sequence is done")
|
|
end
|
|
|
|
do
|
|
-- A box whose phase can no longer dismiss it must not linger: input routing is
|
|
-- phase-gated, so a box left open outside those phases would be undismissable
|
|
-- and would draw over the win/money text.
|
|
local _, _, mon, res = pumpToStatWindow()
|
|
|
|
local savedActive, savedPhase, savedHeadless = Battle._active, Battle._phase, Battle._headless
|
|
Battle._active, Battle._phase, Battle._headless = true, nil, true
|
|
StatGrowth.open(mon, res.steps[1].oldStats, res.steps[1].newStats, function()
|
|
error("a torn-down stat window must not fire its onDone callback")
|
|
end)
|
|
check(StatGrowth.isOpen(), "a stale box is open before Battle.update")
|
|
Battle.update(1 / 60, { input = NO_PRESS })
|
|
check(not StatGrowth.isOpen(), "Battle.update tears down a box outside its phases")
|
|
Battle._active, Battle._phase, Battle._headless = savedActive, savedPhase, savedHeadless
|
|
end
|
|
|
|
T.finish("battle_levelup_statwindow_bug2324")
|