mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-17 19:24:01 +02:00
143 lines
5.2 KiB
Lua
143 lines
5.2 KiB
Lua
-- Driver: the shiny sparkle on a SENT OUT mon (#1431).
|
|
--
|
|
-- POKEPORT_GAME=gold POKEPORT_TOUCH=0 \
|
|
-- POKEPORT_DRIVER=tests/drivers/gold_bug1431_test.lua love .
|
|
-- POKEPORT_SHOT_DIR=/tmp/gold-bug1431 (default)
|
|
--
|
|
-- SendOutPlayerMon calls BattleCheckPlayerShininess and replays
|
|
-- ANIM_SEND_OUT_MON with wBattleAnimParam 1 -- the script's `.Shiny` arm --
|
|
-- between the plain animation and the cry (engine/battle/core.asm:3820-3837);
|
|
-- ShowSetEnemyMonAndSendOutAnimation does the same for every enemy send-out
|
|
-- (:3364-3383). Only the wild-intro path (BattleStartMessage, :8701-8715) had
|
|
-- been ported, so a shiny lead-off, a shiny switch-in and a shiny enemy
|
|
-- replacement all came out silent.
|
|
--
|
|
-- Three send-outs to watch, none of them the wild intro: the player's lead-off,
|
|
-- the player's own switch, and the opponent's replacement after a faint.
|
|
local U = require("tests.drivers.util")
|
|
|
|
local Mon = require("src.battle.gen2.Mon")
|
|
local GbcPalette = require("src.render.GbcPalette")
|
|
|
|
-- constants/battle_constants.asm: the DV pair BATTLETYPE_FORCESHINY forces.
|
|
local SHINY_DVS = { attack = 14, defense = 10, speed = 10, special = 10 }
|
|
|
|
local OUT = os.getenv("POKEPORT_SHOT_DIR") or "/tmp/gold-bug1431"
|
|
|
|
local function tap(game, button, frames)
|
|
game.input.pressQueue[#game.input.pressQueue + 1] = button
|
|
game.input.state[button] = true
|
|
U.wait(2)
|
|
game.input.state[button] = false
|
|
U.wait(frames or 6)
|
|
end
|
|
|
|
local function openBattle(game, opts)
|
|
assert(game.world:startBattle(opts), "startBattle failed")
|
|
for _ = 1, 900 do
|
|
local top = game.stack:top()
|
|
if top and top.battle then return top end
|
|
U.wait(1)
|
|
end
|
|
error("battle screen never came up")
|
|
end
|
|
|
|
-- Stop on the frame the `.Shiny` arm is actually running: animId plus the
|
|
-- wBattleAnimParam the arm branches on (data/moves/animations.asm:414-417).
|
|
local function shinyArm(screen)
|
|
local anim = screen.anim
|
|
return anim ~= nil and anim.animId == "ANIM_SEND_OUT_MON"
|
|
and anim.param == 1
|
|
end
|
|
|
|
local function watch(game, screen, label, frames)
|
|
for _ = 1, (frames or 400) do
|
|
if shinyArm(screen) then
|
|
U.log("[driver] " .. label .. ": .Shiny arm running")
|
|
U.shot(game, ("%s/%s.png"):format(OUT, label))
|
|
return true
|
|
end
|
|
U.wait(1)
|
|
end
|
|
U.log("[driver] " .. label .. ": NO shiny arm seen")
|
|
return false
|
|
end
|
|
|
|
return function(game)
|
|
U.wait(45)
|
|
assert(game.world and game.world.map, "gold world did not boot")
|
|
|
|
-- A shiny only reads as one in colour, and the sparkle rides the same anim.
|
|
GbcPalette.setMode("gbc")
|
|
|
|
local save = game.save
|
|
save.inventory = {}
|
|
local lead = Mon.new(game.data, "CYNDAQUIL", 40, { dvs = SHINY_DVS })
|
|
local bench = Mon.new(game.data, "TOTODILE", 40, { dvs = SHINY_DVS })
|
|
assert(lead.shiny and bench.shiny, "the FORCESHINY DVs did not take")
|
|
local move = assert(game.data.moves.EMBER, "no EMBER in moves.lua")
|
|
lead.moves = { { id = "EMBER", pp = move.pp, maxPp = move.pp } }
|
|
save.party = { lead, bench }
|
|
|
|
local entry = game.world:trainerParty(36, 1) -- BUG_CATCHER member 1
|
|
assert(entry, "no BUG_CATCHER member 1 in trainers.lua")
|
|
local Trainers = require("src.world.gen2.Trainers")
|
|
entry.party = Trainers.party(game.data, entry)
|
|
for _, mon in ipairs(entry.party) do mon.shiny = true end
|
|
local screen = openBattle(game, { trainer = entry })
|
|
|
|
------------------------------------------------------------ enemy lead
|
|
-- ShowSetEnemyMonAndSendOutAnimation, out of the opening sequence.
|
|
watch(game, screen, "00-enemy-sendout", 900)
|
|
|
|
----------------------------------------------------------- player lead
|
|
-- SendOutPlayerMon behind the "Go!" line: this is the one the report is
|
|
-- about, and it never sparkled before the fix.
|
|
local sawPlayer = watch(game, screen, "01-player-sendout", 900)
|
|
|
|
for _ = 1, 600 do
|
|
if screen.phase == "menu" then break end
|
|
tap(game, "a", 2)
|
|
end
|
|
|
|
---------------------------------------------------------- player switch
|
|
-- The same routine again, this time as a voluntary mid-battle switch.
|
|
local sawSwitch = false
|
|
if screen.phase == "menu" and (screen.battle.party or {})[2] then
|
|
screen:submit({ kind = "switch", index = 2 })
|
|
sawSwitch = watch(game, screen, "02-player-switch", 900)
|
|
for _ = 1, 600 do
|
|
if screen.phase == "menu" or screen.battle.over then break end
|
|
tap(game, "a", 2)
|
|
end
|
|
end
|
|
|
|
------------------------------------------------------ enemy replacement
|
|
local sawReplace = false
|
|
if #(screen.battle.enemyParty or {}) > 1 then
|
|
for _ = 1, 600 do
|
|
if screen.battle.over then break end
|
|
if screen.phase == "menu" then
|
|
local enemy = screen.battle.enemy
|
|
if enemy then enemy.hp = 1 end
|
|
screen:chooseMenu("fight")
|
|
U.wait(2)
|
|
screen:chooseMove(1)
|
|
break
|
|
end
|
|
tap(game, "a", 2)
|
|
end
|
|
sawReplace = watch(game, screen, "03-enemy-replacement", 900)
|
|
end
|
|
|
|
U.log(("[driver] player lead-off %s, player switch %s, enemy replacement %s")
|
|
:format(tostring(sawPlayer), tostring(sawSwitch), tostring(sawReplace)))
|
|
U.log("[driver] shots in " .. OUT)
|
|
U.log("[driver] every send-out of a shiny must flash, sparkle and chime")
|
|
U.log("[driver] BEFORE its cry, not only the wild mon at battle start.")
|
|
|
|
while true do
|
|
coroutine.yield()
|
|
end
|
|
end
|