mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 13:33:27 -04:00
220 lines
6.8 KiB
Lua
220 lines
6.8 KiB
Lua
-- ../pokered/engine/events/prize_menu.asm:181 (#2034)
|
|
|
|
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")
|
|
|
|
package.loaded["src.render.Font"] = {
|
|
BORDER = { tl = 1, tr = 2, bl = 3, br = 4, h = 5, v = 6 },
|
|
draw = function() end,
|
|
drawCode = function() end,
|
|
drawBox = function() 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,
|
|
}
|
|
package.loaded["src.core.Sound"] = { play = function() end }
|
|
package.loaded["src.core.GameVersion"] = {
|
|
isBlue = function() return false end,
|
|
isYellow = function() return false end,
|
|
}
|
|
local bagFull = false
|
|
package.loaded["src.inventory.Bag"] = {
|
|
add = function() return not bagFull end,
|
|
}
|
|
|
|
local M = assert(loadfile("data/scripts/story3.lua"))()
|
|
local counters = M.GAME_CORNER_PRIZE_ROOM.talk
|
|
|
|
local pressed, done, ran
|
|
local function mkGame(coins)
|
|
done, ran = false, nil
|
|
local mons = {}
|
|
for _, n in ipairs({ "ABRA", "CLEFAIRY", "NIDORINA" }) 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 mkOw(game)
|
|
return {
|
|
runner = {
|
|
run = function(_, script, extra)
|
|
ran = { script = script, extra = extra, depth = #game.stack.states }
|
|
end,
|
|
},
|
|
}
|
|
end
|
|
|
|
local function open(n, coins)
|
|
local game = mkGame(coins or 5000)
|
|
local ow = mkOw(game)
|
|
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
|
|
|
|
local function pick(game, window, index, yes)
|
|
window.index = index
|
|
pressed = "a"
|
|
window:update(1 / 60)
|
|
pressed = nil
|
|
local ask = game.stack:pop()
|
|
ask.opts.choice(yes)
|
|
end
|
|
|
|
do
|
|
local game, which, window, ow = open(1)
|
|
local cost = window.prizes[1].cost
|
|
pick(game, window, 1, true)
|
|
|
|
check(ran ~= nil, "the mon gift runs on the script runner")
|
|
-- engine/events/prize_menu.asm:24-28,42
|
|
check(ow.prizeWindow ~= nil,
|
|
"the prize list is still drawn while the gift script runs")
|
|
eq(ow.prizeWindow.index, 1, "with the cursor on the picked row")
|
|
eq(ran.depth, 0,
|
|
"WhichPrizeText and the menu come down first, so nothing is orphaned")
|
|
eq(#game.stack.states, 0, "and the callback pushed nothing of its own")
|
|
for _, state in ipairs(game.stack.states) do
|
|
check(state ~= which, "the stay box never survives the transaction")
|
|
end
|
|
eq(game.save.coins, 5000, "coins are the script's job, not the callback's")
|
|
check(type(ran.extra.onDone) == "function",
|
|
"the runner releases the sign when the script ends")
|
|
ran.extra.onDone()
|
|
eq(ow.prizeWindow, nil, "and the window's rows go back with it")
|
|
check(done, "the conversation ends there")
|
|
|
|
local rows = ran.script
|
|
eq(rows[1][1], "give_pokemon", "GivePokemon first (prize_menu.asm:224)")
|
|
eq(rows[1][2], window.prizes[1].prize.species, "for the picked prize")
|
|
eq(rows[1][5], true, "with GotMonText (give_pokemon.asm:46, :68)")
|
|
eq(rows[2][1], "jump_if_false", "carry decides (prize_menu.asm:233)")
|
|
eq(rows[3][1], "take_coins", "only then .subtractCoins")
|
|
eq(rows[3][2], cost, "for the prize's price")
|
|
|
|
local function exec(gave)
|
|
local labels, texts, coins = {}, {}, 0
|
|
for i, row in ipairs(rows) do
|
|
if row[1] == "label" then labels[row[2]] = i end
|
|
end
|
|
local pc, lastCheck = 1, nil
|
|
while pc <= #rows do
|
|
local row = rows[pc]
|
|
local verb = row[1]
|
|
if verb == "give_pokemon" then
|
|
lastCheck = gave
|
|
elseif verb == "take_coins" then
|
|
coins = coins + row[2]
|
|
elseif verb == "show_text" then
|
|
texts[#texts + 1] = row[2]
|
|
elseif verb == "jump" then
|
|
pc = labels[row[2]]
|
|
elseif verb == "jump_if_false" and not lastCheck then
|
|
pc = labels[row[2]]
|
|
end
|
|
pc = pc + 1
|
|
end
|
|
return coins, table.concat(texts, ",")
|
|
end
|
|
|
|
local spent, texts = exec(true)
|
|
eq(spent, cost, "a mon that landed costs its coins")
|
|
eq(texts, "", "and prints nothing beyond GivePokemon's own text")
|
|
spent, texts = exec(false)
|
|
eq(spent, 0, "party and box full: `ret nc`, no coins move")
|
|
eq(texts, "_BoxIsFullText",
|
|
"and the box-full line is GivePokemon's (give_pokemon.asm:40-42)")
|
|
end
|
|
|
|
do
|
|
bagFull = false
|
|
local game, _, window = open(3, 9999)
|
|
local cost = window.prizes[2].cost
|
|
pick(game, window, 2, true)
|
|
eq(ran, nil, "a TM needs no script (prize_menu.asm:209-216)")
|
|
eq(game.save.coins, 9999 - cost, ".subtractCoins runs inline")
|
|
eq(#game.stack.states, 0, "with the menu and its text box both down")
|
|
check(done, "and the sign released")
|
|
end
|
|
|
|
do
|
|
bagFull = true
|
|
local game, _, window = open(3)
|
|
pick(game, window, 1, true)
|
|
eq(game.save.coins, 5000, ".bagFull rets before .subtractCoins")
|
|
eq(#game.stack.states, 1, "one box left over the overworld")
|
|
check(type(game.stack:top().onDone) == "function",
|
|
"PrizeRoomBagIsFullText owns the release (prize_menu.asm:245-246)")
|
|
bagFull = false
|
|
end
|
|
|
|
do
|
|
local game, which, window = open(1)
|
|
pick(game, window, 1, false)
|
|
eq(#game.stack.states, 1, "OhFineThenText is all that is left")
|
|
check(game.stack:top() ~= which, "the stay box is gone")
|
|
eq(game.save.coins, 5000, "no coins move on NO")
|
|
end
|
|
|
|
do
|
|
local game, which, window = open(1, 10)
|
|
pick(game, window, 1, true)
|
|
eq(#game.stack.states, 1, "SorryNeedMoreCoinsText is all that is left")
|
|
check(game.stack:top() ~= which, "the stay box is gone")
|
|
eq(ran, nil, "HasEnoughCoins fails before GivePokemon")
|
|
end
|
|
|
|
do
|
|
local Commands = require("src.script.Commands")
|
|
local ctx = { save = { coins = 500 } }
|
|
Commands.take_coins(ctx, 180)
|
|
eq(ctx.save.coins, 320, "take_coins subtracts")
|
|
Commands.take_coins(ctx, 9999)
|
|
eq(ctx.save.coins, 0, "and clamps at zero")
|
|
end
|
|
|
|
package.loaded["src.render.Font"] = nil
|
|
package.loaded["src.render.TextBox"] = nil
|
|
package.loaded["src.core.Sound"] = nil
|
|
package.loaded["src.core.GameVersion"] = nil
|
|
package.loaded["src.inventory.Bag"] = nil
|
|
|
|
T.finish()
|