mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-12 00:10:56 +02:00
176 lines
7.8 KiB
Lua
176 lines
7.8 KiB
Lua
-- Manual check of the Silph Scope unveil in the POKEMON_TOWER_6F battle (#492).
|
|
-- PrintBeginningBattleText .isMarowak (engine/battle/common_text.asm:49-60)
|
|
-- enters disguised even with the scope and plays UnveiledGhostText + MarowakAnim
|
|
-- over the GHOST before "Wild MAROWAK appeared!"; the port used to open the
|
|
-- battle with MAROWAK already loaded. Sequencing half:
|
|
-- tests/engine/ghost_unveil_bug492.lua. Never under POKEPORT_SPEED -- the
|
|
-- unveil is the thing being timed.
|
|
-- POKEPORT_DRIVER=tests/drivers/ghost_unveil_bug492_test.lua POKEPORT_IDENTITY=bug492 POKEPORT_TOUCH=0 SHOT_DIR=/tmp/shots 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 BattleState = require("src.battle.BattleState")
|
|
|
|
local pass, fail = 0, 0
|
|
local function check(label, ok)
|
|
if ok then pass = pass + 1 else fail = fail + 1 end
|
|
U.log(ok and "PASS" or "FAIL", label)
|
|
return ok
|
|
end
|
|
|
|
-- ---- machine checks ----------------------------------------------------
|
|
-- A missing text key, a renamed asset and an unarmed branch all look like
|
|
-- the bug from outside: the battle just opens with MAROWAK on screen.
|
|
U.log("#492 Silph Scope unveil: machine checks")
|
|
check("SILPH_SCOPE is a real item", game.data.items.SILPH_SCOPE ~= nil)
|
|
check("MAROWAK is a real species", game.data.pokemon.MAROWAK ~= nil)
|
|
check("BattleState:makeUnveiledGhost exists",
|
|
type(BattleState.makeUnveiledGhost) == "function")
|
|
local unveil = game.data.text._UnveiledGhostText
|
|
check("_UnveiledGhostText extracted", type(unveil) == "string" and unveil ~= "")
|
|
if type(unveil) == "string" then
|
|
U.log("the unveil line reads:", (unveil:gsub("[\n\011\012]", " / ")))
|
|
end
|
|
check("_PokemonTower6FBeGoneText extracted",
|
|
type(game.data.text._PokemonTower6FBeGoneText) == "string")
|
|
-- the disguise pic resolves through the same override chain the battle uses
|
|
local Assets = require("src.render.Assets")
|
|
local GHOST_PIC = "assets/generated/battle/front/ghost.png"
|
|
check("the ghost front pic is in the cache",
|
|
Assets.exists(Assets.resolve(GHOST_PIC)))
|
|
|
|
local opts = game.save.options or {}
|
|
U.log("sfxVol", tostring(opts.sfxVol), "musicVol", tostring(opts.musicVol))
|
|
if opts.sfxVol == 0 or opts.musicVol == 0 then
|
|
U.log("a volume is at 0: raise it in OPTION before judging what you hear")
|
|
end
|
|
U.log("no intro cry here is CORRECT -- .isMarowak never reaches PlayCry.")
|
|
U.log("The CHANNELER at (12, 10) is the control: her GASTLY cries normally.")
|
|
|
|
-- ---- reach the trigger -------------------------------------------------
|
|
-- pokered scripts/PokemonTower6F.asm PokemonTower6FMarowakCoords:
|
|
-- dbmapcoord 10, 16. Row 17 is solid wall and (9, 16) is the stairwell
|
|
-- warp down to 5F, so the approach is from (10, 15) facing down.
|
|
local MAP = "POKEMON_TOWER_6F"
|
|
local TRIGGER = { x = 10, y = 16 }
|
|
local STAND = { x = 10, y = 15, facing = "down", step = "down" }
|
|
|
|
game.save.party = { Pokemon.new(game.data, "CHARIZARD", 50) }
|
|
game.save.player.name = "RED"
|
|
game.save.inventory.SILPH_SCOPE = 1
|
|
game.save.flags.EVENT_BEAT_GHOST_MAROWAK = nil
|
|
|
|
U.teleport(game, MAP, STAND.x, STAND.y, STAND.facing)
|
|
U.wait(10)
|
|
local ow = game.overworld
|
|
check("the overworld is up on " .. MAP, ow ~= nil and ow.map ~= nil)
|
|
|
|
if ow and ow.map and not ow.map:isWalkableCell(STAND.x, STAND.y) then
|
|
-- a map edit moved the approach: take any walkable neighbour of the
|
|
-- trigger that is not the stairwell warp, and step back toward it.
|
|
-- {dx, dy, facing} is the offset from the trigger to the stand cell plus
|
|
-- the direction that walks back onto it.
|
|
local sides = { { 0, -1, "down" }, { 1, 0, "left" },
|
|
{ -1, 0, "right" }, { 0, 1, "up" } }
|
|
for _, s in ipairs(sides) do
|
|
local cx, cy = TRIGGER.x + s[1], TRIGGER.y + s[2]
|
|
if ow.map:isWalkableCell(cx, cy) and not ow.map:warpAtCell(cx, cy) then
|
|
U.log(("(%d, %d) is blocked, approaching from"):format(STAND.x, STAND.y),
|
|
cx, cy, "stepping", s[3])
|
|
STAND = { x = cx, y = cy, facing = s[3], step = s[3] }
|
|
U.teleport(game, MAP, cx, cy, s[3])
|
|
U.wait(10)
|
|
ow = game.overworld
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
-- walk onto the trigger; MapScripts onStep fires on the completed step
|
|
U.hold(game, STAND.step, 20)
|
|
U.wait(20)
|
|
check("the Be-gone text opened", game.stack:top() ~= game.overworld)
|
|
|
|
-- ---- into the battle ---------------------------------------------------
|
|
local battle
|
|
for _ = 1, 300 do
|
|
local top = game.stack:top()
|
|
if getmetatable(top) == BattleState then battle = top break end
|
|
U.tap(game, "a")
|
|
U.wait(4)
|
|
end
|
|
check("the MAROWAK battle opened", battle ~= nil)
|
|
if not battle then
|
|
U.log(("machine checks: %d passed, %d failed"):format(pass, fail))
|
|
while true do coroutine.yield() end
|
|
end
|
|
|
|
battle.onFinish = battle.onFinish or function() end
|
|
check("the scope armed the unveil, not a plain wild battle",
|
|
battle.scopeReveal == true)
|
|
check("IsGhostBattle stays false with the scope in the bag", not battle.ghost)
|
|
check("the battle OPENED as the GHOST, not as MAROWAK (#492)",
|
|
battle.enemy and battle.enemy.name == "GHOST")
|
|
check("the real nick is held back for the unveil",
|
|
battle.ghostReal ~= nil and battle.ghostReal.name == "MAROWAK")
|
|
|
|
-- ---- watch the unveil --------------------------------------------------
|
|
-- A turns the "GHOST appeared!" and unveil boxes; stop pressing the moment
|
|
-- MarowakAnim arms so nothing mashes past "Wild MAROWAK appeared!".
|
|
for _ = 1, 600 do
|
|
if battle.ghostReveal then break end
|
|
U.tap(game, "a")
|
|
U.wait(4)
|
|
end
|
|
check("MarowakAnim started", battle.ghostReveal ~= nil)
|
|
|
|
local FLASH = BattleState.GHOST_FLASH_FRAMES
|
|
local FADE_OUT = BattleState.GHOST_FADE_OUT_FRAMES
|
|
local shotFlash, swapT, nameDuringFlash = false, nil, true
|
|
for _ = 1, 400 do
|
|
local gr = battle.ghostReveal
|
|
local t = gr and gr.t or nil
|
|
if t and t <= FLASH + FADE_OUT and battle.enemy.name ~= "GHOST" then
|
|
nameDuringFlash = false
|
|
end
|
|
if t and not swapT and battle.enemy.name ~= "GHOST" then swapT = t end
|
|
if t and t >= 25 and not shotFlash then
|
|
shotFlash = U.shot(game, DIR .. "/bug492_ghost_flashing.png")
|
|
end
|
|
if not gr and swapT then break end
|
|
U.wait(1)
|
|
end
|
|
|
|
check("the GHOST was still on screen through the flash and fade-out (#492)",
|
|
nameDuringFlash)
|
|
check(("the swap landed after the fade-out (frame %s of %d)")
|
|
:format(tostring(swapT), FLASH + FADE_OUT),
|
|
swapT ~= nil and swapT > FLASH + FADE_OUT)
|
|
check("the foe is MAROWAK once the animation finishes",
|
|
battle.enemy.name == "MAROWAK")
|
|
check("captured the flashing ghost", shotFlash)
|
|
|
|
-- the "Wild MAROWAK appeared!" box that closes .isMarowak
|
|
U.wait(30)
|
|
check("captured the unveiled MAROWAK",
|
|
U.shot(game, DIR .. "/bug492_marowak_revealed.png"))
|
|
U.log(("machine checks: %d passed, %d failed"):format(pass, fail))
|
|
|
|
-- ---- hand off ----------------------------------------------------------
|
|
U.log("The pad is yours in the battle the unveil just finished. What you")
|
|
U.log("should have seen: the box says the GHOST appeared, the SILPH SCOPE")
|
|
U.log("line follows, and only THEN does the ghost flash, dissolve and come")
|
|
U.log("back as MAROWAK before \"Wild MAROWAK appeared!\". The near miss to")
|
|
U.log("watch for is the sprite swapping early -- MAROWAK already standing")
|
|
U.log("there while the unveil text is still typing, which is #492 itself.")
|
|
U.log("To see it again: run from the battle (that steps you one cell right),")
|
|
U.log("walk back to (10, 15) and step down onto (10, 16). Beating it sets")
|
|
U.log("EVENT_BEAT_GHOST_MAROWAK and the trigger is spent for this save.")
|
|
U.log("Screenshots: " .. DIR .. "/bug492_*.png")
|
|
|
|
while true do
|
|
coroutine.yield()
|
|
end
|
|
end
|