mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 13:33:27 -04:00
194 lines
6.7 KiB
Lua
194 lines
6.7 KiB
Lua
-- ../pokecrystal/home/text.asm:660 StdBattleTextbox -> PrintText
|
|
-- ../pokecrystal/home/print_text.asm:1 PrintLetterDelay
|
|
-- ../pokecrystal/engine/battle/core.asm:9119 BattleStartMessage
|
|
|
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
|
|
love = require("tests.love_stub")
|
|
|
|
local T = require("tests.harness")
|
|
local eq, check = T.eq, T.check
|
|
|
|
require("src.core.Logger").warn = function() end
|
|
|
|
local Battle = require("src.battle.gen2.Battle")
|
|
local BattleState = require("src.ui.gen2.BattleState")
|
|
|
|
local function newInput()
|
|
local input = { pressed = {}, held = {} }
|
|
function input:press(button) self.pressed[button] = true end
|
|
function input:wasPressed(button)
|
|
if self.pressed[button] then
|
|
self.pressed[button] = nil
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
function input:isDown(button) return self.held[button] == true end
|
|
return input
|
|
end
|
|
|
|
local function newScreen(opts)
|
|
opts = opts or {}
|
|
local input = newInput()
|
|
local game = {
|
|
input = input,
|
|
save = { options = { textSpeed = opts.speed or "MID" } },
|
|
data = {},
|
|
}
|
|
local screen = setmetatable({
|
|
game = game,
|
|
queue = {},
|
|
phase = "resolving",
|
|
slideFrame = 999,
|
|
message = opts.message,
|
|
messageTimer = opts.timer or 0,
|
|
picHidden = {},
|
|
advanced = 0,
|
|
updateAlarm = function() end,
|
|
stepFrontAnim = function() end,
|
|
stepHpAnim = function() return false end,
|
|
stepExpAnim = function() return false end,
|
|
nextPage = function() return false end,
|
|
advanceQueue = function(self) self.advanced = self.advanced + 1 end,
|
|
}, { __index = BattleState })
|
|
return screen, input
|
|
end
|
|
|
|
do
|
|
local screen, input = newScreen({ message = "ABCDE", timer = 48 })
|
|
check(screen:syncTyper(), "the line has not been printed yet")
|
|
eq(screen:messageLines()[1], "", "so the box is empty on the frame it opens")
|
|
eq(screen.typer.total, 5, "five glyphs to spend")
|
|
|
|
for _ = 1, 3 do screen:update(1 / 60) end
|
|
eq(screen.typer.shown, 1, "MID lands one glyph every three frames")
|
|
eq(screen:messageLines()[1], "A", "and the box holds exactly that prefix")
|
|
eq(screen.advanced, 0, "the queue does not move while PrintText is running")
|
|
|
|
input:press("a")
|
|
screen:update(1 / 60)
|
|
eq(screen.messageTimer, 48, "A during the print does not page the box")
|
|
check(screen.typer.shown <= 2, "and does not dump the rest of the line")
|
|
|
|
for _ = 1, 60 do
|
|
if screen.typer:done() then break end
|
|
screen:update(1 / 60)
|
|
end
|
|
check(screen.typer:done(), "the line finishes on its own")
|
|
eq(screen:messageLines()[1], "ABCDE", "with every glyph up")
|
|
eq(screen.advanced, 0, "and it still waits on PromptButton")
|
|
|
|
input:press("a")
|
|
screen:update(1 / 60)
|
|
eq(screen.messageTimer, 0, "now A pages it")
|
|
end
|
|
|
|
do
|
|
local screen, input = newScreen({ message = "ABCDE", speed = "SLOW" })
|
|
input.held.a = true
|
|
local frames = 0
|
|
for _ = 1, 60 do
|
|
if screen.typer and screen.typer:done() then break end
|
|
screen:update(1 / 60)
|
|
frames = frames + 1
|
|
end
|
|
check(screen.typer:done(), "a held A prints the line")
|
|
eq(frames, 5, "at one glyph a frame, not one page a press")
|
|
end
|
|
|
|
do
|
|
local screen = newScreen({ message = "TACKLE!", timer = 0 })
|
|
screen:update(1 / 60)
|
|
eq(screen.advanced, 0, "a move line is typed before the next event")
|
|
for _ = 1, 100 do
|
|
if screen.advanced > 0 then break end
|
|
screen:update(1 / 60)
|
|
end
|
|
check(screen.typer:done(), "the line is whole")
|
|
eq(screen.advanced, 1, "and only then does the queue advance")
|
|
end
|
|
|
|
do
|
|
local long = "The hooked MAGIKARP attacked the whole party at once!"
|
|
local screen = newScreen({ message = long })
|
|
check(screen:syncTyper(), "a long line still types")
|
|
check(#screen.typer.page <= 2,
|
|
"PrintTextboxText has two rows and Paragraph clears the third")
|
|
end
|
|
|
|
do
|
|
eq(BattleState.battleStartText("RATTATA", nil), "Wild RATTATA appeared!",
|
|
"WildPokemonAppearedText is the default arm")
|
|
eq(BattleState.battleStartText("MAGIKARP", Battle.BATTLETYPE_FISH),
|
|
"The hooked MAGIKARP attacked!", "HookedPokemonAttackedText for a rod")
|
|
eq(BattleState.battleStartText("HERACROSS", Battle.BATTLETYPE_TREE),
|
|
"HERACROSS fell out of the tree!", "PokemonFellFromTreeText for a headbutt")
|
|
eq(BattleState.battleStartText("CELEBI", Battle.BATTLETYPE_CELEBI),
|
|
"Wild CELEBI appeared!", "WildCelebiAppearedText reads the same")
|
|
eq(BattleState.battleStartText("MAGIKARP", "fish"),
|
|
"The hooked MAGIKARP attacked!", "the string form folds onto the byte")
|
|
end
|
|
|
|
do
|
|
local asleep = { species = "EXEGGCUTE", status = "sleep" }
|
|
local awake = { species = "HERACROSS" }
|
|
check(BattleState.sleepingTreeMon(asleep, Battle.BATTLETYPE_TREE),
|
|
"a tree mon that entered asleep skips .cry_no_anim")
|
|
check(not BattleState.sleepingTreeMon(awake, Battle.BATTLETYPE_TREE),
|
|
"an awake one still cries")
|
|
check(not BattleState.sleepingTreeMon(asleep, Battle.BATTLETYPE_FISH),
|
|
"and the check returns nc for every other battle type")
|
|
check(not BattleState.sleepingTreeMon(asleep, nil), "including none at all")
|
|
end
|
|
|
|
do
|
|
eq(Battle.battleTypeId("fish"), Battle.BATTLETYPE_FISH, "\"fish\" is 4")
|
|
eq(Battle.battleTypeId("tree"), Battle.BATTLETYPE_TREE, "\"tree\" is 8")
|
|
eq(Battle.battleTypeId(Battle.BATTLETYPE_TRAP), Battle.BATTLETYPE_TRAP,
|
|
"a byte passes through")
|
|
eq(Battle.battleTypeId(nil), nil, "and no type stays no type")
|
|
local battle = Battle.new({ data = {}, party = {}, battleType = "tree" })
|
|
eq(battle.battleType, Battle.BATTLETYPE_TREE,
|
|
"so only the byte leaves Battle.new")
|
|
end
|
|
|
|
do
|
|
local ditto = { species = "DITTO", hp = 20, maxHp = 20, level = 26 }
|
|
local screen = setmetatable({
|
|
queue = {}, shownMon = { enemy = ditto, player = false },
|
|
}, { __index = BattleState })
|
|
ditto.species = "PARASECT"
|
|
local event = { kind = "transform", side = "enemy", mon = ditto,
|
|
species = "PARASECT", from = "DITTO" }
|
|
screen:push(event)
|
|
eq(screen:activeMon("enemy").species, "DITTO",
|
|
"the side keeps drawing what it was until the event is read")
|
|
eq(screen:activeMon("enemy").hp, 20, "with the live HP behind it")
|
|
screen.shownMon.enemy = event.mon
|
|
eq(screen:activeMon("enemy").species, "PARASECT",
|
|
"and takes the copy when the transform is consumed")
|
|
end
|
|
|
|
-- ../pokecrystal/home/text.asm:660 StdBattleTextbox
|
|
do
|
|
local screen = newScreen({ message = "ABCDE" })
|
|
screen.advanceQueue = nil
|
|
screen.battle = {}
|
|
screen.evolvable = {}
|
|
screen.queue = { { kind = "message", text = "ABCDE" } }
|
|
screen:syncTyper()
|
|
for _ = 1, 60 do
|
|
if screen.typer:done() then break end
|
|
screen:update(1 / 60)
|
|
end
|
|
eq(screen:messageLines()[1], "ABCDE", "the first line is whole")
|
|
screen:advanceQueue()
|
|
eq(screen.message, "ABCDE", "the queued line reads the same")
|
|
screen:syncTyper()
|
|
eq(screen.typer.shown, 0, "and it types again from no glyphs")
|
|
eq(screen:messageLines()[1], "", "over an empty box")
|
|
end
|
|
|
|
T.finish("gen2_battle_text_bug2046")
|