From d65d5cb8fd7e87dff287500da218cbedfad52e9f Mon Sep 17 00:00:00 2001 From: Evan Date: Sun, 14 Feb 2021 09:37:04 -0700 Subject: [PATCH] add AI_FLAG_SMART_SWITCHING, some burn checks --- include/battle_ai_util.h | 1 + include/constants/battle_ai.h | 1 + src/battle_ai_main.c | 34 +++++++++++++++++++++------------- src/battle_ai_util.c | 16 ++++++++++++++++ 4 files changed, 39 insertions(+), 13 deletions(-) diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index f83fa8522..db33a7ff1 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -81,6 +81,7 @@ u8 AI_GetMoveEffectiveness(u16 move, u8 battlerAtk, u8 battlerDef); u16 *GetMovesArray(u32 battler); bool32 IsConfusionMoveEffect(u16 moveEffect); bool32 HasMove(u32 battlerId, u32 move); +bool32 HasOnlyMovesWithSplit(u32 battlerId, u32 split, bool32 onlyOffensive); bool32 HasMoveWithSplit(u32 battler, u32 split); bool32 HasMoveWithType(u32 battler, u8 type); bool32 HasMoveWithTypeAndSplit(u32 battler, u8 type, u8 split); diff --git a/include/constants/battle_ai.h b/include/constants/battle_ai.h index 6b17a5379..7f56fbced 100644 --- a/include/constants/battle_ai.h +++ b/include/constants/battle_ai.h @@ -53,6 +53,7 @@ #define AI_FLAG_PREFER_STATUS_MOVES (1 << 12) // AI gets a score bonus for status moves. Should be combined with AI_FLAG_CHECK_BAD_MOVE to prevent using only status moves #define AI_FLAG_STALL (1 << 13) // AI stalls battle and prefers secondary damage/trapping/etc. TODO not finished #define AI_FLAG_SCREENER (1 << 14) // AI prefers screening effects like reflect, mist, etc. TODO unfinished +#define AI_FLAG_SMART_SWITCHING (1 << 15) // AI includes a lot more switching checks // 'other' ai logic flags #define AI_FLAG_ROAMING (1 << 29) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index fcafd648c..18c7a67f2 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -2864,18 +2864,6 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) // check damage if (gBattleMoves[move].power != 0 && GetMoveDamageResult(move) == MOVE_POWER_WEAK) score--; - - /*if (CountUsablePartyMons(battlerAtk) != 0 - && GetMoveDamageResult(move) != 0 && !HasMoveWithSplit(battlerAtk, SPLIT_STATUS) - && GetCurrDamageHpPercent(battlerAtk, battlerDef) < 30) - { - if (GetCurrDamageHpPercent(battlerAtk, battlerDef) > 20) - score--; - else if (GetMoveDamageResult(move) == MOVE_POWER_BEST) - score -= 2; - else - score -= 3; - }*/ // check status move preference if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_PREFER_STATUS_MOVES && IS_MOVE_STATUS(move) && effectiveness != AI_EFFECTIVENESS_x0) @@ -2885,6 +2873,25 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) if ((gBattleMons[battlerAtk].status1 & STATUS1_FREEZE) && IsThawingMove(battlerAtk, move)) score += (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) ? 20 : 10; + // check burn + if (gBattleMons[battlerAtk].status1 & STATUS1_BURN) + { + switch (AI_DATA->atkAbility) + { + case ABILITY_GUTS: + break; + case ABILITY_NATURAL_CURE: + if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_SMART_SWITCHING + && HasOnlyMovesWithSplit(battlerAtk, SPLIT_PHYSICAL, TRUE)) + score = 90; // Force switch if all your attacking moves are physical and you have Natural Cure. + break; + default: + if (IS_MOVE_PHYSICAL(move) && gBattleMoves[move].effect != EFFECT_FACADE) + score -= 2; + break; + } + } + // ability checks switch (AI_DATA->atkAbility) { @@ -4534,7 +4541,8 @@ static s16 AI_SetupFirstTurn(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) || gBattleResults.battleTurnCounter != 0) return score; - if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 1 + if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_SMART_SWITCHING + && GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 1 && CanTargetFaintAi(battlerDef, battlerAtk) && GetMovePriority(battlerAtk, move) == 0) { diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 1c55d0798..2e1dc7123 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1755,6 +1755,22 @@ u16 *GetMovesArray(u32 battler) return gBattleResources->battleHistory->usedMoves[battler]; } +bool32 HasOnlyMovesWithSplit(u32 battlerId, u32 split, bool32 onlyOffensive) +{ + u32 i; + u16 *moves = GetMovesArray(battlerId); + + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (onlyOffensive && IS_MOVE_STATUS(moves[i])) + continue; + if (moves[i] != MOVE_NONE && moves[i] != 0xFFFF && GetBattleMoveSplit(moves[i]) != split) + return FALSE; + } + + return TRUE; +} + bool32 HasMoveWithSplit(u32 battler, u32 split) { u32 i;