Add abstraction layer for battler positions (#6212)

This commit is contained in:
Alex 2025-02-11 17:32:34 +01:00 committed by GitHub
parent 579fa6410d
commit cc9ca81c29
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 81 additions and 64 deletions

View File

@ -1217,11 +1217,37 @@ static inline u32 GetBattlerPosition(u32 battler)
return gBattlerPositions[battler];
}
static inline u32 GetBattlerAtPosition(u32 position)
{
u32 battler;
for (battler = 0; battler < gBattlersCount; battler++)
{
if (GetBattlerPosition(battler) == position)
break;
}
return battler;
}
static inline u32 GetPartnerBattler(u32 battler)
{
return GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)));
}
static inline u32 GetOppositeBattler(u32 battler)
{
return GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerPosition(battler)));
}
static inline u32 GetBattlerSide(u32 battler)
{
return GetBattlerPosition(battler) & BIT_SIDE;
}
static inline u32 GetOpposingSideBattler(u32 battler)
{
return GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerSide(battler)));
}
static inline struct Pokemon* GetPartyBattlerData(u32 battler)
{
u32 index = gBattlerPartyIndexes[battler];

View File

@ -165,7 +165,6 @@ void Trade_MoveSelectedMonToTarget(struct Sprite *sprite);
void DestroyAnimVisualTaskAndDisableBlend(u8 taskId);
void DestroySpriteAndFreeResources_(struct Sprite *sprite);
void SetBattlerSpriteYOffsetFromOtherYScale(u8 spriteId, u8 otherSpriteId);
u8 GetBattlerAtPosition(u8 position);
void ConvertPosDataToTranslateLinearData(struct Sprite *sprite);
void InitAnimFastLinearTranslationWithSpeedAndPos(struct Sprite *sprite);

View File

@ -314,7 +314,7 @@ static bool32 ShouldSwitchIfTruant(u32 battler)
static bool32 ShouldSwitchIfAllMovesBad(u32 battler)
{
u32 moveIndex;
u32 opposingBattler = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerPosition(battler)));
u32 opposingBattler = GetOppositeBattler(battler);
u32 aiMove;
// Switch if no moves affect opponents
@ -347,7 +347,7 @@ static bool32 ShouldSwitchIfAllMovesBad(u32 battler)
static bool32 FindMonThatHitsWonderGuard(u32 battler)
{
u32 opposingBattler = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerPosition(battler)));
u32 opposingBattler = GetOppositeBattler(battler);
s32 i, j;
s32 firstId;
s32 lastId; // + 1
@ -409,7 +409,7 @@ static bool32 FindMonThatAbsorbsOpponentsMove(u32 battler)
s32 lastId;
struct Pokemon *party;
u16 monAbility;
u32 opposingBattler = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerPosition(battler)));
u32 opposingBattler = GetOppositeBattler(battler);
u32 incomingMove = AI_DATA->lastUsedMove[opposingBattler];
u32 incomingType = GetMoveType(incomingMove);
u32 predictedMove = incomingMove; // Update for move prediction
@ -428,10 +428,10 @@ static bool32 FindMonThatAbsorbsOpponentsMove(u32 battler)
if (IsDoubleBattle())
{
battlerIn1 = battler;
if (gAbsentBattlerFlags & (1u << GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)))))
if (gAbsentBattlerFlags & (1u << GetPartnerBattler(battler)))
battlerIn2 = battler;
else
battlerIn2 = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)));
battlerIn2 = GetPartnerBattler(battler);
}
else
{
@ -516,7 +516,7 @@ static bool32 FindMonThatAbsorbsOpponentsMove(u32 battler)
static bool32 ShouldSwitchIfOpponentChargingOrInvulnerable(u32 battler)
{
u32 opposingBattler = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerPosition(battler)));
u32 opposingBattler = GetOppositeBattler(battler);
u32 incomingMove = AI_DATA->lastUsedMove[opposingBattler];
bool32 isOpposingBattlerChargingOrInvulnerable = (IsSemiInvulnerable(opposingBattler, incomingMove) || IsTwoTurnNotSemiInvulnerableMove(opposingBattler, incomingMove));
@ -536,7 +536,7 @@ static bool32 ShouldSwitchIfTrapperInParty(u32 battler)
struct Pokemon *party;
s32 i;
u16 monAbility;
s32 opposingBattler = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerPosition(battler)));
s32 opposingBattler = GetOppositeBattler(battler);
// Only use this if AI_FLAG_SMART_SWITCHING is set for the trainer
if (!(AI_THINKING_STRUCT->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING))
@ -795,10 +795,10 @@ static bool32 FindMonWithFlagsAndSuperEffective(u32 battler, u16 flags, u32 perc
if (IsDoubleBattle())
{
battlerIn1 = battler;
if (gAbsentBattlerFlags & (1u << GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)))))
if (gAbsentBattlerFlags & (1u << GetPartnerBattler(battler)))
battlerIn2 = battler;
else
battlerIn2 = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)));
battlerIn2 = GetPartnerBattler(battler);
}
else
{
@ -870,10 +870,10 @@ static bool32 CanMonSurviveHazardSwitchin(u32 battler)
if (IsDoubleBattle())
{
battlerIn1 = battler;
if (gAbsentBattlerFlags & (1u << GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)))))
if (gAbsentBattlerFlags & (1u << GetPartnerBattler(battler)))
battlerIn2 = battler;
else
battlerIn2 = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)));
battlerIn2 = GetPartnerBattler(battler);
}
else
{
@ -921,7 +921,7 @@ static bool32 CanMonSurviveHazardSwitchin(u32 battler)
static bool32 ShouldSwitchIfEncored(u32 battler)
{
u32 encoredMove = gDisableStructs[battler].encoredMove;
u32 opposingBattler = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerPosition(battler)));
u32 opposingBattler = GetOppositeBattler(battler);
// Only use this if AI_FLAG_SMART_SWITCHING is set for the trainer
if (!(AI_THINKING_STRUCT->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING))
@ -1628,7 +1628,7 @@ static u32 GetSwitchinHitsToKO(s32 damageTaken, u32 battler)
u32 hitsToKO = 0, singleUseItemHeal = 0;
u16 maxHP = AI_DATA->switchinCandidate.battleMon.maxHP, item = AI_DATA->switchinCandidate.battleMon.item, heldItemEffect = ItemId_GetHoldEffect(item);
u8 weatherDuration = gWishFutureKnock.weatherDuration, holdEffectParam = ItemId_GetHoldEffectParam(item);
u32 opposingBattler = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerPosition(battler)));
u32 opposingBattler = GetOppositeBattler(battler);
u32 opposingAbility = gBattleMons[opposingBattler].ability, ability = AI_DATA->switchinCandidate.battleMon.ability;
bool32 usedSingleUseHealingItem = FALSE, opponentCanBreakMold = IsMoldBreakerTypeAbility(opposingBattler, opposingAbility);
s32 currentHP = startingHP;
@ -2073,10 +2073,10 @@ u32 GetMostSuitableMonToSwitchInto(u32 battler, enum SwitchType switchType)
if (IsDoubleBattle())
{
battlerIn1 = battler;
if (gAbsentBattlerFlags & (1u << GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)))))
if (gAbsentBattlerFlags & (1u << GetPartnerBattler(battler)))
battlerIn2 = battler;
else
battlerIn2 = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)));
battlerIn2 = GetPartnerBattler(battler);
opposingBattler = BATTLE_OPPOSITE(battlerIn1);
if (gAbsentBattlerFlags & (1u << opposingBattler))
@ -2084,7 +2084,7 @@ u32 GetMostSuitableMonToSwitchInto(u32 battler, enum SwitchType switchType)
}
else
{
opposingBattler = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerPosition(battler)));
opposingBattler = GetOppositeBattler(battler);
battlerIn1 = battler;
battlerIn2 = battler;
}

