mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 13:33:27 -04:00
245 lines
8.7 KiB
Lua
245 lines
8.7 KiB
Lua
-- engine/events/prize_menu.asm (#1867)
|
|
|
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
|
|
local T = require("tests.harness")
|
|
local check, eq = T.check, T.eq
|
|
love = love or require("tests.love_stub")
|
|
|
|
local realFont = package.loaded["src.render.Font"]
|
|
local realTextBox = package.loaded["src.render.TextBox"]
|
|
local calls = {}
|
|
local FontStub
|
|
FontStub = {
|
|
BORDER = { tl = 1, tr = 2, bl = 3, br = 4, h = 5, v = 6 },
|
|
draw = function(text, x, y) calls[#calls + 1] = { "draw", text, x, y } end,
|
|
drawCode = function(code, x, y) calls[#calls + 1] = { "code", code, x, y } end,
|
|
drawBox = function(tx, ty, tw, th) calls[#calls + 1] = { "box", tx, ty, tw, th } end,
|
|
width = function(text) return #tostring(text) * 8 end,
|
|
split = function(text)
|
|
local out = {}
|
|
for i = 1, #tostring(text) do out[i] = i end
|
|
return out
|
|
end,
|
|
}
|
|
package.loaded["src.render.Font"] = FontStub
|
|
package.loaded["src.render.TextBox"] = {
|
|
new = function(_, text, onDone, opts)
|
|
return { text = text, onDone = onDone, opts = opts, isTextBox = true }
|
|
end,
|
|
}
|
|
package.loaded["src.core.Sound"] = { play = function() end }
|
|
local version = "red"
|
|
package.loaded["src.core.GameVersion"] = {
|
|
isBlue = function() return version == "blue" end,
|
|
isYellow = function() return version == "yellow" end,
|
|
}
|
|
package.loaded["src.ui.PrizeCounter"] = nil
|
|
package.loaded["src.ui.Theme"] = nil
|
|
local PrizeCounter = require("src.ui.PrizeCounter")
|
|
|
|
local M = assert(loadfile("data/scripts/story3.lua"))()
|
|
local counters = M.GAME_CORNER_PRIZE_ROOM.talk
|
|
|
|
local function found(kind, pred)
|
|
for _, c in ipairs(calls) do
|
|
if c[1] == kind and pred(c) then return c end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
local pressed, done
|
|
local function mkGame(coins)
|
|
done = false
|
|
local mons = {}
|
|
for _, n in ipairs({ "ABRA", "CLEFAIRY", "NIDORINA", "VULPIX",
|
|
"WIGGLYTUFF" }) do
|
|
mons[n] = { name = n }
|
|
end
|
|
return {
|
|
data = {
|
|
text = {},
|
|
pokemon = mons,
|
|
items = {
|
|
TM_DRAGON_RAGE = { name = "TM23" },
|
|
TM_HYPER_BEAM = { name = "TM15" },
|
|
TM_SUBSTITUTE = { name = "TM35" },
|
|
},
|
|
},
|
|
save = { coins = coins, inventory = { COIN_CASE = 1 } },
|
|
input = {
|
|
wasPressed = function(_, b) return pressed == b end,
|
|
isDown = function() return false end,
|
|
},
|
|
stack = {
|
|
states = {},
|
|
push = function(self, s) self.states[#self.states + 1] = s end,
|
|
pop = function(self) return table.remove(self.states) end,
|
|
top = function(self) return self.states[#self.states] end,
|
|
},
|
|
}
|
|
end
|
|
|
|
local function open(n, coins)
|
|
local game = mkGame(coins or 5000)
|
|
local ow = {}
|
|
counters["TEXT_GAMECORNERPRIZEROOM_PRIZE_VENDOR_" .. n](
|
|
game, ow, nil, function() done = true end)
|
|
local exchange = game.stack:pop()
|
|
exchange.onDone()
|
|
local which = game.stack:top()
|
|
which.opts.stay.onShown()
|
|
return game, which, game.stack:top(), ow
|
|
end
|
|
|
|
do
|
|
local game, which, window = open(1)
|
|
check(tostring(which.text):find("Which prize", 1, true) ~= nil,
|
|
"WhichPrizeText goes up before the window")
|
|
check(which.opts.stay ~= nil and which.opts.stay.prompt == nil,
|
|
"it ends in `done`: no prompt, and PrintText leaves it up")
|
|
check(getmetatable(window) == PrizeCounter,
|
|
"the prize window is the CeladonPrizeMenu overlay")
|
|
check(window.isOpaque ~= true,
|
|
"so the prize room keeps drawing around it")
|
|
|
|
local names = {}
|
|
for i, row in ipairs(window.prizes) do names[i] = row.name end
|
|
eq(#window.prizes, 3, "one window is three prizes (#623)")
|
|
eq(table.concat(names, ","), "ABRA,CLEFAIRY,NIDORINA",
|
|
"Red's first window, by GetMonName")
|
|
for _, row in ipairs(window.prizes) do
|
|
check(tostring(row.name):find("L%d") == nil,
|
|
row.name .. " carries no level: GetPrizeMonLevel is not menu chrome")
|
|
end
|
|
eq(window.prizes[1].cost, 180, "with prizes.asm's coin prices")
|
|
eq(window.prizes[3].cost, 1200, "including the third row's")
|
|
|
|
calls = {}
|
|
window:draw()
|
|
check(found("box", function(c)
|
|
return c[2] == 11 and c[3] == 0 and c[4] == 9 and c[5] == 3
|
|
end) ~= nil, "PrintPrizePrice's coin box is 9x3 at hlcoord 11,0")
|
|
check(found("draw", function(c)
|
|
return c[2] == "COIN" and c[3] == 96 and c[4] == 0
|
|
end) ~= nil, "with COIN on its top border at hlcoord 12,0")
|
|
local coins = found("draw", function(c) return c[2] == "5000" end)
|
|
if check(coins ~= nil, "and the balance on the row below") then
|
|
eq(coins[3] + FontStub.width("5000"), 136,
|
|
"right-aligned through the BCD field (hlcoord 13,1)")
|
|
eq(coins[4], 8, "on the box's middle row")
|
|
end
|
|
check(found("box", function(c)
|
|
return c[2] == 0 and c[3] == 2 and c[4] == 18 and c[5] == 10
|
|
end) ~= nil, "the prize box is 18x10 at hlcoord 0,2, clear of columns 18-19")
|
|
for i, name in ipairs({ "ABRA", "CLEFAIRY", "NIDORINA" }) do
|
|
local y = 32 + (i - 1) * 16
|
|
check(found("draw", function(c)
|
|
return c[2] == name and c[3] == 16 and c[4] == y
|
|
end) ~= nil, name .. " sits at (16, " .. y .. ")")
|
|
local cost = found("draw", function(c)
|
|
return c[2] == tostring(window.prizes[i].cost)
|
|
end)
|
|
if check(cost ~= nil, "its price is drawn") then
|
|
eq(cost[4], y + 8, "one tile row below the name (hlcoord 13, 5/7/9)")
|
|
eq(cost[3] + FontStub.width(cost[2]), 136, "right-aligned with the coins")
|
|
end
|
|
end
|
|
check(found("draw", function(c)
|
|
return c[2] == "NO THANKS" and c[3] == 16 and c[4] == 80
|
|
end) ~= nil, "NoThanksText is the fourth row at hlcoord 2,10")
|
|
check(found("draw", function(c) return c[2] == "PRIZES (COINS)" end) == nil,
|
|
"and there is no full-screen page title")
|
|
|
|
pressed = "up"
|
|
window:update(1 / 60)
|
|
eq(window.index, 1, "Up on the first prize does nothing")
|
|
pressed = "down"
|
|
for _ = 1, 6 do window:update(1 / 60) end
|
|
eq(window.index, 4, "Down stops on NO THANKS, the fourth row")
|
|
pressed = "a"
|
|
window:update(1 / 60)
|
|
pressed = nil
|
|
check(done, "A on NO THANKS ends the conversation (cp 3 -> .noChoice)")
|
|
eq(#game.stack.states, 0,
|
|
"with the window and WhichPrizeText both taken down")
|
|
end
|
|
|
|
do
|
|
local game, _, window = open(3)
|
|
calls = {}
|
|
window:draw()
|
|
eq(window.prizes[1].name, "TM23", "vendor 3 is GetItemName, not GetMonName")
|
|
eq(window.prizes[3].cost, 7700, "PrizeMenuTMsEntries prices")
|
|
check(found("draw", function(c)
|
|
return c[2] == "3300" and c[4] == 40
|
|
end) ~= nil, "TM prices sit on the row below their name too")
|
|
end
|
|
|
|
do
|
|
version = "yellow"
|
|
local game, _, window = open(1)
|
|
local names = {}
|
|
for i, row in ipairs(window.prizes) do names[i] = row.name end
|
|
eq(table.concat(names, ","), "ABRA,VULPIX,WIGGLYTUFF",
|
|
"pokeyellow/data/events/prizes.asm restocks window 1")
|
|
eq(window.prizes[3].cost, 2680, "with Yellow's prices")
|
|
version = "red"
|
|
end
|
|
|
|
do
|
|
local game, _, window, ow = open(1, 5000)
|
|
window.index = 1
|
|
pressed = "a"
|
|
window:update(1 / 60)
|
|
pressed = nil
|
|
local ask = game.stack:top()
|
|
check(ask.isTextBox and tostring(ask.text):find("ABRA", 1, true) ~= nil,
|
|
"SoYouWantPrizeText names the prize out of wNameBuffer")
|
|
check(tostring(ask.text):find("wNameBuffer", 1, true) == nil,
|
|
"with the token filled in")
|
|
check(ask.opts.choice ~= nil, "and a YES/NO over it")
|
|
-- engine/events/prize_menu.asm:24-28,42
|
|
check(ow.prizeWindow ~= nil, "the overworld takes the window's pixels over")
|
|
eq(ow.prizeWindow.prizes, window.prizes, "with the same three prizes")
|
|
eq(ow.prizeWindow.index, 1, "and the cursor parked on the picked row")
|
|
eq(#game.stack.states, 1, "the menu state itself is off the stack")
|
|
eq(game.save.coins, 5000, "no coins move before the answer")
|
|
|
|
ask.opts.choice(false)
|
|
local oh = game.stack:top()
|
|
check(oh.isTextBox and tostring(oh.text):find("fine then", 1, true) ~= nil,
|
|
"answering NO prints OhFineThenText")
|
|
check(ow.prizeWindow ~= nil, "with the window still drawn underneath it")
|
|
check(not done, "and the conversation not over yet")
|
|
oh.onDone()
|
|
eq(ow.prizeWindow, nil, "only that box closing gives the rows back")
|
|
check(done, "and ends the conversation")
|
|
end
|
|
|
|
do
|
|
local _, _, window = open(1, 5000)
|
|
calls = {}
|
|
window:draw()
|
|
local withCursor = #calls
|
|
local cursors = 0
|
|
for _, c in ipairs(calls) do if c[1] == "code" then cursors = cursors + 1 end end
|
|
eq(cursors, 1, "the live menu draws the cursor")
|
|
calls = {}
|
|
PrizeCounter.drawWindow(window.game, window.prizes, nil)
|
|
eq(#calls, withCursor - 1, "the persistent window draws the same boxes and rows")
|
|
for _, c in ipairs(calls) do
|
|
check(c[1] ~= "code", "minus the cursor, which the menu owns")
|
|
end
|
|
end
|
|
|
|
package.loaded["src.render.Font"] = realFont
|
|
package.loaded["src.render.TextBox"] = realTextBox
|
|
package.loaded["src.core.Sound"] = nil
|
|
package.loaded["src.core.GameVersion"] = nil
|
|
package.loaded["src.ui.PrizeCounter"] = nil
|
|
package.loaded["src.ui.Theme"] = nil
|
|
require("src.ui.Screens").invalidate()
|
|
|
|
T.finish()
|