diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 2705cc4b6d..ec517d5a27 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -191,6 +191,7 @@ bool32 IsHazardMove(u32 move); bool32 IsTwoTurnNotSemiInvulnerableMove(u32 battlerAtk, u32 move); bool32 IsBattlerDamagedByStatus(u32 battler); s32 ProtectChecks(u32 battlerAtk, u32 battlerDef, u32 move, u32 predictedMove); +bool32 ShouldRaiseAnyStat(u32 battlerAtk, u32 battlerDef); bool32 ShouldSetWeather(u32 battler, u32 weather); bool32 ShouldClearWeather(u32 battler, u32 weather); bool32 ShouldSetFieldStatus(u32 battler, u32 fieldStatus); diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index ee3da9f4a5..a43b957a50 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1949,6 +1949,43 @@ bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbil return FALSE; } +bool32 ShouldRaiseAnyStat(u32 battlerAtk, u32 battlerDef) +{ + if (AreBattlersStatsMaxed(battlerAtk)) + return FALSE; + + // Don't increase stats if opposing battler has Unaware + if (HasBattlerSideAbility(battlerDef, ABILITY_UNAWARE, gAiLogicData)) + return FALSE; + + // Don't set up if AI is dead to residual damage from weather + if (GetBattlerSecondaryDamage(battlerAtk) >= gBattleMons[battlerAtk].hp) + return FALSE; + + // Don't increase stats if opposing battler has Opportunist + if (HasBattlerSideAbility(battlerDef, ABILITY_OPPORTUNIST, gAiLogicData)) + return FALSE; + + // Don't increase stats if opposing battler has Encore + if (HasBattlerSideMoveWithEffect(battlerDef, EFFECT_ENCORE)) + return FALSE; + + // Don't increase stats if opposing battler has used Haze effect or AI effect + if (!RandomPercentage(RNG_AI_BOOST_INTO_HAZE, BOOST_INTO_HAZE_CHANCE) + && HasBattlerSideUsedMoveWithEffect(battlerDef, EFFECT_HAZE)) + return FALSE; + + if (CountPositiveStatStages(battlerAtk) > 0 + && HasBattlerSideMoveWithAIEffect(battlerDef, AI_EFFECT_RESET_STATS)) + return FALSE; + + // Don't increase stats if AI could KO target through Sturdy effect, as otherwise it always 2HKOs + if (CanBattlerKOTargetIgnoringSturdy(battlerAtk, battlerDef)) + return FALSE; + + return TRUE; +} + bool32 ShouldSetWeather(u32 battler, u32 weather) { return WeatherChecker(battler, weather, FIELD_EFFECT_POSITIVE); @@ -4559,8 +4596,7 @@ static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, if (considerContrary && gAiLogicData->abilities[battlerAtk] == ABILITY_CONTRARY) return NO_INCREASE; - // Don't increase stats if opposing battler has Unaware - if (HasBattlerSideAbility(battlerDef, ABILITY_UNAWARE, gAiLogicData)) + if (!ShouldRaiseAnyStat(battlerAtk, battlerDef)) return NO_INCREASE; // Don't increase stat if AI is at +4 @@ -4571,32 +4607,6 @@ static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, if (gAiLogicData->hpPercents[battlerAtk] < 70 && noOfHitsToFaint == UNKNOWN_NO_OF_HITS) return NO_INCREASE; - // Don't set up if AI is dead to residual damage from weather - if (GetBattlerSecondaryDamage(battlerAtk) >= gBattleMons[battlerAtk].hp) - return NO_INCREASE; - - // Don't increase stats if opposing battler has Opportunist - if (HasBattlerSideAbility(battlerDef, ABILITY_OPPORTUNIST, gAiLogicData)) - return NO_INCREASE; - - // Don't increase stats if opposing battler has Encore - if (HasBattlerSideMoveWithEffect(battlerDef, EFFECT_ENCORE)) - return NO_INCREASE; - - // Don't increase stats if opposing battler has used Haze effect or AI effect - if (!RandomPercentage(RNG_AI_BOOST_INTO_HAZE, BOOST_INTO_HAZE_CHANCE) - && HasBattlerSideUsedMoveWithEffect(battlerDef, EFFECT_HAZE)) - return NO_INCREASE; - - // Don't increase if AI is at +1 and opponent has Haze effect - if (gBattleMons[battlerAtk].statStages[statId] >= MAX_STAT_STAGE - 5 - && HasBattlerSideMoveWithAIEffect(battlerDef, AI_EFFECT_RESET_STATS)) - return NO_INCREASE; - - // Don't increase stats if AI could KO target through Sturdy effect, as otherwise it always 2HKOs - if (CanBattlerKOTargetIgnoringSturdy(battlerAtk, battlerDef)) - return NO_INCREASE; - // Don't increase stats if player has a move that can change the KO threshold if (HasMoveThatChangesKOThreshold(battlerDef, noOfHitsToFaint, aiIsFaster)) return NO_INCREASE; @@ -4884,11 +4894,7 @@ bool32 ShouldUseZMove(u32 battlerAtk, u32 battlerDef, u32 chosenMove) return TRUE; break; case Z_EFFECT_ALL_STATS_UP_1: - if (AreBattlersStatsMaxed(battlerAtk)) - return FALSE; - return IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_ATK) > 0 - || IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPATK) > 0; - break; + return ShouldRaiseAnyStat(battlerAtk, battlerDef); case Z_EFFECT_BOOST_CRITS: return TRUE; case Z_EFFECT_FOLLOW_ME: @@ -4938,7 +4944,7 @@ bool32 ShouldUseZMove(u32 battlerAtk, u32 battlerDef, u32 chosenMove) } else if (GetMoveEffect(zMove) == EFFECT_EXTREME_EVOBOOST) { - return (!AreBattlersStatsMaxed(battlerAtk) && (IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_ATK_2) || IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPATK_2))); + return ShouldRaiseAnyStat(battlerAtk, battlerDef); } else if (!IsBattleMoveStatus(chosenMove) && IsBattleMoveStatus(zMove)) return FALSE;