diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index b6b16524af..62cba4949e 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -289,7 +289,7 @@ s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct Battl u32 AI_WhoStrikesFirstPartyMon(u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, u32 aiMoveConsidered, u32 playerMoveConsidered, enum ConsiderPriority ConsiderPriority); s32 AI_TryToClearStats(u32 battlerAtk, u32 battlerDef, bool32 isDoubleBattle); bool32 AI_ShouldCopyStatChanges(u32 battlerAtk, u32 battlerDef); -bool32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData); +bool32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, u32 move, struct AiLogicData *aiData); void IncreaseTidyUpScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score); bool32 AI_ShouldSpicyExtract(u32 battlerAtk, u32 battlerAtkPartner, u32 move, struct AiLogicData *aiData); u32 IncreaseSubstituteMoveScore(u32 battlerAtk, u32 battlerDef, u32 move); diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 4b7f8bddd9..528bcbd859 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -4416,11 +4416,13 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(GOOD_EFFECT); } break; + case EFFECT_CEASELESS_EDGE: case EFFECT_SPIKES: case EFFECT_STEALTH_ROCK: case EFFECT_STICKY_WEB: + case EFFECT_STONE_AXE: case EFFECT_TOXIC_SPIKES: - if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, aiData)) + if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, move, aiData)) { if (gDisableStructs[battlerAtk].isFirstTurn) ADJUST_SCORE(BEST_EFFECT); @@ -5319,16 +5321,6 @@ case EFFECT_GUARD_SPLIT: break; } break; - case EFFECT_STONE_AXE: - case EFFECT_CEASELESS_EDGE: - if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, aiData)); - { - if (gDisableStructs[battlerAtk].isFirstTurn) - ADJUST_SCORE(BEST_EFFECT); - else - ADJUST_SCORE(DECENT_EFFECT); - } - break; default: break; } // move effect checks @@ -5473,7 +5465,7 @@ case EFFECT_GUARD_SPLIT: ADJUST_SCORE(DECENT_EFFECT); break; case MOVE_EFFECT_STEALTH_ROCK: - if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, aiData)); + if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, move, aiData)); { if (gDisableStructs[battlerAtk].isFirstTurn) ADJUST_SCORE(BEST_EFFECT); @@ -6062,7 +6054,7 @@ static s32 AI_PowerfulStatus(u32 battlerAtk, u32 battlerDef, u32 move, s32 score case EFFECT_STEALTH_ROCK: case EFFECT_STICKY_WEB: case EFFECT_TOXIC_SPIKES: - if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, gAiLogicData)) + if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, move, gAiLogicData)) ADJUST_SCORE(POWERFUL_STATUS_MOVE); break; case EFFECT_GRASSY_TERRAIN: diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 229a9a8c68..8e6f0d79a2 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1639,6 +1639,9 @@ bool32 DoesBattlerIgnoreAbilityChecks(u32 battlerAtk, u32 atkAbility, u32 move) if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_NEGATE_UNAWARE) return FALSE; // AI handicap flag: doesn't understand ability suppression concept + if (atkAbility == ABILITY_MYCELIUM_MIGHT && IsBattleMoveStatus(move)) + return TRUE; + if (IsMoldBreakerTypeAbility(battlerAtk, atkAbility) || MoveIgnoresTargetAbility(move)) return TRUE; @@ -1750,10 +1753,12 @@ bool32 IsHazardMove(u32 move) u32 i, moveEffect = GetMoveEffect(move); switch (moveEffect) { + case EFFECT_CEASELESS_EDGE: case EFFECT_SPIKES: - case EFFECT_TOXIC_SPIKES: - case EFFECT_STICKY_WEB: case EFFECT_STEALTH_ROCK: + case EFFECT_STICKY_WEB: + case EFFECT_STONE_AXE: + case EFFECT_TOXIC_SPIKES: return TRUE; } @@ -1763,6 +1768,7 @@ bool32 IsHazardMove(u32 move) const struct AdditionalEffect *additionalEffect = GetMoveAdditionalEffectById(move, i); switch (additionalEffect->moveEffect) { + case MOVE_EFFECT_STEALTH_ROCK: case MOVE_EFFECT_STEELSURGE: return TRUE; default: @@ -4967,17 +4973,32 @@ bool32 AI_ShouldCopyStatChanges(u32 battlerAtk, u32 battlerDef) } //TODO - track entire opponent party data to determine hazard effectiveness -bool32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData) +bool32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, u32 move, struct AiLogicData *aiData) { - if (aiData->abilities[battlerDef] == ABILITY_MAGIC_BOUNCE - || CountUsablePartyMons(battlerDef) == 0 - || HasMoveWithEffect(battlerDef, EFFECT_RAPID_SPIN) - || HasMoveWithEffect(battlerDef, EFFECT_TIDY_UP) - || HasMoveWithEffect(battlerDef, EFFECT_DEFOG) - || HasMoveWithAdditionalEffect(battlerDef, MOVE_EFFECT_DEFOG) - || HasMoveWithEffect(battlerDef, EFFECT_MAGIC_COAT)) + if (CountUsablePartyMons(battlerDef) == 0 + || HasBattlerSideMoveWithEffect(battlerDef, EFFECT_COURT_CHANGE) + || HasBattlerSideMoveWithEffect(battlerDef, EFFECT_DEFOG) + || HasBattlerSideMoveWithEffect(battlerDef, EFFECT_RAPID_SPIN) + || HasBattlerSideMoveWithEffect(battlerDef, EFFECT_TIDY_UP) + || HasBattlerSideMoveWithEffect(battlerDef, MOVE_EFFECT_DEFOG)) return FALSE; + if (IsBattleMoveStatus(move)) + { + if (HasMoveWithEffect(battlerDef, EFFECT_MAGIC_COAT)) + return FALSE; + if (DoesBattlerIgnoreAbilityChecks(battlerAtk, aiData->abilities[battlerAtk], move)) + return TRUE; + if (aiData->abilities[battlerDef] == ABILITY_MAGIC_BOUNCE) + return FALSE; + } + else + { + if (DoesBattlerIgnoreAbilityChecks(battlerAtk, aiData->abilities[battlerAtk], move)) + return TRUE; + if (aiData->abilities[battlerDef] == ABILITY_SHIELD_DUST) + return FALSE; + } return TRUE; }