Optimize GetWhichBattlerFasterOrTies (#7953)
Some checks are pending
CI / build (push) Waiting to run
CI / allcontributors (push) Waiting to run

This commit is contained in:
Alex 2025-10-15 15:08:16 +02:00 committed by GitHub
parent 3ad78d0079
commit a77f8d97a1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 121 additions and 75 deletions

View File

@ -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);

View File

@ -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
}

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;

View File

@ -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++)
{