View File

@ -3158,7 +3158,7 @@ bool32 AnyPartyMemberStatused(u32 battlerId, bool32 checkSoundproof)
if (IsDoubleBattle())
{
battlerOnField1 = gBattlerPartyIndexes[battlerId];
battlerOnField2 = gBattlerPartyIndexes[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battlerId)))];
battlerOnField2 = gBattlerPartyIndexes[GetPartnerBattler(battlerId)];
// Check partner's status
if ((GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) == GEN_5
|| AI_DATA->abilities[BATTLE_PARTNER(battlerId)] != ABILITY_SOUNDPROOF
@ -3587,7 +3587,7 @@ s32 CountUsablePartyMons(u32 battlerId)
if (IsDoubleBattle())
{
battlerOnField1 = gBattlerPartyIndexes[battlerId];
battlerOnField2 = gBattlerPartyIndexes[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battlerId)))];
battlerOnField2 = gBattlerPartyIndexes[GetPartnerBattler(battlerId)];
}
else // In singles there's only one battlerId by side.
{

View File

@ -799,18 +799,6 @@ bool32 InitSpritePosToAnimBattler(u32 animBattlerId, struct Sprite *sprite, bool
return TRUE;
}
u8 GetBattlerAtPosition(u8 position)
{
u8 i;
for (i = 0; i < gBattlersCount; i++)
{
if (GetBattlerPosition(i) == position)
break;
}
return i;
}
bool8 IsBattlerSpritePresent(u8 battlerId)
{
if (IsContest())

View File

@ -688,7 +688,7 @@ void HandleInputChooseMove(u32 battler)
if (moveTarget & MOVE_TARGET_USER)
gMultiUsePlayerCursor = battler;
else
gMultiUsePlayerCursor = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerSide(battler)));
gMultiUsePlayerCursor = GetOpposingSideBattler(battler);
if (!gBattleResources->bufferA[battler][1]) // not a double battle
{

View File

@ -4146,7 +4146,7 @@ enum
void SetupAISwitchingData(u32 battler, enum SwitchType switchType)
{
s32 opposingBattler = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerPosition(battler)));
s32 opposingBattler = GetOppositeBattler(battler);
// AI's predicting data
if ((AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_PREDICT_SWITCH))
@ -4361,38 +4361,38 @@ static void HandleTurnActionSelectionState(void)
break;
case B_ACTION_CANCEL_PARTNER:
gBattleCommunication[battler] = STATE_WAIT_SET_BEFORE_ACTION;
gBattleCommunication[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)))] = STATE_BEFORE_ACTION_CHOSEN;
gBattleCommunication[GetPartnerBattler(battler)] = STATE_BEFORE_ACTION_CHOSEN;
RecordedBattle_ClearBattlerAction(battler, 1);
if (gBattleMons[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)))].status2 & STATUS2_MULTIPLETURNS
|| gBattleMons[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)))].status2 & STATUS2_RECHARGE)
if (gBattleMons[GetPartnerBattler(battler)].status2 & STATUS2_MULTIPLETURNS
|| gBattleMons[GetPartnerBattler(battler)].status2 & STATUS2_RECHARGE)
{
BtlController_EmitEndBounceEffect(battler, BUFFER_A);
MarkBattlerForControllerExec(battler);
return;
}
else if (gChosenActionByBattler[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)))] == B_ACTION_SWITCH)
else if (gChosenActionByBattler[GetPartnerBattler(battler)] == B_ACTION_SWITCH)
{
RecordedBattle_ClearBattlerAction(GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler))), 2);
RecordedBattle_ClearBattlerAction(GetPartnerBattler(battler), 2);
}
else if (gChosenActionByBattler[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)))] == B_ACTION_RUN)
else if (gChosenActionByBattler[GetPartnerBattler(battler)] == B_ACTION_RUN)
{
RecordedBattle_ClearBattlerAction(GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler))), 1);
RecordedBattle_ClearBattlerAction(GetPartnerBattler(battler), 1);
}
else if (gChosenActionByBattler[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)))] == B_ACTION_USE_MOVE
&& (gProtectStructs[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)))].noValidMoves
|| gDisableStructs[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)))].encoredMove))
else if (gChosenActionByBattler[GetPartnerBattler(battler)] == B_ACTION_USE_MOVE
&& (gProtectStructs[GetPartnerBattler(battler)].noValidMoves
|| gDisableStructs[GetPartnerBattler(battler)].encoredMove))
{
RecordedBattle_ClearBattlerAction(GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler))), 1);
RecordedBattle_ClearBattlerAction(GetPartnerBattler(battler), 1);
}
else if (gBattleTypeFlags & BATTLE_TYPE_PALACE
&& gChosenActionByBattler[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler)))] == B_ACTION_USE_MOVE)
&& gChosenActionByBattler[GetPartnerBattler(battler)] == B_ACTION_USE_MOVE)
{
gRngValue = gBattlePalaceMoveSelectionRngValue;
RecordedBattle_ClearBattlerAction(GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler))), 1);
RecordedBattle_ClearBattlerAction(GetPartnerBattler(battler), 1);
}
else
{
RecordedBattle_ClearBattlerAction(GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(battler))), 3);
RecordedBattle_ClearBattlerAction(GetPartnerBattler(battler), 3);
}
gBattleStruct->gimmick.toActivate &= ~((1u << BATTLE_PARTNER(GetBattlerPosition(battler))));

