mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-22 21:46:51 +02:00
c0f4315cd8
CLOSES #1484, CLOSES #1486, CLOSES #1513, CLOSES #1517, CLOSES #1556, CLOSES #1564, CLOSES #1567
121 lines
4.8 KiB
Lua
121 lines
4.8 KiB
Lua
-- Driver: #1517, a Gen 2 stat block in a Gen 1 party.
|
|
--
|
|
-- Gen 1's party_struct carries one Special word (macros/ram.asm:28-37) and
|
|
-- PrintStatsBox reads four fixed cells, wLoadedMonAttack/Defense/Speed/Special
|
|
-- (engine/pokemon/status_screen.asm:255-296). Gen 2 splits that word into
|
|
-- SpclAtk/SpclDef (pokegold macros/ram.asm:29-42), so a mod that wrote a Gen 2
|
|
-- block over a Yellow party leaves the port with no `special` to print.
|
|
--
|
|
-- cp -R ~/Library/Application\ Support/LOVE/pokemon-love2d/yellow \
|
|
-- ~/Library/Application\ Support/LOVE/bug1517/yellow
|
|
-- POKEPORT_VERSION=yellow POKEPORT_GAME=yellow POKEPORT_IDENTITY=bug1517 \
|
|
-- POKEPORT_TOUCH=0 POKEPORT_SPEED=8 SHOT_DIR=/tmp/bug1517 \
|
|
-- POKEPORT_DRIVER=tests/drivers/summary_stats_bug1517_test.lua love .
|
|
--
|
|
-- The copy is not optional: a fresh POKEPORT_IDENTITY has no cache and the
|
|
-- boot hangs with no output.
|
|
--
|
|
-- Pre-fix the LOVE window vanishes the moment STATS is chosen, with no error
|
|
-- screen and nothing on stdout (that silence is the other half of #1517).
|
|
-- Post-fix the status screen opens and SPECIAL reads the CalcStats value
|
|
-- logged below. The run ends on the open screen, so a human takes the
|
|
-- controls at exactly the frame the reporter's build died on.
|
|
return function(game)
|
|
local U = dofile("tests/drivers/util.lua")
|
|
local DIR = os.getenv("SHOT_DIR") or "/tmp/bug1517"
|
|
local Pokemon = require("src.pokemon.Pokemon")
|
|
local Stats = require("src.pokemon.Stats")
|
|
local SaveData = require("src.core.SaveData")
|
|
local SummaryMenu = require("src.ui.SummaryMenu")
|
|
|
|
local function top() return game.stack:top() end
|
|
|
|
U.newGame(game)
|
|
U.wait(20)
|
|
|
|
-- BUTTERFREE because the reporter's party led with one, and CONFUSION is a
|
|
-- special move, so the same block would have crashed Damage.applyStage.
|
|
local species = game.data.pokemon.BUTTERFREE and "BUTTERFREE" or "PIDGEY"
|
|
local def = game.data.pokemon[species]
|
|
local mon = Pokemon.new(game.data, species, 21)
|
|
local want = Stats.calc(def, 21, mon.dvs, mon.statExp)
|
|
|
|
-- the shape src/battle/gen2/Mon.lua Mon.stats produces: no `special`
|
|
mon.stats = {
|
|
hp = want.hp, attack = want.attack, defense = want.defense,
|
|
speed = want.speed, specialAttack = want.special, specialDefense = want.special,
|
|
}
|
|
mon.hp = mon.stats.hp
|
|
game.save.party = { mon }
|
|
U.log(("[1517] fixture: %s :L21, stats.special = %s, CalcStats says %d")
|
|
:format(species, tostring(mon.stats.special), want.special))
|
|
|
|
SaveData.validate(game.save, game.data)
|
|
local after = game.save.party[1].stats
|
|
U.log("[1517] after SaveData.validate, special = " .. tostring(after.special)
|
|
.. ", specialAttack = " .. tostring(after.specialAttack))
|
|
U.log("[1517] the repair layer is SaveData.validate -> scrubKnownMon -> "
|
|
.. "Stats.ensure; a nil above means it did not run")
|
|
|
|
U.teleport(game, "PALLET_TOWN", 10, 8, "down")
|
|
U.wait(10)
|
|
|
|
local function cursorTo(menu, field, wanted)
|
|
for _ = 1, 40 do
|
|
if not menu or menu[field] == wanted then return menu and menu[field] == wanted end
|
|
U.tap(game, menu[field] < wanted and "down" or "up")
|
|
U.wait(3)
|
|
end
|
|
return menu[field] == wanted
|
|
end
|
|
|
|
U.tap(game, "start")
|
|
U.wait(10)
|
|
local menu = top()
|
|
if not (menu and menu.screenId == "StartMenu") then
|
|
U.log("[1517] FAIL no start menu; top = " .. tostring(menu and menu.screenId))
|
|
while true do coroutine.yield() end
|
|
end
|
|
local row
|
|
for i, it in ipairs(menu.items or {}) do
|
|
if it.label == "POKéMON" then row = i break end
|
|
end
|
|
if not (row and cursorTo(menu, "index", row)) then
|
|
U.log("[1517] FAIL could not reach the POKéMON row")
|
|
while true do coroutine.yield() end
|
|
end
|
|
U.tap(game, "a")
|
|
U.wait(10)
|
|
|
|
local party = top()
|
|
if not (party and party.screenId == "PartyMenu") then
|
|
U.log("[1517] FAIL no party menu; top = " .. tostring(party and party.screenId))
|
|
while true do coroutine.yield() end
|
|
end
|
|
U.shot(game, DIR .. "/01-party-list.png")
|
|
U.tap(game, "a")
|
|
U.wait(8)
|
|
local subRow
|
|
for i, it in ipairs(party.subItems or {}) do
|
|
if it.action == "stats" then subRow = i break end
|
|
end
|
|
if not (subRow and cursorTo(party, "subIndex", subRow)) then
|
|
U.log("[1517] FAIL could not reach the STATS row")
|
|
while true do coroutine.yield() end
|
|
end
|
|
U.shot(game, DIR .. "/02-stats-selected.png")
|
|
|
|
U.log("[1517] opening STATS -- pre-fix the app dies here, silently")
|
|
U.tap(game, "a")
|
|
U.wait(30)
|
|
|
|
local screen = top()
|
|
local opened = getmetatable(screen) == SummaryMenu or screen.screenId == "SummaryMenu"
|
|
U.log("[1517] SURVIVED, top = " .. tostring(screen and screen.screenId))
|
|
U.shot(game, DIR .. "/03-status-screen.png")
|
|
U.log(("[1517] %s: SPECIAL on screen must read %d")
|
|
:format(opened and "read it off the frame" or "WRONG SCREEN", want.special))
|
|
U.log("[1517] shots in " .. DIR .. " -- the status screen is yours")
|
|
while true do coroutine.yield() end
|
|
end
|