From 3a113e33b26ceaaa8d7f0492796796c677fdab44 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Mon, 8 Nov 2021 19:28:09 +1300 Subject: [PATCH 1/3] Uncomment AI Full Metal Body checks This ability is Clear Body with a different name, so it should be working and doesn't need to be commented out. --- src/battle_ai_util.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 1e229fbe81..781fb50e67 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1685,7 +1685,7 @@ bool32 ShouldLowerAttack(u8 battlerAtk, u8 battlerDef, u16 defAbility) && defAbility != ABILITY_CONTRARY && defAbility != ABILITY_CLEAR_BODY && defAbility != ABILITY_WHITE_SMOKE - //&& defAbility != ABILITY_FULL_METAL_BODY + && defAbility != ABILITY_FULL_METAL_BODY && defAbility != ABILITY_HYPER_CUTTER) return TRUE; return FALSE; @@ -1701,7 +1701,7 @@ bool32 ShouldLowerDefense(u8 battlerAtk, u8 battlerDef, u16 defAbility) && defAbility != ABILITY_CONTRARY && defAbility != ABILITY_CLEAR_BODY && defAbility != ABILITY_WHITE_SMOKE - //&& defAbility != ABILITY_FULL_METAL_BODY + && defAbility != ABILITY_FULL_METAL_BODY && defAbility != ABILITY_BIG_PECKS) return TRUE; return FALSE; @@ -1715,7 +1715,7 @@ bool32 ShouldLowerSpeed(u8 battlerAtk, u8 battlerDef, u16 defAbility) if (IsAiFaster(AI_CHECK_SLOWER) && defAbility != ABILITY_CONTRARY && defAbility != ABILITY_CLEAR_BODY - //&& defAbility != ABILITY_FULL_METAL_BODY + && defAbility != ABILITY_FULL_METAL_BODY && defAbility != ABILITY_WHITE_SMOKE) return TRUE; return FALSE; @@ -1730,7 +1730,7 @@ bool32 ShouldLowerSpAtk(u8 battlerAtk, u8 battlerDef, u16 defAbility) && HasMoveWithSplit(battlerDef, SPLIT_SPECIAL) && defAbility != ABILITY_CONTRARY && defAbility != ABILITY_CLEAR_BODY - //&& defAbility != ABILITY_FULL_METAL_BODY + && defAbility != ABILITY_FULL_METAL_BODY && defAbility != ABILITY_WHITE_SMOKE) return TRUE; return FALSE; @@ -1745,7 +1745,7 @@ bool32 ShouldLowerSpDef(u8 battlerAtk, u8 battlerDef, u16 defAbility) && HasMoveWithSplit(battlerAtk, SPLIT_SPECIAL) && defAbility != ABILITY_CONTRARY && defAbility != ABILITY_CLEAR_BODY - //&& defAbility != ABILITY_FULL_METAL_BODY + && defAbility != ABILITY_FULL_METAL_BODY && defAbility != ABILITY_WHITE_SMOKE) return TRUE; return FALSE; @@ -1759,7 +1759,7 @@ bool32 ShouldLowerAccuracy(u8 battlerAtk, u8 battlerDef, u16 defAbility) if (defAbility != ABILITY_CONTRARY && defAbility != ABILITY_CLEAR_BODY && defAbility != ABILITY_WHITE_SMOKE - //&& defAbility != ABILITY_FULL_METAL_BODY + && defAbility != ABILITY_FULL_METAL_BODY && defAbility != ABILITY_KEEN_EYE) return TRUE; return FALSE; @@ -1773,7 +1773,7 @@ bool32 ShouldLowerEvasion(u8 battlerAtk, u8 battlerDef, u16 defAbility) if (gBattleMons[battlerDef].statStages[STAT_EVASION] > DEFAULT_STAT_STAGE && defAbility != ABILITY_CONTRARY && defAbility != ABILITY_CLEAR_BODY - //&& defAbility != ABILITY_FULL_METAL_BODY + && defAbility != ABILITY_FULL_METAL_BODY && defAbility != ABILITY_WHITE_SMOKE) return TRUE; return FALSE; From d3a845d51170c6b103c15f908300727cb4f6da3c Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Mon, 8 Nov 2021 20:37:28 +1300 Subject: [PATCH 2/3] Fix CanAIFaintTarget Rename CanAIFaintTarget to CanIndexMoveFaintTarget and create a new function, CanAIFaintTarget, that checks if any known move can KO the target. --- include/battle_ai_util.h | 3 ++- src/battle_ai_main.c | 18 +++++++------- src/battle_ai_util.c | 54 +++++++++++++++++++++++++++++----------- 3 files changed, 51 insertions(+), 24 deletions(-) diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index b6df2168ea..1b2591899b 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -35,7 +35,8 @@ u16 AI_GetHoldEffect(u32 battlerId); u32 AI_GetMoveAccuracy(u8 battlerAtk, u8 battlerDef, u16 atkAbility, u16 defAbility, u8 atkHoldEffect, u8 defHoldEffect, u16 move); bool32 DoesBattlerIgnoreAbilityChecks(u16 atkAbility, u16 move); bool32 AI_WeatherHasEffect(void); -bool32 CanAttackerFaintTarget(u8 battlerAtk, u8 battlerDef, u8 index, u8 numHits); +bool32 CanAIFaintTarget(u8 battlerAtk, u8 battlerDef, u8 numHits); +bool32 CanIndexMoveFaintTarget(u8 battlerAtk, u8 battlerDef, u8 index, u8 numHits); bool32 AI_IsTerrainAffected(u8 battlerId, u32 flags); bool32 AI_IsBattlerGrounded(u8 battlerId); bool32 HasDamagingMove(u8 battlerId); diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 77196cf9ad..7fbb432603 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -1473,7 +1473,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) else if (move == MOVE_FAKE_OUT) // filter out first impression { if ((AI_DATA->atkHoldEffect == HOLD_EFFECT_CHOICE_BAND || AI_DATA->atkAbility == ABILITY_GORILLA_TACTICS) - && (CountUsablePartyMons(battlerDef) > 0 || !CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0))) + && (CountUsablePartyMons(battlerDef) > 0 || !CanIndexMoveFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0))) { if (CountUsablePartyMons(battlerAtk) == 0) score -= 10; // Don't lock the attacker into Fake Out if they can't switch out afterwards. @@ -1714,7 +1714,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) if (AI_DATA->defAbility == ABILITY_WONDER_GUARD && effectiveness < AI_EFFECTIVENESS_x2) score -= 10; else if (AI_DATA->atkAbility != ABILITY_TRUANT - && !CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) + && !CanIndexMoveFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) score -= 2; break; case EFFECT_SPITE: @@ -2465,7 +2465,7 @@ static s16 AI_TryToFaint(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) if (gBattleMoves[move].power == 0) return score; // can't make anything faint with no power - if (CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0) && gBattleMoves[move].effect != EFFECT_EXPLOSION) + if (CanIndexMoveFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0) && gBattleMoves[move].effect != EFFECT_EXPLOSION) { // this move can faint the target if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 0 || GetMovePriority(battlerAtk, move) > 0) @@ -2707,7 +2707,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) && !IS_MOVE_STATUS(move) && HasMoveWithSplit(battlerAtkPartner, SPLIT_PHYSICAL) && BattlerStatCanRise(battlerAtkPartner, atkPartnerAbility, STAT_ATK) - && !CanAttackerFaintTarget(battlerAtk, battlerAtkPartner, AI_THINKING_STRUCT->movesetIndex, 1)) + && !CanIndexMoveFaintTarget(battlerAtk, battlerAtkPartner, AI_THINKING_STRUCT->movesetIndex, 1)) { RETURN_SCORE_PLUS(1); } @@ -2716,7 +2716,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) if (!IS_MOVE_STATUS(move) && (moveType == TYPE_DARK || moveType == TYPE_GHOST || moveType == TYPE_BUG) && BattlerStatCanRise(battlerAtkPartner, atkPartnerAbility, STAT_SPEED) - && !CanAttackerFaintTarget(battlerAtk, battlerAtkPartner, AI_THINKING_STRUCT->movesetIndex, 1)) + && !CanIndexMoveFaintTarget(battlerAtk, battlerAtkPartner, AI_THINKING_STRUCT->movesetIndex, 1)) { RETURN_SCORE_PLUS(1); } @@ -2782,7 +2782,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) && !IS_MOVE_STATUS(move) && HasMoveWithSplit(battlerAtkPartner, SPLIT_PHYSICAL) && BattlerStatCanRise(battlerAtkPartner, atkPartnerAbility, STAT_ATK) - && !CanAttackerFaintTarget(battlerAtk, battlerAtkPartner, AI_THINKING_STRUCT->movesetIndex, 0)) + && !CanIndexMoveFaintTarget(battlerAtk, battlerAtkPartner, AI_THINKING_STRUCT->movesetIndex, 0)) { RETURN_SCORE_PLUS(1); } @@ -2971,7 +2971,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) case ABILITY_BEAST_BOOST: if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 0) // attacker should go first { - if (CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) + if (CanIndexMoveFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) score += 8; // prioritize killing target for stat boost } break; @@ -3772,7 +3772,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) case EFFECT_FELL_STINGER: if (gBattleMons[battlerAtk].statStages[STAT_ATK] < MAX_STAT_STAGE && AI_DATA->atkAbility != ABILITY_CONTRARY - && CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) + && CanIndexMoveFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) { if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 0) // Attacker goes first score += 9; @@ -4923,7 +4923,7 @@ static s16 AI_HPAware(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) } // consider target HP - if (CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) + if (CanIndexMoveFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) { score += 2; } diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 781fb50e67..84637b683e 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1048,6 +1048,32 @@ bool32 CanTargetFaintAi(u8 battlerDef, u8 battlerAtk) return FALSE; } +// Check if AI mon has the means to faint the target with any of its moves. +// If numHits > 1, check if the target will be KO'ed by that number of hits (ignoring healing effects) +bool32 CanAIFaintTarget(u8 battlerAtk, u8 battlerDef, u8 numHits) +{ + s32 i, dmg; + u32 unusable = CheckMoveLimitations(battlerAtk, 0, 0xFF & ~MOVE_LIMITATION_PP); + u16 *moves = gBattleMons[battlerAtk].moves; + + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (moves[i] != MOVE_NONE && moves[i] != 0xFFFF && !(unusable & gBitTable[i])) + { + continue; + } + // Use the pre-calculated value in simulatedDmg instead of re-calculating it + dmg = AI_THINKING_STRUCT->simulatedDmg[battlerAtk][battlerDef][i]; + + if (numHits) + dmg *= numHits; + if (gBattleMons[battlerDef].hp <= dmg) + return TRUE; + } + + return FALSE; +} + bool32 CanMoveFaintBattler(u16 move, u8 battlerDef, u8 battlerAtk, u8 nHits) { s32 i, dmg; @@ -1677,7 +1703,7 @@ u32 CountNegativeStatStages(u8 battlerId) bool32 ShouldLowerAttack(u8 battlerAtk, u8 battlerDef, u16 defAbility) { - if (IsAiFaster(AI_CHECK_FASTER) && CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) + if (IsAiFaster(AI_CHECK_FASTER) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) return FALSE; // Don't bother lowering stats if can kill enemy. if (gBattleMons[battlerDef].statStages[STAT_ATK] > 4 @@ -1693,7 +1719,7 @@ bool32 ShouldLowerAttack(u8 battlerAtk, u8 battlerDef, u16 defAbility) bool32 ShouldLowerDefense(u8 battlerAtk, u8 battlerDef, u16 defAbility) { - if (IsAiFaster(AI_CHECK_FASTER) && CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) + if (IsAiFaster(AI_CHECK_FASTER) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) return FALSE; // Don't bother lowering stats if can kill enemy. if (gBattleMons[battlerDef].statStages[STAT_DEF] > 4 @@ -1709,7 +1735,7 @@ bool32 ShouldLowerDefense(u8 battlerAtk, u8 battlerDef, u16 defAbility) bool32 ShouldLowerSpeed(u8 battlerAtk, u8 battlerDef, u16 defAbility) { - if (IsAiFaster(AI_CHECK_FASTER) && CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) + if (IsAiFaster(AI_CHECK_FASTER) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) return FALSE; // Don't bother lowering stats if can kill enemy. if (IsAiFaster(AI_CHECK_SLOWER) @@ -1723,7 +1749,7 @@ bool32 ShouldLowerSpeed(u8 battlerAtk, u8 battlerDef, u16 defAbility) bool32 ShouldLowerSpAtk(u8 battlerAtk, u8 battlerDef, u16 defAbility) { - if (IsAiFaster(AI_CHECK_FASTER) && CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) + if (IsAiFaster(AI_CHECK_FASTER) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) return FALSE; // Don't bother lowering stats if can kill enemy. if (gBattleMons[battlerDef].statStages[STAT_SPATK] > 4 @@ -1738,7 +1764,7 @@ bool32 ShouldLowerSpAtk(u8 battlerAtk, u8 battlerDef, u16 defAbility) bool32 ShouldLowerSpDef(u8 battlerAtk, u8 battlerDef, u16 defAbility) { - if (IsAiFaster(AI_CHECK_FASTER) && CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) + if (IsAiFaster(AI_CHECK_FASTER) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) return FALSE; // Don't bother lowering stats if can kill enemy. if (gBattleMons[battlerDef].statStages[STAT_SPDEF] > 4 @@ -1753,7 +1779,7 @@ bool32 ShouldLowerSpDef(u8 battlerAtk, u8 battlerDef, u16 defAbility) bool32 ShouldLowerAccuracy(u8 battlerAtk, u8 battlerDef, u16 defAbility) { - if (IsAiFaster(AI_CHECK_FASTER) && CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) + if (IsAiFaster(AI_CHECK_FASTER) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) return FALSE; // Don't bother lowering stats if can kill enemy. if (defAbility != ABILITY_CONTRARY @@ -1767,7 +1793,7 @@ bool32 ShouldLowerAccuracy(u8 battlerAtk, u8 battlerDef, u16 defAbility) bool32 ShouldLowerEvasion(u8 battlerAtk, u8 battlerDef, u16 defAbility) { - if (IsAiFaster(AI_CHECK_FASTER) && CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) + if (IsAiFaster(AI_CHECK_FASTER) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) return FALSE; // Don't bother lowering stats if can kill enemy. if (gBattleMons[battlerDef].statStages[STAT_EVASION] > DEFAULT_STAT_STAGE @@ -1779,7 +1805,7 @@ bool32 ShouldLowerEvasion(u8 battlerAtk, u8 battlerDef, u16 defAbility) return FALSE; } -bool32 CanAttackerFaintTarget(u8 battlerAtk, u8 battlerDef, u8 index, u8 numHits) +bool32 CanIndexMoveFaintTarget(u8 battlerAtk, u8 battlerDef, u8 index, u8 numHits) { s32 dmg = AI_THINKING_STRUCT->simulatedDmg[battlerAtk][battlerDef][index]; @@ -2433,9 +2459,9 @@ bool32 ShouldPivot(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u8 mo if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 0) // Attacker goes first { - if (!CanAttackerFaintTarget(battlerAtk, battlerDef, moveIndex, 0)) // Can't KO foe otherwise + if (!CanAIFaintTarget(battlerAtk, battlerDef, 0)) // Can't KO foe otherwise { - if (CanAttackerFaintTarget(battlerAtk, battlerDef, moveIndex, 2)) + if (CanAIFaintTarget(battlerAtk, battlerDef, 2)) { // attacker can kill target in two hits (theoretically) if (CanTargetFaintAi(battlerDef, battlerAtk)) @@ -2500,7 +2526,7 @@ bool32 ShouldPivot(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u8 mo } else if (CanTargetFaintAiWithMod(battlerDef, battlerAtk, 0, 2)) // Foe can 2HKO AI { - if (CanAttackerFaintTarget(battlerAtk, battlerDef, moveIndex, 0)) + if (CanAIFaintTarget(battlerAtk, battlerDef, 0)) { if (!BattlerWillFaintFromSecondaryDamage(battlerAtk, AI_DATA->atkAbility)) return CAN_TRY_PIVOT; // Use this move to KO if you must @@ -2512,7 +2538,7 @@ bool32 ShouldPivot(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u8 mo } else // Foe can 3HKO+ AI { - if (CanAttackerFaintTarget(battlerAtk, battlerDef, moveIndex, 0)) + if (CanAIFaintTarget(battlerAtk, battlerDef, 0)) { if (!BattlerWillFaintFromSecondaryDamage(battlerAtk, AI_DATA->atkAbility) // This is the only move that can KO && !hasStatBoost) //You're not wasting a valuable stat boost @@ -2520,7 +2546,7 @@ bool32 ShouldPivot(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u8 mo return CAN_TRY_PIVOT; } } - else if (CanAttackerFaintTarget(battlerAtk, battlerDef, moveIndex, 2)) + else if (CanAIFaintTarget(battlerAtk, battlerDef, 2)) { // can knock out foe in 2 hits if (IS_MOVE_STATUS(move) && (shouldSwitch //Damaging move @@ -2904,7 +2930,7 @@ bool32 ShouldUseRecoilMove(u8 battlerAtk, u8 battlerDef, u32 recoilDmg, u8 moveI if (recoilDmg >= gBattleMons[battlerAtk].hp //Recoil kills attacker && CountUsablePartyMons(battlerDef) != 0) //Foe has more than 1 target left { - if (recoilDmg >= gBattleMons[battlerDef].hp && !CanAttackerFaintTarget(battlerAtk, battlerDef, moveIndex, 0)) + if (recoilDmg >= gBattleMons[battlerDef].hp && !CanAIFaintTarget(battlerAtk, battlerDef, 0)) return TRUE; //If it's the only KO move then just use it else return FALSE; //Not as good to use move if you'll faint and not win From 03cab2058a7b6d77b670251fc0702e5b3c4cef2f Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Mon, 8 Nov 2021 23:57:16 +1300 Subject: [PATCH 3/3] Fix goof, make AI check PP in move limitations Was skipping valid moves instead of invalid ones in CanAIFaintTarget. Also, remove all instances of ~MOVE_LIMITATION_PP from the AI as it seemed detrimental. --- src/battle_ai_util.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 84637b683e..71dc78d0aa 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -660,9 +660,9 @@ bool32 MovesWithSplitUnusable(u32 attacker, u32 target, u32 split) for (i = 0; i < MAX_MON_MOVES; i++) { if (moves[i] != MOVE_NONE - && moves[i] != 0xFFFF - && GetBattleMoveSplit(moves[i]) == split - && !(unusable & gBitTable[i])) + && moves[i] != 0xFFFF + && GetBattleMoveSplit(moves[i]) == split + && !(unusable & gBitTable[i])) { SetTypeBeforeUsingMove(moves[i], attacker); GET_MOVE_TYPE(moves[i], moveType); @@ -1033,7 +1033,7 @@ bool32 IsAiFaster(u8 battler) bool32 CanTargetFaintAi(u8 battlerDef, u8 battlerAtk) { s32 i, dmg; - u32 unusable = CheckMoveLimitations(battlerDef, 0, 0xFF & ~MOVE_LIMITATION_PP); + u32 unusable = CheckMoveLimitations(battlerDef, 0, 0xFF); u16 *moves = gBattleResources->battleHistory->usedMoves[battlerDef]; for (i = 0; i < MAX_MON_MOVES; i++) @@ -1053,22 +1053,22 @@ bool32 CanTargetFaintAi(u8 battlerDef, u8 battlerAtk) bool32 CanAIFaintTarget(u8 battlerAtk, u8 battlerDef, u8 numHits) { s32 i, dmg; - u32 unusable = CheckMoveLimitations(battlerAtk, 0, 0xFF & ~MOVE_LIMITATION_PP); + u32 moveLimitations = CheckMoveLimitations(battlerAtk, 0, 0xFF); u16 *moves = gBattleMons[battlerAtk].moves; for (i = 0; i < MAX_MON_MOVES; i++) { - if (moves[i] != MOVE_NONE && moves[i] != 0xFFFF && !(unusable & gBitTable[i])) + if (moves[i] != MOVE_NONE && moves[i] != 0xFFFF && !(moveLimitations & gBitTable[i])) { - continue; - } - // Use the pre-calculated value in simulatedDmg instead of re-calculating it - dmg = AI_THINKING_STRUCT->simulatedDmg[battlerAtk][battlerDef][i]; + // Use the pre-calculated value in simulatedDmg instead of re-calculating it + dmg = AI_THINKING_STRUCT->simulatedDmg[battlerAtk][battlerDef][i]; - if (numHits) - dmg *= numHits; - if (gBattleMons[battlerDef].hp <= dmg) - return TRUE; + if (numHits) + dmg *= numHits; + + if (gBattleMons[battlerDef].hp <= dmg) + return TRUE; + } } return FALSE; @@ -1077,7 +1077,7 @@ bool32 CanAIFaintTarget(u8 battlerAtk, u8 battlerDef, u8 numHits) bool32 CanMoveFaintBattler(u16 move, u8 battlerDef, u8 battlerAtk, u8 nHits) { s32 i, dmg; - u32 unusable = CheckMoveLimitations(battlerDef, 0, 0xFF & ~MOVE_LIMITATION_PP); + u32 unusable = CheckMoveLimitations(battlerDef, 0, 0xFF); if (move != MOVE_NONE && move != 0xFFFF && !(unusable & gBitTable[i]) && AI_CalcDamage(move, battlerDef, battlerAtk) >= gBattleMons[battlerAtk].hp) return TRUE; @@ -1089,7 +1089,7 @@ bool32 CanMoveFaintBattler(u16 move, u8 battlerDef, u8 battlerAtk, u8 nHits) bool32 CanTargetFaintAiWithMod(u8 battlerDef, u8 battlerAtk, s32 hpMod, s32 dmgMod) { u32 i; - u32 unusable = CheckMoveLimitations(battlerDef, 0, 0xFF & ~MOVE_LIMITATION_PP); + u32 unusable = CheckMoveLimitations(battlerDef, 0, 0xFF); u16 *moves = gBattleResources->battleHistory->usedMoves[battlerDef]; for (i = 0; i < MAX_MON_MOVES; i++)