From 6482279fa37c0857897a5b9d5fcac2b55ffd53f8 Mon Sep 17 00:00:00 2001 From: sbird Date: Fri, 7 Jul 2023 14:11:49 +0200 Subject: [PATCH] [battle, math] refactor damage calculation to use proper fp type and inlined multiplication --- include/battle.h | 2 +- include/battle_ai_util.h | 2 +- include/battle_util.h | 13 +- include/fpmath.h | 61 ++++++ include/global.h | 27 +-- src/battle_ai_switch_items.c | 12 +- src/battle_ai_util.c | 11 +- src/battle_dome.c | 2 +- src/battle_util.c | 360 +++++++++++++++++------------------ test/fpmath.c | 18 ++ 10 files changed, 279 insertions(+), 229 deletions(-) create mode 100644 include/fpmath.h create mode 100644 test/fpmath.c diff --git a/include/battle.h b/include/battle.h index 5ad99673f..9995a2a24 100644 --- a/include/battle.h +++ b/include/battle.h @@ -656,7 +656,7 @@ struct BattleStruct u8 battleBondTransformed[NUM_BATTLE_SIDES]; // Bitfield for each party. u8 storedHealingWish:4; // Each battler as a bit. u8 storedLunarDance:4; // Each battler as a bit. - u16 supremeOverlordModifier[MAX_BATTLERS_COUNT]; + uq4_12_t supremeOverlordModifier[MAX_BATTLERS_COUNT]; u8 itemPartyIndex[MAX_BATTLERS_COUNT]; u8 itemMoveIndex[MAX_BATTLERS_COUNT]; bool8 trainerSlideHalfHpMsgDone; diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 99eb03f54..580e040d0 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -87,7 +87,7 @@ bool32 MovesWithSplitUnusable(u32 attacker, u32 target, u32 split); s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef, u8 *effectiveness, bool32 considerZPower); u8 GetMoveDamageResult(u16 move); u32 GetCurrDamageHpPercent(u8 battlerAtk, u8 battlerDef); -u16 AI_GetTypeEffectiveness(u16 move, u8 battlerAtk, u8 battlerDef); +uq4_12_t AI_GetTypeEffectiveness(u16 move, u8 battlerAtk, u8 battlerDef); u32 AI_GetMoveEffectiveness(u16 move, u8 battlerAtk, u8 battlerDef); u16 *GetMovesArray(u32 battler); bool32 IsConfusionMoveEffect(u16 moveEffect); diff --git a/include/battle_util.h b/include/battle_util.h index 9976720ee..b6c397bc7 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -166,10 +166,10 @@ bool32 IsBattlerAlive(u8 battlerId); u8 GetBattleMonMoveSlot(struct BattlePokemon *battleMon, u16 move); u32 GetBattlerWeight(u8 battlerId); 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); -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); +s32 CalculateMoveDamageAndEffectiveness(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, uq4_12_t *typeEffectivenessModifier); +uq4_12_t CalcTypeEffectivenessMultiplier(u16 move, u8 moveType, u8 battlerAtk, u8 battlerDef, bool32 recordAbilities); +uq4_12_t CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, u16 abilityDef); +uq4_12_t GetTypeModifier(u8 atkType, u8 defType); s32 GetStealthHazardDamage(u8 hazardType, u8 battlerId); s32 GetStealthHazardDamageByTypesAndHP(u8 hazardType, u8 type1, u8 type2, u32 maxHp); bool32 CanMegaEvolve(u8 battlerId); @@ -240,4 +240,9 @@ u8 GetBattlerGender(u8 battlerId); bool8 AreBattlersOfOppositeGender(u8 battler1, u8 battler2); u32 CalcSecondaryEffectChance(u8 battlerId, u8 secondaryEffectChance); +static inline u32 ApplyModifier(uq4_12_t modifier, u32 val) +{ + return UQ_4_12_TO_INT((modifier * val) + UQ_4_12_ROUND); +} + #endif // GUARD_BATTLE_UTIL_H diff --git a/include/fpmath.h b/include/fpmath.h new file mode 100644 index 000000000..7e25a92a4 --- /dev/null +++ b/include/fpmath.h @@ -0,0 +1,61 @@ +#ifndef FPMATH_H_ +#define FPMATH_H_ + +typedef s32 q4_12_t; +typedef u32 uq4_12_t; + +#define Q_4_12_SHIFT (12) +#define UQ_4_12_SHIFT (12) + +// Converts a number to Q8.8 fixed-point format +#define Q_8_8(n) ((s16)((n) * 256)) + +// Converts a number to Q4.12 fixed-point format +#define Q_4_12(n) ((q4_12_t)((n) * 4096)) +#define UQ_4_12(n) ((uq4_12_t)((n) * 4096)) + +// Converts a number to Q24.8 fixed-point format +#define Q_24_8(n) ((s32)((n) * 256)) + +// Converts a Q8.8 fixed-point format number to a regular integer +#define Q_8_8_TO_INT(n) ((s32)((n) / 256)) + +// Converts a Q4.12 fixed-point format number to a regular integer +#define Q_4_12_TO_INT(n) ((s32)((n) / 4096)) +#define UQ_4_12_TO_INT(n) ((u32)((n) / 4096)) + +// Converts a Q24.8 fixed-point format number to a regular integer +#define Q_24_8_TO_INT(n) ((s32)((n) / 256)) + +// Rounding value for Q4.12 fixed-point format +#define Q_4_12_ROUND ((1) << (Q_4_12_SHIFT - 1)) +#define UQ_4_12_ROUND ((1) << (UQ_4_12_SHIFT - 1)) + +// Basic arithmetic for fixed point number formats +// Consumers should use encapsulated functions where possible + +// FP API does not provide sanity checks against overflows + +static inline uq4_12_t uq4_12_add(uq4_12_t a, uq4_12_t b) +{ + return a + b; +} + +static inline uq4_12_t uq4_12_subtract(uq4_12_t a, uq4_12_t b) +{ + return a - b; +} + +static inline uq4_12_t uq4_12_multiply(uq4_12_t a, uq4_12_t b) +{ + u32 product = (u32) a * b; + return (product + UQ_4_12_ROUND) >> UQ_4_12_SHIFT; +} + +static inline uq4_12_t uq4_12_divide(uq4_12_t dividend, uq4_12_t divisor) +{ + if (divisor == UQ_4_12(0.0)) return UQ_4_12(0); + return (dividend << UQ_4_12_SHIFT) / divisor; +} + +#endif // FPMATH_H_ diff --git a/include/global.h b/include/global.h index eca45bdb6..d30ca045e 100644 --- a/include/global.h +++ b/include/global.h @@ -5,6 +5,7 @@ #include #include "config.h" // we need to define config before gba headers as print stuff needs the functions nulled before defines. #include "gba/gba.h" +#include "fpmath.h" #include "constants/global.h" #include "constants/flags.h" #include "constants/vars.h" @@ -51,32 +52,6 @@ b = temp; \ } -// useful math macros - -// Converts a number to Q8.8 fixed-point format -#define Q_8_8(n) ((s16)((n) * 256)) - -// Converts a number to Q4.12 fixed-point format -#define Q_4_12(n) ((s16)((n) * 4096)) -#define UQ_4_12(n) ((u16)((n) * 4096)) - -// Converts a number to Q24.8 fixed-point format -#define Q_24_8(n) ((s32)((n) << 8)) - -// Converts a Q8.8 fixed-point format number to a regular integer -#define Q_8_8_TO_INT(n) ((int)((n) / 256)) - -// Converts a Q4.12 fixed-point format number to a regular integer -#define Q_4_12_TO_INT(n) ((int)((n) / 4096)) -#define UQ_4_12_TO_INT(n) ((int)((n) / 4096)) - -// Converts a Q24.8 fixed-point format number to a regular integer -#define Q_24_8_TO_INT(n) ((int)((n) >> 8)) - -// Rounding value for Q4.12 fixed-point format -#define Q_4_12_ROUND ((1) << (12 - 1)) -#define UQ_4_12_ROUND ((1) << (12 - 1)) - #define min(a, b) ((a) < (b) ? (a) : (b)) #define max(a, b) ((a) >= (b) ? (a) : (b)) diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index 48ca258a8..73d7ecb64 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -822,7 +822,7 @@ static u32 GetBestMonTypeMatchup(struct Pokemon *party, int firstId, int lastId, while (bits != 0x3F) // All mons were checked. { - u16 bestResist = UQ_4_12(1.0); + uq4_12_t bestResist = UQ_4_12(1.0); int bestMonId = PARTY_SIZE; // Find the mon whose type is the most suitable defensively. for (i = firstId; i < lastId; i++) @@ -830,21 +830,21 @@ static u32 GetBestMonTypeMatchup(struct Pokemon *party, int firstId, int lastId, if (!(gBitTable[i] & invalidMons) && !(gBitTable[i] & bits)) { u16 species = GetMonData(&party[i], MON_DATA_SPECIES); - u16 typeEffectiveness = UQ_4_12(1.0); + uq4_12_t typeEffectiveness = UQ_4_12(1.0); u8 atkType1 = gBattleMons[opposingBattler].type1; u8 atkType2 = gBattleMons[opposingBattler].type2; u8 defType1 = gSpeciesInfo[species].types[0]; u8 defType2 = gSpeciesInfo[species].types[1]; - MulModifier(&typeEffectiveness, (GetTypeModifier(atkType1, defType1))); + typeEffectiveness = uq4_12_multiply(typeEffectiveness, (GetTypeModifier(atkType1, defType1))); if (atkType2 != atkType1) - MulModifier(&typeEffectiveness, (GetTypeModifier(atkType2, defType1))); + typeEffectiveness = uq4_12_multiply(typeEffectiveness, (GetTypeModifier(atkType2, defType1))); if (defType2 != defType1) { - MulModifier(&typeEffectiveness, (GetTypeModifier(atkType1, defType2))); + typeEffectiveness = uq4_12_multiply(typeEffectiveness, (GetTypeModifier(atkType1, defType2))); if (atkType2 != atkType1) - MulModifier(&typeEffectiveness, (GetTypeModifier(atkType2, defType2))); + typeEffectiveness = uq4_12_multiply(typeEffectiveness, (GetTypeModifier(atkType2, defType2))); } if (typeEffectiveness < bestResist) { diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 3deabc5f5..97c0c3202 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -31,7 +31,7 @@ } \ return FALSE -static u32 AI_GetEffectiveness(u16 multiplier); +static u32 AI_GetEffectiveness(uq4_12_t multiplier); // Const Data static const s8 sAiAbilityRatings[ABILITIES_COUNT] = @@ -768,7 +768,7 @@ s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef, u8 *typeEffectiveness, { s32 dmg, moveType, critDmg, normalDmg; s8 critChance; - u16 effectivenessMultiplier; + uq4_12_t effectivenessMultiplier; if (considerZPower && IsViableZMove(battlerAtk, move)) { @@ -1003,9 +1003,10 @@ u32 GetCurrDamageHpPercent(u8 battlerAtk, u8 battlerDef) return (bestDmg * 100) / gBattleMons[battlerDef].maxHP; } -u16 AI_GetTypeEffectiveness(u16 move, u8 battlerAtk, u8 battlerDef) +uq4_12_t AI_GetTypeEffectiveness(u16 move, u8 battlerAtk, u8 battlerDef) { - u16 typeEffectiveness, moveType; + uq4_12_t typeEffectiveness; + u16 moveType; SaveBattlerData(battlerAtk); SaveBattlerData(battlerDef); @@ -1030,7 +1031,7 @@ u32 AI_GetMoveEffectiveness(u16 move, u8 battlerAtk, u8 battlerDef) return AI_GetEffectiveness(AI_GetTypeEffectiveness(move, battlerAtk, battlerDef)); } -static u32 AI_GetEffectiveness(u16 multiplier) +static u32 AI_GetEffectiveness(uq4_12_t multiplier) { switch (multiplier) { diff --git a/src/battle_dome.c b/src/battle_dome.c index deae7e64f..ba8d27b9a 100644 --- a/src/battle_dome.c +++ b/src/battle_dome.c @@ -5206,7 +5206,7 @@ static u16 GetWinningMove(int winnerTournamentId, int loserTournamentId, u8 roun u32 personality = 0; u32 targetSpecies = 0; u32 targetAbility = 0; - u32 typeMultiplier = 0; + uq4_12_t typeMultiplier = 0; do { personality = Random32(); diff --git a/src/battle_util.c b/src/battle_util.c index 06d6e4897..438d98016 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -62,8 +62,8 @@ static bool32 IsUnnerveAbilityOnOpposingSide(u8 battlerId); static u8 GetFlingPowerFromItemId(u16 itemId); static void SetRandomMultiHitCounter(); static u32 GetBattlerItemHoldEffectParam(u8 battlerId, u16 item); -static u16 GetInverseTypeMultiplier(u16 multiplier); -static u16 GetSupremeOverlordModifier(u8 battlerId); +static uq4_12_t GetInverseTypeMultiplier(uq4_12_t multiplier); +static uq4_12_t GetSupremeOverlordModifier(u8 battlerId); static bool8 CanBeInfinitelyConfused(u8 battlerId); extern const u8 *const gBattleScriptsForMoveEffects[]; @@ -1017,7 +1017,7 @@ static const u8 sHoldEffectToType[][2] = }; // percent in UQ_4_12 format -static const u16 sPercentToModifier[] = +static const uq4_12_t sPercentToModifier[] = { UQ_4_12(0.00), // 0 UQ_4_12(0.01), // 1 @@ -1124,7 +1124,7 @@ static const u16 sPercentToModifier[] = #define X UQ_4_12 -static const u16 sTypeEffectivenessTable[NUMBER_OF_MON_TYPES][NUMBER_OF_MON_TYPES] = +static const uq4_12_t sTypeEffectivenessTable[NUMBER_OF_MON_TYPES][NUMBER_OF_MON_TYPES] = { // normal fight flying poison ground rock bug ghost steel mystery fire water grass electric psychic ice dragon dark fairy {X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(0.5), X(1.0), X(0.0), X(0.5), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0)}, // normal @@ -4108,11 +4108,11 @@ bool8 ChangeTypeBasedOnTerrain(u8 battlerId) // Supreme Overlord adds a damage boost for each fainted ally. // The first ally adds a x1.2 boost, and subsequent allies add an extra x0.1 boost each. -static u16 GetSupremeOverlordModifier(u8 battlerId) +static uq4_12_t GetSupremeOverlordModifier(u8 battlerId) { u32 i; struct Pokemon *party = GetBattlerParty(battlerId); - u16 modifier = UQ_4_12(1.0); + uq4_12_t modifier = UQ_4_12(1.0); bool8 appliedFirstBoost = FALSE; for (i = 0; i < PARTY_SIZE; i++) @@ -8297,16 +8297,6 @@ u32 GetMoveTargetCount(u16 move, u8 battlerAtk, u8 battlerDef) } } -void MulModifier(u16 *modifier, u16 val) -{ - *modifier = UQ_4_12_TO_INT((*modifier * val) + UQ_4_12_ROUND); -} - -static u32 ApplyModifier(u16 modifier, u32 val) -{ - return UQ_4_12_TO_INT((modifier * val) + UQ_4_12_ROUND); -} - static const u8 sFlailHpScaleToPowerTable[] = { 1, 200, @@ -8597,7 +8587,7 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) break; case EFFECT_EXPLOSION: if (move == MOVE_MISTY_EXPLOSION && gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN && IsBattlerGrounded(battlerAtk)) - MulModifier(&basePower, UQ_4_12(1.5)); + basePower = uq4_12_multiply(basePower, UQ_4_12(1.5)); break; case EFFECT_DYNAMAX_DOUBLE_DMG: #ifdef B_DYNAMAX @@ -8623,7 +8613,7 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) } case EFFECT_GRAV_APPLE: if (gFieldStatuses & STATUS_FIELD_GRAVITY) - MulModifier(&basePower, UQ_4_12(1.5)); + basePower = uq4_12_multiply(basePower, UQ_4_12(1.5)); break; case EFFECT_TERRAIN_PULSE: if ((gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) @@ -8632,7 +8622,7 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) break; case EFFECT_EXPANDING_FORCE: if (IsBattlerTerrainAffected(battlerAtk, STATUS_FIELD_PSYCHIC_TERRAIN)) - MulModifier(&basePower, UQ_4_12(1.5)); + basePower = uq4_12_multiply(basePower, UQ_4_12(1.5)); break; case EFFECT_RISING_VOLTAGE: if (IsBattlerTerrainAffected(battlerDef, STATUS_FIELD_ELECTRIC_TERRAIN)) @@ -8645,7 +8635,7 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) break; case EFFECT_PSYBLADE: if (IsBattlerTerrainAffected(battlerAtk, STATUS_FIELD_ELECTRIC_TERRAIN)) - MulModifier(&basePower, UQ_4_12(1.5)); + basePower = uq4_12_multiply(basePower, UQ_4_12(1.5)); break; } @@ -8668,8 +8658,8 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe u32 i; u32 holdEffectAtk, holdEffectParamAtk; u16 basePower = CalcMoveBasePower(move, battlerAtk, battlerDef); - u16 holdEffectModifier; - u16 modifier = UQ_4_12(1.0); + uq4_12_t holdEffectModifier; + uq4_12_t modifier = UQ_4_12(1.0); u32 atkSide = GET_BATTLER_SIDE(battlerAtk); u16 atkAbility = GetBattlerAbility(battlerAtk); u16 defAbility = GetBattlerAbility(battlerDef); @@ -8679,135 +8669,135 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe { case ABILITY_TECHNICIAN: if (basePower <= 60) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; case ABILITY_FLARE_BOOST: if (gBattleMons[battlerAtk].status1 & STATUS1_BURN && IS_MOVE_SPECIAL(move)) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; case ABILITY_TOXIC_BOOST: if (gBattleMons[battlerAtk].status1 & STATUS1_PSN_ANY && IS_MOVE_PHYSICAL(move)) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; case ABILITY_RECKLESS: if (IS_MOVE_RECOIL(move)) - MulModifier(&modifier, UQ_4_12(1.2)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.2)); break; case ABILITY_IRON_FIST: if (gBattleMoves[move].punchingMove) - MulModifier(&modifier, UQ_4_12(1.2)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.2)); break; case ABILITY_SHEER_FORCE: if (gBattleMoves[move].sheerForceBoost) - MulModifier(&modifier, UQ_4_12(1.3)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.3)); break; case ABILITY_SAND_FORCE: if ((moveType == TYPE_STEEL || moveType == TYPE_ROCK || moveType == TYPE_GROUND) && gBattleWeather & B_WEATHER_SANDSTORM && WEATHER_HAS_EFFECT) - MulModifier(&modifier, UQ_4_12(1.3)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.3)); break; case ABILITY_RIVALRY: if (AreBattlersOfOppositeGender(battlerAtk, battlerDef)) - MulModifier(&modifier, UQ_4_12(1.25)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.25)); else - MulModifier(&modifier, UQ_4_12(0.75)); + modifier = uq4_12_multiply(modifier, UQ_4_12(0.75)); break; case ABILITY_ANALYTIC: if (GetBattlerTurnOrderNum(battlerAtk) == gBattlersCount - 1 && move != MOVE_FUTURE_SIGHT && move != MOVE_DOOM_DESIRE) - MulModifier(&modifier, UQ_4_12(1.3)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.3)); break; case ABILITY_TOUGH_CLAWS: if (IsMoveMakingContact(move, battlerAtk)) - MulModifier(&modifier, UQ_4_12(1.3)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.3)); break; case ABILITY_STRONG_JAW: if (gBattleMoves[move].bitingMove) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; case ABILITY_MEGA_LAUNCHER: if (gBattleMoves[move].pulseMove) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; case ABILITY_WATER_BUBBLE: if (moveType == TYPE_WATER) - MulModifier(&modifier, UQ_4_12(2.0)); + modifier = uq4_12_multiply(modifier, UQ_4_12(2.0)); break; case ABILITY_STEELWORKER: if (moveType == TYPE_STEEL) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; case ABILITY_PIXILATE: if (moveType == TYPE_FAIRY && gBattleStruct->ateBoost[battlerAtk]) - MulModifier(&modifier, UQ_4_12(1.2)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.2)); break; case ABILITY_GALVANIZE: if (moveType == TYPE_ELECTRIC && gBattleStruct->ateBoost[battlerAtk]) - MulModifier(&modifier, UQ_4_12(1.2)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.2)); break; case ABILITY_REFRIGERATE: if (moveType == TYPE_ICE && gBattleStruct->ateBoost[battlerAtk]) - MulModifier(&modifier, UQ_4_12(1.2)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.2)); break; case ABILITY_AERILATE: if (moveType == TYPE_FLYING && gBattleStruct->ateBoost[battlerAtk]) - MulModifier(&modifier, UQ_4_12(1.2)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.2)); break; case ABILITY_NORMALIZE: if (moveType == TYPE_NORMAL && gBattleStruct->ateBoost[battlerAtk]) - MulModifier(&modifier, UQ_4_12(1.2)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.2)); break; case ABILITY_PUNK_ROCK: if (gBattleMoves[move].soundMove) - MulModifier(&modifier, UQ_4_12(1.3)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.3)); break; case ABILITY_STEELY_SPIRIT: if (moveType == TYPE_STEEL) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; case ABILITY_TRANSISTOR: if (moveType == TYPE_ELECTRIC) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; case ABILITY_DRAGONS_MAW: if (moveType == TYPE_DRAGON) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; case ABILITY_GORILLA_TACTICS: if (IS_MOVE_PHYSICAL(move)) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; case ABILITY_ROCKY_PAYLOAD: if (moveType == TYPE_ROCK) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; case ABILITY_PROTOSYNTHESIS: { u8 atkHighestStat = GetHighestStatId(battlerAtk); if (gBattleWeather & B_WEATHER_SUN && WEATHER_HAS_EFFECT && (atkHighestStat == STAT_ATK || atkHighestStat == STAT_SPATK)) - MulModifier(&modifier, UQ_4_12(1.3)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.3)); } break; case ABILITY_QUARK_DRIVE: { u8 atkHighestStat = GetHighestStatId(battlerAtk); if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN && (atkHighestStat == STAT_ATK || atkHighestStat == STAT_SPATK)) - MulModifier(&modifier, UQ_4_12(1.3)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.3)); } break; case ABILITY_ORICHALCUM_PULSE: if (gBattleWeather & B_WEATHER_SUN && WEATHER_HAS_EFFECT) - MulModifier(&modifier, UQ_4_12(1.3)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.3)); break; case ABILITY_HADRON_ENGINE: if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN) - MulModifier(&modifier, UQ_4_12(1.3)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.3)); break; case ABILITY_SHARPNESS: if (gBattleMoves[move].slicingMove) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; case ABILITY_SUPREME_OVERLORD: - MulModifier(&modifier, gBattleStruct->supremeOverlordModifier[battlerAtk]); + modifier = uq4_12_multiply(modifier, gBattleStruct->supremeOverlordModifier[battlerAtk]); break; } @@ -8816,22 +8806,22 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe || (IsAbilityOnField(ABILITY_FAIRY_AURA) && moveType == TYPE_FAIRY)) { if (IsAbilityOnField(ABILITY_AURA_BREAK)) - MulModifier(&modifier, UQ_4_12(0.75)); + modifier = uq4_12_multiply(modifier, UQ_4_12(0.75)); else - MulModifier(&modifier, UQ_4_12(1.33)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.33)); } if (IsAbilityOnField(ABILITY_VESSEL_OF_RUIN) && atkAbility != ABILITY_VESSEL_OF_RUIN && IS_MOVE_SPECIAL(gCurrentMove)) - MulModifier(&modifier, UQ_4_12(0.25)); + modifier = uq4_12_multiply(modifier, UQ_4_12(0.25)); if (IsAbilityOnField(ABILITY_SWORD_OF_RUIN) && defAbility != ABILITY_SWORD_OF_RUIN && IS_MOVE_PHYSICAL(gCurrentMove)) - MulModifier(&modifier, UQ_4_12(0.25)); + modifier = uq4_12_multiply(modifier, UQ_4_12(0.25)); if (IsAbilityOnField(ABILITY_TABLETS_OF_RUIN) && atkAbility != ABILITY_TABLETS_OF_RUIN && IS_MOVE_PHYSICAL(gCurrentMove)) - MulModifier(&modifier, UQ_4_12(0.25)); + modifier = uq4_12_multiply(modifier, UQ_4_12(0.25)); if (IsAbilityOnField(ABILITY_BEADS_OF_RUIN) && defAbility != ABILITY_BEADS_OF_RUIN && IS_MOVE_SPECIAL(gCurrentMove)) - MulModifier(&modifier, UQ_4_12(0.25)); + modifier = uq4_12_multiply(modifier, UQ_4_12(0.25)); // attacker partner's abilities if (IsBattlerAlive(BATTLE_PARTNER(battlerAtk))) @@ -8840,14 +8830,14 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe { case ABILITY_BATTERY: if (IS_MOVE_SPECIAL(move)) - MulModifier(&modifier, UQ_4_12(1.3)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.3)); break; case ABILITY_POWER_SPOT: - MulModifier(&modifier, UQ_4_12(1.3)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.3)); break; case ABILITY_STEELY_SPIRIT: if (moveType == TYPE_STEEL) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; } } @@ -8859,37 +8849,37 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe case ABILITY_WATER_BUBBLE: if (moveType == TYPE_FIRE) { - MulModifier(&modifier, UQ_4_12(0.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(0.5)); if (updateFlags) RecordAbilityBattle(battlerDef, defAbility); } break; case ABILITY_DRY_SKIN: if (moveType == TYPE_FIRE) - MulModifier(&modifier, UQ_4_12(1.25)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.25)); break; case ABILITY_FLUFFY: if (IsMoveMakingContact(move, battlerAtk)) { - MulModifier(&modifier, UQ_4_12(0.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(0.5)); if (updateFlags) RecordAbilityBattle(battlerDef, defAbility); } if (moveType == TYPE_FIRE) - MulModifier(&modifier, UQ_4_12(2.0)); + modifier = uq4_12_multiply(modifier, UQ_4_12(2.0)); break; case ABILITY_PROTOSYNTHESIS: { u8 defHighestStat = GetHighestStatId(battlerDef); if (gBattleWeather & B_WEATHER_SUN && WEATHER_HAS_EFFECT && (defHighestStat == STAT_DEF || defHighestStat == STAT_SPDEF)) - MulModifier(&modifier, UQ_4_12(0.7)); + modifier = uq4_12_multiply(modifier, UQ_4_12(0.7)); } break; case ABILITY_QUARK_DRIVE: { u8 defHighestStat = GetHighestStatId(battlerDef); if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN && (defHighestStat == STAT_DEF || defHighestStat == STAT_SPDEF)) - MulModifier(&modifier, UQ_4_12(0.7)); + modifier = uq4_12_multiply(modifier, UQ_4_12(0.7)); } break; } @@ -8906,23 +8896,23 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe { case HOLD_EFFECT_MUSCLE_BAND: if (IS_MOVE_PHYSICAL(move)) - MulModifier(&modifier, holdEffectModifier); + modifier = uq4_12_multiply(modifier, holdEffectModifier); break; case HOLD_EFFECT_WISE_GLASSES: if (IS_MOVE_SPECIAL(move)) - MulModifier(&modifier, holdEffectModifier); + modifier = uq4_12_multiply(modifier, holdEffectModifier); break; case HOLD_EFFECT_LUSTROUS_ORB: if (GET_BASE_SPECIES_ID(gBattleMons[battlerAtk].species) == SPECIES_PALKIA && (moveType == TYPE_WATER || moveType == TYPE_DRAGON)) - MulModifier(&modifier, holdEffectModifier); + modifier = uq4_12_multiply(modifier, holdEffectModifier); break; case HOLD_EFFECT_ADAMANT_ORB: if (GET_BASE_SPECIES_ID(gBattleMons[battlerAtk].species) == SPECIES_DIALGA && (moveType == TYPE_STEEL || moveType == TYPE_DRAGON)) - MulModifier(&modifier, holdEffectModifier); + modifier = uq4_12_multiply(modifier, holdEffectModifier); break; case HOLD_EFFECT_GRISEOUS_ORB: if (GET_BASE_SPECIES_ID(gBattleMons[battlerAtk].species) == SPECIES_GIRATINA && (moveType == TYPE_GHOST || moveType == TYPE_DRAGON)) - MulModifier(&modifier, holdEffectModifier); + modifier = uq4_12_multiply(modifier, holdEffectModifier); break; case HOLD_EFFECT_SOUL_DEW: #if B_SOUL_DEW_BOOST >= GEN_7 @@ -8930,11 +8920,11 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe #else if ((gBattleMons[battlerAtk].species == SPECIES_LATIAS || gBattleMons[battlerAtk].species == SPECIES_LATIOS) && !(gBattleTypeFlags & BATTLE_TYPE_FRONTIER) && IS_MOVE_SPECIAL(move)) #endif - MulModifier(&modifier, holdEffectModifier); + modifier = uq4_12_multiply(modifier, holdEffectModifier); break; case HOLD_EFFECT_GEMS: if (gSpecialStatuses[battlerAtk].gemBoost && gBattleMons[battlerAtk].item) - MulModifier(&modifier, UQ_4_12(1.0) + sPercentToModifier[gSpecialStatuses[battlerAtk].gemParam]); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.0) + sPercentToModifier[gSpecialStatuses[battlerAtk].gemParam]); break; case HOLD_EFFECT_BUG_POWER: case HOLD_EFFECT_STEEL_POWER: @@ -8959,18 +8949,18 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe if (holdEffectAtk == sHoldEffectToType[i][0]) { if (moveType == sHoldEffectToType[i][1]) - MulModifier(&modifier, holdEffectModifier); + modifier = uq4_12_multiply(modifier, holdEffectModifier); break; } } break; case HOLD_EFFECT_PLATE: if (moveType == ItemId_GetSecondaryId(gBattleMons[battlerAtk].item)) - MulModifier(&modifier, holdEffectModifier); + modifier = uq4_12_multiply(modifier, holdEffectModifier); break; case HOLD_EFFECT_PUNCHING_GLOVE: if (gBattleMoves[move].punchingMove) - MulModifier(&modifier, UQ_4_12(1.1)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.1)); break; } @@ -8979,40 +8969,40 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe { case EFFECT_FACADE: if (gBattleMons[battlerAtk].status1 & (STATUS1_BURN | STATUS1_PSN_ANY | STATUS1_PARALYSIS | STATUS1_FROSTBITE)) - MulModifier(&modifier, UQ_4_12(2.0)); + modifier = uq4_12_multiply(modifier, UQ_4_12(2.0)); break; case EFFECT_BRINE: if (gBattleMons[battlerDef].hp <= (gBattleMons[battlerDef].maxHP / 2)) - MulModifier(&modifier, UQ_4_12(2.0)); + modifier = uq4_12_multiply(modifier, UQ_4_12(2.0)); break; case EFFECT_BARB_BARRAGE: case EFFECT_VENOSHOCK: if (gBattleMons[battlerDef].status1 & STATUS1_PSN_ANY) - MulModifier(&modifier, UQ_4_12(2.0)); + modifier = uq4_12_multiply(modifier, UQ_4_12(2.0)); break; case EFFECT_RETALIATE: if (gSideTimers[atkSide].retaliateTimer == 1) - MulModifier(&modifier, UQ_4_12(2.0)); + modifier = uq4_12_multiply(modifier, UQ_4_12(2.0)); break; case EFFECT_SOLAR_BEAM: if (IsBattlerWeatherAffected(battlerAtk, (B_WEATHER_HAIL | B_WEATHER_SANDSTORM | B_WEATHER_RAIN | B_WEATHER_SNOW))) - MulModifier(&modifier, UQ_4_12(0.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(0.5)); break; case EFFECT_STOMPING_TANTRUM: if (gBattleStruct->lastMoveFailed & gBitTable[battlerAtk]) - MulModifier(&modifier, UQ_4_12(2.0)); + modifier = uq4_12_multiply(modifier, UQ_4_12(2.0)); break; case EFFECT_BULLDOZE: case EFFECT_MAGNITUDE: case EFFECT_EARTHQUAKE: if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN && !(gStatuses3[battlerDef] & STATUS3_SEMI_INVULNERABLE)) - MulModifier(&modifier, UQ_4_12(0.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(0.5)); break; case EFFECT_KNOCK_OFF: #if B_KNOCK_OFF_DMG >= GEN_6 if (gBattleMons[battlerDef].item != ITEM_NONE && CanBattlerGetOrLoseItem(battlerDef, gBattleMons[battlerDef].item)) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); #endif break; } @@ -9025,19 +9015,19 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe // various effects if (gProtectStructs[battlerAtk].helpingHand) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); if (gStatuses3[battlerAtk] & STATUS3_CHARGED_UP && moveType == TYPE_ELECTRIC) - MulModifier(&modifier, UQ_4_12(2.0)); + modifier = uq4_12_multiply(modifier, UQ_4_12(2.0)); if (gStatuses3[battlerAtk] & STATUS3_ME_FIRST) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN && moveType == TYPE_GRASS && IsBattlerGrounded(battlerAtk) && !(gStatuses3[battlerAtk] & STATUS3_SEMI_INVULNERABLE)) - MulModifier(&modifier, TERRAIN_TYPE_BOOST); + modifier = uq4_12_multiply(modifier, TERRAIN_TYPE_BOOST); if (gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN && moveType == TYPE_DRAGON && IsBattlerGrounded(battlerDef) && !(gStatuses3[battlerDef] & STATUS3_SEMI_INVULNERABLE)) - MulModifier(&modifier, UQ_4_12(0.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(0.5)); if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN && moveType == TYPE_ELECTRIC && IsBattlerGrounded(battlerAtk) && !(gStatuses3[battlerAtk] & STATUS3_SEMI_INVULNERABLE)) - MulModifier(&modifier, TERRAIN_TYPE_BOOST); + modifier = uq4_12_multiply(modifier, TERRAIN_TYPE_BOOST); if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN && moveType == TYPE_PSYCHIC && IsBattlerGrounded(battlerAtk) && !(gStatuses3[battlerAtk] & STATUS3_SEMI_INVULNERABLE)) - MulModifier(&modifier, TERRAIN_TYPE_BOOST); + modifier = uq4_12_multiply(modifier, TERRAIN_TYPE_BOOST); #if B_SPORT_TURNS >= GEN_6 if ((moveType == TYPE_ELECTRIC && gFieldStatuses & STATUS_FIELD_MUDSPORT) || (moveType == TYPE_FIRE && gFieldStatuses & STATUS_FIELD_WATERSPORT)) @@ -9046,9 +9036,9 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe || (moveType == TYPE_FIRE && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, 0, ABILITYEFFECT_WATER_SPORT, 0))) #endif #if B_SPORT_DMG_REDUCTION >= GEN_5 - MulModifier(&modifier, UQ_4_12(0.23)); + modifier = uq4_12_multiply(modifier, UQ_4_12(0.23)); #else - MulModifier(&modifier, UQ_4_12(0.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(0.5)); #endif return ApplyModifier(modifier, basePower); } @@ -9058,7 +9048,7 @@ static u32 CalcAttackStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, b { u8 atkStage; u32 atkStat; - u16 modifier; + uq4_12_t modifier; u16 atkBaseSpeciesId; atkBaseSpeciesId = GET_BASE_SPECIES_ID(gBattleMons[battlerAtk].species); @@ -9114,39 +9104,39 @@ static u32 CalcAttackStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, b case ABILITY_HUGE_POWER: case ABILITY_PURE_POWER: if (IS_MOVE_PHYSICAL(move)) - MulModifier(&modifier, UQ_4_12(2.0)); + modifier = uq4_12_multiply(modifier, UQ_4_12(2.0)); break; case ABILITY_SLOW_START: if (gDisableStructs[battlerAtk].slowStartTimer != 0) - MulModifier(&modifier, UQ_4_12(0.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(0.5)); break; case ABILITY_SOLAR_POWER: if (IS_MOVE_SPECIAL(move) && IsBattlerWeatherAffected(battlerAtk, B_WEATHER_SUN)) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; case ABILITY_DEFEATIST: if (gBattleMons[battlerAtk].hp <= (gBattleMons[battlerAtk].maxHP / 2)) - MulModifier(&modifier, UQ_4_12(0.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(0.5)); break; case ABILITY_FLASH_FIRE: if (moveType == TYPE_FIRE && gBattleResources->flags->flags[battlerAtk] & RESOURCE_FLAG_FLASH_FIRE) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; case ABILITY_SWARM: if (moveType == TYPE_BUG && gBattleMons[battlerAtk].hp <= (gBattleMons[battlerAtk].maxHP / 3)) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; case ABILITY_TORRENT: if (moveType == TYPE_WATER && gBattleMons[battlerAtk].hp <= (gBattleMons[battlerAtk].maxHP / 3)) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; case ABILITY_BLAZE: if (moveType == TYPE_FIRE && gBattleMons[battlerAtk].hp <= (gBattleMons[battlerAtk].maxHP / 3)) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; case ABILITY_OVERGROW: if (moveType == TYPE_GRASS && gBattleMons[battlerAtk].hp <= (gBattleMons[battlerAtk].maxHP / 3)) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; #if B_PLUS_MINUS_INTERACTION >= GEN_5 case ABILITY_PLUS: @@ -9155,34 +9145,34 @@ static u32 CalcAttackStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, b { u32 partnerAbility = GetBattlerAbility(BATTLE_PARTNER(battlerAtk)); if (partnerAbility == ABILITY_PLUS || partnerAbility == ABILITY_MINUS) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); } break; #else case ABILITY_PLUS: if (IS_MOVE_SPECIAL(move) && IsBattlerAlive(BATTLE_PARTNER(battlerAtk)) && GetBattlerAbility(BATTLE_PARTNER(battlerAtk)) == ABILITY_MINUS) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; case ABILITY_MINUS: if (IS_MOVE_SPECIAL(move) && IsBattlerAlive(BATTLE_PARTNER(battlerAtk)) && GetBattlerAbility(BATTLE_PARTNER(battlerAtk)) == ABILITY_PLUS) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; #endif case ABILITY_FLOWER_GIFT: if (gBattleMons[battlerAtk].species == SPECIES_CHERRIM_SUNSHINE && IsBattlerWeatherAffected(battlerAtk, B_WEATHER_SUN) && IS_MOVE_PHYSICAL(move)) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; case ABILITY_HUSTLE: if (IS_MOVE_PHYSICAL(move)) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; case ABILITY_STAKEOUT: if (gDisableStructs[battlerDef].isFirstTurn == 2) // just switched in - MulModifier(&modifier, UQ_4_12(2.0)); + modifier = uq4_12_multiply(modifier, UQ_4_12(2.0)); break; case ABILITY_GUTS: if (gBattleMons[battlerAtk].status1 & STATUS1_ANY && IS_MOVE_PHYSICAL(move)) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; } @@ -9192,14 +9182,14 @@ static u32 CalcAttackStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, b case ABILITY_THICK_FAT: if (moveType == TYPE_FIRE || moveType == TYPE_ICE) { - MulModifier(&modifier, UQ_4_12(0.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(0.5)); if (updateFlags) RecordAbilityBattle(battlerDef, ABILITY_THICK_FAT); } break; case ABILITY_ICE_SCALES: if (IS_MOVE_SPECIAL(move)) - MulModifier(&modifier, UQ_4_12(0.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(0.5)); break; } @@ -9210,7 +9200,7 @@ static u32 CalcAttackStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, b { case ABILITY_FLOWER_GIFT: if (gBattleMons[BATTLE_PARTNER(battlerAtk)].species == SPECIES_CHERRIM_SUNSHINE && IsBattlerWeatherAffected(BATTLE_PARTNER(battlerAtk), B_WEATHER_SUN) && IS_MOVE_PHYSICAL(move)) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; } } @@ -9220,32 +9210,32 @@ static u32 CalcAttackStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, b { case HOLD_EFFECT_THICK_CLUB: if ((atkBaseSpeciesId == SPECIES_CUBONE || atkBaseSpeciesId == SPECIES_MAROWAK) && IS_MOVE_PHYSICAL(move)) - MulModifier(&modifier, UQ_4_12(2.0)); + modifier = uq4_12_multiply(modifier, UQ_4_12(2.0)); break; case HOLD_EFFECT_DEEP_SEA_TOOTH: if (gBattleMons[battlerAtk].species == SPECIES_CLAMPERL && IS_MOVE_SPECIAL(move)) - MulModifier(&modifier, UQ_4_12(2.0)); + modifier = uq4_12_multiply(modifier, UQ_4_12(2.0)); break; case HOLD_EFFECT_LIGHT_BALL: if (atkBaseSpeciesId == SPECIES_PIKACHU) - MulModifier(&modifier, UQ_4_12(2.0)); + modifier = uq4_12_multiply(modifier, UQ_4_12(2.0)); break; case HOLD_EFFECT_CHOICE_BAND: if (IS_MOVE_PHYSICAL(move)) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; case HOLD_EFFECT_CHOICE_SPECS: if (IS_MOVE_SPECIAL(move)) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; } // The offensive stats of a Player's Pokémon are boosted by x1.1 (+10%) if they have the 1st badge and 7th badges. // Having the 1st badge boosts physical attack while having the 7th badge boosts special attack. if (ShouldGetStatBadgeBoost(FLAG_BADGE01_GET, battlerAtk) && IS_MOVE_PHYSICAL(move)) - MulModifier(&modifier, UQ_4_12(1.1)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.1)); if (ShouldGetStatBadgeBoost(FLAG_BADGE07_GET, battlerAtk) && IS_MOVE_SPECIAL(move)) - MulModifier(&modifier, UQ_4_12(1.1)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.1)); return ApplyModifier(modifier, atkStat); } @@ -9267,7 +9257,7 @@ static u32 CalcDefenseStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, bool32 usesDefStat; u8 defStage; u32 defStat, def, spDef; - u16 modifier; + uq4_12_t modifier; if (gFieldStatuses & STATUS_FIELD_WONDER_ROOM) // the defense stats are swapped { @@ -9321,7 +9311,7 @@ static u32 CalcDefenseStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, case ABILITY_MARVEL_SCALE: if (gBattleMons[battlerDef].status1 & STATUS1_ANY && usesDefStat) { - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); if (updateFlags) RecordAbilityBattle(battlerDef, ABILITY_MARVEL_SCALE); } @@ -9329,7 +9319,7 @@ static u32 CalcDefenseStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, case ABILITY_FUR_COAT: if (usesDefStat) { - MulModifier(&modifier, UQ_4_12(2.0)); + modifier = uq4_12_multiply(modifier, UQ_4_12(2.0)); if (updateFlags) RecordAbilityBattle(battlerDef, ABILITY_FUR_COAT); } @@ -9337,22 +9327,22 @@ static u32 CalcDefenseStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, case ABILITY_GRASS_PELT: if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN && usesDefStat) { - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); if (updateFlags) RecordAbilityBattle(battlerDef, ABILITY_GRASS_PELT); } break; case ABILITY_FLOWER_GIFT: if (gBattleMons[battlerDef].species == SPECIES_CHERRIM_SUNSHINE && IsBattlerWeatherAffected(battlerDef, B_WEATHER_SUN) && !usesDefStat) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; case ABILITY_PUNK_ROCK: if (gBattleMoves[move].soundMove) - MulModifier(&modifier, UQ_4_12(2.0)); + modifier = uq4_12_multiply(modifier, UQ_4_12(2.0)); break; case ABILITY_PURIFYING_SALT: if (gBattleMoves[move].type == TYPE_GHOST) - MulModifier(&modifier, UQ_4_12(2.0)); + modifier = uq4_12_multiply(modifier, UQ_4_12(2.0)); break; } @@ -9363,7 +9353,7 @@ static u32 CalcDefenseStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, { case ABILITY_FLOWER_GIFT: if (gBattleMons[BATTLE_PARTNER(battlerDef)].species == SPECIES_CHERRIM_SUNSHINE && IsBattlerWeatherAffected(BATTLE_PARTNER(battlerDef), B_WEATHER_SUN) && !usesDefStat) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; } } @@ -9373,66 +9363,66 @@ static u32 CalcDefenseStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, { case HOLD_EFFECT_DEEP_SEA_SCALE: if (gBattleMons[battlerDef].species == SPECIES_CLAMPERL && !usesDefStat) - MulModifier(&modifier, UQ_4_12(2.0)); + modifier = uq4_12_multiply(modifier, UQ_4_12(2.0)); break; case HOLD_EFFECT_METAL_POWDER: if (gBattleMons[battlerDef].species == SPECIES_DITTO && usesDefStat && !(gBattleMons[battlerDef].status2 & STATUS2_TRANSFORMED)) - MulModifier(&modifier, UQ_4_12(2.0)); + modifier = uq4_12_multiply(modifier, UQ_4_12(2.0)); break; case HOLD_EFFECT_EVIOLITE: if (CanEvolve(gBattleMons[battlerDef].species)) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; case HOLD_EFFECT_ASSAULT_VEST: if (!usesDefStat) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; #if B_SOUL_DEW_BOOST <= GEN_6 case HOLD_EFFECT_SOUL_DEW: if ((gBattleMons[battlerDef].species == SPECIES_LATIAS || gBattleMons[battlerDef].species == SPECIES_LATIOS) && !(gBattleTypeFlags & BATTLE_TYPE_FRONTIER) && !usesDefStat) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; #endif } // sandstorm sp.def boost for rock types if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_ROCK) && gBattleWeather & B_WEATHER_SANDSTORM && WEATHER_HAS_EFFECT && !usesDefStat) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); // snow def boost for ice types if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_ICE) && gBattleWeather & B_WEATHER_SNOW && WEATHER_HAS_EFFECT && usesDefStat) - MulModifier(&modifier, UQ_4_12(1.5)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); // The defensive stats of a Player's Pokémon are boosted by x1.1 (+10%) if they have the 5th badge and 7th badges. // Having the 5th badge boosts physical defense while having the 7th badge boosts special defense. if (ShouldGetStatBadgeBoost(FLAG_BADGE05_GET, battlerDef) && IS_MOVE_PHYSICAL(move)) - MulModifier(&modifier, UQ_4_12(1.1)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.1)); if (ShouldGetStatBadgeBoost(FLAG_BADGE07_GET, battlerDef) && IS_MOVE_SPECIAL(move)) - MulModifier(&modifier, UQ_4_12(1.1)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.1)); return ApplyModifier(modifier, defStat); } -static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, u16 typeEffectivenessModifier, bool32 isCrit, bool32 updateFlags) +static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, uq4_12_t typeEffectivenessModifier, bool32 isCrit, bool32 updateFlags) { u32 percentBoost; u32 abilityAtk = GetBattlerAbility(battlerAtk); u32 abilityDef = GetBattlerAbility(battlerDef); u32 defSide = GET_BATTLER_SIDE(battlerDef); - u16 finalModifier = UQ_4_12(1.0); + uq4_12_t finalModifier = UQ_4_12(1.0); u16 itemDef = gBattleMons[battlerDef].item; // check multiple targets in double battle if (GetMoveTargetCount(move, battlerAtk, battlerDef) >= 2) #if B_MULTIPLE_TARGETS_DMG >= GEN_4 - MulModifier(&finalModifier, UQ_4_12(0.75)); + finalModifier = uq4_12_multiply(finalModifier, UQ_4_12(0.75)); #else - MulModifier(&finalModifier, UQ_4_12(0.5)); + finalModifier = uq4_12_multiply(finalModifier, UQ_4_12(0.5)); #endif // take type effectiveness - MulModifier(&finalModifier, typeEffectivenessModifier); + finalModifier = uq4_12_multiply(finalModifier, typeEffectivenessModifier); // check crit if (isCrit) @@ -9478,9 +9468,9 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move if (IS_BATTLER_OF_TYPE(battlerAtk, moveType) && move != MOVE_STRUGGLE && move != MOVE_NONE) { if (abilityAtk == ABILITY_ADAPTABILITY) - MulModifier(&finalModifier, UQ_4_12(2.0)); + finalModifier = uq4_12_multiply(finalModifier, UQ_4_12(2.0)); else - MulModifier(&finalModifier, UQ_4_12(1.5)); + finalModifier = uq4_12_multiply(finalModifier, UQ_4_12(1.5)); } // reflect, light screen, aurora veil @@ -9492,24 +9482,24 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move && !gProtectStructs[battlerAtk].confusionSelfDmg) { if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) - MulModifier(&finalModifier, UQ_4_12(0.66)); + finalModifier = uq4_12_multiply(finalModifier, UQ_4_12(0.66)); else - MulModifier(&finalModifier, UQ_4_12(0.5)); + finalModifier = uq4_12_multiply(finalModifier, UQ_4_12(0.5)); } // Parental Bond Second Strike if (gSpecialStatuses[battlerAtk].parentalBondState == PARENTAL_BOND_2ND_HIT) { if (B_PARENTAL_BOND_DMG < GEN_7) - MulModifier(&finalModifier, UQ_4_12(0.5)); + finalModifier = uq4_12_multiply(finalModifier, UQ_4_12(0.5)); else - MulModifier(&finalModifier, UQ_4_12(0.25)); + finalModifier = uq4_12_multiply(finalModifier, UQ_4_12(0.25)); } // Z-Moves and Max Moves bypass Protect and do 25% of their original damage if (gBattleStruct->zmove.active && IS_BATTLER_PROTECTED(battlerDef)) { - MulModifier(&finalModifier, UQ_4_12(0.25)); + finalModifier = uq4_12_multiply(finalModifier, UQ_4_12(0.25)); } // attacker's abilities @@ -9517,15 +9507,15 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move { case ABILITY_TINTED_LENS: if (typeEffectivenessModifier <= UQ_4_12(0.5)) - MulModifier(&finalModifier, UQ_4_12(2.0)); + finalModifier = uq4_12_multiply(finalModifier, UQ_4_12(2.0)); break; case ABILITY_SNIPER: if (isCrit) - MulModifier(&finalModifier, UQ_4_12(1.5)); + finalModifier = uq4_12_multiply(finalModifier, UQ_4_12(1.5)); break; case ABILITY_NEUROFORCE: if (typeEffectivenessModifier >= UQ_4_12(2.0)) - MulModifier(&finalModifier, UQ_4_12(1.25)); + finalModifier = uq4_12_multiply(finalModifier, UQ_4_12(1.25)); break; } @@ -9535,13 +9525,13 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move case ABILITY_MULTISCALE: case ABILITY_SHADOW_SHIELD: if (BATTLER_MAX_HP(battlerDef)) - MulModifier(&finalModifier, UQ_4_12(0.5)); + finalModifier = uq4_12_multiply(finalModifier, UQ_4_12(0.5)); break; case ABILITY_FILTER: case ABILITY_SOLID_ROCK: case ABILITY_PRISM_ARMOR: if (typeEffectivenessModifier >= UQ_4_12(2.0)) - MulModifier(&finalModifier, UQ_4_12(0.75)); + finalModifier = uq4_12_multiply(finalModifier, UQ_4_12(0.75)); break; } @@ -9551,7 +9541,7 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move switch (GetBattlerAbility(BATTLE_PARTNER(battlerDef))) { case ABILITY_FRIEND_GUARD: - MulModifier(&finalModifier, UQ_4_12(0.75)); + finalModifier = uq4_12_multiply(finalModifier, UQ_4_12(0.75)); break; } } @@ -9561,14 +9551,14 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move { case HOLD_EFFECT_METRONOME: percentBoost = min((gBattleStruct->sameMoveTurns[battlerAtk] * GetBattlerHoldEffectParam(battlerAtk)), 100); - MulModifier(&finalModifier, UQ_4_12(1.0) + sPercentToModifier[percentBoost]); + finalModifier = uq4_12_multiply(finalModifier, UQ_4_12(1.0) + sPercentToModifier[percentBoost]); break; case HOLD_EFFECT_EXPERT_BELT: if (typeEffectivenessModifier >= UQ_4_12(2.0)) - MulModifier(&finalModifier, UQ_4_12(1.2)); + finalModifier = uq4_12_multiply(finalModifier, UQ_4_12(1.2)); break; case HOLD_EFFECT_LIFE_ORB: - MulModifier(&finalModifier, UQ_4_12(1.3)); + finalModifier = uq4_12_multiply(finalModifier, UQ_4_12(1.3)); break; } @@ -9582,9 +9572,9 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move && !UnnerveOn(battlerDef, itemDef)) { if (abilityDef == ABILITY_RIPEN) - MulModifier(&finalModifier, UQ_4_12(0.25)); + finalModifier = uq4_12_multiply(finalModifier, UQ_4_12(0.25)); else - MulModifier(&finalModifier, UQ_4_12(0.5)); + finalModifier = uq4_12_multiply(finalModifier, UQ_4_12(0.5)); if (updateFlags) gSpecialStatuses[battlerDef].berryReduced = TRUE; } @@ -9592,13 +9582,13 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move } if (gBattleMoves[move].minimizeDoubleDamage && gStatuses3[battlerDef] & STATUS3_MINIMIZED) - MulModifier(&finalModifier, UQ_4_12(2.0)); + finalModifier = uq4_12_multiply(finalModifier, UQ_4_12(2.0)); if (gBattleMoves[move].damagesUnderground && gStatuses3[battlerDef] & STATUS3_UNDERGROUND) - MulModifier(&finalModifier, UQ_4_12(2.0)); + finalModifier = uq4_12_multiply(finalModifier, UQ_4_12(2.0)); if (gBattleMoves[move].damagesUnderwater && gStatuses3[battlerDef] & STATUS3_UNDERWATER) - MulModifier(&finalModifier, UQ_4_12(2.0)); + finalModifier = uq4_12_multiply(finalModifier, UQ_4_12(2.0)); if (gBattleMoves[move].damagesAirborneDoubleDamage && gStatuses3[battlerDef] & STATUS3_ON_AIR) - MulModifier(&finalModifier, UQ_4_12(2.0)); + finalModifier = uq4_12_multiply(finalModifier, UQ_4_12(2.0)); dmg = ApplyModifier(finalModifier, dmg); if (dmg == 0) @@ -9608,7 +9598,7 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move } static s32 DoMoveDamageCalc(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, s32 fixedBasePower, - bool32 isCrit, bool32 randomFactor, bool32 updateFlags, u16 typeEffectivenessModifier) + bool32 isCrit, bool32 randomFactor, bool32 updateFlags, uq4_12_t typeEffectivenessModifier) { s32 dmg; @@ -9651,15 +9641,15 @@ 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, uq4_12_t *typeEffectivenessModifier) { *typeEffectivenessModifier = CalcTypeEffectivenessMultiplier(move, moveType, battlerAtk, battlerDef, FALSE); return DoMoveDamageCalc(move, battlerAtk, battlerDef, moveType, 0, FALSE, FALSE, FALSE, *typeEffectivenessModifier); } -static void MulByTypeEffectiveness(u16 *modifier, u16 move, u8 moveType, u8 battlerDef, u8 defType, u8 battlerAtk, bool32 recordAbilities) +static void MulByTypeEffectiveness(uq4_12_t *modifier, u16 move, u8 moveType, u8 battlerDef, u8 defType, u8 battlerAtk, bool32 recordAbilities) { - u16 mod = GetTypeModifier(moveType, defType); + uq4_12_t mod = GetTypeModifier(moveType, defType); if (mod == UQ_4_12(0.0) && GetBattlerHoldEffect(battlerDef, TRUE) == HOLD_EFFECT_RING_TARGET) { @@ -9694,13 +9684,13 @@ static void MulByTypeEffectiveness(u16 *modifier, u16 move, u8 moveType, u8 batt mod = UQ_4_12(1.0); } - MulModifier(modifier, mod); + *modifier = uq4_12_multiply(*modifier, mod); } -static void TryNoticeIllusionInTypeEffectiveness(u32 move, u32 moveType, u32 battlerAtk, u32 battlerDef, u16 resultingModifier, u32 illusionSpecies) +static void TryNoticeIllusionInTypeEffectiveness(u32 move, u32 moveType, u32 battlerAtk, u32 battlerDef, uq4_12_t resultingModifier, u32 illusionSpecies) { // Check if the type effectiveness would've been different if the pokemon really had the types as the disguise. - u16 presumedModifier = UQ_4_12(1.0); + uq4_12_t presumedModifier = UQ_4_12(1.0); MulByTypeEffectiveness(&presumedModifier, move, moveType, battlerDef, gSpeciesInfo[illusionSpecies].types[0], battlerAtk, FALSE); if (gSpeciesInfo[illusionSpecies].types[1] != gSpeciesInfo[illusionSpecies].types[0]) MulByTypeEffectiveness(&presumedModifier, move, moveType, battlerDef, gSpeciesInfo[illusionSpecies].types[1], battlerAtk, FALSE); @@ -9709,7 +9699,7 @@ static void TryNoticeIllusionInTypeEffectiveness(u32 move, u32 moveType, u32 bat RecordAbilityBattle(battlerDef, ABILITY_ILLUSION); } -static void UpdateMoveResultFlags(u16 modifier) +static void UpdateMoveResultFlags(uq4_12_t modifier) { if (modifier == UQ_4_12(0.0)) { @@ -9732,7 +9722,7 @@ static void UpdateMoveResultFlags(u16 modifier) } } -static u16 CalcTypeEffectivenessMultiplierInternal(u16 move, u8 moveType, u8 battlerAtk, u8 battlerDef, bool32 recordAbilities, u16 modifier) +static u16 CalcTypeEffectivenessMultiplierInternal(u16 move, u8 moveType, u8 battlerAtk, u8 battlerDef, bool32 recordAbilities, uq4_12_t modifier) { u32 illusionSpecies; u16 defAbility = GetBattlerAbility(battlerDef); @@ -9805,9 +9795,9 @@ static u16 CalcTypeEffectivenessMultiplierInternal(u16 move, u8 moveType, u8 bat return modifier; } -u16 CalcTypeEffectivenessMultiplier(u16 move, u8 moveType, u8 battlerAtk, u8 battlerDef, bool32 recordAbilities) +uq4_12_t CalcTypeEffectivenessMultiplier(u16 move, u8 moveType, u8 battlerAtk, u8 battlerDef, bool32 recordAbilities) { - u16 modifier = UQ_4_12(1.0); + uq4_12_t modifier = UQ_4_12(1.0); if (move != MOVE_STRUGGLE && moveType != TYPE_MYSTERY) { @@ -9821,9 +9811,9 @@ u16 CalcTypeEffectivenessMultiplier(u16 move, u8 moveType, u8 battlerAtk, u8 bat return modifier; } -u16 CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, u16 abilityDef) +uq4_12_t CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, u16 abilityDef) { - u16 modifier = UQ_4_12(1.0); + uq4_12_t modifier = UQ_4_12(1.0); u8 moveType = gBattleMoves[move].type; if (move != MOVE_STRUGGLE && moveType != TYPE_MYSTERY) @@ -9842,7 +9832,7 @@ u16 CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, u16 abilit return modifier; } -static u16 GetInverseTypeMultiplier(u16 multiplier) +static uq4_12_t GetInverseTypeMultiplier(uq4_12_t multiplier) { switch (multiplier) { @@ -9857,7 +9847,7 @@ static u16 GetInverseTypeMultiplier(u16 multiplier) } } -u16 GetTypeModifier(u8 atkType, u8 defType) +uq4_12_t GetTypeModifier(u8 atkType, u8 defType) { #if B_FLAG_INVERSE_BATTLE != 0 if (FlagGet(B_FLAG_INVERSE_BATTLE)) @@ -9869,11 +9859,11 @@ u16 GetTypeModifier(u8 atkType, u8 defType) s32 GetStealthHazardDamageByTypesAndHP(u8 hazardType, u8 type1, u8 type2, u32 maxHp) { s32 dmg = 0; - u16 modifier = UQ_4_12(1.0); + uq4_12_t modifier = UQ_4_12(1.0); - MulModifier(&modifier, GetTypeModifier(hazardType, type1)); + modifier = uq4_12_multiply(modifier, GetTypeModifier(hazardType, type1)); if (type2 != type1) - MulModifier(&modifier, GetTypeModifier(hazardType, type2)); + modifier = uq4_12_multiply(modifier, GetTypeModifier(hazardType, type2)); switch (modifier) { diff --git a/test/fpmath.c b/test/fpmath.c new file mode 100644 index 000000000..3f583d063 --- /dev/null +++ b/test/fpmath.c @@ -0,0 +1,18 @@ +#include "global.h" +#include "test.h" + +TEST("uq4_12_add adds 4.12 numbers") { + EXPECT_EQ(uq4_12_add(UQ_4_12(3.5), UQ_4_12(2.5)), UQ_4_12(6.0)); +} + +TEST("uq4_12_subtract subtracts 4.12 numbers") { + EXPECT_EQ(uq4_12_subtract(UQ_4_12(3.5), UQ_4_12(2.0)), UQ_4_12(1.5)); +} + +TEST("uq4_12_multiply multiplies 4.12 numbers") { + EXPECT_EQ(uq4_12_multiply(UQ_4_12(3.5), UQ_4_12(2.0)), UQ_4_12(7.0)); +} + +TEST("uq4_12_divide divides 4.12 numbers") { + EXPECT_EQ(uq4_12_divide(UQ_4_12(5.0), UQ_4_12(2.0)), UQ_4_12(2.5)); +}