mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-25 23:11:15 +02:00
1905261c5b
CLOSES #1483, CLOSES #1610, CLOSES #1615, CLOSES #1646, CLOSES #1649, CLOSES #1651, CLOSES #1653, CLOSES #1656, CLOSES #1683, CLOSES #1685, CLOSES #1686, CLOSES #1687, CLOSES #1688, CLOSES #1689, CLOSES #1690, CLOSES #1693, CLOSES #1694, CLOSES #1695, CLOSES #1696, CLOSES #1702, CLOSES #1704, CLOSES #1705, CLOSES #1706, CLOSES #1707, CLOSES #1708, CLOSES #1710, CLOSES #1711, CLOSES #1712, CLOSES #1713, CLOSES #1716, CLOSES #1717, CLOSES #1718, CLOSES #1719, CLOSES #1720, CLOSES #1721, CLOSES #1725, CLOSES #1732, CLOSES #1745, CLOSES #1748, CLOSES #1749, CLOSES #1751, CLOSES #1754
212 lines
8.2 KiB
Lua
212 lines
8.2 KiB
Lua
-- Manual check of the Pewter museum clerk's back-entrance branches (#1690).
|
|
-- scripts/Museum1F.asm:45 reads wYCoord/wXCoord before the ticket flag, so
|
|
-- (13,4) and (12,3) behind the counter get the AMBER question and row 4 in
|
|
-- front of it gets the ¥50 ask. This walks all three by itself.
|
|
-- Do not add POKEPORT_SPEED: fast-forward scales only the logic clock, and
|
|
-- what is being judged here is page order and the choice box timing.
|
|
-- POKEPORT_DRIVER=tests/drivers/museum_back_entrance_bug1690_test.lua POKEPORT_TOUCH=0 POKEPORT_VERSION=red POKEPORT_IDENTITY=bug1690 SHOT_DIR=/tmp/museum1690 love .
|
|
return function(game)
|
|
local U = dofile("tests/drivers/util.lua")
|
|
local TextBox = require("src.render.TextBox")
|
|
local ChoiceBox = require("src.ui.ChoiceBox")
|
|
local SHOT_DIR = os.getenv("SHOT_DIR") or "/tmp/shots"
|
|
|
|
local MAP = "MUSEUM_1F"
|
|
local CLERK_TEXT = "TEXT_MUSEUM1F_SCIENTIST1"
|
|
-- pokered data/maps/objects/Museum1F.asm: MUSEUM1F_SCIENTIST1 at (12,4),
|
|
-- counter column x==11, back door warps in at (16,7)/(17,7)
|
|
local BEHIND_EAST = { x = 13, y = 4, facing = "left" }
|
|
local BEHIND_NORTH = { x = 12, y = 3, facing = "down" }
|
|
local IN_FRONT = { x = 10, y = 4, facing = "right" }
|
|
|
|
local function check(label, ok)
|
|
U.log(ok and "PASS" or "FAIL", label)
|
|
return ok
|
|
end
|
|
|
|
-- every one of these failing looks exactly like the bug on screen: a
|
|
-- missing string, a renamed key or an unwalkable cell all end in silence
|
|
local t = game.data.text or {}
|
|
for _, key in ipairs({
|
|
"_Museum1FScientist1DoYouKnowWhatAmberIsText",
|
|
"_Museum1FScientist1TheresALabSomewhereText",
|
|
"_Museum1FScientist1AmberIsFossilizedTreeSapText",
|
|
"_Museum1FScientist1GoToOtherSideText",
|
|
"_Museum1FScientist1WouldYouLikeToComeInText",
|
|
}) do
|
|
check(key .. " is in the text catalog",
|
|
type(t[key]) == "string" and t[key] ~= "")
|
|
end
|
|
|
|
local function clerkIn(ow)
|
|
for _, n in ipairs(ow and ow.npcs or {}) do
|
|
if n.def and n.def.text == CLERK_TEXT then return n end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
local function boxText(box)
|
|
local shown = {}
|
|
for _, page in ipairs(box.pages or {}) do
|
|
for _, line in ipairs(page) do shown[#shown + 1] = line end
|
|
end
|
|
return table.concat(shown, " / ")
|
|
end
|
|
|
|
-- talking works either straight at the clerk or across the counter tile
|
|
local function facingTheClerk()
|
|
local ow = game.overworld
|
|
local clerk = clerkIn(ow)
|
|
if not clerk then return false end
|
|
local fx, fy = ow.player:facingCell()
|
|
if ow:npcAtCell(fx, fy) == clerk then return true end
|
|
if ow.map:isCounterCell(fx, fy) then
|
|
local Collision = require("src.world.Collision")
|
|
local bx, by = Collision.target(fx, fy, ow.player.facing)
|
|
return ow:npcAtCell(bx, by) == clerk
|
|
end
|
|
return false
|
|
end
|
|
|
|
-- teleport to `spot`, and if a map edit moved the counter fall back to any
|
|
-- free walkable neighbour of the clerk so this degrades instead of parking
|
|
-- the player at a wall
|
|
local function standAt(spot, label)
|
|
U.teleport(game, MAP, spot.x, spot.y, spot.facing)
|
|
U.wait(10)
|
|
if facingTheClerk() then return check(label .. ": in position", true) end
|
|
local ow = game.overworld
|
|
local clerk = clerkIn(ow)
|
|
if clerk then
|
|
local sides = {
|
|
{ 0, 1, "up" }, { 0, -1, "down" }, { 1, 0, "left" }, { -1, 0, "right" },
|
|
}
|
|
for _, s in ipairs(sides) do
|
|
local cx, cy = clerk.cellX + s[1], clerk.cellY + s[2]
|
|
if ow.map:isWalkableCell(cx, cy) and not ow:npcAtCell(cx, cy) then
|
|
U.log(("(%d,%d) does not reach the clerk, standing on")
|
|
:format(spot.x, spot.y), cx, cy, "facing", s[3])
|
|
U.teleport(game, MAP, cx, cy, s[3])
|
|
U.wait(10)
|
|
break
|
|
end
|
|
end
|
|
end
|
|
return check(label .. ": in position", facingTheClerk())
|
|
end
|
|
|
|
-- press A and wait for the dialogue box to actually mount
|
|
local function talk()
|
|
U.tap(game, "a")
|
|
for _ = 1, 60 do
|
|
local top = game.stack:top()
|
|
if getmetatable(top) == TextBox then return top end
|
|
U.wait(1)
|
|
end
|
|
return nil
|
|
end
|
|
|
|
-- page through until the YES/NO box pops (the clerk's question is two
|
|
-- pages, so one A press sits between the box opening and the choice)
|
|
local function toChoice()
|
|
for _ = 1, 20 do
|
|
if getmetatable(game.stack:top()) == ChoiceBox then
|
|
return game.stack:top()
|
|
end
|
|
U.tap(game, "a")
|
|
U.wait(20)
|
|
end
|
|
return getmetatable(game.stack:top()) == ChoiceBox and game.stack:top() or nil
|
|
end
|
|
|
|
-- ChoiceBox starts on YES; NO is one step down
|
|
local function answer(yes)
|
|
if not yes then U.tap(game, "down") U.wait(10) end
|
|
U.tap(game, "a")
|
|
for _ = 1, 60 do
|
|
local top = game.stack:top()
|
|
if getmetatable(top) == TextBox then return top end
|
|
U.wait(1)
|
|
end
|
|
return nil
|
|
end
|
|
|
|
game.save.flags = game.save.flags or {}
|
|
game.save.flags.EVENT_BOUGHT_MUSEUM_TICKET = nil
|
|
standAt(BEHIND_EAST, "east of the clerk (13,4)")
|
|
|
|
local box = talk()
|
|
if check("A behind the counter opens a box", box ~= nil) then
|
|
U.log("box reads:", boxText(box))
|
|
check("it is the can't-sneak-in-the-back-way line",
|
|
boxText(box):find("sneak", 1, true) ~= nil)
|
|
check("no money window rides along with it", box.money == nil)
|
|
U.shot(game, SHOT_DIR .. "/bug1690_a_sneak.png")
|
|
end
|
|
|
|
local choice = toChoice()
|
|
if check("the AMBER question offers YES/NO", choice ~= nil) then
|
|
U.shot(game, SHOT_DIR .. "/bug1690_b_amber_choice.png")
|
|
local answered = answer(true)
|
|
if check("YES opens a follow-up box", answered ~= nil) then
|
|
U.log("YES reads:", boxText(answered))
|
|
check("YES is the resurrection lab line",
|
|
boxText(answered):find("lab", 1, true) ~= nil)
|
|
U.shot(game, SHOT_DIR .. "/bug1690_c_lab.png")
|
|
end
|
|
end
|
|
|
|
-- with the ticket already bought the coordinate check still wins: a
|
|
-- ticket holder round the back is told off, not thanked (asm:45 runs
|
|
-- before the CheckEvent at asm:59)
|
|
game.save.flags.EVENT_BOUGHT_MUSEUM_TICKET = true
|
|
standAt(BEHIND_NORTH, "north of the clerk (12,3), ticket in hand")
|
|
box = talk()
|
|
if check("A north of the clerk opens a box", box ~= nil) then
|
|
U.log("box reads:", boxText(box))
|
|
check("a ticket holder round the back still gets told off",
|
|
boxText(box):find("sneak", 1, true) ~= nil)
|
|
U.shot(game, SHOT_DIR .. "/bug1690_d_ticket_holder_sneak.png")
|
|
end
|
|
choice = toChoice()
|
|
if check("it still offers YES/NO", choice ~= nil) then
|
|
local answered = answer(false)
|
|
if check("NO opens a follow-up box", answered ~= nil) then
|
|
U.log("NO reads:", boxText(answered))
|
|
check("NO is the fossilized tree sap line",
|
|
boxText(answered):find("tree sap", 1, true) ~= nil)
|
|
U.shot(game, SHOT_DIR .. "/bug1690_e_tree_sap.png")
|
|
end
|
|
end
|
|
|
|
-- the control case: the public side of the counter is untouched
|
|
game.save.flags.EVENT_BOUGHT_MUSEUM_TICKET = nil
|
|
game.save.money = 3000
|
|
standAt(IN_FRONT, "in front of the counter (10,4)")
|
|
box = talk()
|
|
if check("A across the counter opens a box", box ~= nil) then
|
|
U.log("box reads:", boxText(box))
|
|
check("the front of the counter is still the ¥50 ticket ask",
|
|
boxText(box):find("50", 1, true) ~= nil)
|
|
check("and it still raises the money window", box.money ~= nil)
|
|
U.shot(game, SHOT_DIR .. "/bug1690_f_ticket_ask.png")
|
|
end
|
|
|
|
U.log("shots are in " .. SHOT_DIR .. ", in the order they were taken.")
|
|
U.log("behind the counter the clerk should say \"You can't sneak in the back")
|
|
U.log("way!\", then \"Oh, whatever! Do you know what AMBER is?\" with YES/NO,")
|
|
U.log("and never a money window. YES talks about a lab resurrecting ancient")
|
|
U.log("POKeMON, NO says AMBER is fossilized tree sap. The box left on screen")
|
|
U.log("now is the last case: standing at (10,4) with no ticket, which must")
|
|
U.log("still be the ¥50 ask with the money window in the corner.")
|
|
U.log("the near misses to watch for: a money window sitting behind the AMBER")
|
|
U.log("question, or \"Take your time, and enjoy it all!\" at (12,3) once the")
|
|
U.log("ticket flag is set, which would mean the ticket check ran first.")
|
|
U.log("Yellow shares this script, so POKEPORT_VERSION=yellow should read")
|
|
U.log("exactly the same at all three spots.")
|
|
|
|
while true do
|
|
coroutine.yield()
|
|
end
|
|
end
|