From 65244cbeb4bbde865631204c4d662e5a1583ca27 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Fri, 24 Oct 2025 18:56:16 +0200 Subject: [PATCH] Moved usedHeldItem to Party State struct (#8006) --- include/battle.h | 2 +- include/battle_util.h | 1 - include/constants/pokemon.h | 2 +- src/battle_ai_main.c | 8 ++++---- src/battle_main.c | 4 ++-- src/battle_script_commands.c | 12 ++++++------ src/battle_util.c | 19 +++++++------------ 7 files changed, 21 insertions(+), 27 deletions(-) diff --git a/include/battle.h b/include/battle.h index 14c01629ab..4af433f60f 100644 --- a/include/battle.h +++ b/include/battle.h @@ -600,6 +600,7 @@ struct PartyState u32 changedSpecies:11; // For forms when multiple mons can change into the same pokemon. u32 sentOut:1; u32 padding:9; + u16 usedHeldItem; }; // Cleared at the beginning of the battle. Fields need to be cleared when needed manually otherwise. @@ -669,7 +670,6 @@ struct BattleStruct u8 isSkyBattle:1; u8 multipleSwitchInSortedBattlers[MAX_BATTLERS_COUNT]; void (*savedCallback)(void); - u16 usedHeldItems[PARTY_SIZE][NUM_BATTLE_SIDES]; // For each party member and side. For harvest, recycle u16 chosenItem[MAX_BATTLERS_COUNT]; u16 choicedMove[MAX_BATTLERS_COUNT]; u16 changedItems[MAX_BATTLERS_COUNT]; diff --git a/include/battle_util.h b/include/battle_util.h index 281ce2c33b..b5693be0c0 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -340,7 +340,6 @@ bool32 IsBattlerAffectedByHazards(u32 battler, bool32 toxicSpikes); void SortBattlersBySpeed(u8 *battlers, bool32 slowToFast); bool32 CompareStat(u32 battler, u8 statId, u8 cmpTo, u8 cmpKind); bool32 BlocksPrankster(u16 move, u32 battlerPrankster, u32 battlerDef, bool32 checkTarget); -u16 GetUsedHeldItem(u32 battler); bool32 PickupHasValidTarget(u32 battler); bool32 CantPickupItem(u32 battler); bool32 IsBattlerWeatherAffected(u32 battler, u32 weatherFlags); diff --git a/include/constants/pokemon.h b/include/constants/pokemon.h index e87aeda9f9..b23bdb11f2 100644 --- a/include/constants/pokemon.h +++ b/include/constants/pokemon.h @@ -218,7 +218,7 @@ #define EV_ITEM_RAISE_LIMIT ((I_VITAMIN_EV_CAP >= GEN_8) ? MAX_PER_STAT_EVS : 100) // Move category defines. -enum DamageCategory +enum __attribute__((packed)) DamageCategory { DAMAGE_CATEGORY_PHYSICAL, DAMAGE_CATEGORY_SPECIAL, diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index ce7ab09768..0c1baa016b 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -2066,7 +2066,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_RECYCLE: - if (GetUsedHeldItem(battlerAtk) == 0 || gBattleMons[battlerAtk].item != 0) + if (GetBattlerPartyState(battlerAtk)->usedHeldItem == 0 || gBattleMons[battlerAtk].item != 0) ADJUST_SCORE(-10); break; case EFFECT_IMPRISON: @@ -5058,13 +5058,13 @@ static s32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move, stru ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_RECYCLE: - if (GetUsedHeldItem(battlerAtk) != ITEM_NONE) + if (GetBattlerPartyState(battlerAtk)->usedHeldItem != ITEM_NONE) ADJUST_SCORE(WEAK_EFFECT); - if (IsRecycleEncouragedItem(GetUsedHeldItem(battlerAtk))) + if (IsRecycleEncouragedItem(GetBattlerPartyState(battlerAtk)->usedHeldItem)) ADJUST_SCORE(WEAK_EFFECT); if (aiData->abilities[battlerAtk] == ABILITY_RIPEN) { - u32 item = GetUsedHeldItem(battlerAtk); + u32 item = GetBattlerPartyState(battlerAtk)->usedHeldItem; u32 toHeal = (GetItemHoldEffectParam(item) == 10) ? 10 : gBattleMons[battlerAtk].maxHP / GetItemHoldEffectParam(item); if (IsStatBoostingBerry(item) && aiData->hpPercents[battlerAtk] > 60) diff --git a/src/battle_main.c b/src/battle_main.c index 366bcf9281..7a469847e0 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3107,8 +3107,8 @@ static void BattleStartClearSetData(void) for (i = 0; i < PARTY_SIZE; i++) { - gBattleStruct->usedHeldItems[i][B_SIDE_PLAYER] = 0; - gBattleStruct->usedHeldItems[i][B_SIDE_OPPONENT] = 0; + gBattleStruct->partyState[B_SIDE_PLAYER][i].usedHeldItem = ITEM_NONE; + gBattleStruct->partyState[B_SIDE_OPPONENT][i].usedHeldItem = ITEM_NONE; gBattleStruct->itemLost[B_SIDE_PLAYER][i].originalItem = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM); gBattleStruct->itemLost[B_SIDE_OPPONENT][i].originalItem = GetMonData(&gEnemyParty[i], MON_DATA_HELD_ITEM); gPartyCriticalHits[i] = 0; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 084b37dc2d..4f49c90fac 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -6871,7 +6871,7 @@ static void Cmd_moveend(void) u32 item = gBattleMons[gBattlerAttacker].item; gBattleMons[gBattlerAttacker].item = ITEM_NONE; gBattleStruct->battlerState[gBattlerAttacker].canPickupItem = TRUE; - gBattleStruct->usedHeldItems[gBattlerPartyIndexes[gBattlerAttacker]][GetBattlerSide(gBattlerAttacker)] = item; + GetBattlerPartyState(gBattlerAttacker)->usedHeldItem = item; CheckSetUnburden(gBattlerAttacker); BtlController_EmitSetMonData( gBattlerAttacker, @@ -8690,8 +8690,8 @@ static void Cmd_removeitem(void) // Popped Air Balloon cannot be restored by any means. // Corroded items cannot be restored either. if (GetBattlerHoldEffect(battler) != HOLD_EFFECT_AIR_BALLOON - && GetMoveEffect(gCurrentMove) != EFFECT_CORROSIVE_GAS) - gBattleStruct->usedHeldItems[gBattlerPartyIndexes[battler]][GetBattlerSide(battler)] = itemId; // Remember if switched out + && GetMoveEffect(gCurrentMove) != EFFECT_CORROSIVE_GAS) + GetBattlerPartyState(battler)->usedHeldItem = itemId; // Remember if switched out gBattleMons[battler].item = ITEM_NONE; gBattleStruct->battlerState[battler].canPickupItem = TRUE; @@ -13300,9 +13300,9 @@ static void Cmd_tryrecycleitem(void) u16 *usedHeldItem; if (gCurrentMove == MOVE_NONE && GetBattlerAbility(gBattlerAttacker) == ABILITY_PICKUP) - usedHeldItem = &gBattleStruct->usedHeldItems[gBattlerPartyIndexes[gBattlerTarget]][GetBattlerSide(gBattlerTarget)]; + usedHeldItem = &GetBattlerPartyState(gBattlerTarget)->usedHeldItem; else - usedHeldItem = &gBattleStruct->usedHeldItems[gBattlerPartyIndexes[gBattlerAttacker]][GetBattlerSide(gBattlerAttacker)]; + usedHeldItem = &GetBattlerPartyState(gBattlerAttacker)->usedHeldItem; if (*usedHeldItem != ITEM_NONE && gBattleMons[gBattlerAttacker].item == ITEM_NONE) { gLastUsedItem = *usedHeldItem; @@ -16240,7 +16240,7 @@ void BS_HealOneSixth(void) void BS_TryRecycleBerry(void) { NATIVE_ARGS(const u8 *failInstr); - u16* usedHeldItem = &gBattleStruct->usedHeldItems[gBattlerPartyIndexes[gBattlerTarget]][GetBattlerSide(gBattlerTarget)]; + u16 *usedHeldItem = &GetBattlerPartyState(gBattlerTarget)->usedHeldItem; if (gBattleMons[gBattlerTarget].item == ITEM_NONE && gBattleStruct->changedItems[gBattlerTarget] == ITEM_NONE // Will not inherit an item && GetItemPocket(*usedHeldItem) == POCKET_BERRIES) diff --git a/src/battle_util.c b/src/battle_util.c index b3c1c7941c..9f9bf10dc2 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4544,7 +4544,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab && PickupHasValidTarget(battler)) { gBattlerTarget = RandomUniformExcept(RNG_PICKUP, 0, gBattlersCount - 1, CantPickupItem); - gLastUsedItem = GetUsedHeldItem(gBattlerTarget); + gLastUsedItem = GetBattlerPartyState(gBattlerTarget)->usedHeldItem; BattleScriptExecute(BattleScript_PickupActivates); effect++; } @@ -4553,9 +4553,9 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab if ((IsBattlerWeatherAffected(battler, B_WEATHER_SUN) || RandomPercentage(RNG_HARVEST, 50)) && gBattleMons[battler].item == ITEM_NONE && gBattleStruct->changedItems[battler] == ITEM_NONE // Will not inherit an item - && GetItemPocket(GetUsedHeldItem(battler)) == POCKET_BERRIES) + && GetItemPocket(GetBattlerPartyState(battler)->usedHeldItem) == POCKET_BERRIES) { - gLastUsedItem = GetUsedHeldItem(battler); + gLastUsedItem = GetBattlerPartyState(battler)->usedHeldItem; BattleScriptExecute(BattleScript_HarvestActivates); effect++; } @@ -4748,12 +4748,12 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab { gBattleScripting.battler = battler; gDisableStructs[battler].cudChew = FALSE; - gLastUsedItem = gBattleStruct->usedHeldItems[gBattlerPartyIndexes[battler]][GetBattlerSide(battler)]; - gBattleStruct->usedHeldItems[gBattlerPartyIndexes[battler]][GetBattlerSide(battler)] = ITEM_NONE; + gLastUsedItem = GetBattlerPartyState(battler)->usedHeldItem; + GetBattlerPartyState(battler)->usedHeldItem = ITEM_NONE; BattleScriptExecute(BattleScript_CudChewActivates); effect++; } - else if (!gDisableStructs[battler].cudChew && GetItemPocket(GetUsedHeldItem(battler)) == POCKET_BERRIES) + else if (!gDisableStructs[battler].cudChew && GetItemPocket(GetBattlerPartyState(battler)->usedHeldItem) == POCKET_BERRIES) { gDisableStructs[battler].cudChew = TRUE; } @@ -9700,17 +9700,12 @@ bool32 BlocksPrankster(u16 move, u32 battlerPrankster, u32 battlerDef, bool32 ch return TRUE; } -u16 GetUsedHeldItem(u32 battler) -{ - return gBattleStruct->usedHeldItems[gBattlerPartyIndexes[battler]][GetBattlerSide(battler)]; -} - bool32 CantPickupItem(u32 battler) { // Used by RandomUniformExcept() for RNG_PICKUP if (battler == gBattlerAttacker && (GetGenConfig(GEN_PICKUP_WILD) < GEN_9 || gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_LINK))) return TRUE; - return !(IsBattlerAlive(battler) && GetUsedHeldItem(battler) && gBattleStruct->battlerState[battler].canPickupItem); + return !(IsBattlerAlive(battler) && GetBattlerPartyState(battler)->usedHeldItem && gBattleStruct->battlerState[battler].canPickupItem); } bool32 PickupHasValidTarget(u32 battler)