diff --git a/include/battle_util.h b/include/battle_util.h index 684aa2b51565..bd3bad8e2d43 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -166,8 +166,10 @@ bool32 IsBattlerGrounded(u8 battlerId); bool32 IsBattlerAlive(u8 battlerId); u8 GetBattleMonMoveSlot(struct BattlePokemon *battleMon, u16 move); u32 GetBattlerWeight(u8 battlerId); +u32 CalcRolloutBasePower(u32 battlerAtk, u32 basePower, u32 rolloutTimer); +u32 CalcFuryCutterBasePower(u32 basePower, u32 furyCutterCounter); s32 CalculateMoveDamage(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, s32 fixedBasePower, bool32 isCrit, bool32 randomFactor, bool32 updateFlags); -s32 CalculateMoveDamageAndEffectiveness(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, u16 *typeEffectivenessModifier); +s32 CalculateMoveDamageAndEffectiveness(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, s32 fixedBasePower, u16 *typeEffectivenessModifier); u16 CalcTypeEffectivenessMultiplier(u16 move, u8 moveType, u8 battlerAtk, u8 battlerDef, bool32 recordAbilities); u16 CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, u16 abilityDef); u16 GetTypeModifier(u8 atkType, u8 defType); diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 7730604c8798..9fdf08123478 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -785,7 +785,7 @@ static bool32 AI_GetIfCrit(u32 move, u8 battlerAtk, u8 battlerDef) s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef, u8 *typeEffectiveness, bool32 considerZPower) { - s32 dmg, moveType, critDmg, normalDmg; + s32 dmg, moveType, critDmg, normalDmg, fixedBasePower, n; s8 critChance; u16 effectivenessMultiplier; @@ -814,8 +814,22 @@ s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef, u8 *typeEffectiveness, { ProteanTryChangeType(battlerAtk, AI_DATA->abilities[battlerAtk], move, moveType); critChance = GetInverseCritChance(battlerAtk, battlerDef, move); - normalDmg = CalculateMoveDamageAndEffectiveness(move, battlerAtk, battlerDef, moveType, &effectivenessMultiplier); - critDmg = CalculateMoveDamage(move, battlerAtk, battlerDef, moveType, 0, TRUE, FALSE, FALSE); + // Certain moves like Rollout calculate damage based on values which change during the move execution, but before calling dmg calc. + switch (gBattleMoves[move].effect) + { + case EFFECT_ROLLOUT: + n = gDisableStructs[battlerAtk].rolloutTimer - 1; + fixedBasePower = CalcRolloutBasePower(battlerAtk, gBattleMoves[move].power, n < 0 ? 5 : n); + break; + case EFFECT_FURY_CUTTER: + fixedBasePower = CalcFuryCutterBasePower(gBattleMoves[move].power, min(gDisableStructs[battlerAtk].furyCutterCounter + 1, 5)); + break; + default: + fixedBasePower = 0; + break; + } + normalDmg = CalculateMoveDamageAndEffectiveness(move, battlerAtk, battlerDef, moveType, fixedBasePower, &effectivenessMultiplier); + critDmg = CalculateMoveDamage(move, battlerAtk, battlerDef, moveType, fixedBasePower, TRUE, FALSE, FALSE); if (critChance == -1) dmg = normalDmg; diff --git a/src/battle_util.c b/src/battle_util.c index f13e89bff9a2..c9dcab3db3a9 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8453,6 +8453,24 @@ const struct TypePower gNaturalGiftTable[] = [ITEM_TO_BERRY(ITEM_MARANGA_BERRY)] = {TYPE_DARK, 100}, }; +u32 CalcRolloutBasePower(u32 battlerAtk, u32 basePower, u32 rolloutTimer) +{ + u32 i; + for (i = 1; i < (5 - rolloutTimer); i++) + basePower *= 2; + if (gBattleMons[battlerAtk].status2 & STATUS2_DEFENSE_CURL) + basePower *= 2; + return basePower; +} + +u32 CalcFuryCutterBasePower(u32 basePower, u32 furyCutterCounter) +{ + u32 i; + for (i = 1; i < furyCutterCounter; i++) + basePower *= 2; + return basePower; +} + static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) { u32 i; @@ -8489,14 +8507,10 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) basePower = 10 * (MAX_FRIENDSHIP - gBattleMons[battlerAtk].friendship) / 25; break; case EFFECT_FURY_CUTTER: - for (i = 1; i < gDisableStructs[battlerAtk].furyCutterCounter; i++) - basePower *= 2; + basePower = CalcFuryCutterBasePower(basePower, gDisableStructs[battlerAtk].furyCutterCounter); break; case EFFECT_ROLLOUT: - for (i = 1; i < (5 - gDisableStructs[battlerAtk].rolloutTimer); i++) - basePower *= 2; - if (gBattleMons[battlerAtk].status2 & STATUS2_DEFENSE_CURL) - basePower *= 2; + basePower = CalcRolloutBasePower(battlerAtk, basePower, gDisableStructs[battlerAtk].rolloutTimer); break; case EFFECT_MAGNITUDE: basePower = gBattleStruct->magnitudeBasePower; @@ -9700,10 +9714,10 @@ s32 CalculateMoveDamage(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, s32 } // for AI - get move damage and effectiveness with one function call -s32 CalculateMoveDamageAndEffectiveness(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, u16 *typeEffectivenessModifier) +s32 CalculateMoveDamageAndEffectiveness(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, s32 fixedBasePower, u16 *typeEffectivenessModifier) { *typeEffectivenessModifier = CalcTypeEffectivenessMultiplier(move, moveType, battlerAtk, battlerDef, FALSE); - return DoMoveDamageCalc(move, battlerAtk, battlerDef, moveType, 0, FALSE, FALSE, FALSE, *typeEffectivenessModifier); + return DoMoveDamageCalc(move, battlerAtk, battlerDef, moveType, fixedBasePower, FALSE, FALSE, FALSE, *typeEffectivenessModifier); } static void MulByTypeEffectiveness(u16 *modifier, u16 move, u8 moveType, u8 battlerDef, u8 defType, u8 battlerAtk, bool32 recordAbilities)