diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index ad81949a5d..0f38f326d1 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -1744,8 +1744,9 @@ static inline bool32 IsFreeSwitch(bool32 isSwitchAfterKO, u32 battlerSwitchingOu return TRUE; if (AI_DATA->ejectPackSwitch) { + u32 opposingAbility = AI_GetBattlerAbility(opposingBattler); // If faster, not a free switch; likely lowered own stats - if (!movedSecond) + if (!movedSecond && opposingAbility != ABILITY_INTIMIDATE && opposingAbility != ABILITY_SUPERSWEET_SYRUP) // Intimidate triggers switches before turn starts return FALSE; // Otherwise, free switch return TRUE; @@ -1949,8 +1950,9 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, else if (defensiveMonId != PARTY_SIZE) return defensiveMonId; else if (batonPassId != PARTY_SIZE) return batonPassId; } - // If ace mon is the last available Pokemon and U-Turn/Volt Switch was used - switch to the mon. - if (aceMonId != PARTY_SIZE && CountUsablePartyMons(battler) <= aceMonCount && IsSwitchOutEffect(GetMoveEffect(gLastUsedMove))) + // If ace mon is the last available Pokemon and U-Turn/Volt Switch or Eject Pack/Button was used - switch to the mon. + if (aceMonId != PARTY_SIZE && CountUsablePartyMons(battler) <= aceMonCount + && (IsSwitchOutEffect(GetMoveEffect(gLastUsedMove)) || AI_DATA->ejectButtonSwitch || AI_DATA->ejectPackSwitch)) return aceMonId; return PARTY_SIZE; @@ -2065,8 +2067,9 @@ u32 GetMostSuitableMonToSwitchInto(u32 battler, bool32 switchAfterMonKOd) if (bestMonId != PARTY_SIZE) return bestMonId; - // If ace mon is the last available Pokemon and U-Turn/Volt Switch was used - switch to the mon. - if (aceMonId != PARTY_SIZE && CountUsablePartyMons(battler) <= aceMonCount && IsSwitchOutEffect(gMovesInfo[gLastUsedMove].effect)) + // If ace mon is the last available Pokemon and U-Turn/Volt Switch or Eject Pack/Button was used - switch to the mon. + if (aceMonId != PARTY_SIZE && CountUsablePartyMons(battler) <= aceMonCount + && (IsSwitchOutEffect(GetMoveEffect(gLastUsedMove)) || AI_DATA->ejectButtonSwitch || AI_DATA->ejectPackSwitch)) return aceMonId; return PARTY_SIZE; diff --git a/src/battle_util.c b/src/battle_util.c index d7b8d21741..8a4e291492 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -7138,6 +7138,7 @@ static enum ItemEffect TryEjectPack(u32 battler, enum ItemCaseId caseID) { gProtectStructs[battler].statFell = FALSE; gBattleScripting.battler = battler; + AI_DATA->ejectPackSwitch = TRUE; if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN) { BattleScriptExecute(BattleScript_EjectPackActivate_End2); diff --git a/test/battle/ai/ai_switching.c b/test/battle/ai/ai_switching.c index f86dd2b5f9..a6a0eb8d76 100644 --- a/test/battle/ai/ai_switching.c +++ b/test/battle/ai/ai_switching.c @@ -103,6 +103,37 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: U-Turn will send out Ace Mon i } } +AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: Eject Button will send out Ace Mon if it's the only one remaining") +{ + u32 aiSmartMonChoicesFlag; + PARAMETRIZE { aiSmartMonChoicesFlag = 0; } + PARAMETRIZE { aiSmartMonChoicesFlag = AI_FLAG_SMART_MON_CHOICES; } + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | aiSmartMonChoicesFlag | AI_FLAG_ACE_POKEMON); + PLAYER(SPECIES_ZIGZAGOON) { Moves(MOVE_TACKLE); } + OPPONENT(SPECIES_ZIGZAGOON) { Item(ITEM_EJECT_BUTTON); }; + OPPONENT(SPECIES_LINOONE); + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); EXPECT_MOVE(opponent, MOVE_TACKLE); EXPECT_SEND_OUT(opponent, 1); } + } +} + +AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: Eject Pack will send out Ace Mon if it's the only one remaining") +{ + u32 aiSmartMonChoicesFlag; + PARAMETRIZE { aiSmartMonChoicesFlag = 0; } + PARAMETRIZE { aiSmartMonChoicesFlag = AI_FLAG_SMART_MON_CHOICES; } + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | aiSmartMonChoicesFlag | AI_FLAG_ACE_POKEMON); + PLAYER(SPECIES_ZIGZAGOON) { Moves(MOVE_TACKLE); } + PLAYER(SPECIES_ARCANINE) { Ability(ABILITY_INTIMIDATE); Moves(MOVE_TACKLE); } + OPPONENT(SPECIES_ZIGZAGOON) { Item(ITEM_EJECT_PACK); Moves(MOVE_TACKLE); } + OPPONENT(SPECIES_LINOONE) { Moves(MOVE_HEADBUTT); } + } WHEN { + TURN { SWITCH(player, 1); EXPECT_MOVE(opponent, MOVE_TACKLE); EXPECT_SEND_OUT(opponent, 1); } + } +} + // General AI_FLAG_SMART_MON_CHOICES behaviour AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: Number of hits to KO calculation checks whether incoming damage is less than recurring healing to avoid an infinite loop") {