Fixes Berserk Gene infinite loop (#6813)

This commit is contained in:
Alex 2025-05-11 11:34:16 +02:00 committed by GitHub
parent f4f82f2394
commit 0ad3f929ab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 52 additions and 43 deletions

View File

@ -10041,15 +10041,16 @@ BattleScript_CouldntFullyProtect::
return
BattleScript_BerserkGeneRet::
saveattacker
savetarget
copybyte gBattlerTarget, sBATTLER
statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_BerserkGeneRet_TryConfuse
setgraphicalstatchangevalues
playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, sB_ANIM_ARG1
playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, sB_ANIM_ARG1
setbyte cMULTISTRING_CHOOSER, B_MSG_STAT_ROSE_ITEM
call BattleScript_StatUp
BattleScript_BerserkGeneRet_TryConfuse:
jumpifability BS_SCRIPTING, ABILITY_OWN_TEMPO, BattleScript_BerserkGeneRet_OwnTempoPrevents
jumpifability BS_ATTACKER, ABILITY_OWN_TEMPO, BattleScript_BerserkGeneRet_OwnTempoPrevents
jumpifsafeguard BattleScript_BerserkGeneRet_SafeguardProtected
seteffectprimary MOVE_EFFECT_CONFUSION
goto BattleScript_BerserkGeneRet_End
@ -10064,9 +10065,14 @@ BattleScript_BerserkGeneRet_OwnTempoPrevents:
printstring STRINGID_PKMNPREVENTSCONFUSIONWITH
waitmessage B_WAIT_TIME_LONG
BattleScript_BerserkGeneRet_End:
restoreattacker
restoretarget
removeitem BS_SCRIPTING
end3
removeitem BS_ATTACKER
return
BattleScript_BerserkGeneRetEnd2::
call BattleScript_BerserkGeneRet
end2
BattleScript_BoosterEnergyEnd2::
call BattleScript_BoosterEnergyRet

View File

@ -492,6 +492,7 @@ extern const u8 BattleScript_MoveEffectStockpileWoreOff[];
extern const u8 BattleScript_StealthRockActivates[];
extern const u8 BattleScript_SpikesActivates[];
extern const u8 BattleScript_BerserkGeneRet[];
extern const u8 BattleScript_BerserkGeneRetEnd2[];
extern const u8 BattleScript_TargetFormChangeWithStringNoPopup[];
extern const u8 BattleScript_DefDown[];
extern const u8 BattleScript_UltraBurst[];

View File

@ -7163,6 +7163,28 @@ static enum ItemEffect TryEjectPack(u32 battler, enum ItemCaseId caseID)
return ITEM_NO_EFFECT;
}
static enum ItemEffect ConsumeBerserkGene(u32 battler, enum ItemCaseId caseID)
{
if (CanBeInfinitelyConfused(battler))
gStatuses4[battler] |= STATUS4_INFINITE_CONFUSION;
BufferStatChange(battler, STAT_ATK, STRINGID_STATROSE);
gBattlerAttacker = gEffectBattler = battler;
SET_STATCHANGER(STAT_ATK, 2, FALSE);
gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + STAT_ATK;
gBattleScripting.animArg2 = 0;
if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseID == ITEMEFFECT_NORMAL)
{
BattleScriptExecute(BattleScript_BerserkGeneRetEnd2);
}
else
{
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_BerserkGeneRet;
}
return ITEM_STATS_CHANGE;
}
static u32 ItemRestorePp(u32 battler, u32 itemId, enum ItemCaseId caseID)
{
struct Pokemon *party = GetBattlerParty(battler);
@ -7577,19 +7599,7 @@ static u8 ItemEffectMoveEnd(u32 battler, u16 holdEffect)
}
break;
case HOLD_EFFECT_BERSERK_GENE:
BufferStatChange(battler, STAT_ATK, STRINGID_STATROSE);
gEffectBattler = battler;
if (CanBeInfinitelyConfused(gEffectBattler))
{
gStatuses4[gEffectBattler] |= STATUS4_INFINITE_CONFUSION;
}
SET_STATCHANGER(STAT_ATK, 2, FALSE);
gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + STAT_ATK;
gBattleScripting.animArg2 = 0;
BattleScriptPushCursorAndCallback(BattleScript_BerserkGeneRet);
effect = ITEM_STATS_CHANGE;
effect = ConsumeBerserkGene(battler, ITEMEFFECT_NONE);
break;
case HOLD_EFFECT_MIRROR_HERB:
effect = TryConsumeMirrorHerb(battler, ITEMEFFECT_NONE);
@ -7860,19 +7870,7 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler, bool32 moveTurn)
effect = TryEjectPack(battler, caseID);
break;
case HOLD_EFFECT_BERSERK_GENE:
BufferStatChange(battler, STAT_ATK, STRINGID_STATROSE);
gEffectBattler = battler;
if (CanBeInfinitelyConfused(gEffectBattler))
{
gStatuses4[gEffectBattler] |= STATUS4_INFINITE_CONFUSION;
}
SET_STATCHANGER(STAT_ATK, 2, FALSE);
gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + STAT_ATK;
gBattleScripting.animArg2 = 0;
BattleScriptPushCursorAndCallback(BattleScript_BerserkGeneRet);
effect = ITEM_STATS_CHANGE;
effect = ConsumeBerserkGene(battler, caseID);
break;
case HOLD_EFFECT_MIRROR_HERB:
effect = TryConsumeMirrorHerb(battler, caseID);
@ -8072,19 +8070,7 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler, bool32 moveTurn)
effect = TrySetMicleBerry(battler, gLastUsedItem, caseID);
break;
case HOLD_EFFECT_BERSERK_GENE:
BufferStatChange(battler, STAT_ATK, STRINGID_STATROSE);
gEffectBattler = battler;
if (CanBeInfinitelyConfused(gEffectBattler))
{
gStatuses4[gEffectBattler] |= STATUS4_INFINITE_CONFUSION;
}
SET_STATCHANGER(STAT_ATK, 2, FALSE);
gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + STAT_ATK;
gBattleScripting.animArg2 = 0;
BattleScriptPushCursorAndCallback(BattleScript_BerserkGeneRet);
effect = ITEM_STATS_CHANGE;
effect = ConsumeBerserkGene(battler, caseID);
break;
case HOLD_EFFECT_MIRROR_HERB:
effect = TryConsumeMirrorHerb(battler, caseID);

View File

@ -236,3 +236,19 @@ SINGLE_BATTLE_TEST("Berserk Gene causes confusion timer to not tick down", u32 s
EXPECT_EQ(results[0].status2, results[1].status2);
}
}
SINGLE_BATTLE_TEST("Berserk Gene does not cause an infinite loop")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_BESTOW) == EFFECT_BESTOW);
PLAYER(SPECIES_TOXEL) { Item(ITEM_BERSERK_GENE); Ability(ABILITY_KLUTZ); }
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_BESTOW); }
} SCENE {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Using Berserk Gene, the Attack of the opposing Wobbuffet sharply rose!");
}
}