mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 05:32:07 -04:00
556 lines
20 KiB
Lua
556 lines
20 KiB
Lua
#!/usr/bin/env luajit
|
|
-- Dedicated Gen 3 Evolution Scene & Core Parity Tests
|
|
|
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
|
|
local failed = 0
|
|
local function check(cond, msg)
|
|
if cond then
|
|
print("[ok] " .. msg)
|
|
else
|
|
failed = failed + 1
|
|
print("[FAIL] " .. msg)
|
|
end
|
|
end
|
|
|
|
local Cache = require("tests.game3_cache")
|
|
if not Cache.mount("pokemon/evolutions.lua") then
|
|
print("[skip] game3_evolution_scene_test: " .. tostring(Cache.reason))
|
|
os.exit(0)
|
|
end
|
|
|
|
local Pokemon = require("src.core.game3.pokemon")
|
|
local Evolution = require("src.core.game3.evolution")
|
|
local EvolutionScene = require("src.ui.game3.evolution_scene")
|
|
local Bag = require("src.core.game3.bag")
|
|
|
|
print("=== [TEST 1] Nickname Matching & Sanitization (EvolutionRenameMon) ===")
|
|
do
|
|
-- 1. Un-nicknamed (nil)
|
|
local mon1 = { species = 1, speciesId = 1, nickname = nil, name = "BULBASAUR" }
|
|
Evolution.renameMon(mon1, 1, 2)
|
|
check(mon1.nickname == "IVYSAUR" and mon1.name == "IVYSAUR", "un-nicknamed (nil) renamed to IVYSAUR")
|
|
|
|
-- 2. Un-nicknamed matching pre-evo name
|
|
local mon2 = { species = 1, speciesId = 1, nickname = "BULBASAUR", name = "BULBASAUR" }
|
|
Evolution.renameMon(mon2, 1, 2)
|
|
check(mon2.nickname == "IVYSAUR" and mon2.name == "IVYSAUR", "un-nicknamed matching pre-evo renamed to IVYSAUR")
|
|
|
|
-- 3. Un-nicknamed with null-padding / trailing spaces
|
|
local mon3 = { species = 1, speciesId = 1, nickname = "BULBASAUR\0\0 ", name = "BULBASAUR" }
|
|
Evolution.renameMon(mon3, 1, 2)
|
|
check(mon3.nickname == "IVYSAUR" and mon3.name == "IVYSAUR", "padded un-nicknamed renamed to IVYSAUR")
|
|
|
|
-- 4. Custom nickname preserved
|
|
local mon4 = { species = 1, speciesId = 1, nickname = "SPROUT", name = "SPROUT" }
|
|
Evolution.renameMon(mon4, 1, 2)
|
|
check(mon4.nickname == "SPROUT" and mon4.name == "SPROUT", "custom nickname SPROUT preserved on evolution")
|
|
end
|
|
|
|
print("=== [TEST 2] Everstone Protection ===")
|
|
do
|
|
local monNormal = { species = 1, speciesId = 1, level = 16, heldItem = 0 }
|
|
local target, _ = Evolution.levelTarget(monNormal)
|
|
check(target == 2, "normal Lv 16 Bulbasaur evolves into Ivysaur (species 2)")
|
|
|
|
-- pokefirered/include/constants/items.h:206
|
|
local monEverstone = { species = 1, speciesId = 1, level = 16, heldItem = 195 }
|
|
local blockedTarget = Evolution.levelTarget(monEverstone)
|
|
check(blockedTarget == nil, "Everstone blocks level-up evolution")
|
|
|
|
-- pokefirered/src/pokemon.c:5044
|
|
local clefairy = { species = 35, speciesId = 35, level = 16, heldItem = 195 }
|
|
check(Evolution.itemTarget(clefairy, 94) == nil, "Everstone blocks a Moon Stone use")
|
|
check(Evolution.itemCheck(clefairy, 94) == 36, "EVO_MODE_ITEM_CHECK still reports Clefable")
|
|
clefairy.heldItem = 0
|
|
local clefableTarget = Evolution.itemTarget(clefairy, 94) -- ITEM_MOON_STONE (94)
|
|
check(clefableTarget == 36, "Moon Stone bypasses Everstone on Clefairy (evolves to Clefable 36)")
|
|
end
|
|
|
|
print("=== [TEST 3] Stat Recalculation & HP Delta ===")
|
|
do
|
|
-- Alive mon gains HP delta
|
|
local monAlive = { species = 1, speciesId = 1, level = 16, hp = 15, maxHp = 40, iv = { 15, 15, 15, 15, 15, 15 }, ev = { 0, 0, 0, 0, 0, 0 } }
|
|
Evolution.apply(monAlive, 2)
|
|
check(monAlive.species == 2, "mutated to species 2 (Ivysaur)")
|
|
check(monAlive.maxHp > 40, "maxHp increased on evolution")
|
|
local delta = monAlive.maxHp - 40
|
|
check(monAlive.hp == 15 + delta, "current HP gained exact maxHp delta (" .. tostring(monAlive.hp) .. ")")
|
|
|
|
-- Fainted mon preserves 0 HP
|
|
local monFainted = { species = 1, speciesId = 1, level = 16, hp = 0, maxHp = 40, iv = { 15, 15, 15, 15, 15, 15 }, ev = { 0, 0, 0, 0, 0, 0 } }
|
|
Evolution.apply(monFainted, 2)
|
|
check(monFainted.hp == 0, "fainted mon remains at 0 HP after evolution")
|
|
end
|
|
|
|
print("=== [TEST 4] Shedinja Cloning & Sanitization (Nincada Lv 20 -> Ninjask + Shedinja) ===")
|
|
do
|
|
local bag = Bag.new()
|
|
Bag.add(bag, 4, 5) -- 5 standard Poké Balls
|
|
|
|
local party = {
|
|
{
|
|
species = "NINCADA", speciesId = "NINCADA", level = 20,
|
|
hp = 45, maxHp = 45,
|
|
heldItem = 195,
|
|
status = "PSN",
|
|
pokeball = 2, -- Ultra Ball
|
|
ability = 1,
|
|
moves = { 10, 20, 30, 40 },
|
|
iv = { 31, 31, 31, 31, 31, 31 },
|
|
ev = { 0, 0, 0, 0, 0, 0 },
|
|
}
|
|
}
|
|
local session = { party = party, dex = { seen = {}, caught = {} }, bag = bag }
|
|
|
|
local nincada = party[1]
|
|
Evolution.apply(nincada, 302, session, bag)
|
|
|
|
check(#party == 2, "Shedinja spawned into party (party size = 2)")
|
|
check(party[1].species == 302, "primary mon evolved into Ninjask (species 302)")
|
|
|
|
local shedinja = party[2]
|
|
check(shedinja.species == 303, "shedinja species is 303")
|
|
check(shedinja.maxHp == 1 and shedinja.hp == 1, "shedinja maxHp and hp are exactly 1")
|
|
check(shedinja.heldItem == 0, "shedinja heldItem is sanitized to 0 (no duplicate items)")
|
|
check(shedinja.status == 0, "shedinja status condition is sanitized to 0")
|
|
-- pokefirered/src/evolution_scene.c:550
|
|
check(shedinja.pokeball == 2, "shedinja keeps the Nincada's ball")
|
|
check(shedinja.ability == 25, "shedinja ability is Wonder Guard (25)")
|
|
check(Bag.get(bag, 4) == 5, "no Poké Ball was deducted from the bag")
|
|
check(session.dex.caught[303] == true, "Shedinja registered as Caught in Pokédex")
|
|
end
|
|
|
|
print("=== [TEST 5] EvolutionScene State Machine & B-Button Cancellation ===")
|
|
do
|
|
local mon = { species = 1, speciesId = 1, level = 16, hp = 40, maxHp = 40 }
|
|
local cancelled = false
|
|
local evolved = false
|
|
|
|
-- Start EvolutionScene with canStop = true
|
|
local ok = EvolutionScene.start(mon, 2, {
|
|
canStop = true,
|
|
onDone = function(result)
|
|
if result == "stopped" then cancelled = true end
|
|
if result == "evolved" then evolved = true end
|
|
end
|
|
})
|
|
check(ok == true, "EvolutionScene started")
|
|
check(EvolutionScene.isOpen() == true, "EvolutionScene is open")
|
|
|
|
-- Advance frames into cycle phase (reaches cycle at frame 156)
|
|
for _ = 1, 180 do
|
|
EvolutionScene.update(1 / 60)
|
|
end
|
|
check(EvolutionScene._state == "cycle", "entered cycle phase")
|
|
|
|
-- Simulate B-button press to cancel
|
|
local mockInput = {
|
|
isDown = function(_, k) return k == "b" end,
|
|
wasPressed = function(_, k) return k == "b" end,
|
|
}
|
|
EvolutionScene.handleInput(mockInput)
|
|
check(EvolutionScene._state == "cancel", "state transitioned to cancel on B-button")
|
|
check(mon.species == 1, "species remained Bulbasaur (species 1) after cancellation")
|
|
|
|
-- Advance text dismiss (first press skips typewriter, second dismisses)
|
|
EvolutionScene.handleInput(mockInput)
|
|
EvolutionScene.handleInput(mockInput)
|
|
check(EvolutionScene.isOpen() == false, "EvolutionScene closed after cancel")
|
|
check(cancelled == true, "onDone called with result 'stopped'")
|
|
end
|
|
|
|
print("=== [TEST 6] EvolutionScene Point-of-No-Return Completion ===")
|
|
do
|
|
local mon = { species = 1, speciesId = 1, level = 16, hp = 40, maxHp = 40 }
|
|
local completed = false
|
|
|
|
EvolutionScene.start(mon, 2, {
|
|
canStop = false,
|
|
headless = true,
|
|
onDone = function(result)
|
|
if result == "evolved" then completed = true end
|
|
end
|
|
})
|
|
|
|
-- Run through entire animation cycle past acceleration cutoff (speed >= 128)
|
|
for _ = 1, 800 do
|
|
EvolutionScene.update(1 / 60)
|
|
if EvolutionScene._state == "congrats" or EvolutionScene._state == "learn_moves" then
|
|
local mockInput = {
|
|
wasPressed = function(_, k) return k == "a" end,
|
|
isDown = function() return false end,
|
|
}
|
|
EvolutionScene.handleInput(mockInput)
|
|
end
|
|
end
|
|
|
|
check(mon.species == 2, "species successfully mutated to Ivysaur (species 2)")
|
|
check(mon.nickname == "IVYSAUR", "nickname updated to IVYSAUR")
|
|
check(completed == true, "onDone called with result 'evolved'")
|
|
end
|
|
|
|
print("=== [TEST 7] EvolutionScene Audio Sequence & Map Music Restoration ===")
|
|
do
|
|
local Audio = require("src.core.game3.audio")
|
|
local playedSongs = {}
|
|
local origPlaySong = Audio.playSong
|
|
Audio.playSong = function(id, opts)
|
|
playedSongs[#playedSongs + 1] = id
|
|
return origPlaySong(id, opts)
|
|
end
|
|
|
|
Audio._mapSong = 279 -- Pallet Town
|
|
Audio._currentSong = { id = 279 }
|
|
|
|
local mon = { species = 19, speciesId = 19, level = 20, hp = 40, maxHp = 40, moves = { 33, 39, 43, 99 } }
|
|
local completed = false
|
|
|
|
EvolutionScene.start(mon, 20, {
|
|
canStop = false,
|
|
headless = true,
|
|
savedSong = 279,
|
|
onDone = function(result)
|
|
if result == "evolved" then completed = true end
|
|
end
|
|
})
|
|
|
|
check(EvolutionScene._savedSong == 279, "EvolutionScene savedSong preserved as 279")
|
|
|
|
-- Progress past congrats
|
|
for _ = 1, 800 do
|
|
EvolutionScene.update(1 / 60)
|
|
if EvolutionScene._state == "congrats" or EvolutionScene._state == "learn_moves" then
|
|
local mockInput = {
|
|
wasPressed = function(_, k) return k == "a" end,
|
|
isDown = function() return false end,
|
|
}
|
|
EvolutionScene.handleInput(mockInput)
|
|
end
|
|
end
|
|
|
|
check(completed == true, "evolution completed")
|
|
check(playedSongs[#playedSongs] == 279, "Pallet Town map BGM (279) restored at end of evolution sequence")
|
|
|
|
Audio.playSong = origPlaySong
|
|
end
|
|
|
|
print("=== [TEST 8] EvolutionScene Post-Battle Victory Theme Resumption ===")
|
|
do
|
|
local Audio = require("src.core.game3.audio")
|
|
local playedSongs = {}
|
|
local origPlaySong = Audio.playSong
|
|
Audio.playSong = function(id, opts)
|
|
playedSongs[#playedSongs + 1] = id
|
|
return origPlaySong(id, opts)
|
|
end
|
|
|
|
Audio._mapSong = 279 -- Pallet Town
|
|
Audio._currentSong = { id = 311 } -- MUS_VICTORY_WILD
|
|
|
|
local mon = { species = 19, speciesId = 19, level = 20, hp = 40, maxHp = 40, moves = { 33, 39 } }
|
|
local completed = false
|
|
|
|
local EvoSeq = require("src.core.game3.battle.evo_seq")
|
|
local session = { party = { mon } }
|
|
EvoSeq.begin({ { mon = mon, target = 20 } }, {
|
|
session = session,
|
|
onDone = function() completed = true end
|
|
})
|
|
|
|
-- Advance frames and dismiss dialogs
|
|
for _ = 1, 800 do
|
|
EvoSeq.update()
|
|
EvolutionScene.update(1 / 60)
|
|
local Choice = package.loaded["src.ui.game3.choice"]
|
|
if Choice and Choice.active then
|
|
Choice.cancel()
|
|
end
|
|
if EvolutionScene._state == "congrats" or EvolutionScene._state == "learn_moves" then
|
|
local mockInput = {
|
|
wasPressed = function(_, k) return k == "a" end,
|
|
isDown = function() return false end,
|
|
}
|
|
EvolutionScene.handleInput(mockInput)
|
|
end
|
|
end
|
|
EvoSeq.update()
|
|
|
|
check(completed == true, "battle evolution sequence finished")
|
|
check(playedSongs[#playedSongs] == 311, "Victory theme (311) resumed during and after post-battle evolution")
|
|
|
|
Audio.playSong = origPlaySong
|
|
end
|
|
|
|
print("=== [TEST 9] In-Battle Evolution Flow, Input Routing & Ending Transition ===")
|
|
do
|
|
local Battle = require("src.core.game3.battle")
|
|
local mon = { species = 10, speciesId = 10, level = 7, hp = 20, maxHp = 20, moves = { 33, 81 } }
|
|
local session = { party = { mon } }
|
|
|
|
-- Initialize battle state
|
|
Battle.start({
|
|
playerParty = { mon },
|
|
foe = { species = 16, level = 3, hp = 10, maxHp = 10, moves = { 33 } },
|
|
session = session,
|
|
headless = false,
|
|
wild = true,
|
|
})
|
|
|
|
-- Simulate winning battle with level-up to 7 (Caterpie evolves at 7 -> Metapod)
|
|
Battle._leveledUp = { [1] = true }
|
|
Battle._pendingEnd = "win"
|
|
Battle._phase = "awarding"
|
|
local EvoSeq = require("src.core.game3.battle.evo_seq")
|
|
local Evolution = require("src.core.game3.evolution")
|
|
local pending = Evolution.pending(session.party, Battle._leveledUp, session)
|
|
local hooks = Battle._choiceHooksForTests()
|
|
hooks.session = session
|
|
local started = EvoSeq.begin(pending, hooks)
|
|
check(started == true, "EvoSeq began pending evolution for Caterpie")
|
|
Battle._phase = "evolving"
|
|
|
|
local mockGame = {
|
|
input = {
|
|
wasPressed = function(_, k) return k == "a" end,
|
|
isDown = function() return false end,
|
|
}
|
|
}
|
|
|
|
-- First tick of Battle.update runs EvoSeq.update() -> launches EvolutionScene.start()
|
|
Battle.update(1 / 60, mockGame)
|
|
|
|
check(Battle._phase == "evolving", "Battle transitioned to 'evolving' phase")
|
|
check(EvolutionScene.isOpen() == true, "EvolutionScene opened during battle")
|
|
|
|
-- Pump Battle.update through all animation frames until evolution completes
|
|
local guard = 0
|
|
while (Battle._phase == "evolving" or EvolutionScene.isOpen()) and guard < 1000 do
|
|
guard = guard + 1
|
|
Battle.update(1 / 60, mockGame)
|
|
if EvolutionScene.isOpen() then
|
|
EvolutionScene.handleInput(mockGame.input)
|
|
EvolutionScene.update(1 / 60)
|
|
end
|
|
end
|
|
|
|
check(EvolutionScene.isOpen() == false, "EvolutionScene closed cleanly without softlock")
|
|
check(mon.species == 11, "Caterpie evolved into Metapod (species 11)")
|
|
check(Battle._phase == "ending", "Battle transitioned to 'ending' phase after evolution")
|
|
end
|
|
|
|
print("=== [TEST 10] Evolution Audio Choreography Flow (pokefirered Parity) ===")
|
|
do
|
|
local Audio = require("src.core.game3.audio")
|
|
local events = {}
|
|
local origPlaySong = Audio.playSong
|
|
local origPlayFanfare = Audio.playFanfare
|
|
local origPlaySe = Audio.playSe
|
|
local origPlayCry = Audio.playCry
|
|
|
|
Audio.playSong = function(id, opts)
|
|
events[#events + 1] = { kind = "song", id = id }
|
|
return origPlaySong(id, opts)
|
|
end
|
|
Audio.playFanfare = function(id)
|
|
events[#events + 1] = { kind = "fanfare", id = id }
|
|
return origPlayFanfare(id)
|
|
end
|
|
Audio.playSe = function(id)
|
|
events[#events + 1] = { kind = "se", id = id }
|
|
return origPlaySe(id)
|
|
end
|
|
Audio.playCry = function(species)
|
|
events[#events + 1] = { kind = "cry", species = species }
|
|
return origPlayCry(species)
|
|
end
|
|
|
|
Audio._mapSong = 279
|
|
Audio._currentSong = { id = 279 }
|
|
|
|
local mon = { species = 1, speciesId = 1, level = 16, hp = 40, maxHp = 40, moves = { 33, 39, 43, 99 } }
|
|
EvolutionScene.start(mon, 2, {
|
|
canStop = false,
|
|
headless = true,
|
|
savedSong = 279,
|
|
})
|
|
|
|
for _ = 1, 800 do
|
|
EvolutionScene.update(1 / 60)
|
|
if EvolutionScene._state == "congrats" or EvolutionScene._state == "learn_moves" then
|
|
local mockInput = {
|
|
wasPressed = function(_, k) return k == "a" end,
|
|
isDown = function() return false end,
|
|
}
|
|
EvolutionScene.handleInput(mockInput)
|
|
end
|
|
end
|
|
|
|
-- Verify audio event sequence:
|
|
-- 1. Pre-evo cry
|
|
-- 2. MUS_EVOLUTION_INTRO (263)
|
|
-- 3. MUS_EVOLUTION (264)
|
|
-- 4. Stop evolution BGM (song 0) + SE_M_PETAL_DANCE (195) (NOT SE_EXP!)
|
|
-- 5. Post-evo cry
|
|
-- 6. MUS_EVOLVED (259)
|
|
local foundPreCry, foundIntroSong, foundEvoSong, foundBurstSe, foundPostCry, foundEvolvedFanfare = false, false, false, false, false, false
|
|
local hasWrongSeExp = false
|
|
|
|
for _, ev in ipairs(events) do
|
|
if ev.kind == "se" and ev.id == 27 then -- SE_EXP
|
|
hasWrongSeExp = true
|
|
end
|
|
end
|
|
check(not hasWrongSeExp, "SE_EXP (27) is NOT played before or during evolution fanfare")
|
|
|
|
-- Check ordering
|
|
local idx = 1
|
|
for _, ev in ipairs(events) do
|
|
if idx == 1 and ev.kind == "cry" and ev.species == 1 then
|
|
foundPreCry = true
|
|
idx = 2
|
|
elseif idx == 2 and ev.kind == "song" and ev.id == 263 then
|
|
foundIntroSong = true
|
|
idx = 3
|
|
elseif idx == 3 and ev.kind == "song" and ev.id == 264 then
|
|
foundEvoSong = true
|
|
idx = 4
|
|
elseif idx == 4 and ev.kind == "se" and ev.id == 195 then -- SE_M_PETAL_DANCE
|
|
foundBurstSe = true
|
|
idx = 5
|
|
elseif idx == 5 and ev.kind == "cry" and ev.species == 2 then
|
|
foundPostCry = true
|
|
idx = 6
|
|
elseif idx == 6 and (ev.kind == "song" or ev.kind == "fanfare") and ev.id == 259 then
|
|
foundEvolvedFanfare = true
|
|
idx = 7
|
|
end
|
|
end
|
|
|
|
check(foundPreCry, "1. Pre-evo cry played first")
|
|
check(foundIntroSong, "2. MUS_EVOLUTION_INTRO (263) played")
|
|
check(foundEvoSong, "3. MUS_EVOLUTION (264) played")
|
|
check(foundBurstSe, "4. SE_M_PETAL_DANCE (195) played on burst")
|
|
check(foundPostCry, "5. Post-evo cry played after burst")
|
|
check(foundEvolvedFanfare, "6. MUS_EVOLVED (259) fanfare played on congratulations")
|
|
|
|
Audio.playSong = origPlaySong
|
|
Audio.playFanfare = origPlayFanfare
|
|
Audio.playSe = origPlaySe
|
|
Audio.playCry = origPlayCry
|
|
end
|
|
|
|
print("=== [TEST 11] In-Battle Evolution Scene Has One Input Owner ===")
|
|
do
|
|
local Battle = require("src.core.game3.battle")
|
|
local saved = {
|
|
active = Battle._active, phase = Battle._phase, auto = Battle._auto, headless = Battle._headless,
|
|
open = EvolutionScene.open, handleInput = EvolutionScene.handleInput,
|
|
summary = package.loaded["src.ui.game3.summary_menu"],
|
|
}
|
|
local evoCalls, summaryCalls, summaryOpen = 0, 0, false
|
|
EvolutionScene.handleInput = function() evoCalls = evoCalls + 1 end
|
|
package.loaded["src.ui.game3.summary_menu"] = {
|
|
isOpen = function() return summaryOpen end,
|
|
handleInput = function() summaryCalls = summaryCalls + 1 end,
|
|
}
|
|
local mockGame = {
|
|
input = {
|
|
wasPressed = function(_, k) return k == "down" end,
|
|
isDown = function() return false end,
|
|
}
|
|
}
|
|
Battle._active, Battle._phase, Battle._auto, Battle._headless = true, "evolving", false, true
|
|
EvolutionScene.open = true
|
|
|
|
Battle.update(1 / 60, mockGame)
|
|
check(evoCalls == 0, "Battle.update leaves the evolution scene yes/no to Hud (" .. evoCalls .. " calls)")
|
|
|
|
summaryOpen = true
|
|
Battle.update(1 / 60, mockGame)
|
|
check(evoCalls == 0 and summaryCalls == 1,
|
|
"forget-move summary over the evolution scene gets the press (" .. summaryCalls .. " calls)")
|
|
|
|
Battle._auto = true
|
|
summaryOpen = false
|
|
Battle.update(1 / 60, mockGame)
|
|
check(evoCalls == 0, "auto battle does not drive the evolution scene either (" .. evoCalls .. " calls)")
|
|
|
|
Battle._active, Battle._phase, Battle._auto, Battle._headless =
|
|
saved.active, saved.phase, saved.auto, saved.headless
|
|
EvolutionScene.open = saved.open
|
|
EvolutionScene.handleInput = saved.handleInput
|
|
package.loaded["src.ui.game3.summary_menu"] = saved.summary
|
|
end
|
|
|
|
print("=== [TEST 12] Hud Drives The Evolution Scene Once, Only From The Frame's Input Top ===")
|
|
do
|
|
local Battle = require("src.core.game3.battle")
|
|
local Hud = require("src.ui.game3.hud")
|
|
local Stack = require("src.ui.game3.stack")
|
|
local savedActive, savedLayers = Battle._active, Stack._layers
|
|
local calls = 0
|
|
local fakeScene = { handleInput = function() calls = calls + 1 end }
|
|
local game = {
|
|
input = {
|
|
wasPressed = function(_, k) return k == "a" end,
|
|
isDown = function() return false end,
|
|
}
|
|
}
|
|
local function run(active, sameTop)
|
|
Stack._layers = {}
|
|
Battle._active = active
|
|
Stack.push("summary", { handleInput = function() end })
|
|
local summaryLayer = Stack.top()
|
|
Stack.pop("summary")
|
|
Stack.push("evolution_scene", fakeScene, { hideBelow = true, fullscreen = true })
|
|
calls = 0
|
|
Hud.update(game, 1 / 60, sameTop and Stack.top() or summaryLayer)
|
|
return calls
|
|
end
|
|
|
|
check(run(false, true) == 1, "field evolution scene gets the press from Hud")
|
|
check(run(false, false) == 1, "field evolution scene still gets the press when it opened this frame")
|
|
check(run(true, true) == 1, "in-battle evolution scene gets the press from Hud once")
|
|
local leaked = run(true, false)
|
|
check(leaked == 0, "in-battle summary close press is not replayed into the evolution scene (" .. leaked .. " calls)")
|
|
|
|
Battle._active = savedActive
|
|
Stack._layers = savedLayers
|
|
end
|
|
|
|
print("=== [TEST 13] Learn-Move Yes/No Cursor Does Not Wrap ===")
|
|
do
|
|
local Choice = require("src.ui.game3.choice")
|
|
local savedOpen = EvolutionScene.open
|
|
local answer
|
|
EvolutionScene.open = true
|
|
Choice.yesNo(function(yes) answer = yes end, { left = 24, top = 9, style = "battle" })
|
|
local function press(key)
|
|
EvolutionScene.handleInput({
|
|
wasPressed = function(_, k) return k == key end,
|
|
isDown = function() return false end,
|
|
})
|
|
end
|
|
press("up")
|
|
check(Choice.cursor == 1, "UP on YES stays on YES (cursor " .. tostring(Choice.cursor) .. ")")
|
|
press("down")
|
|
check(Choice.cursor == 2, "DOWN on YES moves to NO (cursor " .. tostring(Choice.cursor) .. ")")
|
|
press("down")
|
|
check(Choice.cursor == 2, "DOWN on NO stays on NO (cursor " .. tostring(Choice.cursor) .. ")")
|
|
press("up")
|
|
check(Choice.cursor == 1, "UP on NO moves to YES (cursor " .. tostring(Choice.cursor) .. ")")
|
|
press("down")
|
|
press("a")
|
|
check(answer == false, "A on NO answers no")
|
|
Choice.active = false
|
|
EvolutionScene.open = savedOpen
|
|
end
|
|
|
|
if failed > 0 then
|
|
print(string.format("\n[FAILED] %d test(s) failed", failed))
|
|
os.exit(1)
|
|
else
|
|
print("\nALL 13 EVOLUTION SCENE TESTS PASSED CLEANLY!")
|
|
end
|