From 406e5b1def8c08d47de86b5be0148e4af5e120b9 Mon Sep 17 00:00:00 2001 From: surskitty Date: Mon, 1 Sep 2025 13:02:56 -0400 Subject: [PATCH] IncreaseStatUpScore adjustments for Simple, +3 moves, Acupressure, max move effects (#7662) --- include/battle_ai_main.h | 5 ++ src/battle_ai_main.c | 23 +++++++- src/battle_ai_util.c | 119 ++++++++++++++++++++++++--------------- 3 files changed, 101 insertions(+), 46 deletions(-) diff --git a/include/battle_ai_main.h b/include/battle_ai_main.h index b3bc57c4e9..4330f9d2bc 100644 --- a/include/battle_ai_main.h +++ b/include/battle_ai_main.h @@ -23,6 +23,11 @@ enum StatChange STAT_CHANGE_SPEED_2, STAT_CHANGE_SPATK_2, STAT_CHANGE_SPDEF_2, + STAT_CHANGE_ATK_3, + STAT_CHANGE_DEF_3, + STAT_CHANGE_SPEED_3, + STAT_CHANGE_SPATK_3, + STAT_CHANGE_SPDEF_3, STAT_CHANGE_ACC, STAT_CHANGE_EVASION }; diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 91e8046b7c..8d9397fec7 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -4119,13 +4119,15 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_ATK_2)); break; case EFFECT_DEFENSE_UP: - case EFFECT_DEFENSE_UP_3: ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_DEF)); break; case EFFECT_STUFF_CHEEKS: case EFFECT_DEFENSE_UP_2: ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_DEF_2)); break; + case EFFECT_DEFENSE_UP_3: + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_DEF_3)); + break; case EFFECT_SPEED_UP: ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPEED)); break; @@ -4137,9 +4139,11 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPATK)); break; case EFFECT_SPECIAL_ATTACK_UP_2: - case EFFECT_SPECIAL_ATTACK_UP_3: ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPATK_2)); break; + case EFFECT_SPECIAL_ATTACK_UP_3: + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPATK_3)); + break; case EFFECT_SPECIAL_DEFENSE_UP: ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPDEF)); break; @@ -4188,7 +4192,10 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case EFFECT_BIDE: if (aiData->hpPercents[battlerAtk] < 90) ADJUST_SCORE(-2); // Should be either removed or turned into increasing score + // treat as offense booster case EFFECT_ACUPRESSURE: + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_ATK_2)); + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPATK_2)); break; case EFFECT_GEAR_UP: if (aiData->abilities[battlerAtk] == ABILITY_PLUS || aiData->abilities[battlerAtk] == ABILITY_MINUS) @@ -5688,6 +5695,18 @@ case EFFECT_GUARD_SPLIT: ADJUST_SCORE(IncreaseStatDownScore(battlerAtk, battlerDef, statId)); break; } + case MOVE_EFFECT_RAISE_TEAM_ATTACK: + case MOVE_EFFECT_RAISE_TEAM_DEFENSE: + case MOVE_EFFECT_RAISE_TEAM_SPEED: + case MOVE_EFFECT_RAISE_TEAM_SP_ATK: + case MOVE_EFFECT_RAISE_TEAM_SP_DEF: + { + enum StatChange StageStatId = STAT_CHANGE_ATK + additionalEffect->moveEffect - MOVE_EFFECT_RAISE_TEAM_ATTACK; + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, StageStatId)); + if (hasPartner) + ADJUST_SCORE(IncreaseStatUpScore(BATTLE_PARTNER(battlerAtk), battlerDef, StageStatId)); + break; + } case MOVE_EFFECT_LOWER_ATTACK_SIDE: case MOVE_EFFECT_LOWER_DEFENSE_SIDE: case MOVE_EFFECT_LOWER_SPEED_SIDE: diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index c3d4b66965..71ecb3da32 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -4480,18 +4480,23 @@ static u32 GetStatBeingChanged(enum StatChange statChange) { case STAT_CHANGE_ATK: case STAT_CHANGE_ATK_2: + case STAT_CHANGE_ATK_3: return STAT_ATK; case STAT_CHANGE_DEF: case STAT_CHANGE_DEF_2: + case STAT_CHANGE_DEF_3: return STAT_DEF; case STAT_CHANGE_SPEED: case STAT_CHANGE_SPEED_2: + case STAT_CHANGE_SPEED_3: return STAT_SPEED; case STAT_CHANGE_SPATK: case STAT_CHANGE_SPATK_2: + case STAT_CHANGE_SPATK_3: return STAT_SPATK; case STAT_CHANGE_SPDEF: case STAT_CHANGE_SPDEF_2: + case STAT_CHANGE_SPDEF_3: return STAT_SPDEF; case STAT_CHANGE_ACC: return STAT_ACC; @@ -4501,6 +4506,34 @@ static u32 GetStatBeingChanged(enum StatChange statChange) return 0; // STAT_HP, should never be getting changed } +static u32 GetStagesOfStatChange(enum StatChange statChange) +{ + switch(statChange) + { + case STAT_CHANGE_ATK: + case STAT_CHANGE_DEF: + case STAT_CHANGE_SPEED: + case STAT_CHANGE_SPATK: + case STAT_CHANGE_SPDEF: + case STAT_CHANGE_ACC: + case STAT_CHANGE_EVASION: + return 1; + case STAT_CHANGE_ATK_2: + case STAT_CHANGE_DEF_2: + case STAT_CHANGE_SPEED_2: + case STAT_CHANGE_SPATK_2: + case STAT_CHANGE_SPDEF_2: + return 2; + case STAT_CHANGE_ATK_3: + case STAT_CHANGE_DEF_3: + case STAT_CHANGE_SPEED_3: + case STAT_CHANGE_SPATK_3: + case STAT_CHANGE_SPDEF_3: + return 3; + } + return 0; // STAT_HP, should never be getting changed +} + static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, enum StatChange statChange, bool32 considerContrary) { enum AIScore tempScore = NO_INCREASE; @@ -4510,6 +4543,7 @@ static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, u32 shouldSetUp = ((noOfHitsToFaint >= 2 && aiIsFaster) || (noOfHitsToFaint >= 3 && !aiIsFaster) || noOfHitsToFaint == UNKNOWN_NO_OF_HITS); u32 i; u32 statId = GetStatBeingChanged(statChange); + u32 stages = GetStagesOfStatChange(statChange); if (considerContrary && gAiLogicData->abilities[battlerAtk] == ABILITY_CONTRARY) return NO_INCREASE; @@ -4531,7 +4565,7 @@ static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, return NO_INCREASE; // Don't increase stats if opposing battler has Opportunist - if (gAiLogicData->abilities[battlerDef] == ABILITY_OPPORTUNIST) + if (HasBattlerSideAbility(battlerDef, ABILITY_OPPORTUNIST, gAiLogicData)) return NO_INCREASE; // Don't increase stats if opposing battler has Encore @@ -4556,6 +4590,10 @@ static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, if (HasMoveThatChangesKOThreshold(battlerDef, noOfHitsToFaint, aiIsFaster)) return NO_INCREASE; + // Stat stages are effectively doubled under Simple. + if (gAiLogicData->abilities[battlerAtk] == ABILITY_SIMPLE) + stages *= 2; + // Predicting switch if (IsBattlerPredictedToSwitch(battlerDef)) { @@ -4574,73 +4612,62 @@ static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, tempScore += WEAK_EFFECT; } - switch (statChange) + switch (statId) { - case STAT_CHANGE_ATK: + case STAT_ATK: if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_PHYSICAL) && shouldSetUp) - tempScore += DECENT_EFFECT; + { + if (stages == 1) + tempScore += DECENT_EFFECT; + else + tempScore += GOOD_EFFECT; + } break; - case STAT_CHANGE_DEF: + case STAT_DEF: if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_PHYSICAL) || !HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL)) { if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_STALL) - tempScore += DECENT_EFFECT; - else tempScore += WEAK_EFFECT; + if (stages == 1) + tempScore += WEAK_EFFECT; + else + tempScore += DECENT_EFFECT; } break; - case STAT_CHANGE_SPEED: + case STAT_SPEED: if ((noOfHitsToFaint >= 3 && !aiIsFaster) || noOfHitsToFaint == UNKNOWN_NO_OF_HITS) - tempScore += DECENT_EFFECT; + { + if (stages == 1) + tempScore += DECENT_EFFECT; + else + tempScore += GOOD_EFFECT; + } break; - case STAT_CHANGE_SPATK: + case STAT_SPATK: if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_SPECIAL) && shouldSetUp) - tempScore += DECENT_EFFECT; + { + if (stages == 1) + tempScore += DECENT_EFFECT; + else + tempScore += GOOD_EFFECT; + } break; - case STAT_CHANGE_SPDEF: + case STAT_SPDEF: if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL) || !HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_PHYSICAL)) { if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_STALL) - tempScore += DECENT_EFFECT; - else tempScore += WEAK_EFFECT; - } - break; - case STAT_CHANGE_ATK_2: - if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_PHYSICAL) && shouldSetUp) - tempScore += GOOD_EFFECT; - break; - case STAT_CHANGE_DEF_2: - if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_PHYSICAL) || !HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL)) - { - if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_STALL) - tempScore += GOOD_EFFECT; + if (stages == 1) + tempScore += WEAK_EFFECT; else tempScore += DECENT_EFFECT; } break; - case STAT_CHANGE_SPEED_2: - if ((noOfHitsToFaint >= 3 && !aiIsFaster) || noOfHitsToFaint == UNKNOWN_NO_OF_HITS) - tempScore += GOOD_EFFECT; - break; - case STAT_CHANGE_SPATK_2: - if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_SPECIAL) && shouldSetUp) - tempScore += GOOD_EFFECT; - break; - case STAT_CHANGE_SPDEF_2: - if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL) || !HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_PHYSICAL)) - { - if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_STALL) - tempScore += GOOD_EFFECT; - else - tempScore += DECENT_EFFECT; - } - break; - case STAT_CHANGE_ACC: + case STAT_ACC: if (gBattleMons[battlerAtk].statStages[statId] <= 3) // Increase only if necessary tempScore += DECENT_EFFECT; break; - case STAT_CHANGE_EVASION: + case STAT_EVASION: if (noOfHitsToFaint > 3 || noOfHitsToFaint == UNKNOWN_NO_OF_HITS) tempScore += GOOD_EFFECT; else @@ -4648,6 +4675,10 @@ static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, break; } + // if already inclined to boost, be slightly more likely to if boost levels matter + if (tempScore > 0 && HasMoveWithEffect(battlerAtk, EFFECT_STORED_POWER)) + tempScore += WEAK_EFFECT; + return tempScore; }