Fix recharge moves + add recharge move tests (#8181)

This commit is contained in:
FosterProgramming 2025-11-09 17:46:22 +01:00 committed by GitHub
parent bdaf4ae3b3
commit 43f9a78da5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 58 additions and 14 deletions

View File

@ -160,7 +160,6 @@ enum VolatileFlags
F(VOLATILE_INFATUATION, infatuation, (enum BattlerId, MAX_BITS(4))) \
F(VOLATILE_DEFENSE_CURL, defenseCurl, (u32, 1)) \
F(VOLATILE_TRANSFORMED, transformed, (u32, 1)) \
F(VOLATILE_RECHARGE, recharge, (u32, 1)) \
F(VOLATILE_RAGE, rage, (u32, 1)) \
F(VOLATILE_SUBSTITUTE, substitute, (u32, 1), V_BATON_PASSABLE) \
F(VOLATILE_DESTINY_BOND, destinyBond, (u32, 1)) \

View File

@ -3435,7 +3435,7 @@ bool32 IsBattlerIncapacitated(u32 battler, u32 ability)
if (gBattleMons[battler].status1 & STATUS1_SLEEP && !HasMoveWithEffect(battler, EFFECT_SLEEP_TALK))
return TRUE;
if (gBattleMons[battler].volatiles.recharge || (ability == ABILITY_TRUANT && gDisableStructs[battler].truantCounter != 0))
if (gDisableStructs[battler].rechargeTimer > 0 || (ability == ABILITY_TRUANT && gDisableStructs[battler].truantCounter != 0))
return TRUE;
return FALSE;

View File

@ -361,7 +361,6 @@ static const struct ListMenuItem sVolatileStatusListItems[] =
{COMPOUND_STRING("Torment"), VOLATILE_TORMENT},
{COMPOUND_STRING("Powder"), VOLATILE_POWDER},
{COMPOUND_STRING("DefenseCurl"), VOLATILE_DEFENSE_CURL},
{COMPOUND_STRING("Recharge"), VOLATILE_RECHARGE},
{COMPOUND_STRING("Rage"), VOLATILE_RAGE},
{COMPOUND_STRING("DestinyBond"), VOLATILE_DESTINY_BOND},
{COMPOUND_STRING("EscapePrevention"), VOLATILE_ESCAPE_PREVENTION},

View File

@ -4213,7 +4213,7 @@ static void HandleTurnActionSelectionState(void)
else
{
if (gBattleMons[battler].volatiles.multipleTurns
|| gBattleMons[battler].volatiles.recharge)
|| gDisableStructs[battler].rechargeTimer > 0)
{
gChosenActionByBattler[battler] = B_ACTION_USE_MOVE;
gBattleCommunication[battler] = STATE_WAIT_ACTION_CONFIRMED_STANDBY;
@ -4368,7 +4368,7 @@ static void HandleTurnActionSelectionState(void)
gBattleCommunication[GetPartnerBattler(battler)] = STATE_BEFORE_ACTION_CHOSEN;
RecordedBattle_ClearBattlerAction(battler, 1);
if (gBattleMons[GetPartnerBattler(battler)].volatiles.multipleTurns
|| gBattleMons[GetPartnerBattler(battler)].volatiles.recharge)
|| gDisableStructs[GetPartnerBattler(battler)].rechargeTimer > 0)
{
BtlController_EmitEndBounceEffect(battler, B_COMM_TO_CONTROLLER);
MarkBattlerForControllerExec(battler);
@ -5132,11 +5132,8 @@ static void TurnValuesCleanUp(bool8 var0)
gDisableStructs[i].isFirstTurn--;
if (gDisableStructs[i].rechargeTimer)
{
gDisableStructs[i].rechargeTimer--;
if (gDisableStructs[i].rechargeTimer == 0)
gBattleMons[i].volatiles.recharge = FALSE;
}
gBattleStruct->battlerState[i].canPickupItem = FALSE;
}

View File

@ -3314,7 +3314,6 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai
if (B_SKIP_RECHARGE == GEN_1 && !IsBattlerAlive(gBattlerTarget)) // Skip recharge if gen 1 and foe is KO'd
break;
gBattleMons[gEffectBattler].volatiles.recharge = TRUE;
gDisableStructs[gEffectBattler].rechargeTimer = 2;
gLockedMoves[gEffectBattler] = gCurrentMove;
gBattlescriptCurrInstr++;

View File

@ -406,7 +406,7 @@ void HandleAction_UseMove(void)
gHitMarker |= HITMARKER_NO_PPDEDUCT;
gBattleStruct->moveTarget[gBattlerAttacker] = GetBattleMoveTarget(MOVE_STRUGGLE, NO_TARGET_OVERRIDE);
}
else if (gBattleMons[gBattlerAttacker].volatiles.multipleTurns || gBattleMons[gBattlerAttacker].volatiles.recharge)
else if (gBattleMons[gBattlerAttacker].volatiles.multipleTurns || gDisableStructs[gBattlerAttacker].rechargeTimer > 0)
{
gCurrentMove = gChosenMove = gLockedMoves[gBattlerAttacker];
}
@ -1928,10 +1928,8 @@ static enum MoveCanceller CancellerSkyDrop(void)
static enum MoveCanceller CancellerRecharge(void)
{
if (gBattleMons[gBattlerAttacker].volatiles.recharge)
if (gDisableStructs[gBattlerAttacker].rechargeTimer > 0)
{
gBattleMons[gBattlerAttacker].volatiles.recharge = FALSE;
gDisableStructs[gBattlerAttacker].rechargeTimer = 0;
CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK);
gBattlescriptCurrInstr = BattleScript_MoveUsedMustRecharge;
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;

View File

@ -0,0 +1,52 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(MoveHasAdditionalEffectSelf(MOVE_METEOR_ASSAULT, MOVE_EFFECT_RECHARGE) == TRUE);
}
SINGLE_BATTLE_TEST("Recharge moves make the user unable to attack for exactly one turn")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { }
OPPONENT(SPECIES_WOBBUFFET) { }
} WHEN {
TURN { MOVE(player, MOVE_METEOR_ASSAULT);}
TURN { SKIP_TURN(player);}
TURN { MOVE(player, MOVE_TACKLE);}
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_METEOR_ASSAULT, player);
MESSAGE("Wobbuffet must recharge!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player);
}
}
SINGLE_BATTLE_TEST("Recharge moves don't timeout when all battlers are recharging")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { }
OPPONENT(SPECIES_WOBBUFFET) { }
} WHEN {
TURN { MOVE(player, MOVE_METEOR_ASSAULT); MOVE(opponent, MOVE_METEOR_ASSAULT);}
}
}
DOUBLE_BATTLE_TEST("Recharge moves don't timeout when all battlers are recharging (doubles")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { }
PLAYER(SPECIES_WYNAUT) { }
OPPONENT(SPECIES_WOBBUFFET) { }
OPPONENT(SPECIES_WYNAUT) { }
} WHEN {
TURN {
MOVE(playerLeft, MOVE_METEOR_ASSAULT, target: opponentLeft);
MOVE(playerRight, MOVE_METEOR_ASSAULT, target: opponentRight);
MOVE(opponentLeft, MOVE_METEOR_ASSAULT, target: playerLeft);
MOVE(opponentRight, MOVE_METEOR_ASSAULT, target: playerRight);
}
}
}