Skip to content

Commit

Permalink
Fixes choiced moves not locked in after ability block (#5738)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexOn1ine authored Dec 1, 2024
1 parent 987264c commit 0ca5889
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 47 deletions.
2 changes: 1 addition & 1 deletion include/battle.h
Original file line number Diff line number Diff line change
Expand Up @@ -802,8 +802,8 @@ struct BattleStruct
u8 categoryOverride; // for Z-Moves and Max Moves
u32 stellarBoostFlags[NUM_BATTLE_SIDES]; // stored as a bitfield of flags for all types for each side
u8 fickleBeamBoosted:1;
u8 obedienceResult:3;
u8 redCardActivates:1;
u8 padding:6;
u8 usedMicleBerry;
};

Expand Down
1 change: 1 addition & 0 deletions include/battle_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ enum
CANCELLER_SKY_DROP,
CANCELLER_ASLEEP,
CANCELLER_FROZEN,
CANCELLER_OBEDIENCE,
CANCELLER_TRUANT,
CANCELLER_RECHARGE,
CANCELLER_FLINCH,
Expand Down
40 changes: 0 additions & 40 deletions src/battle_script_commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -1282,46 +1282,6 @@ static void Cmd_attackcanceler(void)

gHitMarker &= ~HITMARKER_ALLOW_NO_PP;

if (!(gHitMarker & HITMARKER_OBEYS) && !(gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS))
{
switch (gBattleStruct->obedienceResult)
{
case OBEYS:
break;
case DISOBEYS_LOAFS:
// Randomly select, then print a disobedient string
// B_MSG_LOAFING, B_MSG_WONT_OBEY, B_MSG_TURNED_AWAY, or B_MSG_PRETEND_NOT_NOTICE
gBattleCommunication[MULTISTRING_CHOOSER] = MOD(Random(), NUM_LOAF_STRINGS);
gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAround;
gMoveResultFlags |= MOVE_RESULT_MISSED;
return;
case DISOBEYS_HITS_SELF:
gBattlerTarget = gBattlerAttacker;
gBattleMoveDamage = CalculateMoveDamage(MOVE_NONE, gBattlerAttacker, gBattlerAttacker, TYPE_MYSTERY, 40, FALSE, FALSE, TRUE);
gBattlescriptCurrInstr = BattleScript_IgnoresAndHitsItself;
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
gHitMarker |= HITMARKER_OBEYS;
return;
case DISOBEYS_FALL_ASLEEP:
gBattlescriptCurrInstr = BattleScript_IgnoresAndFallsAsleep;
gMoveResultFlags |= MOVE_RESULT_MISSED;
return;
case DISOBEYS_WHILE_ASLEEP:
gBattlescriptCurrInstr = BattleScript_IgnoresWhileAsleep;
gMoveResultFlags |= MOVE_RESULT_MISSED;
return;
case DISOBEYS_RANDOM_MOVE:
gCalledMove = gBattleMons[gBattlerAttacker].moves[gCurrMovePos];
SetAtkCancellerForCalledMove();
gBattlescriptCurrInstr = BattleScript_IgnoresAndUsesRandomMove;
gBattlerTarget = GetMoveTarget(gCalledMove, NO_TARGET_OVERRIDE);
gHitMarker |= HITMARKER_DISOBEDIENT_MOVE;
gHitMarker |= HITMARKER_OBEYS;
return;
}
}

