diff --git a/include/battle_main.h b/include/battle_main.h index 844da53033..400d793b20 100644 --- a/include/battle_main.h +++ b/include/battle_main.h @@ -1,6 +1,7 @@ #ifndef GUARD_BATTLE_MAIN_H #define GUARD_BATTLE_MAIN_H +#include "battle_util.h" #include "pokemon.h" #include "data.h" #include "constants/hold_effects.h" @@ -97,14 +98,12 @@ u8 IsRunningFromBattleImpossible(u32 battler); void SwitchTwoBattlersInParty(u32 battler, u32 battler2); void SwitchPartyOrder(u32 battler); void SwapTurnOrder(u8 id1, u8 id2); -u32 GetBattlerTotalSpeedStatArgs(u32 battler, enum Ability ability, enum HoldEffect holdEffect); -u32 GetBattlerTotalSpeedStat(u32 battler); +u32 GetBattlerTotalSpeedStat(u32 battler, enum Ability ability, enum HoldEffect holdEffect); s32 GetChosenMovePriority(u32 battler, enum Ability ability); s32 GetBattleMovePriority(u32 battler, enum Ability ability, u32 move); -s32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMoves, enum Ability ability1, enum Ability ability2, - enum HoldEffect holdEffectBattler1, enum HoldEffect holdEffectBattler2, u32 speedBattler1, u32 speedBattler2, s32 priority1, s32 priority2); -s32 GetWhichBattlerFasterOrTies(u32 battler1, u32 battler2, bool32 ignoreChosenMoves); -s32 GetWhichBattlerFaster(u32 battler1, u32 battler2, bool32 ignoreChosenMoves); +s32 GetWhichBattlerFasterArgs(struct BattleContext *ctx, bool32 ignoreChosenMoves, u32 speedBattler1, u32 speedBattler2, s32 priority1, s32 priority2); +s32 GetWhichBattlerFasterOrTies(struct BattleContext *ctx, bool32 ignoreChosenMoves); +s32 GetWhichBattlerFaster(struct BattleContext *ctx, bool32 ignoreChosenMoves); void RunBattleScriptCommands_PopCallbacksStack(void); void RunBattleScriptCommands(void); u32 GetDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, enum MonState monInBattle); diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index e7a85e211e..034ca30fc9 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -558,7 +558,7 @@ void SetBattlerAiData(u32 battler, struct AiLogicData *aiData) aiData->lastUsedMove[battler] = gLastMoves[battler]; aiData->hpPercents[battler] = GetHealthPercentage(battler); aiData->moveLimitations[battler] = CheckMoveLimitations(battler, 0, MOVE_LIMITATIONS_ALL); - aiData->speedStats[battler] = GetBattlerTotalSpeedStatArgs(battler, ability, holdEffect); + aiData->speedStats[battler] = GetBattlerTotalSpeedStat(battler, ability, holdEffect); if (IsAiBattlerAssumingStab()) RecordMovesBasedOnStab(battler); @@ -3004,6 +3004,19 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) return score; } +static s32 AI_GetWhichBattlerFasterOrTies(u32 battlerAtk, u32 battlerDef, bool32 ignoreChosenMoves) +{ + struct BattleContext ctx = {0}; + ctx.battlerAtk = battlerAtk; + ctx.battlerDef = battlerDef; + ctx.abilities[battlerAtk] = gAiLogicData->abilities[battlerAtk]; + ctx.abilities[battlerDef] = gAiLogicData->abilities[battlerDef]; + ctx.holdEffects[battlerAtk] = gAiLogicData->holdEffects[battlerAtk]; + ctx.holdEffects[battlerDef] = gAiLogicData->holdEffects[battlerDef]; + + return GetWhichBattlerFasterOrTies(&ctx, ignoreChosenMoves); +} + static s32 AI_TryToFaint(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { u32 movesetIndex = gAiThinkingStruct->movesetIndex; @@ -3025,7 +3038,7 @@ static s32 AI_TryToFaint(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(SLOW_KILL); } else if (CanTargetFaintAi(battlerDef, battlerAtk) - && GetWhichBattlerFasterOrTies(battlerAtk, battlerDef, TRUE) != AI_IS_FASTER + && AI_GetWhichBattlerFasterOrTies(battlerAtk, battlerDef, TRUE) != AI_IS_FASTER && GetBattleMovePriority(battlerAtk, gAiLogicData->abilities[battlerAtk], move) > 0) { if (RandomPercentage(RNG_AI_PRIORITIZE_LAST_CHANCE, PRIORITIZE_LAST_CHANCE_CHANCE)) @@ -5059,7 +5072,7 @@ static s32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move, stru if (IsStatBoostingBerry(item) && aiData->hpPercents[battlerAtk] > 60) ADJUST_SCORE(WEAK_EFFECT); else if (ShouldRestoreHpBerry(battlerAtk, item) && !CanAIFaintTarget(battlerAtk, battlerDef, 0) - && ((GetWhichBattlerFasterOrTies(battlerAtk, battlerDef, TRUE) == 1 && CanTargetFaintAiWithMod(battlerDef, battlerAtk, 0, 0)) + && ((AI_GetWhichBattlerFasterOrTies(battlerAtk, battlerDef, TRUE) == 1 && CanTargetFaintAiWithMod(battlerDef, battlerAtk, 0, 0)) || !CanTargetFaintAiWithMod(battlerDef, battlerAtk, toHeal, 0))) ADJUST_SCORE(WEAK_EFFECT); // 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 7ab9fb1195..20b15d6cfe 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1374,8 +1374,8 @@ s32 AI_WhoStrikesFirst(u32 battlerAI, u32 battler, u32 aiMoveConsidered, u32 pla return AI_IS_SLOWER; } - speedBattlerAI = GetBattlerTotalSpeedStatArgs(battlerAI, abilityAI, holdEffectAI); - speedBattler = GetBattlerTotalSpeedStatArgs(battler, abilityPlayer, holdEffectPlayer); + speedBattlerAI = GetBattlerTotalSpeedStat(battlerAI, abilityAI, holdEffectAI); + speedBattler = GetBattlerTotalSpeedStat(battler, abilityPlayer, holdEffectPlayer); if (holdEffectAI == HOLD_EFFECT_LAGGING_TAIL && holdEffectPlayer != HOLD_EFFECT_LAGGING_TAIL) return AI_IS_SLOWER; diff --git a/src/battle_end_turn.c b/src/battle_end_turn.c index 4b42d05efd..6dc762e5c7 100644 --- a/src/battle_end_turn.c +++ b/src/battle_end_turn.c @@ -121,15 +121,21 @@ static bool32 HandleEndTurnOrder(u32 battler) gBattleStruct->endTurnEventsCounter++; u32 i, j; + struct BattleContext ctx = {0}; for (i = 0; i < gBattlersCount; i++) { gBattlerByTurnOrder[i] = i; + ctx.abilities[i] = GetBattlerAbility(i); + ctx.holdEffects[i] = GetBattlerHoldEffect(i); } for (i = 0; i < gBattlersCount - 1; i++) { for (j = i + 1; j < gBattlersCount; j++) { - if (GetWhichBattlerFaster(gBattlerByTurnOrder[i], gBattlerByTurnOrder[j], FALSE) == -1) + ctx.battlerAtk = gBattlerByTurnOrder[i]; + ctx.battlerDef = gBattlerByTurnOrder[j]; + + if (GetWhichBattlerFaster(&ctx, FALSE) == -1) SwapTurnOrder(i, j); } } diff --git a/src/battle_main.c b/src/battle_main.c index 81a5205250..1685a4d606 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -14,7 +14,6 @@ #include "battle_scripts.h" #include "battle_setup.h" #include "battle_tower.h" -#include "battle_util.h" #include "battle_z_move.h" #include "battle_gimmick.h" #include "berry.h" @@ -112,7 +111,7 @@ static void SetActionsAndBattlersTurnOrder(void); static void UpdateBattlerPartyOrdersOnSwitch(u32 battler); static bool8 AllAtActionConfirmed(void); static void TryChangeTurnOrder(void); -static void TryChangingTurnOrderEffects(u32 battler1, u32 battler2, u32 *quickClawRandom, u32 *quickDrawRandom); +static void TryChangingTurnOrderEffects(struct BattleContext *ctx, u32 *quickClawRandom, u32 *quickDrawRandom); static void CheckChangingTurnOrderEffects(void); static void FreeResetData_ReturnToOvOrDoEvolutions(void); static void ReturnFromBattleToOverworld(void); @@ -3801,13 +3800,21 @@ static void TryDoEventsBeforeFirstTurn(void) gBattleStruct->speedTieBreaks = RandomUniform(RNG_SPEED_TIE, 0, Factorial(MAX_BATTLERS_COUNT) - 1); gBattleTurnCounter = 0; + struct BattleContext ctx = {0}; for (i = 0; i < gBattlersCount; i++) + { gBattlerByTurnOrder[i] = i; + ctx.abilities[i] = GetBattlerAbility(i); + ctx.holdEffects[i] = GetBattlerHoldEffect(i); + } for (i = 0; i < gBattlersCount - 1; i++) { for (j = i + 1; j < gBattlersCount; j++) { - if (GetWhichBattlerFaster(gBattlerByTurnOrder[i], gBattlerByTurnOrder[j], TRUE) == -1) + ctx.battlerAtk = gBattlerByTurnOrder[i]; + ctx.battlerDef = gBattlerByTurnOrder[j]; + + if (GetWhichBattlerFaster(&ctx, TRUE) == -1) SwapTurnOrder(i, j); } } @@ -4759,7 +4766,7 @@ void SwapTurnOrder(u8 id1, u8 id2) } // For AI, so it doesn't 'cheat' by knowing player's ability -u32 GetBattlerTotalSpeedStatArgs(u32 battler, enum Ability ability, enum HoldEffect holdEffect) +u32 GetBattlerTotalSpeedStat(u32 battler, enum Ability ability, enum HoldEffect holdEffect) { u32 speed = gBattleMons[battler].speed; @@ -4826,13 +4833,6 @@ u32 GetBattlerTotalSpeedStatArgs(u32 battler, enum Ability ability, enum HoldEff return speed; } -u32 GetBattlerTotalSpeedStat(u32 battler) -{ - enum Ability ability = GetBattlerAbility(battler); - enum HoldEffect holdEffect = GetBattlerHoldEffect(battler); - return GetBattlerTotalSpeedStatArgs(battler, ability, holdEffect); -} - s32 GetChosenMovePriority(u32 battler, enum Ability ability) { u16 move; @@ -4886,8 +4886,7 @@ s32 GetBattleMovePriority(u32 battler, enum Ability ability, u32 move) return priority; } -s32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMoves, enum Ability ability1, enum Ability ability2, - enum HoldEffect holdEffectBattler1, enum HoldEffect holdEffectBattler2, u32 speedBattler1, u32 speedBattler2, s32 priority1, s32 priority2) +s32 GetWhichBattlerFasterArgs(struct BattleContext *ctx, bool32 ignoreChosenMoves, u32 speedBattler1, u32 speedBattler2, s32 priority1, s32 priority2) { u32 strikesFirst = 0; @@ -4896,18 +4895,18 @@ s32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMov // Quick Claw / Quick Draw / Custap Berry - always first // Stall / Mycelium Might - last but before Lagging Tail // Lagging Tail - always last - bool32 battler1HasQuickEffect = gProtectStructs[battler1].quickDraw || gProtectStructs[battler1].usedCustapBerry; - bool32 battler2HasQuickEffect = gProtectStructs[battler2].quickDraw || gProtectStructs[battler2].usedCustapBerry; - bool32 battler1HasStallingAbility = ability1 == ABILITY_STALL || gProtectStructs[battler1].myceliumMight; - bool32 battler2HasStallingAbility = ability2 == ABILITY_STALL || gProtectStructs[battler2].myceliumMight; + bool32 battler1HasQuickEffect = gProtectStructs[ctx->battlerAtk].quickDraw || gProtectStructs[ctx->battlerAtk].usedCustapBerry; + bool32 battler2HasQuickEffect = gProtectStructs[ctx->battlerDef].quickDraw || gProtectStructs[ctx->battlerDef].usedCustapBerry; + bool32 battler1HasStallingAbility = ctx->abilities[ctx->battlerAtk] == ABILITY_STALL || gProtectStructs[ctx->battlerAtk].myceliumMight; + bool32 battler2HasStallingAbility = ctx->abilities[ctx->battlerDef] == ABILITY_STALL || gProtectStructs[ctx->battlerDef].myceliumMight; if (battler1HasQuickEffect && !battler2HasQuickEffect) strikesFirst = 1; else if (battler2HasQuickEffect && !battler1HasQuickEffect) strikesFirst = -1; - else if (gProtectStructs[battler1].laggingTail && !gProtectStructs[battler2].laggingTail) + else if (gProtectStructs[ctx->battlerAtk].laggingTail && !gProtectStructs[ctx->battlerDef].laggingTail) strikesFirst = -1; - else if (gProtectStructs[battler2].laggingTail && !gProtectStructs[battler1].laggingTail) + else if (gProtectStructs[ctx->battlerDef].laggingTail && !gProtectStructs[ctx->battlerAtk].laggingTail) strikesFirst = 1; else if (battler1HasStallingAbility && !battler2HasStallingAbility) strikesFirst = -1; @@ -4949,32 +4948,27 @@ s32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMov return strikesFirst; } -s32 GetWhichBattlerFasterOrTies(u32 battler1, u32 battler2, bool32 ignoreChosenMoves) +s32 GetWhichBattlerFasterOrTies(struct BattleContext *ctx, bool32 ignoreChosenMoves) { s32 priority1 = 0, priority2 = 0; - enum Ability ability1 = GetBattlerAbility(battler1); - u32 speedBattler1 = GetBattlerTotalSpeedStat(battler1); - enum HoldEffect holdEffectBattler1 = GetBattlerHoldEffect(battler1); - u32 speedBattler2 = GetBattlerTotalSpeedStat(battler2); - enum HoldEffect holdEffectBattler2 = GetBattlerHoldEffect(battler2); - enum Ability ability2 = GetBattlerAbility(battler2); + u32 speedBattler1 = GetBattlerTotalSpeedStat(ctx->battlerAtk, ctx->abilities[ctx->battlerAtk], ctx->holdEffects[ctx->battlerAtk]); + u32 speedBattler2 = GetBattlerTotalSpeedStat(ctx->battlerDef, ctx->abilities[ctx->battlerDef], ctx->holdEffects[ctx->battlerDef]); if (!ignoreChosenMoves) { - if (gChosenActionByBattler[battler1] == B_ACTION_USE_MOVE) - priority1 = GetChosenMovePriority(battler1, ability1); - if (gChosenActionByBattler[battler2] == B_ACTION_USE_MOVE) - priority2 = GetChosenMovePriority(battler2, ability2); + if (gChosenActionByBattler[ctx->battlerAtk] == B_ACTION_USE_MOVE) + priority1 = GetChosenMovePriority(ctx->battlerAtk, ctx->abilities[ctx->battlerAtk]); + if (gChosenActionByBattler[ctx->battlerDef] == B_ACTION_USE_MOVE) + priority2 = GetChosenMovePriority(ctx->battlerDef, ctx->abilities[ctx->battlerDef]); } return GetWhichBattlerFasterArgs( - battler1, battler2, + ctx, ignoreChosenMoves, - ability1, ability2, - holdEffectBattler1, holdEffectBattler2, - speedBattler1, speedBattler2, - priority1, priority2 - ); + speedBattler1, + speedBattler2, + priority1, + priority2); } // 24 == MAX_BATTLERS_COUNT!. @@ -5008,13 +5002,13 @@ static const u8 sBattlerOrders[24][4] = { 3, 2, 1, 0 }, }; -s32 GetWhichBattlerFaster(u32 battler1, u32 battler2, bool32 ignoreChosenMoves) +s32 GetWhichBattlerFaster(struct BattleContext *ctx, bool32 ignoreChosenMoves) { - s32 strikesFirst = GetWhichBattlerFasterOrTies(battler1, battler2, ignoreChosenMoves); + s32 strikesFirst = GetWhichBattlerFasterOrTies(ctx, ignoreChosenMoves); if (strikesFirst == 0) { - s32 order1 = sBattlerOrders[gBattleStruct->speedTieBreaks][battler1]; - s32 order2 = sBattlerOrders[gBattleStruct->speedTieBreaks][battler2]; + s32 order1 = sBattlerOrders[gBattleStruct->speedTieBreaks][ctx->battlerAtk]; + s32 order2 = sBattlerOrders[gBattleStruct->speedTieBreaks][ctx->battlerDef]; if (order1 < order2) strikesFirst = 1; else @@ -5108,13 +5102,19 @@ static void SetActionsAndBattlersTurnOrder(void) turnOrderId++; } } + struct BattleContext ctx = {0}; + for (i = 0; i < gBattlersCount; i++) + { + ctx.abilities[i] = GetBattlerAbility(i); + ctx.holdEffects[i] = GetBattlerHoldEffect(i); + } for (i = 0; i < gBattlersCount - 1; i++) { for (j = i + 1; j < gBattlersCount; j++) { - u8 battler1 = gBattlerByTurnOrder[i]; - u8 battler2 = gBattlerByTurnOrder[j]; - TryChangingTurnOrderEffects(battler1, battler2, quickClawRandom, quickDrawRandom); + ctx.battlerAtk = gBattlerByTurnOrder[i]; + ctx.battlerDef = gBattlerByTurnOrder[j]; + TryChangingTurnOrderEffects(&ctx, quickClawRandom, quickDrawRandom); if (gActionsByTurnOrder[i] != B_ACTION_USE_ITEM && gActionsByTurnOrder[j] != B_ACTION_USE_ITEM && gActionsByTurnOrder[i] != B_ACTION_SWITCH @@ -5122,7 +5122,7 @@ static void SetActionsAndBattlersTurnOrder(void) && gActionsByTurnOrder[i] != B_ACTION_THROW_BALL && gActionsByTurnOrder[j] != B_ACTION_THROW_BALL) { - if (GetWhichBattlerFaster(battler1, battler2, FALSE) == -1) + if (GetWhichBattlerFaster(&ctx, FALSE) == -1) SwapTurnOrder(i, j); } } @@ -5270,29 +5270,38 @@ static bool32 TryDoMoveEffectsBeforeMoves(void) static void TryChangeTurnOrder(void) { u32 i, j; + + struct BattleContext ctx = {0}; + for (i = 0; i < gBattlersCount; i++) + { + ctx.abilities[i] = GetBattlerAbility(i); + ctx.holdEffects[i] = GetBattlerHoldEffect(i); + } for (i = gCurrentTurnActionNumber; i < gBattlersCount - 1; i++) { for (j = i + 1; j < gBattlersCount; j++) { - u32 battler1 = gBattlerByTurnOrder[i]; - u32 battler2 = gBattlerByTurnOrder[j]; + ctx.battlerAtk = gBattlerByTurnOrder[i]; + ctx.battlerDef = gBattlerByTurnOrder[j]; if (gActionsByTurnOrder[i] == B_ACTION_USE_MOVE && gActionsByTurnOrder[j] == B_ACTION_USE_MOVE) { - if (GetWhichBattlerFaster(battler1, battler2, FALSE) == -1) + if (GetWhichBattlerFaster(&ctx, FALSE) == -1) SwapTurnOrder(i, j); } } } } -static void TryChangingTurnOrderEffects(u32 battler1, u32 battler2, u32 *quickClawRandom, u32 *quickDrawRandom) +static void TryChangingTurnOrderEffects(struct BattleContext *ctx, u32 *quickClawRandom, u32 *quickDrawRandom) { - enum Ability ability1 = GetBattlerAbility(battler1); - enum HoldEffect holdEffectBattler1 = GetBattlerHoldEffect(battler1); - enum HoldEffect holdEffectBattler2 = GetBattlerHoldEffect(battler2); - enum Ability ability2 = GetBattlerAbility(battler2); + u32 battler1 = ctx->battlerAtk; + u32 battler2 = ctx->battlerDef; + enum Ability ability1 = ctx->abilities[ctx->battlerAtk]; + enum Ability ability2 = ctx->abilities[ctx->battlerDef]; + enum HoldEffect holdEffectBattler1 = ctx->holdEffects[ctx->battlerAtk]; + enum HoldEffect holdEffectBattler2 = ctx->holdEffects[ctx->battlerDef]; // Battler 1 // Quick Draw diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index f99fafcf3f..8b6e331424 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -15563,13 +15563,22 @@ void BS_TryQuash(void) // If the above condition is not true, it means we are faster than the foe, so we can set the quash bit gProtectStructs[gBattlerTarget].quash = TRUE; + struct BattleContext ctx = {0}; + for (i = 0; i < gBattlersCount; i++) + { + ctx.abilities[i] = GetBattlerAbility(i); + ctx.holdEffects[i] = GetBattlerHoldEffect(i); + } // this implementation assumes turn order is correct when using Quash i = GetBattlerTurnOrderNum(gBattlerTarget); for (j = i + 1; j < gBattlersCount; j++) { + ctx.battlerAtk = gBattlerByTurnOrder[i]; + ctx.battlerDef = gBattlerByTurnOrder[j]; + // Gen 7- config makes target go last so that the order of quash targets is kept for the correct turn order // Gen 8+ config alters Turn Order of the target according to speed, dynamic speed should handle the rest - if (B_QUASH_TURN_ORDER < GEN_8 || GetWhichBattlerFaster(gBattlerByTurnOrder[i], gBattlerByTurnOrder[j], FALSE) == -1) + if (B_QUASH_TURN_ORDER < GEN_8 || GetWhichBattlerFaster(&ctx, FALSE) == -1) SwapTurnOrder(i, j); else break; diff --git a/src/battle_util.c b/src/battle_util.c index 3c83a80cab..2bb0c032e9 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -953,27 +953,34 @@ void HandleAction_ActionFinished(void) { // i starts at `gCurrentTurnActionNumber` because we don't want to recalculate turn order for mon that have already // taken action. It's been previously increased, which we want in order to not recalculate the turn of the mon that just finished its action + + struct BattleContext ctx = {0}; + for (i = 0; i < gBattlersCount; i++) + { + ctx.abilities[i] = GetBattlerAbility(i); + ctx.holdEffects[i] = GetBattlerHoldEffect(i); + } for (i = gCurrentTurnActionNumber; i < gBattlersCount - 1; i++) { for (j = i + 1; j < gBattlersCount; j++) { - u32 battler1 = gBattlerByTurnOrder[i]; - u32 battler2 = gBattlerByTurnOrder[j]; + ctx.battlerAtk = gBattlerByTurnOrder[i]; + ctx.battlerDef = gBattlerByTurnOrder[j]; - if (gProtectStructs[battler1].quash || gProtectStructs[battler2].quash - || gProtectStructs[battler1].shellTrap || gProtectStructs[battler2].shellTrap) + if (gProtectStructs[ctx.battlerAtk].quash || gProtectStructs[ctx.battlerDef].quash + || gProtectStructs[ctx.battlerAtk].shellTrap || gProtectStructs[ctx.battlerDef].shellTrap) continue; // We recalculate order only for action of the same priority. If any action other than switch/move has been taken, they should // 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) == -1) + if (GetWhichBattlerFaster(&ctx, FALSE) == -1) SwapTurnOrder(i, j); } else if ((gActionsByTurnOrder[i] == B_ACTION_SWITCH && gActionsByTurnOrder[j] == B_ACTION_SWITCH)) { - if (GetWhichBattlerFaster(battler1, battler2, TRUE) == -1) // If the actions chosen are switching, we recalc order but ignoring the moves + if (GetWhichBattlerFaster(&ctx, TRUE) == -1) // If the actions chosen are switching, we recalc order but ignoring the moves SwapTurnOrder(i, j); } } @@ -6948,21 +6955,21 @@ static inline u32 CalcMoveBasePower(struct DamageContext *ctx) basePower += (CountBattlerStatIncreases(battlerAtk, TRUE) * 20); break; case EFFECT_ELECTRO_BALL: - speed = GetBattlerTotalSpeedStat(battlerAtk) / GetBattlerTotalSpeedStat(battlerDef); + speed = GetBattlerTotalSpeedStat(battlerAtk, ctx->abilityAtk, ctx->holdEffectAtk) / GetBattlerTotalSpeedStat(battlerDef, ctx->abilityDef, ctx->holdEffectDef); if (speed >= ARRAY_COUNT(sSpeedDiffPowerTable)) speed = ARRAY_COUNT(sSpeedDiffPowerTable) - 1; basePower = sSpeedDiffPowerTable[speed]; break; case EFFECT_GYRO_BALL: { - u32 attackerSpeed = GetBattlerTotalSpeedStat(battlerAtk); + u32 attackerSpeed = GetBattlerTotalSpeedStat(battlerAtk, ctx->abilityAtk, ctx->holdEffectAtk); if (attackerSpeed == 0) { basePower = 1; } else { - basePower = ((25 * GetBattlerTotalSpeedStat(battlerDef)) / attackerSpeed) + 1; + basePower = ((25 * GetBattlerTotalSpeedStat(battlerDef, ctx->abilityDef, ctx->holdEffectDef)) / attackerSpeed) + 1; if (basePower > 150) basePower = 150; } @@ -9511,7 +9518,10 @@ void SortBattlersBySpeed(u8 *battlers, bool32 slowToFast) u16 speeds[MAX_BATTLERS_COUNT] = {0}; for (i = 0; i < gBattlersCount; i++) - speeds[i] = GetBattlerTotalSpeedStat(battlers[i]); + { + u32 battler = battlers[i]; + speeds[i] = GetBattlerTotalSpeedStat(battler, GetBattlerAbility(battler), GetBattlerHoldEffect(battler)); + } for (i = 1; i < gBattlersCount; i++) {