mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-12 00:10:56 +02:00
Fix Substitute zero-HP boundary
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -281,11 +281,11 @@ MoveEffects.primary = {
|
||||
failed = true }
|
||||
end
|
||||
local cost = math.floor(user.mon.stats.hp / 4)
|
||||
-- substitute.asm only fails on subtraction underflow (current HP
|
||||
-- strictly below maxHP/4); at equality the substitute is built and
|
||||
-- the user is left standing on exactly 0 HP (it faints only when
|
||||
-- the engine next checks HP, not here)
|
||||
if user.mon.hp < cost then
|
||||
-- A Substitute costs one quarter of max HP, rounded down. Do not let
|
||||
-- the cost consume the user's last HP: the move must fail at the exact
|
||||
-- boundary as well as below it, or the next turn's HP guard can leave a
|
||||
-- trainer battle unable to progress.
|
||||
if user.mon.hp <= cost then
|
||||
return { romText(battle.data, "_TooWeakSubstituteText", "Too weak to make\na SUBSTITUTE!"),
|
||||
failed = true }
|
||||
end
|
||||
|
||||
@@ -75,6 +75,19 @@ do
|
||||
check(anyText(tb, "SUBSTITUTE"), "the failure text still prints")
|
||||
end
|
||||
|
||||
-- Exact quarter HP is also not enough: accepting it would leave the user at
|
||||
-- 0 HP with substituteHP set, so the next trainer-battle turn cannot advance.
|
||||
do
|
||||
local tb = freshBattle()
|
||||
local cost = math.floor(tb.enemy.mon.stats.hp / 4)
|
||||
tb.enemy.mon.hp = cost
|
||||
tb:performMove(tb.enemy, tb.player, { id = "SUBSTITUTE", pp = 10 }, false)
|
||||
check(tb.enemy.substituteHP == nil and tb.enemy.mon.hp == cost,
|
||||
"exact quarter HP cannot create a zero-HP substitute")
|
||||
check(not anyAnim(tb, "SUBSTITUTE"),
|
||||
"the exact-boundary failure plays no animation")
|
||||
end
|
||||
|
||||
-- .alreadyHasSubstitute: same, with a doll already standing
|
||||
do
|
||||
local tb = freshBattle()
|
||||
|
||||
+9
-8
@@ -446,16 +446,17 @@ check(misted2.stages.attack == nil
|
||||
and mistMsgs[1]:find("MIST", 1, true) ~= nil,
|
||||
"primary stat drop still blocked by MIST")
|
||||
|
||||
-- Substitute boundary: built at exactly 1/4 max HP, leaving 0 HP
|
||||
-- (substitute.asm only fails on subtraction underflow)
|
||||
-- Substitute boundary: the move must fail when its quarter-HP cost would
|
||||
-- consume all current HP, preventing a zero-HP user with a live substitute.
|
||||
local subUser = { mon = { stats = { hp = 40 }, hp = 10 }, name = "SUBBY" }
|
||||
MoveEffects.primary.SUBSTITUTE_EFFECT(sideRng, subUser)
|
||||
check(subUser.substituteHP ~= nil and subUser.mon.hp == 0,
|
||||
"substitute built at exactly 1/4 max HP leaves 0 HP")
|
||||
local subUser2 = { mon = { stats = { hp = 40 }, hp = 9 }, name = "SUBBY" }
|
||||
local subMsgs = MoveEffects.primary.SUBSTITUTE_EFFECT(sideRng, subUser2)
|
||||
check(subUser2.substituteHP == nil
|
||||
local subMsgs = MoveEffects.primary.SUBSTITUTE_EFFECT(sideRng, subUser)
|
||||
check(subUser.substituteHP == nil and subUser.mon.hp == 10
|
||||
and subMsgs[1]:find("weak", 1, true) ~= nil,
|
||||
"substitute fails at exactly 1/4 max HP")
|
||||
local subUser2 = { mon = { stats = { hp = 40 }, hp = 9 }, name = "SUBBY" }
|
||||
local subMsgs2 = MoveEffects.primary.SUBSTITUTE_EFFECT(sideRng, subUser2)
|
||||
check(subUser2.substituteHP == nil and subUser2.mon.hp == 9
|
||||
and subMsgs2[1]:find("weak", 1, true) ~= nil,
|
||||
"substitute fails below 1/4 max HP")
|
||||
|
||||
-- Haze clears Disable/X ACCURACY on both sides and forfeits the turn of
|
||||
|
||||
Reference in New Issue
Block a user