From 52d61546c92bce6ee94201116232b9aa12a017a5 Mon Sep 17 00:00:00 2001 From: GGbond Date: Tue, 20 Jan 2026 02:14:56 +0800 Subject: [PATCH] Fix AI absorber switching for edge cases (#8964) --- src/battle_ai_switch_items.c | 23 ++++++++++++++--------- test/battle/ai/ai_switching.c | 5 ++++- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index d1daded86e..defc1c3c89 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -471,7 +471,7 @@ static bool32 FindMonThatAbsorbsOpponentsMove(u32 battler) { u8 battlerIn1, battlerIn2; u8 numAbsorbingAbilities = 0; - enum Ability absorbingTypeAbilities[3]; // Array size is maximum number of absorbing abilities for a single type + enum Ability absorbingTypeAbilities[8]; // Max needed for type + move property absorbers s32 firstId; s32 lastId; struct Pokemon *party; @@ -530,42 +530,47 @@ static bool32 FindMonThatAbsorbsOpponentsMove(u32 battler) { absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_FLASH_FIRE; } - else if (incomingType == TYPE_WATER || (isOpposingBattlerChargingOrInvulnerable && incomingType == TYPE_WATER)) + if (incomingType == TYPE_WATER || (isOpposingBattlerChargingOrInvulnerable && incomingType == TYPE_WATER)) { absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_WATER_ABSORB; absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_DRY_SKIN; if (GetConfig(CONFIG_REDIRECT_ABILITY_IMMUNITY) >= GEN_5) absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_STORM_DRAIN; } - else if (incomingType == TYPE_ELECTRIC || (isOpposingBattlerChargingOrInvulnerable && incomingType == TYPE_ELECTRIC)) + if (incomingType == TYPE_ELECTRIC || (isOpposingBattlerChargingOrInvulnerable && incomingType == TYPE_ELECTRIC)) { absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_VOLT_ABSORB; absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_MOTOR_DRIVE; if (GetConfig(CONFIG_REDIRECT_ABILITY_IMMUNITY) >= GEN_5) absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_LIGHTNING_ROD; } - else if (incomingType == TYPE_GRASS || (isOpposingBattlerChargingOrInvulnerable && incomingType == TYPE_GRASS)) + if (incomingType == TYPE_GRASS || (isOpposingBattlerChargingOrInvulnerable && incomingType == TYPE_GRASS)) { absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_SAP_SIPPER; } - else if (incomingType == TYPE_GROUND || (isOpposingBattlerChargingOrInvulnerable && incomingType == TYPE_GROUND)) + if (incomingType == TYPE_GROUND || (isOpposingBattlerChargingOrInvulnerable && incomingType == TYPE_GROUND)) { absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_EARTH_EATER; absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_LEVITATE; } - else if (IsSoundMove(incomingMove) || (isOpposingBattlerChargingOrInvulnerable && IsSoundMove(incomingMove))) + if (IsSoundMove(incomingMove) || (isOpposingBattlerChargingOrInvulnerable && IsSoundMove(incomingMove))) { absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_SOUNDPROOF; } - else if (IsBallisticMove(incomingMove) || (isOpposingBattlerChargingOrInvulnerable && IsBallisticMove(incomingMove))) + if (IsBallisticMove(incomingMove) || (isOpposingBattlerChargingOrInvulnerable && IsBallisticMove(incomingMove))) { absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_BULLETPROOF; } - else if (IsWindMove(incomingMove) || (isOpposingBattlerChargingOrInvulnerable && IsWindMove(incomingMove))) + if (IsWindMove(incomingMove) || (isOpposingBattlerChargingOrInvulnerable && IsWindMove(incomingMove))) { absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_WIND_RIDER; } - else + if (IsPowderMove(incomingMove) || (isOpposingBattlerChargingOrInvulnerable && IsPowderMove(incomingMove))) + { + if (GetConfig(CONFIG_POWDER_OVERCOAT) >= GEN_6) + absorbingTypeAbilities[numAbsorbingAbilities++] = ABILITY_OVERCOAT; + } + if (numAbsorbingAbilities == 0) { return FALSE; } diff --git a/test/battle/ai/ai_switching.c b/test/battle/ai/ai_switching.c index 82c3c6d42a..36a859f62c 100644 --- a/test/battle/ai/ai_switching.c +++ b/test/battle/ai/ai_switching.c @@ -1101,15 +1101,18 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if it has an PARAMETRIZE { aiMon = SPECIES_JOLTEON; absorbingAbility = ABILITY_VOLT_ABSORB; move = MOVE_THUNDERBOLT; } PARAMETRIZE { aiMon = SPECIES_ELECTIVIRE; absorbingAbility = ABILITY_MOTOR_DRIVE; move = MOVE_THUNDERBOLT; } PARAMETRIZE { aiMon = SPECIES_MANECTRIC; absorbingAbility = ABILITY_LIGHTNING_ROD; move = MOVE_THUNDERBOLT; } - PARAMETRIZE { aiMon = SPECIES_ELECTIVIRE; absorbingAbility = ABILITY_MOTOR_DRIVE; move = MOVE_THUNDERBOLT; } PARAMETRIZE { aiMon = SPECIES_AZUMARILL; absorbingAbility = ABILITY_SAP_SIPPER; move = MOVE_GIGA_DRAIN; } PARAMETRIZE { aiMon = SPECIES_ORTHWORM; absorbingAbility = ABILITY_EARTH_EATER; move = MOVE_EARTHQUAKE; } PARAMETRIZE { aiMon = SPECIES_BRONZONG; absorbingAbility = ABILITY_LEVITATE; move = MOVE_EARTHQUAKE; } PARAMETRIZE { aiMon = SPECIES_ELECTRODE; absorbingAbility = ABILITY_SOUNDPROOF; move = MOVE_HYPER_VOICE; } PARAMETRIZE { aiMon = SPECIES_CHESNAUGHT; absorbingAbility = ABILITY_BULLETPROOF; move = MOVE_SLUDGE_BOMB; } PARAMETRIZE { aiMon = SPECIES_BRAMBLEGHAST; absorbingAbility = ABILITY_WIND_RIDER; move = MOVE_HURRICANE; } + PARAMETRIZE { aiMon = SPECIES_BRAMBLEGHAST; absorbingAbility = ABILITY_WIND_RIDER; move = MOVE_HEAT_WAVE; } + PARAMETRIZE { aiMon = SPECIES_SHELLDER; absorbingAbility = ABILITY_OVERCOAT; move = MOVE_MAGIC_POWDER; } + PARAMETRIZE { aiMon = SPECIES_SHELLDER; absorbingAbility = ABILITY_OVERCOAT; move = MOVE_STUN_SPORE; } GIVEN { WITH_CONFIG(CONFIG_REDIRECT_ABILITY_IMMUNITY, GEN_5); + WITH_CONFIG(CONFIG_POWDER_OVERCOAT, GEN_6); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING); PLAYER(SPECIES_ZIGZAGOON) { Moves(move); } OPPONENT(SPECIES_ZIGZAGOON) { Moves(MOVE_SCRATCH); }