mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-12 16:31:05 +02:00
233 lines
9.0 KiB
Lua
233 lines
9.0 KiB
Lua
-- Manual check that Team Rocket leaves Silph Co and the president keeps talking
|
|
-- (#392). pokered scripts/SilphCo11F.asm: the Giovanni win runs
|
|
-- SilphCo11FTeamRocketLeavesScript (HideObject over TOGGLE_SILPH_CO_2F_2..11F_3),
|
|
-- and SilphCo11FSilphPresidentText prints .MasterBallDescriptionText on every
|
|
-- later talk. No POKEPORT_SPEED: fast-forward desynchronizes the jingle.
|
|
-- SHOT_DIR=/tmp/shots POKEPORT_DRIVER=tests/drivers/silph_rockets_bug392_test.lua POKEPORT_IDENTITY=bug392 POKEPORT_TOUCH=0 POKEPORT_VERSION=red love .
|
|
return function(game)
|
|
local U = dofile("tests/drivers/util.lua")
|
|
local DIR = os.getenv("SHOT_DIR") or "/tmp/shots"
|
|
local Pokemon = require("src.pokemon.Pokemon")
|
|
local TextBox = require("src.render.TextBox")
|
|
local BattleState = require("src.battle.BattleState")
|
|
local ScriptRunner = require("src.script.ScriptRunner")
|
|
local mapScripts = require("data.scripts.init")
|
|
|
|
-- pokered data/maps/objects/SilphCo11F.asm: president (7,5) STAY DOWN, so
|
|
-- he is read from (6,5) facing right; GIOVANNI (6,9), ROCKET1 (3,16),
|
|
-- ROCKET2 (15,9). SilphCo11FDefaultScript.PlayerCoordsArray is (6,13) and
|
|
-- (7,12), each stepped onto from the cell below it (teleport ignores
|
|
-- collision, so the stand cell only has to be south of the trigger).
|
|
local PRESIDENT = { x = 7, y = 5 }
|
|
local READ = { x = 6, y = 5, facing = "right" }
|
|
local TRIGGERS = { { stand = { 7, 13 }, cell = { 7, 12 } },
|
|
{ stand = { 6, 14 }, cell = { 6, 13 } } }
|
|
local ELEVENTH = { "SILPHCO11F_GIOVANNI", "SILPHCO11F_ROCKET1",
|
|
"SILPHCO11F_ROCKET2" }
|
|
-- one floor per shape: 3F is rocket + scientist + an item ball, 5F adds the
|
|
-- rocket-aligned ROCKER, 7F keeps the rival out of the hide list
|
|
local FLOORS = {
|
|
{ "SILPH_CO_3F", { 22, 7 },
|
|
gone = { "SILPHCO3F_ROCKET", "SILPHCO3F_SCIENTIST" },
|
|
stays = { "SILPHCO3F_HYPER_POTION", "SILPHCO3F_SILPH_WORKER_M" } },
|
|
{ "SILPH_CO_5F", { 13, 10 },
|
|
gone = { "SILPHCO5F_ROCKET1", "SILPHCO5F_SCIENTIST",
|
|
"SILPHCO5F_ROCKER", "SILPHCO5F_ROCKET2" },
|
|
stays = { "SILPHCO5F_CARD_KEY", "SILPHCO5F_SILPH_WORKER_M" } },
|
|
{ "SILPH_CO_7F", { 10, 9 },
|
|
gone = { "SILPHCO7F_ROCKET1", "SILPHCO7F_SCIENTIST",
|
|
"SILPHCO7F_ROCKET2", "SILPHCO7F_ROCKET3" },
|
|
stays = { "SILPHCO7F_TM_SWORDS_DANCE", "SILPHCO7F_SILPH_WORKER_M3" } },
|
|
}
|
|
|
|
local function check(label, ok)
|
|
U.log(ok and "PASS" or "FAIL", label)
|
|
return ok
|
|
end
|
|
|
|
local function spawned(name)
|
|
for _, n in ipairs(game.overworld and game.overworld.npcs or {}) do
|
|
if n.def and n.def.name == name then return n end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
local rows = mapScripts.get("SILPH_CO_11F").talk
|
|
.TEXT_SILPHCO11F_SILPH_PRESIDENT
|
|
check("the president has a hand-ported talk script", type(rows) == "table")
|
|
if type(rows) == "table" then
|
|
local problems = ScriptRunner.validate(rows)
|
|
check("his script validates: " .. (problems[1] or "no problems"),
|
|
#problems == 0)
|
|
end
|
|
for _, key in ipairs({ "_SilphCo11FSilphPresidentText",
|
|
"_SilphCo11FSilphPresidentReceivedMasterBallText",
|
|
"_SilphCo11FSilphPresidentMasterBallDescriptionText" }) do
|
|
local body = game.data.text[key]
|
|
check(key .. " is extracted", type(body) == "string" and body ~= "")
|
|
end
|
|
|
|
local vol = game.save.options and game.save.options.sfxVol
|
|
if (vol or 0) == 0 then
|
|
U.log("sfxVol is 0: the key-item jingle will be silent, raise it in OPTION")
|
|
else
|
|
U.log("sfxVol", tostring(vol), "-- the ball arrives on the key-item jingle")
|
|
end
|
|
|
|
game.save.party = {
|
|
Pokemon.new(game.data, "CHARIZARD", 70),
|
|
Pokemon.new(game.data, "SNORLAX", 70),
|
|
Pokemon.new(game.data, "LAPRAS", 70),
|
|
}
|
|
game.save.player.name = "bryan"
|
|
game.save.flags.EVENT_BEAT_SILPH_CO_GIOVANNI = nil
|
|
game.save.flags.EVENT_GOT_MASTER_BALL = nil
|
|
game.save.objectToggles = {}
|
|
|
|
U.teleport(game, "SILPH_CO_11F", READ.x, READ.y, READ.facing)
|
|
U.wait(10)
|
|
local ow = game.overworld
|
|
for _, name in ipairs(ELEVENTH) do
|
|
check(name .. " is on the floor before the fight", spawned(name) ~= nil)
|
|
end
|
|
U.shot(game, DIR .. "/silph392_0_before.png")
|
|
|
|
local function facingThePresident()
|
|
local o = game.overworld
|
|
local fx, fy = o.player:facingCell()
|
|
return o:npcAtCell(fx, fy) == spawned("SILPHCO11F_SILPH_PRESIDENT")
|
|
end
|
|
|
|
if not facingThePresident() then
|
|
-- a map edit moved him: stand on any free walkable neighbour.
|
|
-- {dx, dy, facing} is the offset from the president plus the way back.
|
|
local sides = {
|
|
{ 0, 1, "up" }, { 0, -1, "down" }, { 1, 0, "left" }, { -1, 0, "right" },
|
|
}
|
|
for _, s in ipairs(sides) do
|
|
local cx, cy = PRESIDENT.x + s[1], PRESIDENT.y + s[2]
|
|
if ow.map:isWalkableCell(cx, cy) and not ow:npcAtCell(cx, cy) then
|
|
U.log("president moved; standing on", cx, cy, "facing", s[3])
|
|
U.teleport(game, "SILPH_CO_11F", cx, cy, s[3])
|
|
U.wait(10)
|
|
ow = game.overworld
|
|
break
|
|
end
|
|
end
|
|
end
|
|
check("the player is facing the president", facingThePresident())
|
|
|
|
local function boxText(top)
|
|
local lines = {}
|
|
for _, page in ipairs(top.pages or {}) do
|
|
for _, line in ipairs(page) do lines[#lines + 1] = line end
|
|
end
|
|
return table.concat(lines, " ")
|
|
end
|
|
|
|
-- one whole talk: A to open, then A through every box until the world is back
|
|
local function talk()
|
|
local seen = {}
|
|
U.tap(game, "a")
|
|
U.wait(20)
|
|
for _ = 1, 120 do
|
|
local top = game.stack:top()
|
|
if getmetatable(top) == TextBox then
|
|
local txt = boxText(top)
|
|
if txt ~= "" and seen[#seen] ~= txt then seen[#seen + 1] = txt end
|
|
elseif top == game.overworld then
|
|
break
|
|
end
|
|
U.tap(game, "a")
|
|
U.wait(10)
|
|
end
|
|
return table.concat(seen, " / ")
|
|
end
|
|
|
|
local first = talk()
|
|
U.log("first talk reads:", first)
|
|
check("the first talk prints his thank-you", first ~= "")
|
|
check("and hands over the MASTER BALL",
|
|
(game.save.inventory.MASTER_BALL or 0) > 0)
|
|
check("EVENT_GOT_MASTER_BALL is set", game.save.flags.EVENT_GOT_MASTER_BALL == true)
|
|
|
|
U.wait(20)
|
|
local second = talk()
|
|
U.log("second talk reads:", second)
|
|
check("the second talk is not silence", second ~= "")
|
|
check("it is the MASTER BALL description",
|
|
second:find("prototype", 1, true) ~= nil)
|
|
check("and no second ball is handed out",
|
|
(game.save.inventory.MASTER_BALL or 0) == 1)
|
|
U.shot(game, DIR .. "/silph392_1_president.png")
|
|
|
|
-- the hide pass, floor by floor: this is what a save that beat Giovanni sees
|
|
-- on its next visit, and what the win itself does in one go
|
|
game.save.flags.EVENT_BEAT_SILPH_CO_GIOVANNI = true
|
|
for i, floor in ipairs(FLOORS) do
|
|
local mapId, at = floor[1], floor[2]
|
|
U.teleport(game, mapId, at[1], at[2], "down")
|
|
U.wait(10)
|
|
for _, name in ipairs(floor.gone) do
|
|
check(name .. " left " .. mapId, spawned(name) == nil)
|
|
end
|
|
for _, name in ipairs(floor.stays) do
|
|
check(name .. " is still there", spawned(name) ~= nil)
|
|
end
|
|
local toggles = game.save.objectToggles[mapId] or {}
|
|
check(mapId .. " toggles were written to the save",
|
|
toggles[floor.gone[1]] == false)
|
|
U.shot(game, ("%s/silph392_2_%s.png"):format(DIR, mapId:lower()))
|
|
if i == #FLOORS then
|
|
check("the 7F rival keeps his toggle",
|
|
toggles.SILPHCO7F_RIVAL ~= false)
|
|
end
|
|
end
|
|
|
|
-- put the fight back on the table: clear the event, the toggles and the
|
|
-- battle records so the coordinate trigger re-arms
|
|
game.save.flags.EVENT_BEAT_SILPH_CO_GIOVANNI = nil
|
|
game.save.objectToggles = {}
|
|
game.save.defeatedTrainers = {}
|
|
game.save.flags.EVENT_BEAT_SILPH_CO_11F_TRAINER_0 = nil
|
|
game.save.flags.EVENT_BEAT_SILPH_CO_11F_TRAINER_1 = nil
|
|
|
|
local fired, cell
|
|
for i, t in ipairs(TRIGGERS) do
|
|
U.teleport(game, "SILPH_CO_11F", t.stand[1], t.stand[2], "up")
|
|
U.wait(10)
|
|
ow = game.overworld
|
|
if i == 1 then
|
|
for _, name in ipairs(ELEVENTH) do
|
|
check(name .. " is back on the floor", spawned(name) ~= nil)
|
|
end
|
|
U.shot(game, DIR .. "/silph392_3_rearmed.png")
|
|
end
|
|
U.hold(game, "up", 24)
|
|
for _ = 1, 300 do
|
|
U.wait(1)
|
|
if getmetatable(game.stack:top()) == BattleState then break end
|
|
end
|
|
if getmetatable(game.stack:top()) == BattleState
|
|
or (ow.player.cellX == t.cell[1] and ow.player.cellY == t.cell[2]) then
|
|
fired, cell = true, t.cell
|
|
break
|
|
end
|
|
U.log(("the step up from (%d,%d) missed the trigger; trying the other pad")
|
|
:format(t.stand[1], t.stand[2]))
|
|
end
|
|
cell = cell or TRIGGERS[1].cell
|
|
check(("stepping onto (%d,%d) started GIOVANNI"):format(cell[1], cell[2]),
|
|
fired == true)
|
|
U.shot(game, DIR .. "/silph392_4_giovanni.png")
|
|
|
|
U.log("Win the fight: after the fade GIOVANNI and both ROCKETs, (3,16) and")
|
|
U.log("(15,9), should be gone, and every grunt and lab-coat trainer on")
|
|
U.log("3F/5F/7F with them. The president at (7,5) has the ball already, so")
|
|
U.log("A on him should describe it again, never an empty beat.")
|
|
|
|
while true do
|
|
coroutine.yield()
|
|
end
|
|
end
|