mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-12 00:10:56 +02:00
fix: enemy mon appears before its send-out animation
The trainer intro was the only enemy send-out path that never set enemySendingOut, so the front sprite drew at full size the moment the trainer pic walked off, held through "X sent out Y!", and the grow-in then played over a mon that had already arrived. Set it with the pic teardown and clear it with startGrowIn, matching the mid-battle replacement and the player's own send-out. Also repairs two parity suites that could not load at all: their game stubs lacked input.isDown, which battle text has read every frame since typing started honouring PrintLetterDelay. intro_chrome additionally pressed A inside PromptText's ProtectedDelay3 hold, which ignores the button for TEXT_PRE_ADVANCE frames.
This commit is contained in:
@@ -1476,12 +1476,21 @@ function BattleState:enter()
|
||||
table.insert(self.queue, { wait = 16 })
|
||||
self:act(function()
|
||||
self.showEnemyTrainer = false
|
||||
-- the slot is EMPTY from here until AnimateSendingOutMon runs below:
|
||||
-- the pic has walked off and the mon is still in its ball, so nothing
|
||||
-- stands in the enemy slot while TrainerSentOutText prints. Without
|
||||
-- this the front sprite popped in full-size the instant the trainer
|
||||
-- left, sat there through the whole text box, and the grow-in then
|
||||
-- restarted it from nothing -- the mon appearing before it was sent
|
||||
-- out. Mirrors the flag the mid-battle replacement already sets.
|
||||
self.enemySendingOut = true
|
||||
self:slidePic("foe")
|
||||
end)
|
||||
self:say(Strings("%s sent\nout %s!", self.trainer.name, self.enemy.name))
|
||||
self:act(function()
|
||||
-- EnemySendOutFirstMon (core.asm:1421-1434): after the text the
|
||||
-- pic grows out of the ball (AnimateSendingOutMon), then the cry
|
||||
self.enemySendingOut = false
|
||||
self:startGrowIn(self.enemy)
|
||||
end)
|
||||
queueEnemyCry()
|
||||
|
||||
@@ -19,6 +19,7 @@ local Pokemon = require("src.pokemon.Pokemon")
|
||||
local SaveData = require("src.core.SaveData")
|
||||
local Sound = require("src.core.Sound")
|
||||
local Music = require("src.core.Music")
|
||||
local Timing = require("src.core.Timing")
|
||||
|
||||
-- Silence audio: BattleState reaches both modules through require() at the
|
||||
-- call site, so patching the fields here is what the battle ends up calling.
|
||||
@@ -40,8 +41,11 @@ local function makeGame(party)
|
||||
function stack:push(state) self.states[#self.states + 1] = state end
|
||||
function stack:pop() return table.remove(self.states) end
|
||||
function stack:top() return self.states[#self.states] end
|
||||
-- isDown as well as wasPressed: battle text collapses PrintLetterDelay
|
||||
-- while A or B is held, and the typing path reads it every frame
|
||||
return { data = Data, save = save, stack = stack,
|
||||
input = { wasPressed = function(_, b) return press[b] == true end } }
|
||||
input = { wasPressed = function(_, b) return press[b] == true end,
|
||||
isDown = function(_, b) return press[b] == true end } }
|
||||
end
|
||||
|
||||
-- One fixed step with A held. updateQueue only reads the button once a page
|
||||
@@ -128,6 +132,12 @@ end
|
||||
check(prompted, "a typed-out intro page raises the prompt flag (blinking arrow)")
|
||||
eq(wild.introBalls, true, "the ball row is still up while the arrow blinks")
|
||||
|
||||
-- PromptText writes the arrow and then runs ProtectedDelay3 before
|
||||
-- ManualTextScroll starts watching the joypad (home/text.asm:213-217), so the
|
||||
-- page ignores the button for TEXT_PRE_ADVANCE frames. The loop above breaks
|
||||
-- on the frame the arrow goes up, which is inside that hold.
|
||||
for _ = 1, Timing.TEXT_PRE_ADVANCE do press.a = false wild:update(1 / 60) end
|
||||
|
||||
-- press A: ClearSprites + both ClearScreenAreas, then the enemy HUD
|
||||
step(wild)
|
||||
eq(wild.msgPrompt, nil, "the prompt flag clears on the A press")
|
||||
@@ -196,6 +206,26 @@ check(foeDone ~= nil and sentFrame ~= nil and foeDone < sentFrame,
|
||||
"the slide finishes BEFORE TrainerSentOutText (core.asm:1308-1310)")
|
||||
eq(tr.showEnemyTrainer, false, "only then is the trainer pic taken down")
|
||||
|
||||
-- ...and the mon is not standing in that slot yet. The pic walks off at
|
||||
-- core.asm:1308-1310 but AnimateSendingOutMon does not run until :1421-1434,
|
||||
-- so the slot is empty for the whole of TrainerSentOutText -- the mon is
|
||||
-- still in its ball. It used to pop in full-size the instant the trainer
|
||||
-- left and sit there through the text, so the grow-in played over a mon that
|
||||
-- had already arrived; the mid-battle replacement always held it back.
|
||||
check(tr.enemySendingOut, "the foe's mon stays in its ball while announced")
|
||||
eq(tr:growInScale(tr.enemy), nil, "and nothing is growing into the slot yet")
|
||||
|
||||
local firstGrowScale
|
||||
for _ = 1, 400 do
|
||||
step(tr)
|
||||
if tr.growIn and tr.growIn.battler == tr.enemy then
|
||||
firstGrowScale = tr:growInScale(tr.enemy)
|
||||
break
|
||||
end
|
||||
end
|
||||
eq(firstGrowScale, 0, "the send-out opens on the ball beat, not a finished pic")
|
||||
eq(tr.enemySendingOut, false, "which is when the slot is handed over")
|
||||
|
||||
-- and the window never reopens: drive the rest of the intro out
|
||||
for _ = 1, 400 do
|
||||
step(tr)
|
||||
|
||||
@@ -36,8 +36,11 @@ local function makeGame(party)
|
||||
function stack:push(state) self.states[#self.states + 1] = state end
|
||||
function stack:pop() return table.remove(self.states) end
|
||||
function stack:top() return self.states[#self.states] end
|
||||
-- isDown as well as wasPressed: battle text collapses PrintLetterDelay
|
||||
-- while A or B is held, and the typing path reads it every frame
|
||||
return { data = Data, save = save, stack = stack,
|
||||
input = { wasPressed = function(_, b) return press[b] == true end } }
|
||||
input = { wasPressed = function(_, b) return press[b] == true end,
|
||||
isDown = function(_, b) return press[b] == true end } }
|
||||
end
|
||||
|
||||
-- A held: updateQueue only reads the button once a page is typed out, so an
|
||||
|
||||
Reference in New Issue
Block a user