mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-16 16:21:30 +02:00
Tick residuals after each move in Gen 1 mode
In pokered, MainInBattleLoop calls HandlePoisonBurnLeechSeed right after every Execute*Move (core.asm:426-464), so a seeded, poisoned or burned mon takes its residual before the slower side acts. The port ran the whole sweep in endOfTurn, which made leech seed behave like Gen 3+ and never showed the drain animation (#784). The residual sweep now runs per action under the gen1_faithful ruleset, gated by a new residualAfterMove flag; modern_clean keeps the end of round sweep. The leech seed drain plays the ABSORB animation from the healing side, the way the original flips hWhoseTurn before PlayMoveAnimation. Item, ball, failed run and ghost-fear turns still tick the player's residual, matching ExecutePlayerMoveDone.
This commit is contained in:
@@ -1889,6 +1889,9 @@ function BattleState:update(dt)
|
||||
self:act(function()
|
||||
self:executeAction(self.enemy, self.player, self:enemyAction())
|
||||
end)
|
||||
-- the scared turn still ticks the player's residual (PrintGhostText
|
||||
-- -> ExecutePlayerMoveDone, core.asm:3056, 3275-3279)
|
||||
self:queueResidual(self.player, self.enemy)
|
||||
self:act(function() self:endOfTurn() end)
|
||||
elseif choice == "fight" then
|
||||
-- After the menu: own trapping/Bide or foe Wrap skips the move
|
||||
@@ -2358,6 +2361,48 @@ function BattleState:resolveSwitch(newMon)
|
||||
self:act(function() self:endOfTurn() end)
|
||||
end
|
||||
|
||||
-- Gen 1 calls HandlePoisonBurnLeechSeed right after the acting side's
|
||||
-- move (core.asm:426-464), so the drain lands before the slower mon acts;
|
||||
-- the modern ruleset sweeps residuals at end of round instead (Gen 3+).
|
||||
local function residualAfterMove(battle)
|
||||
local ruleset = battle.ruleset
|
||||
return not ruleset or ruleset.residualAfterMove ~= false
|
||||
end
|
||||
|
||||
-- HandlePoisonBurnLeechSeed for one side, run right after its action.
|
||||
-- Skipped when the action settled the battle (a Teleport escape rets
|
||||
-- before the call), when an AI switch swapped the side out mid-action, or
|
||||
-- when the move already knocked the opponent out (core.asm:423-425,
|
||||
-- 452-454) -- the same bypass the end-of-round sweep applies.
|
||||
function BattleState:residualFor(b, opp)
|
||||
if self.result then return end
|
||||
if self.player ~= b and self.enemy ~= b then return end
|
||||
if b.mon.hp <= 0 or opp.mon.hp <= 0 then return end
|
||||
local msgs = Status.residual(b, opp, self)
|
||||
for _, m in ipairs(msgs) do self:sayNext(prefixEnemy(m, b)) end
|
||||
if b.leechSeeded and b.mon.hp > 0 then
|
||||
-- the drain plays the ABSORB animation from the healing side
|
||||
-- (core.asm:506-517 flips hWhoseTurn before PlayMoveAnimation)
|
||||
self:animNext("ABSORB", opp.isPlayer)
|
||||
end
|
||||
if #msgs > 0 then self:drainNext() end -- poison/burn/seed HP moved
|
||||
self.sideToxic = self.sideToxic or {}
|
||||
if b.toxicCounter then
|
||||
self.sideToxic[b.isPlayer and "player" or "enemy"] = b.toxicCounter
|
||||
end
|
||||
if b.mon.hp <= 0 then
|
||||
self:onFaint(b)
|
||||
end
|
||||
end
|
||||
|
||||
-- append one side's residual to the queue under Gen 1 timing; a no-op
|
||||
-- under the modern ruleset, whose sweep runs in endOfTurn instead
|
||||
function BattleState:queueResidual(b, opp)
|
||||
if residualAfterMove(self) then
|
||||
self:act(function() self:residualFor(b, opp) end)
|
||||
end
|
||||
end
|
||||
|
||||
function BattleState:endOfTurn()
|
||||
-- the same ret: a decided battle never reaches HandlePoisonBurnLeechSeed
|
||||
-- or CheckNumAttacksLeft (core.asm:417-421, 456-460), so the residual
|
||||
@@ -2377,6 +2422,9 @@ function BattleState:endOfTurn()
|
||||
-- that sets the flag also zeroes the counter, so a stale value is
|
||||
-- unobservable (a switch or cure downgrades Toxic to plain poison).
|
||||
self.sideToxic = self.sideToxic or {}
|
||||
-- Gen 1 timing already ran each side's residual right after its move
|
||||
-- (see executeAction); the end-of-round sweep is the modern ruleset's
|
||||
local sweep = not residualAfterMove(self)
|
||||
-- a battler whose opponent was already knocked out by a move this turn
|
||||
-- skips its own residual (HandlePoisonBurnLeechSeed is bypassed when the
|
||||
-- move faints the target); snapshot before residual so one side's
|
||||
@@ -2386,7 +2434,7 @@ function BattleState:endOfTurn()
|
||||
for _, pair in ipairs({ { self.player, self.enemy, "player", enemyAlive },
|
||||
{ self.enemy, self.player, "enemy", playerAlive } }) do
|
||||
local b, opp, side, oppAlive = pair[1], pair[2], pair[3], pair[4]
|
||||
if b.mon.hp > 0 and oppAlive then
|
||||
if sweep and b.mon.hp > 0 and oppAlive then
|
||||
local msgs = Status.residual(b, opp, self)
|
||||
for _, m in ipairs(msgs) do self:sayNext(prefixEnemy(m, b)) end
|
||||
if #msgs > 0 then self:drainNext() end -- poison/burn/seed HP moved
|
||||
@@ -2397,6 +2445,9 @@ function BattleState:endOfTurn()
|
||||
self:onFaint(b)
|
||||
end
|
||||
end
|
||||
-- the Haze move-forfeit only covers the turn Haze was used; if the
|
||||
-- cured mon had already moved, drop the flag before next turn
|
||||
b.skipMove = nil
|
||||
-- CheckNumAttacksLeft (core.asm:683-697): a trapping counter that
|
||||
-- hit 0 this turn releases its bit only now, at the end of the turn
|
||||
if b.trappingTurns and b.trappingTurns <= 0 then
|
||||
@@ -3181,6 +3232,12 @@ function BattleState:executeAction(user, target, action)
|
||||
run()
|
||||
-- after announce/anim/effect text (pokered DrawHUDsAndHPBars)
|
||||
self:actNext(function() self:syncShownStatus() end)
|
||||
-- MainInBattleLoop calls HandlePoisonBurnLeechSeed right after each
|
||||
-- Execute*Move (core.asm:426-464): the acting side's poison/burn/leech
|
||||
-- seed ticks before the slower mon acts, not at end of round
|
||||
if residualAfterMove(self) then
|
||||
self:actNext(function() self:residualFor(user, target) end)
|
||||
end
|
||||
end
|
||||
|
||||
-- Sleep / confusion onomatopoeia from Check*StatusConditions
|
||||
@@ -4245,6 +4302,9 @@ function BattleState:tryRun()
|
||||
self:act(function()
|
||||
self:executeAction(self.enemy, self.player, self:enemyAction())
|
||||
end)
|
||||
-- a failed escape loses the turn (core.asm:1572): the player's
|
||||
-- residual still ticks, same as an item turn
|
||||
self:queueResidual(self.player, self.enemy)
|
||||
self:act(function() self:endOfTurn() end)
|
||||
end
|
||||
end
|
||||
@@ -4267,6 +4327,11 @@ function BattleState:itemUsed(messages)
|
||||
self:act(function()
|
||||
self:executeAction(self.enemy, self.player, self:enemyAction())
|
||||
end)
|
||||
-- the item spends the player's move, but its residual still ticks:
|
||||
-- ExecutePlayerMove rets early on wActionResultOrTookBattleTurn and
|
||||
-- MainInBattleLoop calls HandlePoisonBurnLeechSeed anyway
|
||||
-- (core.asm:3086-3088, 3275-3279)
|
||||
self:queueResidual(self.player, self.enemy)
|
||||
self:act(function() self:endOfTurn() end)
|
||||
end
|
||||
|
||||
@@ -4448,6 +4513,9 @@ function BattleState:throwBall(ball)
|
||||
self:act(function()
|
||||
self:executeAction(self.enemy, self.player, self:enemyAction())
|
||||
end)
|
||||
-- a thrown ball spends the turn like an item: the player's residual
|
||||
-- still ticks (core.asm:3275-3279)
|
||||
self:queueResidual(self.player, self.enemy)
|
||||
self:act(function() self:endOfTurn() end)
|
||||
return
|
||||
end
|
||||
@@ -4466,6 +4534,9 @@ function BattleState:throwBall(ball)
|
||||
self:act(function()
|
||||
self:executeAction(self.enemy, self.player, self:enemyAction())
|
||||
end)
|
||||
-- a thrown ball spends the turn like an item: the player's residual
|
||||
-- still ticks (core.asm:3275-3279)
|
||||
self:queueResidual(self.player, self.enemy)
|
||||
self:act(function() self:endOfTurn() end)
|
||||
return
|
||||
end
|
||||
@@ -4492,6 +4563,9 @@ function BattleState:throwBall(ball)
|
||||
self:act(function()
|
||||
self:executeAction(self.enemy, self.player, self:enemyAction())
|
||||
end)
|
||||
-- a thrown ball spends the turn like an item: the player's residual
|
||||
-- still ticks (core.asm:3275-3279)
|
||||
self:queueResidual(self.player, self.enemy)
|
||||
self:act(function() self:endOfTurn() end)
|
||||
end
|
||||
end)
|
||||
|
||||
Reference in New Issue
Block a user