gHitMarker |= HITMARKER_OBEYS;
// Check if no available target present on the field or if Sky Battles ban the move
if ((NoTargetPresent(gBattlerAttacker, gCurrentMove)
&& (!gBattleMoveEffects[gMovesInfo[gCurrentMove].effect].twoTurnEffect || (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)))
Expand Down
56 changes: 50 additions & 6 deletions src/battle_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,6 @@ void HandleAction_UseMove(void)
gBattleScripting.savedMoveEffect = 0;
gCurrMovePos = gChosenMovePos = *(gBattleStruct->chosenMovePositions + gBattlerAttacker);

gBattleStruct->obedienceResult = GetAttackerObedienceForAction();

// choose move
if (gProtectStructs[gBattlerAttacker].noValidMoves)
{
Expand Down Expand Up @@ -3222,7 +3220,8 @@ void SetAtkCancellerForCalledMove(void)

u8 AtkCanceller_UnableToUseMove(u32 moveType)
{
u8 effect = 0;
u32 effect = 0;
u32 obedienceResult;
do
{
switch (gBattleStruct->atkCancellerTracker)
Expand Down Expand Up @@ -3306,6 +3305,53 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType)
}
gBattleStruct->atkCancellerTracker++;
break;
case CANCELLER_OBEDIENCE:
obedienceResult = GetAttackerObedienceForAction();
if (obedienceResult != OBEYS
&& !(gHitMarker & HITMARKER_NO_PPDEDUCT) // Don't check obedience after first hit of multi target move or multi hit moves
&& !(gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS))
{
switch (obedienceResult)
{
case DISOBEYS_LOAFS:
// Randomly select, then print a disobedient string
// B_MSG_LOAFING, B_MSG_WONT_OBEY, B_MSG_TURNED_AWAY, or B_MSG_PRETEND_NOT_NOTICE
gBattleCommunication[MULTISTRING_CHOOSER] = MOD(Random(), NUM_LOAF_STRINGS);
gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAround;
gMoveResultFlags |= MOVE_RESULT_MISSED;
break;
case DISOBEYS_HITS_SELF:
gBattlerTarget = gBattlerAttacker;
gBattleMoveDamage = CalculateMoveDamage(MOVE_NONE, gBattlerAttacker, gBattlerAttacker, TYPE_MYSTERY, 40, FALSE, FALSE, TRUE);
gBattlescriptCurrInstr = BattleScript_IgnoresAndHitsItself;
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
gHitMarker |= HITMARKER_OBEYS;
break;
case DISOBEYS_FALL_ASLEEP:
gBattlescriptCurrInstr = BattleScript_IgnoresAndFallsAsleep;
gMoveResultFlags |= MOVE_RESULT_MISSED;
break;
case DISOBEYS_WHILE_ASLEEP:
gBattlescriptCurrInstr = BattleScript_IgnoresWhileAsleep;
gMoveResultFlags |= MOVE_RESULT_MISSED;
break;
case DISOBEYS_RANDOM_MOVE:
gCalledMove = gBattleMons[gBattlerAttacker].moves[gCurrMovePos];
SetAtkCancellerForCalledMove();
gBattlescriptCurrInstr = BattleScript_IgnoresAndUsesRandomMove;
gBattlerTarget = GetMoveTarget(gCalledMove, NO_TARGET_OVERRIDE);
gHitMarker |= HITMARKER_DISOBEDIENT_MOVE;
gHitMarker |= HITMARKER_OBEYS;
break;
}
effect = 1;
}
else
{
gHitMarker |= HITMARKER_OBEYS;
}
gBattleStruct->atkCancellerTracker++;
break;
case CANCELLER_TRUANT: // truant
if (GetBattlerAbility(gBattlerAttacker) == ABILITY_TRUANT && gDisableStructs[gBattlerAttacker].truantCounter)
{
Expand Down Expand Up @@ -3554,7 +3600,6 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType)
gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / 4;

if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE
|| gBattleStruct->obedienceResult != OBEYS
|| HasTrainerUsedGimmick(gBattlerAttacker, GIMMICK_Z_MOVE))
gBattlescriptCurrInstr = BattleScript_MoveUsedPowder;
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
Expand All @@ -3575,8 +3620,7 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType)
gBattleStruct->atkCancellerTracker++;
break;
case CANCELLER_Z_MOVES:
if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE
&& gBattleStruct->obedienceResult == OBEYS)
if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE)
{
// For Z-Mirror Move, so it doesn't play the animation twice.
bool32 alreadyUsed = HasTrainerUsedGimmick(gBattlerAttacker, GIMMICK_Z_MOVE);
Expand Down
25 changes: 25 additions & 0 deletions test/battle/ai/ai.c
Original file line number Diff line number Diff line change
Expand Up @@ -805,3 +805,28 @@ AI_SINGLE_BATTLE_TEST("AI uses a guaranteed KO move instead of the move with the
NOT MESSAGE("Wobbuffet fainted!");
}
}

AI_SINGLE_BATTLE_TEST("AI stays choice locked into moves in spite of the player's ability disabling them")
{
u32 playerMon, ability, aiMove;
PARAMETRIZE { ability = ABILITY_DAZZLING; playerMon = SPECIES_BRUXISH; aiMove = MOVE_QUICK_ATTACK; }
PARAMETRIZE { ability = ABILITY_QUEENLY_MAJESTY; playerMon = SPECIES_TSAREENA; aiMove = MOVE_QUICK_ATTACK; }
PARAMETRIZE { ability = ABILITY_ARMOR_TAIL; playerMon = SPECIES_FARIGIRAF; aiMove = MOVE_QUICK_ATTACK; }
PARAMETRIZE { ability = ABILITY_SOUNDPROOF; playerMon = SPECIES_EXPLOUD; aiMove = MOVE_BOOMBURST; }
PARAMETRIZE { ability = ABILITY_BULLETPROOF; playerMon = SPECIES_CHESNAUGHT; aiMove = MOVE_BULLET_SEED; }

GIVEN {
ASSUME(gItemsInfo[ITEM_CHOICE_BAND].holdEffect == HOLD_EFFECT_CHOICE_BAND);
ASSUME(gMovesInfo[MOVE_QUICK_ATTACK].priority == 1);
ASSUME(gMovesInfo[MOVE_BOOMBURST].soundMove == TRUE);
ASSUME(gMovesInfo[MOVE_BULLET_SEED].ballisticMove == TRUE);
ASSUME(gMovesInfo[MOVE_TAIL_WHIP].category == DAMAGE_CATEGORY_STATUS);
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(playerMon) { Ability(ability); }
OPPONENT(SPECIES_SMEARGLE) { Item(ITEM_CHOICE_BAND); Moves(aiMove, MOVE_TACKLE); }
} WHEN {
TURN { SWITCH(player, 1); EXPECT_MOVE(opponent, aiMove); }
TURN { EXPECT_MOVE(opponent, aiMove); }
}
}

0 comments on commit 0ca5889

Please sign in to comment.