Files
gen1recomp/tests/drivers/game3_r4_item_rom_text.lua
bryanthaboi dee935a4ea CLOSES #2430
2026-09-23 11:58:32 -04:00

279 lines
9.9 KiB
Lua

local U = require("tests.drivers.util")
local DIR = os.getenv("POKEPORT_SHOT_DIR") or "/tmp/game3_r4_item_rom_text"
-- pokefirered/include/constants/items.h:90
local ITEM_REPEL = 86
local ITEM_POTION = 13
local ITEM_POKE_BALL = 4
local ITEM_ORAN_BERRY = 139
local ITEM_TM01 = 289
local ITEM_TM_CASE = 364
local ITEM_BERRY_POUCH = 365
local failures = 0
local function result(ok, label)
print((ok and "PASS " or "FAIL ") .. label)
if not ok then failures = failures + 1 end
return ok
end
local function finish()
if failures == 0 then
print("PASS r4_item_rom_text")
love.event.quit(0)
else
print("FAIL r4_item_rom_text failures=" .. failures)
love.event.quit(1)
end
end
return function(game)
for _ = 1, 900 do
if game.phase == "boot" and game.boot then break end
U.wait(1)
end
game:_handleBootAction({ action = "new_game", name = "RED" })
U.wait(240)
local Runtime = require("src.core.game3.runtime")
local Bag = require("src.core.game3.bag")
local ItemsData = require("src.core.game3.items_data")
local RomText = require("src.core.game3.rom_text")
local BagMenu = require("src.ui.game3.bag_menu")
local TmCase = require("src.ui.game3.tm_case")
local BerryPouch = require("src.ui.game3.berry_pouch")
local ShopMenu = require("src.ui.game3.shop_menu")
local session = Runtime.getSession()
if not result(session ~= nil, "new game reached the game3 field") then return finish() end
session.money = 3000
Bag.add(session.bag, ITEM_REPEL, 3)
Bag.add(session.bag, ITEM_POTION, 2)
Bag.add(session.bag, ITEM_TM_CASE, 1)
Bag.add(session.bag, ITEM_TM01, 1)
Bag.add(session.bag, ITEM_BERRY_POUCH, 1)
Bag.add(session.bag, ITEM_ORAN_BERRY, 3)
local function toRow(itemId)
local target
for i, r in ipairs(BagMenu.list()) do
if ItemsData.toNumericId(r.id) == itemId then target = i end
end
if not target then return false end
for _ = 1, 30 do
if BagMenu.cursor == target then return true end
U.tap(game, BagMenu.cursor < target and "down" or "up")
U.wait(8)
end
return BagMenu.cursor == target
end
local function toPocket(pocket)
local want
for i, p in ipairs(ItemsData.BAG_POCKET_ORDER) do
if p == pocket then want = i end
end
for _ = 1, 12 do
if BagMenu.currentPocket() == pocket then return true end
U.tap(game, (want or 1) > BagMenu.pocketIdx and "right" or "left")
U.wait(20)
end
return BagMenu.currentPocket() == pocket
end
BagMenu.show(session, { bag = session.bag })
for _ = 1, 60 do
if BagMenu.isOpen() and not BagMenu._open then break end
U.wait(4)
end
result(BagMenu.isOpen(), "the bag opened")
result(toPocket("ITEMS"), "on the ITEMS pocket")
result(ItemsData.POCKET_LABEL.ITEMS == RomText.plain("sPocketNames[0]"), "pocket label is sPocketNames[0]")
result(toRow(ITEM_REPEL), "cursor on REPEL")
U.tap(game, "a")
U.wait(12)
result(BagMenu.mode == "action", "the item menu opened")
result(RomText.at("sItemMenuContextActions", 0) == "USE", "USE comes from sItemMenuContextActions[0]")
U.shot(game, DIR .. "/r4_bag_repel_selected_actions.png")
for _ = 1, 8 do
if BagMenu.ACTIONS[BagMenu.actionCursor] == "TOSS" then break end
U.tap(game, "down")
U.wait(8)
end
U.tap(game, "a")
U.wait(12)
result(BagMenu.mode == "toss", "TOSS asks how many (item_menu.c:1497), mode=" .. tostring(BagMenu.mode))
U.shot(game, DIR .. "/r4_bag_toss_out_how_many.png")
U.tap(game, "up")
U.wait(8)
U.tap(game, "a")
U.wait(12)
result(BagMenu.mode == "toss_confirm", "A asks gText_ThrowAwayStrVar2OfThisItemQM, mode=" .. tostring(BagMenu.mode))
U.shot(game, DIR .. "/r4_bag_throw_away_confirm.png")
U.tap(game, "a")
U.wait(12)
result(BagMenu.mode == "toss_done", "YES prints gText_ThrewAwayStrVar2StrVar1s, mode=" .. tostring(BagMenu.mode))
U.shot(game, DIR .. "/r4_bag_threw_away.png")
U.tap(game, "a")
U.wait(12)
result(Bag.get(session.bag, ITEM_REPEL) == 1, "two REPELs were thrown away, left " .. tostring(Bag.get(session.bag, ITEM_REPEL)))
result(toPocket("KEY_ITEMS"), "on the KEY ITEMS pocket")
result(toRow(ITEM_TM_CASE), "cursor on the TM CASE")
U.tap(game, "a")
U.wait(12)
result(BagMenu.mode == "action", "the TM CASE item menu opened")
U.shot(game, DIR .. "/r4_bag_tm_case_open_action.png")
U.tap(game, "b")
U.wait(12)
BagMenu.close()
U.wait(30)
TmCase.show(session, session.bag)
U.wait(40)
result(TmCase.isOpen(), "the TM CASE opened")
local Pokemon = require("src.core.game3.pokemon")
-- pokefirered/src/data/battle_moves.h:3439
result(tonumber((Pokemon.battleMove(Pokemon.moveFromTmItem(ITEM_TM01)) or {}).type) == 1,
"TM01 FOCUS PUNCH is type 1 (FIGHTING)")
local labelText = {}
for _, seg in ipairs(TmCase.labelIr(ITEM_TM01)) do
if seg.t == "text" then labelText[#labelText + 1] = seg.s end
end
labelText = table.concat(labelText)
-- pokefirered/src/tm_case.c:678 GetTMNumberAndMoveString
result(labelText == "№01 FOCUS PUNCH", "TM row label is №01 FOCUS PUNCH: " .. labelText)
U.shot(game, DIR .. "/r4_tm_case_list.png")
U.tap(game, "a")
U.wait(12)
result(TmCase.mode == "action", "TM01 is selected, mode=" .. tostring(TmCase.mode))
U.shot(game, DIR .. "/r4_tm_case_selected.png")
U.tap(game, "down")
U.wait(8)
U.tap(game, "a")
U.wait(12)
result(TmCase.mode == "message" and tostring(TmCase.messageText):find("can't be held", 1, true) ~= nil,
"GIVE prints gText_ItemCantBeHeld: " .. tostring(TmCase.messageText))
U.shot(game, DIR .. "/r4_tm_case_cant_be_held.png")
TmCase.close()
U.wait(30)
BerryPouch.show(session, session.bag)
U.wait(40)
result(BerryPouch.isOpen(), "the BERRY POUCH opened")
U.tap(game, "a")
U.wait(12)
result(BerryPouch.mode == "action", "ORAN BERRY is selected")
U.shot(game, DIR .. "/r4_berry_pouch_selected.png")
BerryPouch.close()
U.wait(30)
ShopMenu.show({ items = { ITEM_POKE_BALL, ITEM_POTION }, session = session })
U.wait(20)
result(ShopMenu._status == RomText.box("Text_MayIHelpYou"), "the clerk line is Text_MayIHelpYou")
U.shot(game, DIR .. "/r4_shop_may_i_help_you.png")
U.tap(game, "a")
U.wait(60)
result(ShopMenu.mode == "buy", "BUY opened the stock list")
U.tap(game, "a")
U.wait(12)
result(ShopMenu.mode == "buy_qty" and ShopMenu._status:find("Certainly", 1, true) ~= nil,
"gText_Var1CertainlyHowMany: " .. tostring(ShopMenu._status))
U.shot(game, DIR .. "/r4_shop_certainly_how_many.png")
U.tap(game, "up")
U.wait(8)
U.tap(game, "a")
U.wait(12)
result(ShopMenu._status == "POKé BALL, and you want 2.\nThat will be ¥400. Okay?",
"gText_Var1AndYouWantedVar2: " .. tostring(ShopMenu._status))
U.shot(game, DIR .. "/r4_shop_and_you_want.png")
U.tap(game, "a")
U.wait(12)
result(Bag.get(session.bag, ITEM_POKE_BALL) == 2 and Bag.get(session.bag, 12) == 0,
"two POKé BALLs and no PREMIER BALL")
U.shot(game, DIR .. "/r4_shop_here_you_are.png")
U.tap(game, "a")
U.wait(12)
U.tap(game, "b")
U.wait(60)
U.tap(game, "down")
U.wait(8)
U.tap(game, "a")
for _ = 1, 90 do
if BagMenu.isOpen() and not BagMenu._open then break end
U.wait(4)
end
-- pokefirered/src/shop.c:288 CB2_GoToSellMenu
result(BagMenu.isOpen() and BagMenu._location == "shop", "SELL opened the bag in shop mode")
result(toPocket("ITEMS"), "sell bag on the ITEMS pocket")
result(toRow(ITEM_POTION), "sell cursor on POTION")
local moneyBefore = session.money
U.tap(game, "a")
U.wait(12)
local sell = BagMenu._sell
result(BagMenu.mode == "sell" and sell and sell.state == "qty"
and tostring(sell.text):find("How many would you like to sell?", 1, true) ~= nil,
"gText_HowManyWouldYouLikeToSell: " .. tostring(sell and sell.text))
U.tap(game, "up")
U.wait(8)
result(sell and sell.qty == 2, "quantity went to 2")
U.shot(game, DIR .. "/r4_shop_how_many_sell.png")
U.tap(game, "a")
U.wait(12)
result(sell and sell.state == "confirm" and sell.text == "I can pay ¥300.\nWould that be okay?",
"gText_ICanPayThisMuch_WouldThatBeOkay: " .. tostring(sell and sell.text))
U.shot(game, DIR .. "/r4_shop_i_can_pay.png")
U.tap(game, "a")
U.wait(12)
result(sell and sell.state == "done" and tostring(sell.text):find("Turned over the", 1, true) ~= nil,
"gText_TurnedOverItemsWorthYen: " .. tostring(sell and sell.text))
result(session.money == moneyBefore + 300 and Bag.get(session.bag, ITEM_POTION) == 0,
"sold 2 POTIONs for 300, money=" .. tostring(session.money))
U.shot(game, DIR .. "/r4_shop_turned_over.png")
U.tap(game, "a")
U.wait(12)
result(BagMenu.mode == "list" and BagMenu._sell == nil, "back on the sell bag list")
result(toPocket("KEY_ITEMS"), "sell bag on the KEY ITEMS pocket")
result(toRow(ITEM_TM_CASE), "sell cursor on TM CASE")
U.tap(game, "a")
for _ = 1, 60 do
if TmCase.isOpen() then break end
U.wait(4)
end
U.wait(20)
-- pokefirered/src/item_menu.c:1825 GoToTMCase_Sell
result(TmCase.isOpen() and TmCase._sellMode == true, "TM CASE opened in sell mode")
U.tap(game, "a")
U.wait(12)
local tmSell = TmCase._sell
result(TmCase.mode == "sell" and tmSell and tmSell.state == "confirm"
and tostring(tmSell.text):find("I can pay ¥1500.", 1, true) ~= nil,
"single TM01 goes straight to the price: " .. tostring(tmSell and tmSell.text))
U.shot(game, DIR .. "/r4_tm_case_sell_i_can_pay.png")
U.tap(game, "b")
U.wait(12)
result(TmCase.mode == "list" and Bag.get(session.bag, ITEM_TM01) == 1, "B keeps the TM")
U.tap(game, "b")
for _ = 1, 60 do
if BagMenu.isOpen() and not BagMenu._open and not TmCase.isOpen() then break end
U.wait(4)
end
U.tap(game, "b")
for _ = 1, 90 do
if not BagMenu.isOpen() then break end
U.wait(4)
end
U.wait(30)
-- pokefirered/src/shop.c:330
result(ShopMenu.isOpen() and ShopMenu.mode == "root"
and ShopMenu._status == RomText.box("gText_AnythingElseICanHelp"),
"closing the sell bag returns to the shop menu: " .. tostring(ShopMenu._status))
U.shot(game, DIR .. "/r4_shop_anything_else.png")
ShopMenu.close()
U.wait(10)
finish()
end