View File

@ -13946,9 +13946,10 @@ static void Cmd_healpartystatus(void)
{
CMD_ARGS();
u32 i, zero = 0;
u32 i = 0;
u32 zero = 0;
u32 toHeal = 0;
u32 partner = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gBattlerAttacker)));
u8 toHeal = 0;
struct Pokemon *party = GetBattlerParty(gBattlerAttacker);
bool32 isSoundMove = IsSoundMove(gCurrentMove);
@ -16270,6 +16271,8 @@ static void Cmd_displaydexinfo(void)
switch (gBattleCommunication[0])
{
case 0:
FREE_AND_SET_NULL(gBattleResources->aiData);
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK);
gBattleCommunication[0]++;
break;
@ -16309,8 +16312,9 @@ static void Cmd_displaydexinfo(void)
}
break;
case 5:
if (!gPaletteFade.active)
if (!gPaletteFade.active) {
gBattlescriptCurrInstr = cmd->nextInstr;
}
break;
}
}

View File

@ -382,7 +382,7 @@ void HandleAction_UseMove(void)
if (!IsBattlerAlive(gBattlerTarget) && GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gBattlerTarget))
{
gBattlerTarget = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gBattlerTarget)));
gBattlerTarget = GetPartnerBattler(gBattlerTarget);
}
}
else
@ -405,7 +405,7 @@ void HandleAction_UseMove(void)
if (gAbsentBattlerFlags & (1u << gBattlerTarget)
&& GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gBattlerTarget))
{
gBattlerTarget = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gBattlerTarget)));
gBattlerTarget = GetPartnerBattler(gBattlerTarget);
}
}
else if (moveTarget == MOVE_TARGET_ALLY)
@ -432,7 +432,7 @@ void HandleAction_UseMove(void)
&& moveTarget != MOVE_TARGET_OPPONENTS_FIELD
&& (GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gBattlerTarget)))
{
gBattlerTarget = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gBattlerTarget)));
gBattlerTarget = GetPartnerBattler(gBattlerTarget);
}
}
@ -4235,7 +4235,7 @@ bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 ability
u32 atkPriority = AI_DATA->aiCalcInProgress ? GetBattleMovePriority(battlerAtk, move) : GetChosenMovePriority(battlerAtk);
u32 moveTarget = GetBattlerMoveTargetType(battlerAtk, move);
u32 battlerAbility = battlerDef;
switch (abilityDef)
{
case ABILITY_SOUNDPROOF:
@ -4292,10 +4292,10 @@ bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 ability
break;
}
}
if (battleScriptBlocksMove == NULL)
return FALSE;
if (option == ABILITY_RUN_SCRIPT)
{
gBattleScripting.battler = gBattlerAbility = battlerAbility;
@ -4377,10 +4377,10 @@ bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32
effect = MOVE_ABSORBED_BY_BOOST_FLASH_FIRE;
break;
}
if (effect == MOVE_ABSORBED_BY_NO_ABILITY || option == ABILITY_CHECK_TRIGGER)
return effect;
switch (effect)
{
default:
@ -4828,7 +4828,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
case ABILITY_UNNERVE:
if (!gSpecialStatuses[battler].switchInAbilityDone)
{
gBattlerTarget = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerAtPosition(battler)));
gBattlerTarget = GetOppositeBattler(battler);
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_UNNERVE;
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
BattleScriptPushCursorAndCallback(BattleScript_SwitchInAbilityMsg);
@ -4839,7 +4839,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
case ABILITY_AS_ONE_SHADOW_RIDER:
if (!gSpecialStatuses[battler].switchInAbilityDone)
{
gBattlerTarget = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerAtPosition(battler)));
gBattlerTarget = GetOppositeBattler(battler);
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_ASONE;
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
BattleScriptPushCursorAndCallback(BattleScript_ActivateAsOne);
@ -5595,7 +5595,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
return effect;
case ABILITYEFFECT_MOVES_BLOCK:
effect = CanAbilityBlockMove(gBattlerAttacker, battler, move, gLastUsedAbility, ABILITY_RUN_SCRIPT);
// prankster check
if (effect == 0
&& GetChosenMovePriority(gBattlerAttacker) > 0
@ -8568,12 +8568,12 @@ u32 GetBattleMoveTarget(u16 move, u8 setTarget)
case MOVE_TARGET_DEPENDS:
case MOVE_TARGET_BOTH:
case MOVE_TARGET_FOES_AND_ALLY:
targetBattler = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerSide(gBattlerAttacker)));
targetBattler = GetOpposingSideBattler(gBattlerAttacker);
if (!IsBattlerAlive(targetBattler))
targetBattler ^= BIT_FLANK;
break;
case MOVE_TARGET_OPPONENTS_FIELD:
targetBattler = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerSide(gBattlerAttacker)));
targetBattler = GetOpposingSideBattler(gBattlerAttacker);
break;
case MOVE_TARGET_RANDOM:
side = BATTLE_OPPOSITE(GetBattlerSide(gBattlerAttacker));
@ -8582,7 +8582,7 @@ u32 GetBattleMoveTarget(u16 move, u8 setTarget)
else if (IsDoubleBattle() && moveTarget & MOVE_TARGET_RANDOM)
targetBattler = SetRandomTarget(gBattlerAttacker);
else
targetBattler = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerSide(gBattlerAttacker)));
targetBattler = GetOpposingSideBattler(gBattlerAttacker);
break;
case MOVE_TARGET_USER_OR_SELECTED:
case MOVE_TARGET_USER: