mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-20 12:40:21 +02:00
Clear drainHold once the HP-bar drain actually finishes
stepHPDrain counts drainHold down to 0 as the last step of every phase (pixel slide, HP-number step, closing frames) but never let go of the field afterward, so it sat at 0 -- not nil -- for the rest of the battle. BattleSafety.inspect uses drainHold ~= nil as its settled-presentation gate for checkpoint capture, so the very first HP change in a battle permanently refused every checkpoint after it with battle_phase_busy, even once the bar had long since caught up. Only nil the field when the whole drain is actually over (bar pixel, HP number and the closing-frame hold all settled), not on every mid-sequence 0 -- a fresh HP change still needs drainHold to read as busy so BattleSafety keeps refusing captures until that one settles too.
This commit is contained in:
@@ -1103,6 +1103,15 @@ function BattleState:stepHPDrain()
|
|||||||
if not b.shownPx then b.shownPx = targetPx end
|
if not b.shownPx then b.shownPx = targetPx end
|
||||||
if (b.drainHold or 0) > 0 then
|
if (b.drainHold or 0) > 0 then
|
||||||
b.drainHold = b.drainHold - 1
|
b.drainHold = b.drainHold - 1
|
||||||
|
-- Once the count runs out with nothing left pending (bar and
|
||||||
|
-- number already on the final total), the drain is over, not just
|
||||||
|
-- between steps: leave the field at 0 and BattleSafety.inspect
|
||||||
|
-- reads it as still mid-animation for the rest of the battle,
|
||||||
|
-- since drainHold ~= nil is its settled-presentation gate.
|
||||||
|
if b.drainHold <= 0 and b.shownPx == targetPx and b.shownHP == goal
|
||||||
|
and not b.draining then
|
||||||
|
b.drainHold = nil
|
||||||
|
end
|
||||||
busy = true
|
busy = true
|
||||||
elseif b.shownPx ~= targetPx then
|
elseif b.shownPx ~= targetPx then
|
||||||
-- .barAnimationLoop redraws the bar one pixel at a time, `ld c, 2 /
|
-- .barAnimationLoop redraws the bar one pixel at a time, `ld c, 2 /
|
||||||
|
|||||||
@@ -131,4 +131,25 @@ T.same(Checkpoint.inspect(game), {
|
|||||||
canCapture = true, canRestore = true, kind = "overworld",
|
canCapture = true, canRestore = true, kind = "overworld",
|
||||||
}, "settled overworld remains supported")
|
}, "settled overworld remains supported")
|
||||||
|
|
||||||
|
-- drainHold gates capture (see the refused() case above) exactly because it
|
||||||
|
-- marks an HP bar mid-animation. Once stepHPDrain settles the bar it must
|
||||||
|
-- let go of that gate too, or the very first drain of a battle leaves the
|
||||||
|
-- checkpoint contract refused for everything after it.
|
||||||
|
do
|
||||||
|
local game3, _, battle3 = makeGame()
|
||||||
|
battle3.enemy.mon.hp = battle3.enemy.mon.hp - 5
|
||||||
|
local frames = 0
|
||||||
|
while battle3:stepHPDrain() and frames < 10000 do
|
||||||
|
frames = frames + 1
|
||||||
|
end
|
||||||
|
T.eq(battle3.enemy.shownHP, battle3.enemy.mon.hp,
|
||||||
|
"the HP bar settles on the new total")
|
||||||
|
T.eq(battle3.enemy.drainHold, nil,
|
||||||
|
"drainHold releases the checkpoint gate once the bar finishes draining")
|
||||||
|
local capability = Checkpoint.inspect(game3)
|
||||||
|
T.check(capability.canCapture == true,
|
||||||
|
"a checkpoint is capturable again after the drain settles: "
|
||||||
|
.. tostring(capability.reason))
|
||||||
|
end
|
||||||
|
|
||||||
T.finish()
|
T.finish()
|
||||||
|
|||||||
Reference in New Issue
Block a user