diff --git a/include/battle.h b/include/battle.h index c78101b1a2..8a5fd34c04 100644 --- a/include/battle.h +++ b/include/battle.h @@ -819,6 +819,7 @@ struct BattleStruct u8 pursuitSwitchByMove:1; u8 pursuitStoredSwitch; // Stored id for the Pursuit target's switch s32 battlerExpReward; + u16 prevTurnSpecies[MAX_BATTLERS_COUNT]; // Stores species the AI has in play at start of turn // Simultaneous hp reduction for spread moves s32 moveDamage[MAX_BATTLERS_COUNT]; diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index a10ed1f550..df865cb6cb 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -348,6 +348,9 @@ static bool32 FindMonThatAbsorbsOpponentsMove(u32 battler) if (!(AI_THINKING_STRUCT->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING)) return FALSE; + if (gBattleStruct->prevTurnSpecies[battler] != gBattleMons[battler].species) // AI mon has changed, player's behaviour no longer reliable; note to override this if using AI_FLAG_PREDICT_MOVE + return FALSE; + if (HasSuperEffectiveMoveAgainstOpponents(battler, TRUE) && (RandomPercentage(RNG_AI_SWITCH_ABSORBING, 66) || AI_DATA->aiSwitchPredictionInProgress)) return FALSE; diff --git a/src/battle_main.c b/src/battle_main.c index 5d16f5c3bc..3000005917 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -4157,6 +4157,7 @@ void SetupAISwitchingData(u32 battler, enum SwitchType switchType) if (ShouldSwitch(opposingBattler)) AI_DATA->shouldSwitch |= (1u << opposingBattler); AI_DATA->aiSwitchPredictionInProgress = FALSE; + gBattleStruct->prevTurnSpecies[opposingBattler] = gBattleMons[opposingBattler].species; // Determine whether AI will use predictions this turn AI_DATA->predictingSwitch = RandomPercentage(RNG_AI_PREDICT_SWITCH, 50); @@ -4166,6 +4167,7 @@ void SetupAISwitchingData(u32 battler, enum SwitchType switchType) AI_DATA->mostSuitableMonId[battler] = GetMostSuitableMonToSwitchInto(battler, switchType); if (ShouldSwitch(battler)) AI_DATA->shouldSwitch |= (1u << battler); + gBattleStruct->prevTurnSpecies[battler] = gBattleMons[battler].species; } static void HandleTurnActionSelectionState(void) diff --git a/test/battle/ai/ai_switching.c b/test/battle/ai/ai_switching.c index 4f42fa9233..82ad5440aa 100644 --- a/test/battle/ai/ai_switching.c +++ b/test/battle/ai/ai_switching.c @@ -1026,3 +1026,17 @@ AI_SINGLE_BATTLE_TEST("Switch AI: AI won't switch in ace mon after U-Turn if oth TURN { EXPECT_MOVE(opponent, MOVE_U_TURN); EXPECT_SEND_OUT(opponent, 2); MOVE(player, MOVE_SURF); } } } + +AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI won't switch in absorbing mon immediately after sending out new mon") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_BLAZIKEN) { Moves(MOVE_FLAMETHROWER, MOVE_CLOSE_COMBAT); } + OPPONENT(SPECIES_FERROTHORN) { Moves(MOVE_GYRO_BALL); } + OPPONENT(SPECIES_DIALGA) { Moves(MOVE_DRACO_METEOR); } + OPPONENT(SPECIES_HEATRAN) { Moves(MOVE_EARTH_POWER, MOVE_FLAMETHROWER); } + } WHEN { + TURN { MOVE(player, MOVE_FLAMETHROWER); EXPECT_SEND_OUT(opponent, 1); } + TURN { MOVE(player, MOVE_CLOSE_COMBAT); EXPECT_MOVE(opponent, MOVE_DRACO_METEOR); } + } +}