Fix faint slide starting partway down (#671)

The faint slide was shortened from 30 to Timing.FAINT_SLIDE (14) frames
in the timing-parity pass, but fxFaintOffset still computed the offset
with a stale (30 - frames) * 2.  With frames starting at 14 the sprite
teleported 32px down on the first frame and only slid the remaining
28px, cutting the animation short.

SlideDownFaintedMonPic drops the pic one 8px row per 2-frame step, so
the offset advances Timing.FAINT_SLIDE_STEP (4px) per frame at 1x and
covers the full 56px PIC_HEIGHT over the 14-frame budget.
This commit is contained in:
Shane McGovern
2026-08-02 16:34:02 +01:00
parent 0f45bb5792
commit 733450bf86
3 changed files with 26 additions and 1 deletions
+5 -1
View File
@@ -4542,11 +4542,15 @@ end
-- pixels, so it scales with the pic's draw scale (the player's default 2x -- pixels, so it scales with the pic's draw scale (the player's default 2x
-- sinks 2x as fast to sink at the same visual rate); a mod scale composes -- sinks 2x as fast to sink at the same visual rate); a mod scale composes
-- the same way. scale defaults to the vanilla side scale when unknown. -- the same way. scale defaults to the vanilla side scale when unknown.
-- SlideDownFaintedMonPic drops the pic one 8px row per 2-frame step, so
-- the offset advances Timing.FAINT_SLIDE_STEP (4px) per frame at 1x --
-- the full 56px PIC_HEIGHT slide over the 14-frame budget (#671: the
-- old (30 - frames) math teleported the sprite 32px down on frame one).
function BattleState:fxFaintOffset(battler, scale) function BattleState:fxFaintOffset(battler, scale)
local fx = self.fx local fx = self.fx
if self:fxFaintActive(battler) then if self:fxFaintActive(battler) then
scale = scale or (battler.isPlayer and 2 or 1) scale = scale or (battler.isPlayer and 2 or 1)
return (30 - fx.faint.frames) * 2 * scale return (Timing.FAINT_SLIDE - fx.faint.frames) * Timing.FAINT_SLIDE_STEP * scale
end end
return 0 return 0
end end
+1
View File
@@ -129,6 +129,7 @@ Timing.NO_MOVES_LEFT = 60 -- core.asm:2753-2754
Timing.TRAINER_VICTORY = 40 -- core.asm:940-941 Timing.TRAINER_VICTORY = 40 -- core.asm:940-941
Timing.PLAYER_BLACKOUT = 40 -- core.asm:1143-1144 Timing.PLAYER_BLACKOUT = 40 -- core.asm:1143-1144
Timing.FAINT_SLIDE_ROW = 2 -- core.asm:1216-1217, per row Timing.FAINT_SLIDE_ROW = 2 -- core.asm:1216-1217, per row
Timing.FAINT_SLIDE_STEP = 8 / Timing.FAINT_SLIDE_ROW -- 4px per frame at 1x
Timing.TRAINER_SLIDE_COL = 2 -- core.asm:1267-1268, per column Timing.TRAINER_SLIDE_COL = 2 -- core.asm:1267-1268, per column
-- HP bar (engine/gfx/hp_bar.asm) --------------------------------------------- -- HP bar (engine/gfx/hp_bar.asm) ---------------------------------------------
+20
View File
@@ -273,6 +273,26 @@ T.eq(Timing.BLINK_MON % 10, 0,
-- SlideDownFaintedMonPic: b = PIC_HEIGHT slide steps of DelayFrames 2 -- SlideDownFaintedMonPic: b = PIC_HEIGHT slide steps of DelayFrames 2
T.eq(Timing.FAINT_SLIDE, 14, "the faint slide is 7 steps x 2 frames") T.eq(Timing.FAINT_SLIDE, 14, "the faint slide is 7 steps x 2 frames")
-- #671: the slide must start at the sprite's resting spot and sink the
-- full PIC_HEIGHT (7 rows x 8px = 56px at 1x) across those 14 frames.
-- The old (30 - frames) * 2 math teleported the pic 32px down on frame
-- one once the budget was shortened from 30 to 14 frames.
local faintBattle = newBattle()
faintBattle.fx = { faint = { battler = faintBattle.enemy,
frames = Timing.FAINT_SLIDE } }
T.eq(faintBattle:fxFaintOffset(faintBattle.enemy, 1), 0,
"the faint slide starts at offset 0 (#671)")
faintBattle.fx.faint.frames = Timing.FAINT_SLIDE - 7
T.eq(faintBattle:fxFaintOffset(faintBattle.enemy, 1),
7 * Timing.FAINT_SLIDE_STEP,
"the slide sinks one 8px row per step")
faintBattle.fx.faint.frames = 1
T.eq(faintBattle:fxFaintOffset(faintBattle.enemy, 1),
(Timing.FAINT_SLIDE - 1) * Timing.FAINT_SLIDE_STEP,
"the slide reaches 52px by the last visible frame")
T.eq(Timing.FAINT_SLIDE * Timing.FAINT_SLIDE_STEP, 56,
"and covers the full 7-row pic height over the whole budget")
T.eq(Timing.MOVE_STATUS_OR_MISS, 30, T.eq(Timing.MOVE_STATUS_OR_MISS, 30,
"a status move or a miss holds DelayFrames 30 before its text") "a status move or a miss holds DelayFrames 30 before its text")