diff --git a/include/battle.h b/include/battle.h index 13fc659768..fe7c740639 100644 --- a/include/battle.h +++ b/include/battle.h @@ -350,7 +350,7 @@ struct AiLogicData u16 partnerMove; u16 speedStats[MAX_BATTLERS_COUNT]; // Speed stats for all battles, calculated only once, same way as damages struct SimulatedDamage simulatedDmg[MAX_BATTLERS_COUNT][MAX_BATTLERS_COUNT][MAX_MON_MOVES]; // attacker, target, moveIndex - u8 effectiveness[MAX_BATTLERS_COUNT][MAX_BATTLERS_COUNT][MAX_MON_MOVES]; // attacker, target, moveIndex + uq4_12_t 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]; u8 monToSwitchInId[MAX_BATTLERS_COUNT]; // ID of the mon to switch in. diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 552faa1306..44aa9a9ce6 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -101,15 +101,14 @@ bool32 ShouldLowerEvasion(u32 battlerAtk, u32 battlerDef, u32 defAbility); bool32 IsAffectedByPowder(u32 battler, u32 ability, u32 holdEffect); bool32 MovesWithCategoryUnusable(u32 attacker, u32 target, u32 category); s32 AI_WhichMoveBetter(u32 move1, u32 move2, u32 battlerAtk, u32 battlerDef, s32 noOfHitsToKo); -struct SimulatedDamage AI_CalcDamageSaveBattlers(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectiveness, bool32 considerZPower, enum DamageRollType rollType); -struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectiveness, bool32 considerZPower, u32 weather, enum DamageRollType rollType); +struct SimulatedDamage AI_CalcDamageSaveBattlers(u32 move, u32 battlerAtk, u32 battlerDef, uq4_12_t *typeEffectiveness, bool32 considerZPower, enum DamageRollType rollType); +struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, uq4_12_t *typeEffectiveness, bool32 considerZPower, u32 weather, enum DamageRollType rollType); bool32 AI_IsDamagedByRecoil(u32 battler); u32 GetNoOfHitsToKO(u32 dmg, s32 hp); u32 GetNoOfHitsToKOBattlerDmg(u32 dmg, u32 battlerDef); u32 GetNoOfHitsToKOBattler(u32 battlerAtk, u32 battlerDef, u32 moveIndex); u32 GetCurrDamageHpPercent(u32 battlerAtk, u32 battlerDef); -uq4_12_t AI_GetTypeEffectiveness(u32 move, u32 battlerAtk, u32 battlerDef); -u32 AI_GetMoveEffectiveness(u32 move, u32 battlerAtk, u32 battlerDef); +uq4_12_t AI_GetMoveEffectiveness(u32 move, u32 battlerAtk, u32 battlerDef); u16 *GetMovesArray(u32 battler); bool32 IsConfusionMoveEffect(u32 moveEffect); bool32 HasMove(u32 battlerId, u32 move); diff --git a/include/constants/battle_ai.h b/include/constants/battle_ai.h index e4cf747818..8ba2c72096 100644 --- a/include/constants/battle_ai.h +++ b/include/constants/battle_ai.h @@ -14,16 +14,6 @@ #define AI_TYPE2_USER 3 #define AI_TYPE_MOVE 4 -// type effectiveness -#define AI_EFFECTIVENESS_x8 7 -#define AI_EFFECTIVENESS_x4 6 -#define AI_EFFECTIVENESS_x2 5 -#define AI_EFFECTIVENESS_x1 4 -#define AI_EFFECTIVENESS_x0_5 3 -#define AI_EFFECTIVENESS_x0_25 2 -#define AI_EFFECTIVENESS_x0_125 1 -#define AI_EFFECTIVENESS_x0 0 - // AI Flags. Most run specific functions to update score, new flags are used for internal logic in other scripts // See docs/ai_flags.md for more details. #define AI_FLAG_CHECK_BAD_MOVE (1 << 0) // AI will avoid using moves that are likely to fail or be ineffective in the current situation. diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index d40cf2968f..cadf627e20 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -421,7 +421,7 @@ static void CalcBattlerAiMovesData(struct AiLogicData *aiData, u32 battlerAtk, u for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++) { struct SimulatedDamage dmg = {0}; - u8 effectiveness = AI_EFFECTIVENESS_x0; + uq4_12_t effectiveness = Q_4_12(0.0); move = moves[moveIndex]; if (move != MOVE_NONE @@ -722,14 +722,14 @@ static inline void BattleAI_DoAIProcessing(struct AI_ThinkingStruct *aiThink, u3 void BattleAI_DoAIProcessing_PredictedSwitchin(struct AI_ThinkingStruct *aiThink, struct AiLogicData *aiData, u32 battlerAtk, u32 battlerDef) { struct BattlePokemon switchoutCandidate = gBattleMons[battlerDef]; - struct SimulatedDamage simulatedDamageSwitchout[4]; - u8 effectivenessSwitchout[4]; - u8 moveAccuracySwitchout[4]; + struct SimulatedDamage simulatedDamageSwitchout[MAX_MON_MOVES]; + uq4_12_t effectivenessSwitchout[MAX_MON_MOVES]; + u8 moveAccuracySwitchout[MAX_MON_MOVES]; struct BattlePokemon switchinCandidate; - struct SimulatedDamage simulatedDamageSwitchin[4]; - u8 effectivenessSwitchin[4]; - u8 moveAccuracySwitchin[4]; + struct SimulatedDamage simulatedDamageSwitchin[MAX_MON_MOVES]; + uq4_12_t effectivenessSwitchin[MAX_MON_MOVES]; + u8 moveAccuracySwitchin[MAX_MON_MOVES]; struct Pokemon *party = GetBattlerParty(battlerDef); struct BattlePokemon *savedBattleMons = AllocSaveBattleMons(); @@ -839,7 +839,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) s32 moveType; u32 moveTarget = GetBattlerMoveTargetType(battlerAtk, move); struct AiLogicData *aiData = AI_DATA; - u32 effectiveness = aiData->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex]; + uq4_12_t effectiveness = aiData->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex]; bool32 isDoubleBattle = IsValidDoubleBattle(battlerAtk); u32 i; u32 weather; @@ -863,14 +863,12 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (gBattleStruct->battlerState[battlerDef].commandingDondozo) RETURN_SCORE_MINUS(20); - // check if negates type - switch (effectiveness) + if (effectiveness == UQ_4_12(0.0)) { - case AI_EFFECTIVENESS_x0: RETURN_SCORE_MINUS(20); - break; - case AI_EFFECTIVENESS_x0_125: - case AI_EFFECTIVENESS_x0_25: + } + else if (effectiveness < UQ_4_12(0.5)) + { switch (moveEffect) { case EFFECT_FIXED_DAMAGE_ARG: @@ -889,7 +887,6 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) default: RETURN_SCORE_MINUS(10); } - break; } // check non-user target @@ -922,7 +919,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } break; case ABILITY_WONDER_GUARD: - if (effectiveness < AI_EFFECTIVENESS_x2) + if (effectiveness < UQ_4_12(2.0)) RETURN_SCORE_MINUS(20); break; case ABILITY_JUSTIFIED: @@ -1117,7 +1114,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (!(AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_WILL_SUICIDE)) ADJUST_SCORE(-2); - if (effectiveness == AI_EFFECTIVENESS_x0) + if (effectiveness == UQ_4_12(0.0)) { ADJUST_SCORE(-10); } @@ -1452,7 +1449,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_FIXED_DAMAGE_ARG: case EFFECT_FOCUS_PUNCH: // AI_CBM_HighRiskForDamage - if (aiData->abilities[battlerDef] == ABILITY_WONDER_GUARD && effectiveness < AI_EFFECTIVENESS_x2) + if (aiData->abilities[battlerDef] == ABILITY_WONDER_GUARD && effectiveness < UQ_4_12(2.0)) ADJUST_SCORE(-10); if (HasDamagingMove(battlerDef) && !((gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE) || IsBattlerIncapacitated(battlerDef, aiData->abilities[battlerDef]) @@ -2840,7 +2837,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_MAGNET_RISE: if (IsBattlerGrounded(battlerAtk) && (HasMove(battlerAtkPartner, MOVE_EARTHQUAKE) || HasMove(battlerAtkPartner, MOVE_MAGNITUDE)) - && (AI_GetMoveEffectiveness(MOVE_EARTHQUAKE, battlerAtk, battlerAtkPartner) != AI_EFFECTIVENESS_x0)) // Doesn't resist ground move + && (AI_GetMoveEffectiveness(MOVE_EARTHQUAKE, battlerAtk, battlerAtkPartner) != UQ_4_12(0.0))) // Doesn't resist ground move { RETURN_SCORE_PLUS(DECENT_EFFECT); // partner has earthquake or magnitude -> good idea to use magnet rise } @@ -3309,7 +3306,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) u32 moveEffect = GetMoveEffect(move); struct AiLogicData *aiData = AI_DATA; u32 movesetIndex = AI_THINKING_STRUCT->movesetIndex; - u32 effectiveness = aiData->effectiveness[battlerAtk][battlerDef][movesetIndex]; + uq4_12_t effectiveness = aiData->effectiveness[battlerAtk][battlerDef][movesetIndex]; s32 score = 0; u32 predictedMove = aiData->lastUsedMove[battlerDef]; @@ -3323,7 +3320,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) moveEffect = EFFECT_PROTECT; // check status move preference - if (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_PREFER_STATUS_MOVES && IsBattleMoveStatus(move) && effectiveness != AI_EFFECTIVENESS_x0) + if (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_PREFER_STATUS_MOVES && IsBattleMoveStatus(move) && effectiveness != UQ_4_12(0.0)) ADJUST_SCORE(10); // check thawing moves @@ -3346,7 +3343,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) IncreaseSleepScore(battlerAtk, battlerDef, move, &score); break; case EFFECT_ABSORB: - if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_BIG_ROOT && effectiveness >= AI_EFFECTIVENESS_x1) + if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_BIG_ROOT && effectiveness >= UQ_4_12(1.0)) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_EXPLOSION: @@ -4488,7 +4485,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) break; case EFFECT_MAGNET_RISE: if (IsBattlerGrounded(battlerAtk) && HasDamagingMoveOfType(battlerDef, TYPE_ELECTRIC) - && !(AI_GetMoveEffectiveness(MOVE_EARTHQUAKE, battlerDef, battlerAtk) == AI_EFFECTIVENESS_x0)) // Doesn't resist ground move + && !(effectiveness == UQ_4_12(0.0))) // Doesn't resist ground move { if (AI_IsFaster(battlerAtk, battlerDef, move)) // Attacker goes first { @@ -4506,7 +4503,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) break; case EFFECT_CAMOUFLAGE: if (predictedMove != MOVE_NONE && AI_IsFaster(battlerAtk, battlerDef, move) // Attacker goes first - && !IsBattleMoveStatus(move) && AI_GetMoveEffectiveness(predictedMove, battlerDef, battlerAtk) != AI_EFFECTIVENESS_x0) + && !IsBattleMoveStatus(move) && effectiveness != UQ_4_12(0.0)) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_TOXIC_THREAD: @@ -5408,7 +5405,7 @@ static s32 AI_PredictSwitch(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) u32 aiHazardFlags = gSideStatuses[GetBattlerSide(battlerAtk)] & (SIDE_STATUS_HAZARDS_ANY); u32 moveEffect = gMovesInfo[move].effect; struct AiLogicData *aiData = AI_DATA; - u32 effectiveness = aiData->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex]; + uq4_12_t effectiveness = aiData->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex]; // Switch benefit switch (moveEffect) @@ -5429,7 +5426,7 @@ static s32 AI_PredictSwitch(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(DECENT_EFFECT); if (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_CHECK_BAD_MOVE) { - if (aiData->abilities[battlerDef] == ABILITY_WONDER_GUARD && effectiveness < AI_EFFECTIVENESS_x2) + if (aiData->abilities[battlerDef] == ABILITY_WONDER_GUARD && effectiveness < UQ_4_12(2.0)) ADJUST_SCORE(10); if (HasDamagingMove(battlerDef) && !((gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE) || IsBattlerIncapacitated(battlerDef, aiData->abilities[battlerDef]) diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index 0f38f326d1..e90423a796 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -88,11 +88,12 @@ static inline bool32 SetSwitchinAndSwitch(u32 battler, u32 switchinId) static bool32 ShouldSwitchIfHasBadOdds(u32 battler) { //Variable initialization - u8 opposingPosition, atkType1, atkType2, defType1, defType2, effectiveness; + u8 opposingPosition, atkType1, atkType2, defType1, defType2; s32 i, damageDealt = 0, maxDamageDealt = 0, damageTaken = 0, maxDamageTaken = 0; u32 aiMove, playerMove, aiBestMove = MOVE_NONE, aiAbility = AI_DATA->abilities[battler], opposingBattler, weather = AI_GetWeather(AI_DATA); bool32 getsOneShot = FALSE, hasStatusMove = FALSE, hasSuperEffectiveMove = FALSE; u16 typeEffectiveness = UQ_4_12(1.0), aiMoveEffect; //baseline typing damage + uq4_12_t effectiveness; // Only use this if AI_FLAG_SMART_SWITCHING is set for the trainer if (!(AI_THINKING_STRUCT->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING)) @@ -133,7 +134,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) if (!IsBattleMoveStatus(aiMove)) { // Check if mon has a super effective move - if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) >= AI_EFFECTIVENESS_x2) + if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) >= UQ_4_12(2.0)) hasSuperEffectiveMove = TRUE; // Get maximum damage mon can deal @@ -254,8 +255,8 @@ static bool32 ShouldSwitchIfAllMovesBad(u32 battler) for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++) { aiMove = gBattleMons[battler].moves[moveIndex]; - if ((AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) > AI_EFFECTIVENESS_x0 - || AI_GetMoveEffectiveness(aiMove, battler, opposingPartner) > AI_EFFECTIVENESS_x0) + if ((AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) > UQ_4_12(0.0) + || AI_GetMoveEffectiveness(aiMove, battler, opposingPartner) > UQ_4_12(0.0)) && aiMove != MOVE_NONE) return FALSE; } @@ -265,7 +266,7 @@ static bool32 ShouldSwitchIfAllMovesBad(u32 battler) for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++) { aiMove = gBattleMons[battler].moves[moveIndex]; - if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) > AI_EFFECTIVENESS_x0 && aiMove != MOVE_NONE) + if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) > UQ_4_12(0.0) && aiMove != MOVE_NONE) return FALSE; } } @@ -294,7 +295,7 @@ static bool32 FindMonThatHitsWonderGuard(u32 battler) move = gBattleMons[battler].moves[i]; if (move != MOVE_NONE) { - if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= AI_EFFECTIVENESS_x2) + if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= UQ_4_12(2.0)) return FALSE; } } @@ -319,7 +320,7 @@ static bool32 FindMonThatHitsWonderGuard(u32 battler) if (move != MOVE_NONE) { // Found a mon - if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= AI_EFFECTIVENESS_x2) + if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= UQ_4_12(2.0)) return SetSwitchinAndSwitch(battler, i); } } @@ -527,7 +528,7 @@ static bool32 ShouldSwitchIfBadlyStatused(u32 battler) || monAbility == ABILITY_EARLY_BIRD) || holdEffect == (HOLD_EFFECT_CURE_SLP | HOLD_EFFECT_CURE_STATUS) || HasMove(battler, MOVE_SLEEP_TALK) - || (HasMoveEffect(battler, MOVE_SNORE) && AI_GetMoveEffectiveness(MOVE_SNORE, battler, opposingBattler) >= AI_EFFECTIVENESS_x2) + || (HasMoveEffect(battler, MOVE_SNORE) && AI_GetMoveEffectiveness(MOVE_SNORE, battler, opposingBattler) >= UQ_4_12(2.0)) || (IsBattlerGrounded(battler) && (HasMove(battler, MOVE_MISTY_TERRAIN) || HasMove(battler, MOVE_ELECTRIC_TERRAIN))) ) @@ -643,7 +644,7 @@ static bool32 HasSuperEffectiveMoveAgainstOpponents(u32 battler, bool32 noRng) if (move == MOVE_NONE) continue; - if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= AI_EFFECTIVENESS_x2) + if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= UQ_4_12(2.0)) { if (noRng) return TRUE; @@ -665,7 +666,7 @@ static bool32 HasSuperEffectiveMoveAgainstOpponents(u32 battler, bool32 noRng) if (move == MOVE_NONE) continue; - if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= AI_EFFECTIVENESS_x2) + if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= UQ_4_12(2.0)) { if (noRng) return TRUE; @@ -764,7 +765,7 @@ static bool32 FindMonWithFlagsAndSuperEffective(u32 battler, u16 flags, u32 perc if (move == 0) continue; - if (AI_GetMoveEffectiveness(move, battler, battlerIn1) >= AI_EFFECTIVENESS_x2 && (RandomPercentage(RNG_AI_SWITCH_SE_DEFENSIVE, percentChance) || AI_DATA->aiSwitchPredictionInProgress)) + if (AI_GetMoveEffectiveness(move, battler, battlerIn1) >= UQ_4_12(2.0) && (RandomPercentage(RNG_AI_SWITCH_SE_DEFENSIVE, percentChance) || AI_DATA->aiSwitchPredictionInProgress)) return SetSwitchinAndSwitch(battler, i); } } @@ -858,7 +859,7 @@ static bool32 ShouldSwitchIfEncored(u32 battler) return SetSwitchinAndSwitch(battler, PARTY_SIZE); // Stay in if effective move - else if (AI_GetMoveEffectiveness(encoredMove, battler, opposingBattler) >= AI_EFFECTIVENESS_x2) + else if (AI_GetMoveEffectiveness(encoredMove, battler, opposingBattler) >= UQ_4_12(2.0)) return FALSE; // Switch out 50% of the time otherwise @@ -1210,7 +1211,7 @@ static u32 GetBestMonTypeMatchup(struct Pokemon *party, int firstId, int lastId, for (i = 0; i < MAX_MON_MOVES; i++) { u32 move = GetMonData(&party[bestMonId], MON_DATA_MOVE1 + i); - if (move != MOVE_NONE && AI_GetMoveEffectiveness(move, battler, opposingBattler) >= AI_EFFECTIVENESS_x2) + if (move != MOVE_NONE && AI_GetMoveEffectiveness(move, battler, opposingBattler) >= UQ_4_12(2.0)) break; } @@ -1866,7 +1867,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, { if (typeMatchup < bestResistEffective) { - if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) >= AI_EFFECTIVENESS_x2) + if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) >= UQ_4_12(2.0)) { if (canSwitchinWin1v1) { diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 04e0804ab7..dbb5aa8414 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -23,8 +23,6 @@ #include "constants/moves.h" #include "constants/items.h" -static u32 AI_GetEffectiveness(uq4_12_t multiplier); - // Functions u32 GetDmgRollType(u32 battlerAtk) { @@ -387,7 +385,7 @@ bool32 MovesWithCategoryUnusable(u32 attacker, u32 target, u32 category) } // To save computation time this function has 2 variants. One saves, sets and restores battlers, while the other doesn't. -struct SimulatedDamage AI_CalcDamageSaveBattlers(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectiveness, bool32 considerZPower, enum DamageRollType rollType) +struct SimulatedDamage AI_CalcDamageSaveBattlers(u32 move, u32 battlerAtk, u32 battlerDef, uq4_12_t *typeEffectiveness, bool32 considerZPower, enum DamageRollType rollType) { struct SimulatedDamage dmg; @@ -395,7 +393,7 @@ struct SimulatedDamage AI_CalcDamageSaveBattlers(u32 move, u32 battlerAtk, u32 b SaveBattlerData(battlerDef); SetBattlerData(battlerAtk); SetBattlerData(battlerDef); - dmg = AI_CalcDamage(move, battlerAtk, battlerDef, typeEffectiveness, considerZPower, AI_GetWeather(AI_DATA), rollType); + dmg = AI_CalcDamage(move, battlerAtk, battlerDef, typeEffectiveness, considerZPower, AI_GetWeather(AI_DATA), rollType); RestoreBattlerData(battlerAtk); RestoreBattlerData(battlerDef); return dmg; @@ -631,7 +629,7 @@ static inline void CalcDynamicMoveDamage(struct DamageCalculationData *damageCal *minimumDamage = minimum; } -struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectiveness, bool32 considerZPower, u32 weather, enum DamageRollType rollType) +struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, uq4_12_t *typeEffectiveness, bool32 considerZPower, u32 weather, enum DamageRollType rollType) { struct SimulatedDamage simDamage; s32 moveType; @@ -755,7 +753,7 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u } // convert multiper to AI_EFFECTIVENESS_xX - *typeEffectiveness = AI_GetEffectiveness(effectivenessMultiplier); + *typeEffectiveness = effectivenessMultiplier; // Undo temporary settings gBattleStruct->dynamicMoveType = 0; @@ -1040,7 +1038,7 @@ u32 GetCurrDamageHpPercent(u32 battlerAtk, u32 battlerDef) return (bestDmg * 100) / gBattleMons[battlerDef].maxHP; } -uq4_12_t AI_GetTypeEffectiveness(u32 move, u32 battlerAtk, u32 battlerDef) +uq4_12_t AI_GetMoveEffectiveness(u32 move, u32 battlerAtk, u32 battlerDef) { uq4_12_t typeEffectiveness; u32 moveType; @@ -1062,35 +1060,6 @@ uq4_12_t AI_GetTypeEffectiveness(u32 move, u32 battlerAtk, u32 battlerDef) return typeEffectiveness; } -u32 AI_GetMoveEffectiveness(u32 move, u32 battlerAtk, u32 battlerDef) -{ - return AI_GetEffectiveness(AI_GetTypeEffectiveness(move, battlerAtk, battlerDef)); -} - -static u32 AI_GetEffectiveness(uq4_12_t multiplier) -{ - switch (multiplier) - { - case UQ_4_12(0.0): - return AI_EFFECTIVENESS_x0; - case UQ_4_12(0.125): - return AI_EFFECTIVENESS_x0_125; - case UQ_4_12(0.25): - return AI_EFFECTIVENESS_x0_25; - case UQ_4_12(0.5): - return AI_EFFECTIVENESS_x0_5; - case UQ_4_12(1.0): - default: - return AI_EFFECTIVENESS_x1; - case UQ_4_12(2.0): - return AI_EFFECTIVENESS_x2; - case UQ_4_12(4.0): - return AI_EFFECTIVENESS_x4; - case UQ_4_12(8.0): - return AI_EFFECTIVENESS_x8; - } -} - /* Checks to see if AI will move ahead of another battler * The function uses a stripped down version of the checks from GetWhichBattlerFasterArgs * Output: @@ -3012,7 +2981,7 @@ bool32 ShouldPoisonSelf(u32 battler, u32 ability) bool32 AI_CanPoison(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 partnerMove) { if (!CanBePoisoned(battlerAtk, battlerDef, GetBattlerAbility(battlerDef)) - || AI_DATA->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex] == AI_EFFECTIVENESS_x0 + || AI_DATA->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex] == UQ_4_12(0.0) || DoesSubstituteBlockMove(battlerAtk, battlerDef, move) || PartnerMoveEffectIsStatusSameTarget(BATTLE_PARTNER(battlerAtk), battlerDef, partnerMove)) return FALSE; @@ -3027,7 +2996,7 @@ bool32 AI_CanPoison(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u3 bool32 AI_CanParalyze(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 partnerMove) { if (!CanBeParalyzed(battlerDef, defAbility) - || AI_DATA->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex] == AI_EFFECTIVENESS_x0 + || AI_DATA->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex] == UQ_4_12(0.0) || gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_SAFEGUARD || DoesSubstituteBlockMove(battlerAtk, battlerDef, move) || PartnerMoveEffectIsStatusSameTarget(BATTLE_PARTNER(battlerAtk), battlerDef, partnerMove)) @@ -3089,7 +3058,7 @@ bool32 ShouldBurnSelf(u32 battler, u32 ability) bool32 AI_CanBurn(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 battlerAtkPartner, u32 move, u32 partnerMove) { if (!CanBeBurned(battlerDef, defAbility) - || AI_DATA->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex] == AI_EFFECTIVENESS_x0 + || AI_DATA->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex] == UQ_4_12(0.0) || DoesSubstituteBlockMove(battlerAtk, battlerDef, move) || PartnerMoveEffectIsStatusSameTarget(battlerAtkPartner, battlerDef, partnerMove)) { @@ -3101,7 +3070,7 @@ bool32 AI_CanBurn(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 battlerAtk bool32 AI_CanGiveFrostbite(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 battlerAtkPartner, u32 move, u32 partnerMove) { if (!AI_CanGetFrostbite(battlerDef, defAbility) - || AI_DATA->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex] == AI_EFFECTIVENESS_x0 + || AI_DATA->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex] == UQ_4_12(0.0) || DoesSubstituteBlockMove(battlerAtk, battlerDef, move) || PartnerMoveEffectIsStatusSameTarget(battlerAtkPartner, battlerDef, partnerMove)) { @@ -3113,7 +3082,7 @@ bool32 AI_CanGiveFrostbite(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 b bool32 AI_CanBeInfatuated(u32 battlerAtk, u32 battlerDef, u32 defAbility) { if ((gBattleMons[battlerDef].status2 & STATUS2_INFATUATION) - || AI_DATA->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex] == AI_EFFECTIVENESS_x0 + || AI_DATA->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex] == UQ_4_12(0.0) || defAbility == ABILITY_OBLIVIOUS || !AreBattlersOfOppositeGender(battlerAtk, battlerDef) || AI_IsAbilityOnSide(battlerDef, ABILITY_AROMA_VEIL)) @@ -3575,7 +3544,7 @@ void FreeRestoreBattleMons(struct BattlePokemon *savedBattleMons) s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, bool32 isPartyMonAttacker, enum DamageRollType rollType) { struct SimulatedDamage dmg; - u8 effectiveness; + uq4_12_t effectiveness; struct BattlePokemon *savedBattleMons = AllocSaveBattleMons(); if (isPartyMonAttacker) @@ -4048,7 +4017,7 @@ bool32 ShouldUseZMove(u32 battlerAtk, u32 battlerDef, u32 chosenMove) if (IsViableZMove(battlerAtk, chosenMove)) { - u8 effectiveness; + uq4_12_t effectiveness; u32 zMove = GetUsableZMove(battlerAtk, chosenMove); struct SimulatedDamage dmg;