mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 13:33:27 -04:00
23617f43b4
CLOSES #2290, CLOSES #2338, CLOSES #2186, CLOSES #2305, CLOSES #2332, CLOSES #2320, CLOSES #2344, CLOSES #2291, CLOSES #2335, CLOSES #2340, CLOSES #2385, CLOSES #2352, CLOSES #2378, CLOSES #2403, CLOSES #2404, CLOSES #2405, CLOSES #2367, CLOSES #2037, CLOSES #2177, CLOSES #2368, CLOSES #2382, CLOSES #1951
279 lines
9.8 KiB
Lua
279 lines
9.8 KiB
Lua
-- home/pokemon.asm:246
|
|
-- engine/items/item_effects.asm:1979-2006
|
|
-- engine/pokemon/learn_move.asm:119-181
|
|
|
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
if not _G.love then _G.love = require("tests.love_stub") end
|
|
|
|
local S = require("tests.harness").suite("PP UP / TM move box #2320")
|
|
local check, eq = S.check, S.eq
|
|
|
|
local ItemEffects = require("src.inventory.ItemEffects")
|
|
|
|
do
|
|
local Data = {
|
|
items = { PP_UP = { name = "PP UP" } },
|
|
moves = { LICK = { name = "LICK", pp = 30 } },
|
|
pokemon = { GENGAR = { name = "GENGAR" } },
|
|
text = {},
|
|
}
|
|
local t = { species = "GENGAR", hp = 20, stats = { hp = 20 },
|
|
moves = { { id = "LICK", pp = 48, ppUps = 3 } } }
|
|
local result, payload = ItemEffects.use(Data, {}, "PP_UP", t, nil, 1)
|
|
eq(result, "ppmaxed", "PP UP on a move with 3 PP Ups reports maxed out")
|
|
eq(payload and payload[1], "LICK's PP\nis maxed out.", "and prints PPMaxedOutText")
|
|
eq(t.moves[1].ppUps, 3, "the move is untouched")
|
|
end
|
|
|
|
local draws
|
|
local FontStub = {
|
|
drawBox = function(tx, ty, tw, th) draws[#draws + 1] = { "box", tx, ty, tw, th } end,
|
|
draw = function(text, x, y) draws[#draws + 1] = { "text", text, x, y } end,
|
|
drawCode = function(code, x, y) draws[#draws + 1] = { "code", code, x, y } end,
|
|
}
|
|
package.loaded["src.render.Font"] = FontStub
|
|
|
|
local boxes = {}
|
|
local TextBoxStub = {}
|
|
TextBoxStub.strip = function(text)
|
|
if type(text) ~= "string" then return text end
|
|
return (text:gsub("{DONE}", ""):gsub("{PROMPT}", ""))
|
|
end
|
|
TextBoxStub.new = function(game, text, onDone, opts)
|
|
local b = { fake = true, text = text, onDone = onDone, opts = opts }
|
|
boxes[#boxes + 1] = b
|
|
return b
|
|
end
|
|
package.loaded["src.render.TextBox"] = TextBoxStub
|
|
package.loaded["src.render.HudTiles"] = {
|
|
tile = function() end, drawHPBar = function() end, statusTile = function() end,
|
|
}
|
|
package.loaded["src.render.PaletteFX"] = {
|
|
shader = function() return nil end, pal = function() return nil end,
|
|
}
|
|
|
|
local MoveSelectMenu = require("src.ui.MoveSelectMenu")
|
|
local MoveLearnMenu = require("src.ui.MoveLearnMenu")
|
|
local PartyMenu = require("src.ui.PartyMenu")
|
|
PartyMenu.drawIcon = function() end
|
|
|
|
local pressed = {}
|
|
local function newGame()
|
|
local game = {
|
|
input = { wasPressed = function(_, b) return pressed[b] == true end,
|
|
isDown = function() return false end },
|
|
data = {
|
|
moves = { LICK = { name = "LICK" }, HYPNOSIS = { name = "HYPNOSIS" },
|
|
SURF = { name = "SURF" }, MEGA_PUNCH = { name = "MEGA PUNCH", pp = 20 } },
|
|
pokemon = { GENGAR = { name = "GENGAR" } },
|
|
statuses = {},
|
|
text = {},
|
|
},
|
|
}
|
|
game.stack = {
|
|
states = {},
|
|
push = function(self, s, ...)
|
|
self.states[#self.states + 1] = s
|
|
if type(s.enter) == "function" then s:enter(...) end
|
|
end,
|
|
pop = function(self) return table.remove(self.states) end,
|
|
top = function(self) return self.states[#self.states] end,
|
|
}
|
|
return game
|
|
end
|
|
|
|
local function press(state, btn)
|
|
pressed = { [btn] = true }
|
|
state:update(1 / 60)
|
|
pressed = {}
|
|
end
|
|
|
|
local function finishBox(game)
|
|
local b = game.stack:top()
|
|
if b and b.fake and b.opts and b.opts.stay and b.opts.stay.onShown then
|
|
b.opts.stay.onShown()
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
local function cursorGlyphAt(y)
|
|
for _, d in ipairs(draws) do
|
|
if d[1] == "code" and d[3] == 0 and d[4] == y then return d[2] end
|
|
end
|
|
end
|
|
|
|
do
|
|
local game = newGame()
|
|
local mon = { species = "GENGAR", level = 30, hp = 60, stats = { hp = 60 },
|
|
moves = { { id = "LICK", pp = 30 }, { id = "HYPNOSIS", pp = 20 } } }
|
|
game.save = { party = { mon, { species = "GENGAR", level = 5, hp = 10,
|
|
stats = { hp = 10 }, moves = {} } } }
|
|
local menuRef, chosen
|
|
local picker = PartyMenu.new(game, {
|
|
pickOnly = true, itemUse = true, keepOpen = true,
|
|
onSwitch = function(m, p)
|
|
menuRef = MoveSelectMenu.new(game, m, "Raise PP of which\ntechnique?{DONE}",
|
|
function(i, menu) chosen = { i, menu } end, nil, p)
|
|
game.stack:push(menuRef)
|
|
end,
|
|
})
|
|
game.stack:push(picker)
|
|
|
|
draws = {}
|
|
picker:draw()
|
|
eq(cursorGlyphAt(8), 0xED, "the party cursor is the filled arrow before the pick")
|
|
|
|
press(picker, "a")
|
|
check(picker.chosenHollow == true, "A on a kept-open picker marks the row chosen")
|
|
draws = {}
|
|
picker:draw()
|
|
eq(cursorGlyphAt(8), 0xEC, "the chosen mon's arrow turns hollow")
|
|
|
|
check(menuRef ~= nil, "the move menu was pushed")
|
|
local top = game.stack:top()
|
|
check(top and top.fake, "a text box types the prompt before the move box")
|
|
eq(top and top.text, "Raise PP of which\ntechnique?{DONE}", "with the item's prompt")
|
|
check(top and top.opts and top.opts.stay ~= nil, "a done-text stay box")
|
|
eq(menuRef.ready, false, "the move menu takes no input while the prompt types")
|
|
draws = {}
|
|
menuRef:draw()
|
|
eq(#draws, 0, "and draws nothing yet")
|
|
pressed = { a = true }
|
|
menuRef:update(1 / 60)
|
|
pressed = {}
|
|
eq(chosen, nil, "an A press during the prompt picks nothing")
|
|
|
|
check(finishBox(game), "the prompt finished typing")
|
|
eq(game.stack:top(), menuRef, "the prompt box hands the screen to the move menu")
|
|
eq(menuRef.ready, true, "the move menu is live")
|
|
draws = {}
|
|
menuRef:draw()
|
|
eq(draws[1][1], "box", "prompt text box drawn first")
|
|
eq(draws[1][2], 0, "at column 0")
|
|
eq(draws[1][3], 12, "row 12")
|
|
local last
|
|
for _, d in ipairs(draws) do if d[1] == "box" then last = d end end
|
|
eq(last and last[2], 4, "the move box is the last box drawn")
|
|
eq(last and last[3], 7, "at 4,7, over the text box's top edge")
|
|
|
|
press(menuRef, "down")
|
|
press(menuRef, "a")
|
|
eq(chosen and chosen[1], 2, "A hands back the picked slot")
|
|
eq(chosen and chosen[2], menuRef, "and the menu")
|
|
eq(game.stack:top(), picker, "nothing was pushed over it, so it released itself")
|
|
eq(#game.stack.states, 1, "back to the party menu")
|
|
|
|
menuRef = nil
|
|
press(picker, "a")
|
|
finishBox(game)
|
|
local held = game.stack:top()
|
|
eq(getmetatable(held), MoveSelectMenu, "the move menu is up again")
|
|
local result = { fake = true, text = "LICK's PP\nincreased." }
|
|
held.onChoose = function() game.stack:push(result) end
|
|
press(held, "a")
|
|
eq(game.stack:top(), result, "the result text is on top")
|
|
check(held.held == true, "the move menu is held under it")
|
|
eq(game.stack.states[#game.stack.states - 1], held, "still on the stack under the result")
|
|
draws = {}
|
|
held:draw()
|
|
local moveBox
|
|
for _, d in ipairs(draws) do
|
|
if d[1] == "box" and d[2] == 4 and d[3] == 7 then moveBox = d end
|
|
if d[1] == "box" and d[2] == 0 and d[3] == 12 then moveBox = "prompt" end
|
|
end
|
|
check(type(moveBox) == "table", "the held menu keeps drawing the move box, not its prompt")
|
|
draws = {}
|
|
picker:draw()
|
|
eq(cursorGlyphAt(8), 0xEC, "the party arrow stays hollow under the result")
|
|
|
|
game.stack:pop()
|
|
picker:close()
|
|
eq(#game.stack.states, 0, "closing the picker drops the held move box too")
|
|
end
|
|
|
|
do
|
|
local game = newGame()
|
|
local mon = { species = "GENGAR", moves = { { id = "LICK" } } }
|
|
local p = { fake = "picker" }
|
|
local other = MoveSelectMenu.new(game, mon, "x", nil, nil, nil)
|
|
game.stack.states = { p, other }
|
|
PartyMenu.close(setmetatable({ game = game }, { __index = p }))
|
|
eq(#game.stack.states, 2, "close leaves a menu it does not own alone")
|
|
end
|
|
|
|
do
|
|
local game = newGame()
|
|
local mon = { species = "GENGAR", moves = { { id = "LICK" }, { id = "HYPNOSIS" } } }
|
|
local m = MoveSelectMenu.new(game, mon, "Raise PP of which\ntechnique?")
|
|
game.stack:push(m)
|
|
finishBox(game)
|
|
press(m, "down")
|
|
local maxed = { fake = true }
|
|
m.onChoose = function() game.stack:push(maxed) end
|
|
press(m, "a")
|
|
game.stack:pop()
|
|
m:ask()
|
|
local reprompt = game.stack:top()
|
|
check(reprompt.fake and reprompt.text == "Raise PP of which\ntechnique?",
|
|
"ask() types the prompt again")
|
|
eq(m.ready, false, "the menu waits for it")
|
|
draws = {}
|
|
m:draw()
|
|
local promptBox, moveBox = false, false
|
|
for _, d in ipairs(draws) do
|
|
if d[1] == "box" and d[3] == 12 then promptBox = true end
|
|
if d[1] == "box" and d[3] == 7 then moveBox = true end
|
|
end
|
|
check(moveBox and not promptBox, "the move box stays up while the prompt retypes")
|
|
finishBox(game)
|
|
eq(m.index, 1, "the cursor starts over on the first move")
|
|
eq(m.ready, true, "and the menu is live again")
|
|
end
|
|
|
|
do
|
|
local game = newGame()
|
|
local mon = { species = "GENGAR", level = 30,
|
|
moves = { { id = "SURF" }, { id = "LICK" }, { id = "HYPNOSIS" }, { id = "LICK" } } }
|
|
local m = MoveLearnMenu.new(game, mon, "MEGA_PUNCH", function() end)
|
|
game.stack:push(m)
|
|
local ask = game.stack:top()
|
|
check(ask.fake and ask.opts and ask.opts.choice, "TryingToLearn YES/NO first")
|
|
game.stack:pop()
|
|
ask.opts.choice(true)
|
|
local forget = game.stack:top()
|
|
check(forget.fake and forget.text:find("Which move should", 1, true) ~= nil,
|
|
"YES types WhichMoveToForgetText")
|
|
check(forget.opts and forget.opts.stay ~= nil, "as a done-text stay box")
|
|
eq(m.selecting, false, "the forget list waits for the text")
|
|
draws = {}
|
|
m:draw()
|
|
eq(#draws, 0, "and is not drawn yet")
|
|
finishBox(game)
|
|
eq(game.stack:top(), m, "the text hands off to the forget list")
|
|
eq(m.selecting, true, "which is live")
|
|
draws = {}
|
|
m:draw()
|
|
eq(draws[1][1], "box", "text box first")
|
|
eq(draws[1][3], 12, "at row 12")
|
|
local last
|
|
for _, d in ipairs(draws) do if d[1] == "box" then last = d end end
|
|
eq(last and last[2], 4, "forget box last")
|
|
eq(last and last[3], 7, "at 4,7")
|
|
|
|
press(m, "a")
|
|
local hm = game.stack:top()
|
|
check(hm.fake and hm.text:find("HM techniques", 1, true) ~= nil, "SURF is refused")
|
|
eq(m.selecting, false, "the forget box is gone under the refusal")
|
|
game.stack:pop()
|
|
hm.onDone()
|
|
local again = game.stack:top()
|
|
check(again.fake and again.text:find("Which move should", 1, true) ~= nil,
|
|
"then the prompt types again")
|
|
finishBox(game)
|
|
eq(m.selecting, true, "and the forget list comes back")
|
|
eq(m.index, 1, "on the first move")
|
|
end
|
|
|
|
S.finish()
|