diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index d4a66f2028..473a8758a5 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -102,6 +102,7 @@ s32 AI_DecideKnownAbilityForTurn(u32 battlerId); enum ItemHoldEffect AI_DecideHoldEffectForTurn(u32 battlerId); bool32 DoesBattlerIgnoreAbilityChecks(u32 battlerAtk, u32 atkAbility, u32 move); u32 AI_GetWeather(void); +u32 AI_GetSwitchinWeather(struct BattlePokemon battleMon); enum WeatherState IsWeatherActive(u32 flags); bool32 CanAIFaintTarget(u32 battlerAtk, u32 battlerDef, u32 numHits); bool32 CanIndexMoveFaintTarget(u32 battlerAtk, u32 battlerDef, u32 index, enum DamageCalcContext calcContext); diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index ff81162d52..b480ac6118 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1638,6 +1638,33 @@ u32 AI_GetWeather(void) return gBattleWeather; } +u32 AI_GetSwitchinWeather(struct BattlePokemon battleMon) +{ + u32 ability = battleMon.ability; + // Forced weather behaviour + if (!AI_WeatherHasEffect()) + return B_WEATHER_NONE; + if (ability == ABILITY_CLOUD_NINE || ability == ABILITY_AIR_LOCK) + return B_WEATHER_NONE; + if (gBattleWeather & B_WEATHER_PRIMAL_ANY) + return gBattleWeather; + + // Switchin will introduce new weather + switch(ability) + { + case ABILITY_DRIZZLE: + return B_WEATHER_RAIN_NORMAL; + case ABILITY_DROUGHT: + return B_WEATHER_SUN_NORMAL; + case ABILITY_SAND_STREAM: + return B_WEATHER_SANDSTORM; + case ABILITY_SNOW_WARNING: + return B_SNOW_WARNING >= GEN_9 ? B_WEATHER_SNOW : B_WEATHER_HAIL; + default: + return gBattleWeather; + } +} + enum WeatherState IsWeatherActive(u32 flags) { enum WeatherState state = WEATHER_INACTIVE; @@ -4057,7 +4084,7 @@ s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct Battl gAiThinkingStruct->saved[battlerAtk].saved = FALSE; } - dmg = AI_CalcDamage(move, battlerAtk, battlerDef, &effectiveness, NO_GIMMICK, NO_GIMMICK, AI_GetWeather()); + dmg = AI_CalcDamage(move, battlerAtk, battlerDef, &effectiveness, NO_GIMMICK, NO_GIMMICK, AI_GetSwitchinWeather(switchinCandidate)); // restores original gBattleMon struct FreeRestoreBattleMons(savedBattleMons); diff --git a/test/battle/ai/ai_switching.c b/test/battle/ai/ai_switching.c index 0aae647030..2eb6834c6c 100644 --- a/test/battle/ai/ai_switching.c +++ b/test/battle/ai/ai_switching.c @@ -1267,3 +1267,22 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI considers 0 hits to KO as los TURN { MOVE(player, MOVE_TACKLE); EXPECT_SEND_OUT(opponent, 2); } } } + +AI_SINGLE_BATTLE_TEST("AI_SMART_MON_CHOICES: AI sees its own weather setting ability when considering switchin candidates") +{ + u32 ability = ABILITY_NONE; + PARAMETRIZE { ability = ABILITY_WATER_ABSORB; } + PARAMETRIZE { ability = ABILITY_DRIZZLE; } + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_ZIGZAGOON) { Speed(2); Moves(MOVE_SCRATCH); } + OPPONENT(SPECIES_ZIGZAGOON) { Speed(1); Level(1); Moves(MOVE_SCRATCH); } + OPPONENT(SPECIES_POLITOED) { Speed(5); Ability(ability); Moves(MOVE_BUBBLE_BEAM); } + OPPONENT(SPECIES_CONKELDURR) { Speed(1); Ability(ABILITY_GUTS); Moves(MOVE_SUPERPOWER); } + } WHEN { + if (ability == ABILITY_DRIZZLE) + TURN { MOVE(player, MOVE_SCRATCH); EXPECT_MOVE(opponent, MOVE_SCRATCH); EXPECT_SEND_OUT(opponent, 1); } + else + TURN { MOVE(player, MOVE_SCRATCH); EXPECT_MOVE(opponent, MOVE_SCRATCH); EXPECT_SEND_OUT(opponent, 2); } + } +}