diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 43f6db694e..f8a5a01cc1 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -2,8 +2,8 @@ #define GUARD_BATTLE_AI_UTIL_H // for AI_WhoStrikesFirst -#define AI_IS_FASTER 0 -#define AI_IS_SLOWER 1 +#define AI_IS_FASTER 1 +#define AI_IS_SLOWER -1 #define FOE(battler) ((BATTLE_OPPOSITE(battler)) & BIT_SIDE) @@ -30,7 +30,7 @@ bool32 IsTruantMonVulnerable(u32 battlerAI, u32 opposingBattler); bool32 AtMaxHp(u32 battler); u32 GetHealthPercentage(u32 battler); bool32 IsBattlerTrapped(u32 battler, bool32 switching); -u32 AI_WhoStrikesFirst(u32 battlerAI, u32 battler2, u32 moveConsidered); +s32 AI_WhoStrikesFirst(u32 battlerAI, u32 battler2, u32 moveConsidered); bool32 CanTargetFaintAi(u32 battlerDef, u32 battlerAtk); bool32 CanTargetMoveFaintAi(u32 move, u32 battlerDef, u32 battlerAtk, u32 nHits); bool32 CanTargetFaintAiWithMod(u32 battlerDef, u32 battlerAtk, s32 hpMod, s32 dmgMod); @@ -85,7 +85,7 @@ bool32 ShouldLowerEvasion(u32 battlerAtk, u32 battlerDef, u32 defAbility); // move checks bool32 IsAffectedByPowder(u32 battler, u32 ability, u32 holdEffect); bool32 MovesWithCategoryUnusable(u32 attacker, u32 target, u32 category); -u32 AI_WhichMoveBetter(u32 move1, u32 move2, u32 battlerAtk, u32 battlerDef, s32 noOfHitsToKo); +s32 AI_WhichMoveBetter(u32 move1, u32 move2, u32 battlerAtk, u32 battlerDef, s32 noOfHitsToKo); s32 AI_CalcDamageSaveBattlers(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectiveness, bool32 considerZPower); s32 AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectiveness, bool32 considerZPower, u32 weather); bool32 AI_IsDamagedByRecoil(u32 battler); diff --git a/include/battle_main.h b/include/battle_main.h index 9bb9bbdfb0..4943f69a70 100644 --- a/include/battle_main.h +++ b/include/battle_main.h @@ -63,9 +63,9 @@ u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, u32 holdEffect); u32 GetBattlerTotalSpeedStat(u32 battler); s8 GetChosenMovePriority(u32 battlerId); s8 GetMovePriority(u32 battlerId, u16 move); -u32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMoves, u32 ability1, u32 ability2, +s32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMoves, u32 ability1, u32 ability2, u32 holdEffectBattler1, u32 holdEffectBattler2, u32 speedBattler1, u32 speedBattler2, s32 priority1, s32 priority2); -u32 GetWhichBattlerFaster(u32 battler1, u32 battler2, bool32 ignoreChosenMoves); +s32 GetWhichBattlerFaster(u32 battler1, u32 battler2, bool32 ignoreChosenMoves); void RunBattleScriptCommands_PopCallbacksStack(void); void RunBattleScriptCommands(void); void SpecialStatusesClear(void); diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index f38551fb06..dbe1e29e3e 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -3075,16 +3075,16 @@ static bool32 IsPinchBerryItemEffect(u32 holdEffect) return FALSE; } -static u32 CompareMoveAccuracies(u32 battlerAtk, u32 battlerDef, u32 moveSlot1, u32 moveSlot2) +static s32 CompareMoveAccuracies(u32 battlerAtk, u32 battlerDef, u32 moveSlot1, u32 moveSlot2) { u32 acc1 = AI_DATA->moveAccuracy[battlerAtk][battlerDef][moveSlot1]; u32 acc2 = AI_DATA->moveAccuracy[battlerAtk][battlerDef][moveSlot2]; if (acc1 > acc2) - return 0; - else if (acc2 > acc1) return 1; - return 2; + else if (acc2 > acc1) + return -1; + return 0; } static s32 AI_CompareDamagingMoves(u32 battlerAtk, u32 battlerDef, u32 currId) @@ -3146,19 +3146,19 @@ static s32 AI_CompareDamagingMoves(u32 battlerAtk, u32 battlerDef, u32 currId) switch (CompareMoveAccuracies(battlerAtk, battlerDef, currId, i)) { - case 0: + case 1: viableMoveScores[i] -= 2; break; - case 1: + case -1: viableMoveScores[currId] -= 2; break; } switch (AI_WhichMoveBetter(moves[currId], moves[i], battlerAtk, battlerDef, noOfHits[currId])) { - case 0: + case 1: viableMoveScores[i] -= 1; break; - case 1: + case -1: viableMoveScores[currId] -= 1; break; } @@ -4367,7 +4367,7 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score if (IsStatBoostingBerry(item) && aiData->hpPercents[battlerAtk] > 60) ADJUST_SCORE(1); else if (ShouldRestoreHpBerry(battlerAtk, item) && !CanAIFaintTarget(battlerAtk, battlerDef, 0) - && ((GetWhichBattlerFaster(battlerAtk, battlerDef, TRUE) == 0 && CanTargetFaintAiWithMod(battlerDef, battlerAtk, 0, 0)) + && ((GetWhichBattlerFaster(battlerAtk, battlerDef, TRUE) == 1 && CanTargetFaintAiWithMod(battlerDef, battlerAtk, 0, 0)) || !CanTargetFaintAiWithMod(battlerDef, battlerAtk, toHeal, 0))) ADJUST_SCORE(1); // Recycle healing berry if we can't otherwise faint the target and the target wont kill us after we activate the berry } diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 9fab0ef65a..686a34d30c 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -988,7 +988,7 @@ static bool32 AI_IsMoveEffectInMinus(u32 battlerAtk, u32 battlerDef, u32 move, s } // Checks if one of the moves has side effects or perks, assuming equal dmg or equal no of hits to KO -u32 AI_WhichMoveBetter(u32 move1, u32 move2, u32 battlerAtk, u32 battlerDef, s32 noOfHitsToKo) +s32 AI_WhichMoveBetter(u32 move1, u32 move2, u32 battlerAtk, u32 battlerDef, s32 noOfHitsToKo) { bool32 effect1, effect2; s32 defAbility = AI_DATA->abilities[battlerDef]; @@ -1008,18 +1008,18 @@ u32 AI_WhichMoveBetter(u32 move1, u32 move2, u32 battlerAtk, u32 battlerDef, s32 effect1 = AI_IsMoveEffectInMinus(battlerAtk, battlerDef, move1, noOfHitsToKo); effect2 = AI_IsMoveEffectInMinus(battlerAtk, battlerDef, move2, noOfHitsToKo); if (effect2 && !effect1) - return 0; - if (effect1 && !effect2) return 1; + if (effect1 && !effect2) + return -1; effect1 = AI_IsMoveEffectInPlus(battlerAtk, battlerDef, move1, noOfHitsToKo); effect2 = AI_IsMoveEffectInPlus(battlerAtk, battlerDef, move2, noOfHitsToKo); if (effect2 && !effect1) - return 1; + return -1; if (effect1 && !effect2) - return 0; + return 1; - return 2; + return 0; } u32 GetNoOfHitsToKO(u32 dmg, s32 hp) @@ -1103,7 +1103,7 @@ static u32 AI_GetEffectiveness(uq4_12_t multiplier) * AI_IS_FASTER: is user(ai) faster * AI_IS_SLOWER: is target faster */ -u32 AI_WhoStrikesFirst(u32 battlerAI, u32 battler2, u32 moveConsidered) +s32 AI_WhoStrikesFirst(u32 battlerAI, u32 battler2, u32 moveConsidered) { u32 fasterAI = 0, fasterPlayer = 0, i; s8 prioAI = 0; @@ -1142,7 +1142,7 @@ u32 AI_WhoStrikesFirst(u32 battlerAI, u32 battler2, u32 moveConsidered) AI_DATA->abilities[battlerAI], AI_DATA->abilities[battler2], AI_DATA->holdEffects[battlerAI], AI_DATA->holdEffects[battler2], AI_DATA->speedStats[battlerAI], AI_DATA->speedStats[battler2], - prioAI, prioBattler2) == 0) + prioAI, prioBattler2) == 1) return AI_IS_FASTER; else return AI_IS_SLOWER; diff --git a/src/battle_main.c b/src/battle_main.c index 26a6380efe..e0fba09ed0 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3723,7 +3723,7 @@ static void TryDoEventsBeforeFirstTurn(void) { for (j = i + 1; j < gBattlersCount; j++) { - if (GetWhichBattlerFaster(gBattlerByTurnOrder[i], gBattlerByTurnOrder[j], TRUE) != 0) + if (GetWhichBattlerFaster(gBattlerByTurnOrder[i], gBattlerByTurnOrder[j], TRUE) == -1) SwapTurnOrder(i, j); } } @@ -4698,7 +4698,7 @@ s8 GetMovePriority(u32 battler, u16 move) } // Function for AI with variables provided as arguments to speed the computation time -u32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMoves, u32 ability1, u32 ability2, +s32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMoves, u32 ability1, u32 ability2, u32 holdEffectBattler1, u32 holdEffectBattler2, u32 speedBattler1, u32 speedBattler2, s32 priority1, s32 priority2) { u32 strikesFirst = 0; @@ -4710,62 +4710,62 @@ u32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMov // STALL - always last if (gProtectStructs[battler1].quickDraw && !gProtectStructs[battler2].quickDraw) - strikesFirst = 0; + strikesFirst = 1; else if (!gProtectStructs[battler1].quickDraw && gProtectStructs[battler2].quickDraw) - strikesFirst = 1; + strikesFirst = -1; else if (gProtectStructs[battler1].usedCustapBerry && !gProtectStructs[battler2].usedCustapBerry) - strikesFirst = 0; + strikesFirst = 1; else if (gProtectStructs[battler2].usedCustapBerry && !gProtectStructs[battler1].usedCustapBerry) - strikesFirst = 1; + strikesFirst = -1; else if (holdEffectBattler1 == HOLD_EFFECT_LAGGING_TAIL && holdEffectBattler2 != HOLD_EFFECT_LAGGING_TAIL) - strikesFirst = 1; + strikesFirst = -1; else if (holdEffectBattler2 == HOLD_EFFECT_LAGGING_TAIL && holdEffectBattler1 != HOLD_EFFECT_LAGGING_TAIL) - strikesFirst = 0; + strikesFirst = 1; else if (ability1 == ABILITY_STALL && ability2 != ABILITY_STALL) - strikesFirst = 1; + strikesFirst = -1; else if (ability2 == ABILITY_STALL && ability1 != ABILITY_STALL) - strikesFirst = 0; - else if (ability1 == ABILITY_MYCELIUM_MIGHT && ability2 != ABILITY_MYCELIUM_MIGHT && IS_MOVE_STATUS(gCurrentMove)) strikesFirst = 1; + else if (ability1 == ABILITY_MYCELIUM_MIGHT && ability2 != ABILITY_MYCELIUM_MIGHT && IS_MOVE_STATUS(gCurrentMove)) + strikesFirst = -1; else if (ability2 == ABILITY_MYCELIUM_MIGHT && ability1 != ABILITY_MYCELIUM_MIGHT && IS_MOVE_STATUS(gCurrentMove)) - strikesFirst = 0; + strikesFirst = 1; else { if (speedBattler1 == speedBattler2 && Random() & 1) { - strikesFirst = 2; // same speeds, same priorities + strikesFirst = 0; // same speeds, same priorities } else if (speedBattler1 < speedBattler2) { // battler2 has more speed if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM) - strikesFirst = 0; - else strikesFirst = 1; + else + strikesFirst = -1; } else { // battler1 has more speed if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM) - strikesFirst = 1; + strikesFirst = -1; else - strikesFirst = 0; + strikesFirst = 1; } } } else if (priority1 < priority2) { - strikesFirst = 1; // battler2's move has greater priority + strikesFirst = -1; // battler2's move has greater priority } else { - strikesFirst = 0; // battler1's move has greater priority + strikesFirst = 1; // battler1's move has greater priority } return strikesFirst; } -u32 GetWhichBattlerFaster(u32 battler1, u32 battler2, bool32 ignoreChosenMoves) +s32 GetWhichBattlerFaster(u32 battler1, u32 battler2, bool32 ignoreChosenMoves) { s32 priority1 = 0, priority2 = 0; u32 ability1 = GetBattlerAbility(battler1); @@ -4881,7 +4881,7 @@ static void SetActionsAndBattlersTurnOrder(void) && gActionsByTurnOrder[i] != B_ACTION_THROW_BALL && gActionsByTurnOrder[j] != B_ACTION_THROW_BALL) { - if (GetWhichBattlerFaster(battler1, battler2, FALSE)) + if (GetWhichBattlerFaster(battler1, battler2, FALSE) == -1) SwapTurnOrder(i, j); } } @@ -5051,7 +5051,7 @@ static void TryChangeTurnOrder(void) if (gActionsByTurnOrder[i] == B_ACTION_USE_MOVE && gActionsByTurnOrder[j] == B_ACTION_USE_MOVE) { - if (GetWhichBattlerFaster(battler1, battler2, FALSE)) + if (GetWhichBattlerFaster(battler1, battler2, FALSE) == -1) SwapTurnOrder(i, j); } } diff --git a/src/battle_util.c b/src/battle_util.c index c348c268f0..25a84b8bab 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -883,12 +883,12 @@ void HandleAction_ActionFinished(void) // have been executed before. The only recalculation needed is for moves/switch. Mega evolution is handled in src/battle_main.c/TryChangeOrder if((gActionsByTurnOrder[i] == B_ACTION_USE_MOVE && gActionsByTurnOrder[j] == B_ACTION_USE_MOVE)) { - if (GetWhichBattlerFaster(battler1, battler2, FALSE)) + if (GetWhichBattlerFaster(battler1, battler2, FALSE) == -1) SwapTurnOrder(i, j); } else if ((gActionsByTurnOrder[i] == B_ACTION_SWITCH && gActionsByTurnOrder[j] == B_ACTION_SWITCH)) { - if (GetWhichBattlerFaster(battler1, battler2, TRUE)) // If the actions chosen are switching, we recalc order but ignoring the moves + if (GetWhichBattlerFaster(battler1, battler2, TRUE) == -1) // If the actions chosen are switching, we recalc order but ignoring the moves SwapTurnOrder(i, j); } } @@ -1980,7 +1980,7 @@ u8 DoFieldEndTurnEffects(void) { if (!gProtectStructs[i].quash && !gProtectStructs[j].quash - && GetWhichBattlerFaster(gBattlerByTurnOrder[i], gBattlerByTurnOrder[j], FALSE)) + && GetWhichBattlerFaster(gBattlerByTurnOrder[i], gBattlerByTurnOrder[j], FALSE) == -1) SwapTurnOrder(i, j); } }