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
237 lines
8.7 KiB
Lua
237 lines
8.7 KiB
Lua
-- home/pokemon.asm:246
|
|
-- engine/items/item_effects.asm:1967-2006
|
|
-- engine/pokemon/learn_move.asm:119-181
|
|
return function(game)
|
|
local U = dofile("tests/drivers/util.lua")
|
|
local Pokemon = require("src.pokemon.Pokemon")
|
|
local Screens = require("src.ui.Screens")
|
|
local Bag = require("src.inventory.Bag")
|
|
local PartyMenu = require("src.ui.PartyMenu")
|
|
local MoveSelectMenu = require("src.ui.MoveSelectMenu")
|
|
local MoveLearnMenu = require("src.ui.MoveLearnMenu")
|
|
local ChoiceBox = require("src.ui.ChoiceBox")
|
|
local TextBox = require("src.render.TextBox")
|
|
local DIR = os.getenv("POKEPORT_SHOT_DIR") or os.getenv("SHOT_DIR") or "/tmp/shots2320"
|
|
local fail = 0
|
|
|
|
local function check(label, ok)
|
|
if not ok then fail = fail + 1 end
|
|
U.log(ok and "PASS" or "FAIL", label)
|
|
return ok
|
|
end
|
|
local function top() return game.stack:top() end
|
|
local function isBox(s) return getmetatable(s) == TextBox end
|
|
local function isParty(s) return getmetatable(s) == PartyMenu end
|
|
local function isMoveMenu(s) return getmetatable(s) == MoveSelectMenu end
|
|
local function isLearn(s) return getmetatable(s) == MoveLearnMenu end
|
|
local function find(pred)
|
|
for _, s in ipairs(game.stack.states or {}) do
|
|
if pred(s) then return s end
|
|
end
|
|
end
|
|
local function boxText(b)
|
|
local out = {}
|
|
for _, page in ipairs((b and b.pages) or {}) do
|
|
for _, l in ipairs(page) do out[#out + 1] = tostring(l) end
|
|
end
|
|
return table.concat(out, " ")
|
|
end
|
|
local function waitFor(pred, n)
|
|
for _ = 1, n or 240 do
|
|
if pred() then return true end
|
|
U.wait(1)
|
|
end
|
|
return pred()
|
|
end
|
|
local function cursorTo(menu, want)
|
|
for _ = 1, 40 do
|
|
if menu.index == want then return true end
|
|
U.tap(game, menu.index < want and "down" or "up")
|
|
U.wait(3)
|
|
end
|
|
return menu.index == want
|
|
end
|
|
|
|
local gengar = Pokemon.new(game.data, "GENGAR", 30)
|
|
gengar.moves = {
|
|
{ id = "LICK", pp = 30 }, { id = "CONFUSE_RAY", pp = 10 },
|
|
{ id = "NIGHT_SHADE", pp = 15 }, { id = "HYPNOSIS", pp = 20 },
|
|
}
|
|
local nido = Pokemon.new(game.data, "NIDOKING", 40)
|
|
nido.moves = {
|
|
{ id = "SURF", pp = 15 }, { id = "HORN_ATTACK", pp = 25 },
|
|
{ id = "POISON_STING", pp = 35 }, { id = "LEER", pp = 30 },
|
|
}
|
|
game.save.party = { gengar, nido }
|
|
game.save.player.name = "RED"
|
|
game.save.inventory = {}
|
|
Bag.add(game.save, "PP_UP", 5, game.data)
|
|
Bag.add(game.save, "TM_MEGA_PUNCH", 1, game.data)
|
|
U.teleport(game, "PALLET_TOWN", 10, 8, "down")
|
|
U.wait(10)
|
|
|
|
local function openPicker(id)
|
|
while #game.stack.states > 1 do game.stack:pop() end
|
|
U.wait(2)
|
|
local bag = Screens.push(game, "BagMenu", {})
|
|
U.wait(12)
|
|
local row
|
|
for i, r in ipairs(bag.items or {}) do
|
|
if r.value == id then row = i break end
|
|
end
|
|
if not row or not cursorTo(bag, row) then return nil end
|
|
U.tap(game, "a")
|
|
U.wait(12)
|
|
local ut = top()
|
|
if ut and ut.items and ut.items[1] and ut.items[1].label == "USE" then
|
|
cursorTo(ut, 1)
|
|
U.tap(game, "a")
|
|
U.wait(4)
|
|
end
|
|
if not waitFor(function()
|
|
if isParty(top()) then return true end
|
|
local t = top()
|
|
if isBox(t) and (t.done or t.waiting) then U.tap(game, "a") end
|
|
if getmetatable(t) == ChoiceBox then U.tap(game, "a") end
|
|
return false
|
|
end, 600) then return nil end
|
|
return top()
|
|
end
|
|
|
|
local function pickMon(picker, slot)
|
|
cursorTo(picker, slot)
|
|
U.tap(game, "a")
|
|
end
|
|
|
|
U.log("======== pass 1: timing, no shots ========")
|
|
local picker = openPicker("PP_UP")
|
|
if check("PP UP party picker opened", picker ~= nil) then
|
|
pickMon(picker, 1)
|
|
local promptBox = top()
|
|
check("A on GENGAR: a text box is on top, not the move box", isBox(promptBox))
|
|
local mm = find(isMoveMenu)
|
|
check("the move menu waits underneath, not ready", mm ~= nil and not mm.ready)
|
|
check("the chosen arrow is hollow", picker.chosenHollow == true)
|
|
check("the prompt is still typing", isBox(promptBox) and not promptBox.done)
|
|
local frames = 0
|
|
while not (isMoveMenu(top()) and top().ready) and frames < 400 do
|
|
U.wait(1)
|
|
frames = frames + 1
|
|
end
|
|
U.log("prompt frames before the move box:", frames)
|
|
check("the move box waited for the typed prompt (" .. frames .. " frames)",
|
|
frames >= 10 and frames < 400)
|
|
U.tap(game, "b")
|
|
U.wait(4)
|
|
check("B returns to the party menu", isParty(top()))
|
|
U.wait(2)
|
|
check("the party arrow is filled again", not picker.chosenHollow)
|
|
end
|
|
|
|
U.log("======== pass 2: PP UP with shots ========")
|
|
picker = openPicker("PP_UP")
|
|
if check("PP UP party picker opened again", picker ~= nil) then
|
|
pickMon(picker, 1)
|
|
U.wait(3)
|
|
U.shot(game, DIR .. "/2320_01_prompt_typing_hollow_arrow.png")
|
|
check("move box ready after the prompt",
|
|
waitFor(function() return isMoveMenu(top()) and top().ready end, 400))
|
|
local mm = top()
|
|
U.wait(2)
|
|
U.shot(game, DIR .. "/2320_02_move_box_over_textbox.png")
|
|
cursorTo(mm, 1)
|
|
U.tap(game, "a")
|
|
check("the result box opened",
|
|
waitFor(function() return isBox(top()) end, 30))
|
|
local res = top()
|
|
check("result reads PP increased", boxText(res):find("increased") ~= nil)
|
|
check("the move box is held under the result", mm.held == true and find(isMoveMenu) == mm)
|
|
check("the party arrow is still hollow", picker.chosenHollow == true)
|
|
waitFor(function() return res.done end, 240)
|
|
U.shot(game, DIR .. "/2320_03_result_keeps_move_box.png")
|
|
waitFor(function()
|
|
if isBox(top()) then U.tap(game, "a") end
|
|
return not find(isParty)
|
|
end, 120)
|
|
check("dismissing closes both the move box and the picker",
|
|
not find(isParty) and not find(isMoveMenu))
|
|
check("LICK got one PP Up", (gengar.moves[1].ppUps or 0) == 1)
|
|
end
|
|
|
|
U.log("======== PP UP on a maxed move reprompts ========")
|
|
gengar.moves[1].ppUps = 3
|
|
local before = game.save.inventory.PP_UP
|
|
picker = openPicker("PP_UP")
|
|
if check("PP UP party picker opened for the maxed move", picker ~= nil) then
|
|
pickMon(picker, 1)
|
|
waitFor(function() return isMoveMenu(top()) and top().ready end, 400)
|
|
local mm = top()
|
|
cursorTo(mm, 1)
|
|
U.tap(game, "a")
|
|
waitFor(function() return isBox(top()) end, 30)
|
|
local res = top()
|
|
check("maxed out text prints", boxText(res):find("maxed out") ~= nil)
|
|
waitFor(function() return res.done end, 240)
|
|
U.shot(game, DIR .. "/2320_04_pp_maxed_out.png")
|
|
U.tap(game, "a")
|
|
U.wait(2)
|
|
check("the prompt types again", isBox(top()) and find(isMoveMenu) == mm and not mm.ready)
|
|
check("the move box comes back",
|
|
waitFor(function() return top() == mm and mm.ready end, 400))
|
|
U.wait(2)
|
|
U.shot(game, DIR .. "/2320_05_maxed_reprompt.png")
|
|
check("no PP UP was spent", game.save.inventory.PP_UP == before)
|
|
U.tap(game, "b")
|
|
U.wait(4)
|
|
U.tap(game, "b")
|
|
U.wait(8)
|
|
end
|
|
|
|
U.log("======== TM on a full moveset ========")
|
|
picker = openPicker("TM_MEGA_PUNCH")
|
|
if check("TM party picker opened", picker ~= nil) then
|
|
pickMon(picker, 2)
|
|
local learn
|
|
local ok = waitFor(function()
|
|
learn = find(isLearn)
|
|
local t = top()
|
|
if learn and isBox(t) and boxText(t):find("forgotten") then return true end
|
|
if getmetatable(t) == ChoiceBox then U.tap(game, "a")
|
|
elseif isBox(t) and (t.done or t.waiting) then U.tap(game, "a") end
|
|
return false
|
|
end, 900)
|
|
check("Which move should be forgotten? types first", ok and learn and not learn.selecting)
|
|
U.wait(3)
|
|
U.shot(game, DIR .. "/2320_06_forget_prompt_typing.png")
|
|
check("the forget box follows the text",
|
|
waitFor(function() return learn and top() == learn and learn.selecting end, 400))
|
|
U.wait(2)
|
|
U.shot(game, DIR .. "/2320_07_forget_box_over_textbox.png")
|
|
cursorTo(learn, 1)
|
|
U.tap(game, "a")
|
|
U.wait(2)
|
|
check("SURF is refused and the forget box is gone",
|
|
isBox(top()) and boxText(top()):find("HM") ~= nil and not learn.selecting)
|
|
waitFor(function() return top().done end, 240)
|
|
U.shot(game, DIR .. "/2320_08_hm_refused_no_box.png")
|
|
U.tap(game, "a")
|
|
check("the forget prompt retypes, then the box returns",
|
|
waitFor(function() return top() == learn and learn.selecting end, 400))
|
|
cursorTo(learn, 2)
|
|
U.tap(game, "a")
|
|
U.wait(2)
|
|
check("the forget box is gone for 1, 2 and... Poof!", not find(isLearn))
|
|
waitFor(function()
|
|
local t = top()
|
|
if isBox(t) and (t.done or t.waiting) then U.tap(game, "a") end
|
|
return not find(isParty)
|
|
end, 900)
|
|
local knows = false
|
|
for _, mv in ipairs(nido.moves) do if mv.id == "MEGA_PUNCH" then knows = true end end
|
|
check("NIDOKING learned MEGA PUNCH", knows)
|
|
end
|
|
|
|
U.log(fail == 0 and "PASS pp_up_move_box_2320" or ("FAIL pp_up_move_box_2320 (" .. fail .. ")"))
|
|
love.event.quit(fail == 0 and 0 or 1)
|
|
end
|