diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 4855184fac..d8dca70130 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -22,6 +22,14 @@ enum AIPivot SHOULD_PIVOT, }; +enum WeatherState +{ + WEATHER_INACTIVE, + WEATHER_ACTIVE, + WEATHER_ACTIVE_BUT_BLOCKED, + WEATHER_INACTIVE_AND_BLOCKED, +}; + bool32 AI_IsFaster(u32 battlerAi, u32 battlerDef, u32 move); bool32 AI_IsSlower(u32 battlerAi, u32 battlerDef, u32 move); bool32 AI_RandLessThan(u32 val); @@ -58,6 +66,7 @@ s32 AI_DecideKnownAbilityForTurn(u32 battlerId); u32 AI_DecideHoldEffectForTurn(u32 battlerId); bool32 DoesBattlerIgnoreAbilityChecks(u32 battlerAtk, u32 atkAbility, u32 move); u32 AI_GetWeather(void); +enum WeatherState IsWeatherActive(u32 flags); bool32 CanAIFaintTarget(u32 battlerAtk, u32 battlerDef, u32 numHits); bool32 CanIndexMoveFaintTarget(u32 battlerAtk, u32 battlerDef, u32 index, u32 numHits); bool32 HasDamagingMove(u32 battlerId); diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index b823e6e23e..de854bc738 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -5407,19 +5407,19 @@ static s32 AI_PowerfulStatus(u32 battlerAtk, u32 battlerDef, u32 move, s32 score ADJUST_SCORE(POWERFUL_STATUS_MOVE); break; case EFFECT_SUNNY_DAY: - if (!(AI_GetWeather() & (B_WEATHER_SUN | B_WEATHER_PRIMAL_ANY))) + if (IsWeatherActive(B_WEATHER_SUN | B_WEATHER_PRIMAL_ANY) == WEATHER_INACTIVE) ADJUST_SCORE(POWERFUL_STATUS_MOVE); break; case EFFECT_RAIN_DANCE: - if (!(AI_GetWeather() & (B_WEATHER_RAIN | B_WEATHER_PRIMAL_ANY))) + if (IsWeatherActive(B_WEATHER_RAIN | B_WEATHER_PRIMAL_ANY) == WEATHER_INACTIVE) ADJUST_SCORE(POWERFUL_STATUS_MOVE); break; case EFFECT_HAIL: - if (!(AI_GetWeather() & (B_WEATHER_HAIL | B_WEATHER_PRIMAL_ANY))) + if (IsWeatherActive(B_WEATHER_HAIL | B_WEATHER_PRIMAL_ANY) == WEATHER_INACTIVE) ADJUST_SCORE(POWERFUL_STATUS_MOVE); break; case EFFECT_SNOWSCAPE: - if (!(AI_GetWeather() & (B_WEATHER_SNOW | B_WEATHER_PRIMAL_ANY))) + if (IsWeatherActive(B_WEATHER_SNOW | B_WEATHER_PRIMAL_ANY) == WEATHER_INACTIVE) ADJUST_SCORE(POWERFUL_STATUS_MOVE); } diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 9a3f95674c..ce98f3b357 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1418,6 +1418,26 @@ u32 AI_GetWeather(void) return gBattleWeather; } +enum WeatherState IsWeatherActive(u32 flags) +{ + enum WeatherState state = WEATHER_INACTIVE; + + if (gBattleWeather & flags) + state = WEATHER_ACTIVE; + else + state = WEATHER_INACTIVE; + + if (!AI_WeatherHasEffect()) + { + if (state == WEATHER_ACTIVE) + state = WEATHER_ACTIVE_BUT_BLOCKED; + else + state = WEATHER_INACTIVE_AND_BLOCKED; + } + + return state; +} + bool32 IsAromaVeilProtectedEffect(u32 moveEffect) { switch (moveEffect) @@ -1619,19 +1639,18 @@ bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbil bool32 ShouldSetSandstorm(u32 battler, u32 ability, u32 holdEffect) { - u32 weather = AI_GetWeather(); - if (weather & B_WEATHER_SANDSTORM) + if (IsWeatherActive(B_WEATHER_SANDSTORM | B_WEATHER_PRIMAL_ANY) != WEATHER_INACTIVE) return FALSE; if (ability == ABILITY_SAND_VEIL - || ability == ABILITY_SAND_RUSH - || ability == ABILITY_SAND_FORCE - || ability == ABILITY_OVERCOAT - || ability == ABILITY_MAGIC_GUARD - || holdEffect == HOLD_EFFECT_SAFETY_GOGGLES - || IS_BATTLER_ANY_TYPE(battler, TYPE_ROCK, TYPE_GROUND, TYPE_STEEL) - || HasMoveEffect(battler, EFFECT_SHORE_UP) - || HasMoveEffect(battler, EFFECT_WEATHER_BALL)) + || ability == ABILITY_SAND_RUSH + || ability == ABILITY_SAND_FORCE + || ability == ABILITY_OVERCOAT + || ability == ABILITY_MAGIC_GUARD + || holdEffect == HOLD_EFFECT_SAFETY_GOGGLES + || IS_BATTLER_ANY_TYPE(battler, TYPE_ROCK, TYPE_GROUND, TYPE_STEEL) + || HasMoveEffect(battler, EFFECT_SHORE_UP) + || HasMoveEffect(battler, EFFECT_WEATHER_BALL)) { return TRUE; } @@ -1640,21 +1659,20 @@ bool32 ShouldSetSandstorm(u32 battler, u32 ability, u32 holdEffect) bool32 ShouldSetHail(u32 battler, u32 ability, u32 holdEffect) { - u32 weather = AI_GetWeather(); - if (weather & (B_WEATHER_HAIL | B_WEATHER_SNOW)) + if (IsWeatherActive(B_WEATHER_HAIL | B_WEATHER_SNOW | B_WEATHER_PRIMAL_ANY) != WEATHER_INACTIVE) return FALSE; if (ability == ABILITY_SNOW_CLOAK - || ability == ABILITY_ICE_BODY - || ability == ABILITY_FORECAST - || ability == ABILITY_SLUSH_RUSH - || ability == ABILITY_MAGIC_GUARD - || ability == ABILITY_OVERCOAT - || holdEffect == HOLD_EFFECT_SAFETY_GOGGLES - || IS_BATTLER_OF_TYPE(battler, TYPE_ICE) - || HasMoveEffect(battler, EFFECT_BLIZZARD) - || HasMoveEffect(battler, EFFECT_AURORA_VEIL) - || HasMoveEffect(battler, EFFECT_WEATHER_BALL)) + || ability == ABILITY_ICE_BODY + || ability == ABILITY_FORECAST + || ability == ABILITY_SLUSH_RUSH + || ability == ABILITY_MAGIC_GUARD + || ability == ABILITY_OVERCOAT + || holdEffect == HOLD_EFFECT_SAFETY_GOGGLES + || IS_BATTLER_OF_TYPE(battler, TYPE_ICE) + || HasMoveEffect(battler, EFFECT_BLIZZARD) + || HasMoveEffect(battler, EFFECT_AURORA_VEIL) + || HasMoveEffect(battler, EFFECT_WEATHER_BALL)) { return TRUE; } @@ -1663,8 +1681,7 @@ bool32 ShouldSetHail(u32 battler, u32 ability, u32 holdEffect) bool32 ShouldSetRain(u32 battlerAtk, u32 atkAbility, u32 holdEffect) { - u32 weather = AI_GetWeather(); - if (weather & B_WEATHER_RAIN) + if (IsWeatherActive(B_WEATHER_RAIN | B_WEATHER_PRIMAL_ANY) != WEATHER_INACTIVE) return FALSE; if (holdEffect != HOLD_EFFECT_UTILITY_UMBRELLA @@ -1684,8 +1701,7 @@ bool32 ShouldSetRain(u32 battlerAtk, u32 atkAbility, u32 holdEffect) bool32 ShouldSetSun(u32 battlerAtk, u32 atkAbility, u32 holdEffect) { - u32 weather = AI_GetWeather(); - if (weather & B_WEATHER_SUN) + if (IsWeatherActive(B_WEATHER_SUN | B_WEATHER_PRIMAL_ANY) != WEATHER_INACTIVE) return FALSE; if (holdEffect != HOLD_EFFECT_UTILITY_UMBRELLA @@ -1710,18 +1726,17 @@ bool32 ShouldSetSun(u32 battlerAtk, u32 atkAbility, u32 holdEffect) bool32 ShouldSetSnow(u32 battler, u32 ability, u32 holdEffect) { - u32 weather = AI_GetWeather(); - if (weather & (B_WEATHER_SNOW | B_WEATHER_HAIL)) + if (IsWeatherActive(B_WEATHER_SNOW | B_WEATHER_HAIL | B_WEATHER_PRIMAL_ANY) != WEATHER_INACTIVE) return FALSE; if (ability == ABILITY_SNOW_CLOAK - || ability == ABILITY_ICE_BODY - || ability == ABILITY_FORECAST - || ability == ABILITY_SLUSH_RUSH - || IS_BATTLER_OF_TYPE(battler, TYPE_ICE) - || HasMoveEffect(battler, EFFECT_BLIZZARD) - || HasMoveEffect(battler, EFFECT_AURORA_VEIL) - || HasMoveEffect(battler, EFFECT_WEATHER_BALL)) + || ability == ABILITY_ICE_BODY + || ability == ABILITY_FORECAST + || ability == ABILITY_SLUSH_RUSH + || IS_BATTLER_OF_TYPE(battler, TYPE_ICE) + || HasMoveEffect(battler, EFFECT_BLIZZARD) + || HasMoveEffect(battler, EFFECT_AURORA_VEIL) + || HasMoveEffect(battler, EFFECT_WEATHER_BALL)) { return TRUE; } diff --git a/test/battle/ai/ai.c b/test/battle/ai/ai.c index 6b837a543c..5359ebe58f 100644 --- a/test/battle/ai/ai.c +++ b/test/battle/ai/ai.c @@ -914,3 +914,24 @@ SINGLE_BATTLE_TEST("AI correctly records used moves") EXPECT_EQ(BATTLE_HISTORY->usedMoves[B_POSITION_OPPONENT_LEFT][3], MOVE_EARTHQUAKE); } } + +AI_SINGLE_BATTLE_TEST("AI will not set up Weather if it wont have any affect") +{ + u32 ability; + + PARAMETRIZE { ability = ABILITY_CLOUD_NINE; } + PARAMETRIZE { ability = ABILITY_DAMP; } + + GIVEN { + ASSUME(GetMoveEffect(MOVE_RAIN_DANCE) == EFFECT_RAIN_DANCE); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY); + PLAYER(SPECIES_GOLDUCK) { Ability(ability); Moves(MOVE_SCRATCH); } + OPPONENT(SPECIES_KABUTOPS) { Ability(ABILITY_SWIFT_SWIM); Moves(MOVE_RAIN_DANCE, MOVE_POUND); } + } WHEN { + if (ability == ABILITY_CLOUD_NINE) + TURN { MOVE(player, MOVE_SCRATCH); EXPECT_MOVE(opponent, MOVE_POUND); } + else + TURN { MOVE(player, MOVE_SCRATCH); EXPECT_MOVE(opponent, MOVE_RAIN_DANCE); } + } +} +