mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 13:33:27 -04:00
a9ce423bdc
CLOSES #1275, CLOSES #1295, CLOSES #1384, CLOSES #1628, CLOSES #1677, CLOSES #1682, CLOSES #1691, CLOSES #1813, CLOSES #1822, CLOSES #1861, CLOSES #1867, CLOSES #1868, CLOSES #1869, CLOSES #1870, CLOSES #1871, CLOSES #1872, CLOSES #1874, CLOSES #1876, CLOSES #1878, CLOSES #1880, CLOSES #1881, CLOSES #1882, CLOSES #1884, CLOSES #1885, CLOSES #1886, CLOSES #1887, CLOSES #1888, CLOSES #1889, CLOSES #1890, CLOSES #1891, CLOSES #1892, CLOSES #1893, CLOSES #1894, CLOSES #1895, CLOSES #1896, CLOSES #1899, CLOSES #1900, CLOSES #1901
215 lines
7.1 KiB
Lua
215 lines
7.1 KiB
Lua
-- engine/events/vending_machine.asm (#1876)
|
|
|
|
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 = {}
|
|
package.loaded["src.render.Font"] = {
|
|
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.TextBox"] = {
|
|
new = function(_, text, onDone, opts)
|
|
return { text = text, onDone = onDone, opts = opts, isTextBox = true }
|
|
end,
|
|
}
|
|
local sounds = {}
|
|
package.loaded["src.core.Sound"] = {
|
|
play = function(_, name) sounds[#sounds + 1] = name end,
|
|
}
|
|
local bagFull = false
|
|
local bagged = {}
|
|
package.loaded["src.inventory.Bag"] = {
|
|
add = function(_, id)
|
|
if bagFull then return false end
|
|
bagged[#bagged + 1] = id
|
|
return true
|
|
end,
|
|
}
|
|
package.loaded["src.ui.Menu"] = nil
|
|
package.loaded["src.ui.Theme"] = nil
|
|
|
|
local M = assert(loadfile("data/scripts/story4.lua"))()
|
|
local machine = M.CELADON_MART_ROOF.talk.TEXT_CELADONMARTROOF_VENDING_MACHINE1
|
|
|
|
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(cash)
|
|
sounds, bagged, done = {}, {}, false
|
|
return {
|
|
data = {
|
|
text = {
|
|
_VendingMachineText1 = "A vending machine!\nHere's the menu!",
|
|
_VendingMachineText4 = "Oops, not enough\nmoney!",
|
|
_VendingMachineText5 = "{RAM:wStringBuffer}\npopped out!",
|
|
_VendingMachineText6 = "There's no more\nroom for stuff!",
|
|
_VendingMachineText7 = "Not thirsty!",
|
|
},
|
|
items = {
|
|
FRESH_WATER = { name = "FRESH WATER" },
|
|
SODA_POP = { name = "SODA POP" },
|
|
LEMONADE = { name = "LEMONADE" },
|
|
},
|
|
},
|
|
save = { money = cash, inventory = {} },
|
|
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(cash)
|
|
local game = mkGame(cash)
|
|
machine(game, nil, nil, function() done = true end)
|
|
local intro = game.stack:top()
|
|
return game, intro
|
|
end
|
|
|
|
do
|
|
local game, intro = open(3000)
|
|
check(intro.isTextBox, "talking to the sign prints VendingMachineText1")
|
|
check(tostring(intro.text):find("vending machine", 1, true) ~= nil,
|
|
"with the machine's own greeting")
|
|
check(intro.opts.money ~= nil, "DisplayTextBoxID MONEY_BOX rides along")
|
|
check(intro.opts.stay ~= nil and intro.opts.stay.prompt,
|
|
"the greeting prompts, then stays up under the list")
|
|
|
|
intro.opts.stay.onShown()
|
|
local menu = game.stack:top()
|
|
check(menu ~= intro and menu.items ~= nil, "the drink list opens over it")
|
|
eq(menu.tx, 0, "TextBoxBorder at hlcoord 0,3")
|
|
eq(menu.ty, 3, "row 3")
|
|
eq(menu.tw, 14, "14 tiles wide (b=8, c=12)")
|
|
eq(menu.th, 10, "10 tiles tall")
|
|
eq(#menu.items, 4, "wMaxMenuItem 3: three drinks and CANCEL")
|
|
eq(menu.items[4].label, "CANCEL", "CANCEL is the last row")
|
|
eq(menu.noWrap, true,
|
|
"wMenuWrappingEnabled is never set (home/window.asm:56-83)")
|
|
|
|
calls = {}
|
|
menu:draw()
|
|
for i, name in ipairs({ "FRESH WATER", "SODA POP", "LEMONADE", "CANCEL" }) do
|
|
local y = (5 + (i - 1) * 2) * 8
|
|
check(found("draw", function(c)
|
|
return c[2] == name and c[3] == 16 and c[4] == y
|
|
end) ~= nil, name .. " sits at (16, " .. y .. ")")
|
|
end
|
|
for i, price in ipairs({ "¥200", "¥300", "¥350" }) do
|
|
local y = (6 + (i - 1) * 2) * 8
|
|
check(found("draw", function(c)
|
|
return c[2] == price and c[3] == 72 and c[4] == y
|
|
end) ~= nil, price .. " sits a row under its drink at (72, " .. y .. ")")
|
|
end
|
|
end
|
|
|
|
do
|
|
local game, intro = open(3000)
|
|
intro.opts.stay.onShown()
|
|
local menu = game.stack:top()
|
|
menu.items[1].onSelect()
|
|
local waiter = game.stack:top()
|
|
check(waiter ~= menu and waiter.update ~= nil,
|
|
"the delivery rumble runs before the text")
|
|
eq(game.save.money, 3000, "money is still untouched during the rumble")
|
|
for _ = 1, 120 do
|
|
if game.stack:top() ~= waiter then break end
|
|
waiter:update(1 / 60)
|
|
end
|
|
eq(#sounds, 60, "SFX_PUSH_BOULDER restarts 60 times")
|
|
eq(sounds[1], "Push_Boulder", "and it is the boulder push, not Cut")
|
|
check(bagged[1] == "FRESH_WATER", "the drink lands in the bag")
|
|
eq(game.save.money, 2800, "SubBCDPredef takes the drink's price")
|
|
local result = game.stack:top()
|
|
check(result.isTextBox and tostring(result.text):find("popped out") ~= nil,
|
|
"then VendingMachineText5 names the drink")
|
|
check(tostring(result.text):find("FRESH WATER", 1, true) ~= nil,
|
|
"out of wStringBuffer")
|
|
check(result.opts ~= nil and result.opts.money ~= nil,
|
|
"the money box is redrawn with the new balance")
|
|
eq(#game.stack.states, 1,
|
|
"the drink list and the greeting are gone by then")
|
|
result.onDone()
|
|
check(done, "dismissing it hands control back to the script")
|
|
end
|
|
|
|
do
|
|
local game, intro = open(3000)
|
|
intro.opts.stay.onShown()
|
|
local menu = game.stack:top()
|
|
menu.index = 4
|
|
pressed = "a"
|
|
menu:update(1 / 60)
|
|
pressed = nil
|
|
local result = game.stack:top()
|
|
check(result.isTextBox and tostring(result.text):find("thirsty") ~= nil,
|
|
"CANCEL prints VendingMachineText7")
|
|
eq(#game.stack.states, 1, "with the list and the greeting closed")
|
|
eq(#bagged, 0, "and nothing bought")
|
|
|
|
game, intro = open(3000)
|
|
intro.opts.stay.onShown()
|
|
menu = game.stack:top()
|
|
pressed = "b"
|
|
menu:update(1 / 60)
|
|
pressed = nil
|
|
check(tostring(game.stack:top().text):find("thirsty") ~= nil,
|
|
"B does the same (.notThirsty)")
|
|
end
|
|
|
|
do
|
|
local game, intro = open(100)
|
|
intro.opts.stay.onShown()
|
|
game.stack:top().items[1].onSelect()
|
|
local result = game.stack:top()
|
|
check(tostring(result.text):find("enough", 1, true) ~= nil,
|
|
"no money prints VendingMachineText4")
|
|
eq(game.save.money, 100, "and spends nothing")
|
|
eq(#bagged, 0, "and hands over no drink")
|
|
|
|
bagFull = true
|
|
game, intro = open(3000)
|
|
intro.opts.stay.onShown()
|
|
game.stack:top().items[1].onSelect()
|
|
result = game.stack:top()
|
|
check(tostring(result.text):find("room for stuff", 1, true) ~= nil,
|
|
"a full bag prints VendingMachineText6")
|
|
eq(game.save.money, 3000, "with the money untouched (.BagFull)")
|
|
bagFull = false
|
|
end
|
|
|
|
package.loaded["src.render.Font"] = realFont
|
|
package.loaded["src.render.TextBox"] = realTextBox
|
|
package.loaded["src.core.Sound"] = nil
|
|
package.loaded["src.inventory.Bag"] = nil
|
|
package.loaded["src.ui.Menu"] = nil
|
|
package.loaded["src.ui.Theme"] = nil
|
|
require("src.ui.Screens").invalidate()
|
|
|
|
T.finish()
|