From 5e027754c707881f62d66adb1fc22e12ca435622 Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Sun, 29 Sep 2024 12:16:33 -0400 Subject: [PATCH] Add ShouldSwitch result to AiLogicData (#5440) * Add ShouldSwitch to AiLogicData * Convert shouldSwitch to bitfield * Update include/battle.h Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> * Update include/battle.h --------- Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> --- include/battle.h | 3 ++- src/battle_ai_main.c | 6 +++--- src/battle_ai_switch_items.c | 4 ++-- src/battle_ai_util.c | 8 +++----- src/battle_main.c | 2 ++ 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/include/battle.h b/include/battle.h index 3b3c42e054..f1628ddd9b 100644 --- a/include/battle.h +++ b/include/battle.h @@ -366,11 +366,12 @@ struct AiLogicData u8 effectiveness[MAX_BATTLERS_COUNT][MAX_BATTLERS_COUNT][MAX_MON_MOVES]; // attacker, target, moveIndex u8 moveAccuracy[MAX_BATTLERS_COUNT][MAX_BATTLERS_COUNT][MAX_MON_MOVES]; // attacker, target, moveIndex u8 moveLimitations[MAX_BATTLERS_COUNT]; - bool8 shouldSwitchMon; // Because all available moves have no/little effect. Each bit per battler. + u8 shouldSwitchIfBadMoves; // Because all available moves have no/little effect. Each bit per battler. u8 monToSwitchId[MAX_BATTLERS_COUNT]; // ID of the mon to switch. bool8 weatherHasEffect; // The same as WEATHER_HAS_EFFECT. Stored here, so it's called only once. u8 mostSuitableMonId[MAX_BATTLERS_COUNT]; // Stores result of GetMostSuitableMonToSwitchInto, which decides which generic mon the AI would switch into if they decide to switch. This can be overruled by specific mons found in ShouldSwitch; the final resulting mon is stored in AI_monToSwitchIntoId. struct SwitchinCandidate switchinCandidate; // Struct used for deciding which mon to switch to in battle_ai_switch_items.c + u8 shouldSwitch; // Stores result of ShouldSwitch, which decides whether a mon should be switched out }; struct AI_ThinkingStruct diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 8848ac2c17..acc13a7378 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -504,12 +504,12 @@ static bool32 AI_SwitchMonIfSuitable(u32 battler, bool32 doubleBattle) if (doubleBattle) { u32 partner = BATTLE_PARTNER(battler); - if (AI_DATA->shouldSwitchMon & (1u << partner) && AI_DATA->monToSwitchId[partner] == monToSwitchId) + if (AI_DATA->shouldSwitchIfBadMoves & (1u << partner) && AI_DATA->monToSwitchId[partner] == monToSwitchId) { return FALSE; } } - AI_DATA->shouldSwitchMon |= 1 << battler; + AI_DATA->shouldSwitchIfBadMoves |= 1 << battler; AI_DATA->monToSwitchId[battler] = monToSwitchId; return TRUE; } @@ -3679,7 +3679,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) } break; case EFFECT_BATON_PASS: - if (ShouldSwitch(battlerAtk, FALSE) && (gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE + if ((AI_DATA->shouldSwitch & (1u << battlerAtk)) && (gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE || (gStatuses3[battlerAtk] & (STATUS3_ROOTED | STATUS3_AQUA_RING | STATUS3_MAGNET_RISE | STATUS3_POWER_TRICK)) || AnyStatIsRaised(battlerAtk))) ADJUST_SCORE(BEST_EFFECT); diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index b46fe29631..3f13a8c3f4 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -218,9 +218,9 @@ static bool32 HasBadOdds(u32 battler, bool32 emitResult) static bool32 ShouldSwitchIfAllBadMoves(u32 battler, bool32 emitResult) { - if (AI_DATA->shouldSwitchMon & (1u << battler)) + if (AI_DATA->shouldSwitchIfBadMoves & (1u << battler)) { - AI_DATA->shouldSwitchMon &= ~(1u << battler); + AI_DATA->shouldSwitchIfBadMoves &= ~(1u << battler); gBattleStruct->AI_monToSwitchIntoId[battler] = AI_DATA->monToSwitchId[battler]; if (emitResult) BtlController_EmitTwoReturnValues(battler, BUFFER_B, B_ACTION_SWITCH, 0); diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 3f08ace393..14f5c44ffc 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -2699,10 +2699,8 @@ enum { bool32 ShouldPivot(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 moveIndex) { bool32 hasStatBoost = AnyUsefulStatIsRaised(battlerAtk) || gBattleMons[battlerDef].statStages[STAT_EVASION] >= 9; //Significant boost in evasion for any class - bool32 shouldSwitch; u32 battlerToSwitch; - shouldSwitch = ShouldSwitch(battlerAtk, FALSE); battlerToSwitch = gBattleStruct->AI_monToSwitchIntoId[battlerAtk]; if (PartyBattlerShouldAvoidHazards(battlerAtk, battlerToSwitch)) @@ -2727,7 +2725,7 @@ bool32 ShouldPivot(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 if (CanTargetFaintAi(battlerDef, battlerAtk)) return PIVOT; // Won't get the two turns, pivot - if (!IS_MOVE_STATUS(move) && (shouldSwitch + if (!IS_MOVE_STATUS(move) && ((AI_DATA->shouldSwitch & (1u << battlerAtk)) || (AtMaxHp(battlerDef) && (AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_FOCUS_SASH || (B_STURDY >= GEN_5 && defAbility == ABILITY_STURDY) || defAbility == ABILITY_MULTISCALE @@ -2742,7 +2740,7 @@ bool32 ShouldPivot(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 || defAbility == ABILITY_SHADOW_SHIELD))) return PIVOT; // pivot to break sash/sturdy/multiscale - if (shouldSwitch) + if (AI_DATA->shouldSwitch & (1u << battlerAtk)) return PIVOT; /* TODO - check if switchable mon unafffected by/will remove hazards @@ -2813,7 +2811,7 @@ bool32 ShouldPivot(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 else if (CanAIFaintTarget(battlerAtk, battlerDef, 2)) { // can knock out foe in 2 hits - if (IS_MOVE_STATUS(move) && (shouldSwitch //Damaging move + if (IS_MOVE_STATUS(move) && ((AI_DATA->shouldSwitch & (1u << battlerAtk)) //Damaging move //&& (switchScore >= SWITCHING_INCREASE_RESIST_ALL_MOVES + SWITCHING_INCREASE_KO_FOE //remove hazards || (AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_FOCUS_SASH && AtMaxHp(battlerDef)))) return DONT_PIVOT; // Pivot to break the sash diff --git a/src/battle_main.c b/src/battle_main.c index e8c37c60b0..92e1618fc7 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -4178,6 +4178,8 @@ static void HandleTurnActionSelectionState(void) if ((gBattleTypeFlags & BATTLE_TYPE_HAS_AI || IsWildMonSmart()) && (BattlerHasAi(battler) && !(gBattleTypeFlags & BATTLE_TYPE_PALACE))) { + if (ShouldSwitch(battler, FALSE)) + AI_DATA->shouldSwitch |= (1u << battler); if (AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_RISKY) // Risky AI switches aggressively even mid battle AI_DATA->mostSuitableMonId[battler] = GetMostSuitableMonToSwitchInto(battler, TRUE); else