diff --git a/Makefile b/Makefile index ebf7679af3..7456a9073b 100644 --- a/Makefile +++ b/Makefile @@ -124,7 +124,7 @@ ARMCC := $(PREFIX)gcc PATH_ARMCC := PATH="$(PATH)" $(ARMCC) CC1 := $(shell $(PATH_ARMCC) --print-prog-name=cc1) -quiet -override CFLAGS += -mthumb -mthumb-interwork -O$(O_LEVEL) -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -Wno-pointer-to-int-cast -std=gnu17 -Werror -Wall -Wno-strict-aliasing -Wno-attribute-alias -Woverride-init +override CFLAGS += -mthumb -mthumb-interwork -O$(O_LEVEL) -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -Wno-pointer-to-int-cast -std=gnu17 -Werror -Wall -Wno-strict-aliasing -Wno-attribute-alias -Woverride-init -Wnonnull ifneq ($(LTO),0) ifneq ($(TEST),1) diff --git a/include/constants/item.h b/include/constants/item.h index a8266c7237..bd35bdb861 100644 --- a/include/constants/item.h +++ b/include/constants/item.h @@ -11,7 +11,7 @@ enum Pocket POCKETS_COUNT, }; -#define POCKET_NONE POCKETS_COUNT +#define POCKET_DUMMY POCKETS_COUNT #define REPEL_LURE_MASK (1 << 15) #define IS_LAST_USED_LURE(var) (var & REPEL_LURE_MASK) diff --git a/include/gba/defines.h b/include/gba/defines.h index 481f203052..674c5fdc14 100644 --- a/include/gba/defines.h +++ b/include/gba/defines.h @@ -26,6 +26,7 @@ #define ALIGNED(n) __attribute__((aligned(n))) #define PACKED __attribute__((packed)) #define TRANSPARENT __attribute__ ((__transparent_union__)) +#define NONNULL __attribute__((__nonnull__)) #define SOUND_INFO_PTR (*(struct SoundInfo **)0x3007FF0) #define INTR_CHECK (*(u16 *)0x3007FF8) diff --git a/include/item.h b/include/item.h index b14d9bdf14..565784c85a 100644 --- a/include/item.h +++ b/include/item.h @@ -68,7 +68,8 @@ struct Item struct ALIGNED(2) BagPocket { struct ItemSlot *itemSlots; - u16 capacity; + u16 capacity:10; + enum Pocket id:6; }; struct TmHmIndexKey @@ -135,35 +136,42 @@ static inline u16 GetTMHMMoveId(enum TMHMIndex index) return gTMHMItemMoveIds[index].moveId; } +enum SortPocket +{ + SORT_NONE, + SORT_POCKET_BY_ITEM_ID, + SORT_POCKET_TM_HM, +}; + +void GetBagItemIdAndQuantity(enum Pocket pocketId, u32 pocketPos, u16 *itemId, u16 *quantity); u16 GetBagItemId(enum Pocket pocketId, u32 pocketPos); u16 GetBagItemQuantity(enum Pocket pocketId, u32 pocketPos); -void SetBagItemQuantity(enum Pocket pocketId, u32 pocketPos, u16 newValue); void ApplyNewEncryptionKeyToBagItems(u32 newKey); void SetBagItemsPointers(void); u8 *CopyItemName(u16 itemId, u8 *dst); u8 *CopyItemNameHandlePlural(u16 itemId, u8 *dst, u32 quantity); -bool8 IsBagPocketNonEmpty(enum Pocket pocketId); -bool8 CheckBagHasItem(u16 itemId, u16 count); -bool8 HasAtLeastOneBerry(void); -bool8 HasAtLeastOnePokeBall(void); -bool8 CheckBagHasSpace(u16 itemId, u16 count); +bool32 IsBagPocketNonEmpty(enum Pocket pocketId); +bool32 CheckBagHasItem(u16 itemId, u16 count); +bool32 HasAtLeastOneBerry(void); +bool32 HasAtLeastOnePokeBall(void); +bool32 CheckBagHasSpace(u16 itemId, u16 count); u32 GetFreeSpaceForItemInBag(u16 itemId); -bool8 AddBagItem(u16 itemId, u16 count); -bool8 RemoveBagItem(u16 itemId, u16 count); +bool32 AddBagItem(u16 itemId, u16 count); +bool32 RemoveBagItem(u16 itemId, u16 count); u8 CountUsedPCItemSlots(void); -bool8 CheckPCHasItem(u16 itemId, u16 count); -bool8 AddPCItem(u16 itemId, u16 count); +bool32 CheckPCHasItem(u16 itemId, u16 count); +bool32 AddPCItem(u16 itemId, u16 count); void RemovePCItem(u8 index, u16 count); void CompactPCItems(void); void SwapRegisteredBike(void); void CompactItemsInBagPocket(enum Pocket pocketId); -void SortBerriesOrTMHMs(enum Pocket pocketId); +void SortPocket(enum Pocket pocketId, enum SortPocket sortPocket); void MoveItemSlotInPocket(enum Pocket pocketId, u32 from, u32 to); void MoveItemSlotInPC(struct ItemSlot *itemSlots, u32 from, u32 to); void ClearBag(void); u16 CountTotalItemQuantityInBag(u16 itemId); -bool8 AddPyramidBagItem(u16 itemId, u16 count); -bool8 RemovePyramidBagItem(u16 itemId, u16 count); +bool32 AddPyramidBagItem(u16 itemId, u16 count); +bool32 RemovePyramidBagItem(u16 itemId, u16 count); const u8 *GetItemName(u16 itemId); u32 GetItemPrice(u16 itemId); const u8 *GetItemEffect(u32 itemId); diff --git a/src/item.c b/src/item.c index f0f9071c5a..45a3dfe421 100644 --- a/src/item.c +++ b/src/item.c @@ -21,10 +21,19 @@ #include "constants/item_effects.h" #include "constants/hold_effects.h" -static bool8 CheckPyramidBagHasItem(u16 itemId, u16 count); -static bool8 CheckPyramidBagHasSpace(u16 itemId, u16 count); +#define DUMMY_PC_BAG_POCKET \ +{ \ + .id = POCKET_DUMMY, \ + .capacity = PC_ITEMS_COUNT, \ + .itemSlots = gSaveBlock1Ptr->pcItems, \ +} + +static bool32 CheckPyramidBagHasItem(u16 itemId, u16 count); +static bool32 CheckPyramidBagHasSpace(u16 itemId, u16 count); static const u8 *GetItemPluralName(u16); static bool32 DoesItemHavePluralName(u16); +static void BagPocket_GetSetSlotDataGeneric(struct BagPocket *pocket, u32 pocketPos, u16 *itemId, u16 *quantity, bool32 isSetting); +static void BagPocket_GetSetSlotDataPC(struct BagPocket *pocket, u32 pocketPos, u16 *itemId, u16 *quantity, bool32 isSetting); EWRAM_DATA struct BagPocket gBagPockets[POCKETS_COUNT] = {0}; @@ -52,54 +61,71 @@ const struct TmHmIndexKey gTMHMItemMoveIds[NUM_ALL_MACHINES + 1] = #undef UNPACK_TM_ITEM_ID #undef UNPACK_HM_ITEM_ID -static inline u16 GetBagItemIdPocket(struct BagPocket *pocket, u32 pocketPos) +static void (*const sBagPocket_GetSetSlotDataFuncs[])(struct BagPocket *pocket, u32 pocketPos, u16 *itemId, u16 *quantity, bool32 isSetting) = { - return pocket->itemSlots[pocketPos].itemId; + [POCKET_ITEMS] = BagPocket_GetSetSlotDataGeneric, + [POCKET_KEY_ITEMS] = BagPocket_GetSetSlotDataGeneric, + [POCKET_POKE_BALLS] = BagPocket_GetSetSlotDataGeneric, + [POCKET_TM_HM] = BagPocket_GetSetSlotDataGeneric, + [POCKET_BERRIES] = BagPocket_GetSetSlotDataGeneric, + [POCKET_DUMMY] = BagPocket_GetSetSlotDataPC, +}; + +static void NONNULL BagPocket_GetSetSlotDataGeneric(struct BagPocket *pocket, u32 pocketPos, u16 *itemId, u16 *quantity, bool32 isSetting) +{ + if (isSetting) + { + pocket->itemSlots[pocketPos].itemId = *quantity ? *itemId : ITEM_NONE; // Sets to zero if quantity is zero + pocket->itemSlots[pocketPos].quantity = *quantity ^ gSaveBlock2Ptr->encryptionKey; + } + else + { + *itemId = pocket->itemSlots[pocketPos].itemId; + *quantity = pocket->itemSlots[pocketPos].quantity ^ gSaveBlock2Ptr->encryptionKey; + } } -static inline u16 GetBagItemQuantityPocket(struct BagPocket *pocket, u32 pocketPos) +static void NONNULL BagPocket_GetSetSlotDataPC(struct BagPocket *pocket, u32 pocketPos, u16 *itemId, u16 *quantity, bool32 isSetting) { - return gSaveBlock2Ptr->encryptionKey ^ pocket->itemSlots[pocketPos].quantity; + if (isSetting) + { + pocket->itemSlots[pocketPos].itemId = *quantity ? *itemId : ITEM_NONE; // Sets to zero if quantity is zero + pocket->itemSlots[pocketPos].quantity = *quantity; + } + else + { + *itemId = pocket->itemSlots[pocketPos].itemId; + *quantity = pocket->itemSlots[pocketPos].quantity; + } } -static inline void SetBagItemIdPocket(struct BagPocket *pocket, u32 pocketPos, u16 itemId) +static inline void NONNULL BagPocket_GetSlotData(struct BagPocket *pocket, u32 pocketPos, u16 *itemId, u16 *quantity) { - pocket->itemSlots[pocketPos].itemId = itemId; + sBagPocket_GetSetSlotDataFuncs[pocket->id](pocket, pocketPos, itemId, quantity, FALSE); } -static inline void SetBagItemQuantityPocket(struct BagPocket *pocket, u32 pocketPos, u16 newValue) +static inline void NONNULL BagPocket_SetSlotData(struct BagPocket *pocket, u32 pocketPos, u16 *itemId, u16 *quantity) { - pocket->itemSlots[pocketPos].quantity = newValue ^ gSaveBlock2Ptr->encryptionKey; + sBagPocket_GetSetSlotDataFuncs[pocket->id](pocket, pocketPos, itemId, quantity, TRUE); +} + +void GetBagItemIdAndQuantity(enum Pocket pocketId, u32 pocketPos, u16 *itemId, u16 *quantity) +{ + BagPocket_GetSlotData(&gBagPockets[pocketId], pocketPos, itemId, quantity); } u16 GetBagItemId(enum Pocket pocketId, u32 pocketPos) { - return GetBagItemIdPocket(&gBagPockets[pocketId], pocketPos); + u16 itemId, quantity; + BagPocket_GetSlotData(&gBagPockets[pocketId], pocketPos, &itemId, &quantity); + return itemId; } u16 GetBagItemQuantity(enum Pocket pocketId, u32 pocketPos) { - return GetBagItemQuantityPocket(&gBagPockets[pocketId], pocketPos); -} - -static void SetBagItemId(enum Pocket pocketId, u32 pocketPos, u16 itemId) -{ - SetBagItemIdPocket(&gBagPockets[pocketId], pocketPos, itemId); -} - -void SetBagItemQuantity(enum Pocket pocketId, u32 pocketPos, u16 newValue) -{ - SetBagItemQuantityPocket(&gBagPockets[pocketId], pocketPos, newValue); -} - -static u16 GetPCItemQuantity(u16 *quantity) -{ - return *quantity; -} - -static void SetPCItemQuantity(u16 *quantity, u16 newValue) -{ - *quantity = newValue; + u16 itemId, quantity; + BagPocket_GetSlotData(&gBagPockets[pocketId], pocketPos, &itemId, &quantity); + return quantity; } void ApplyNewEncryptionKeyToBagItems(u32 newKey) @@ -117,18 +143,23 @@ void SetBagItemsPointers(void) { gBagPockets[POCKET_ITEMS].itemSlots = gSaveBlock1Ptr->bag.items; gBagPockets[POCKET_ITEMS].capacity = BAG_ITEMS_COUNT; + gBagPockets[POCKET_ITEMS].id = POCKET_ITEMS; gBagPockets[POCKET_KEY_ITEMS].itemSlots = gSaveBlock1Ptr->bag.keyItems; gBagPockets[POCKET_KEY_ITEMS].capacity = BAG_KEYITEMS_COUNT; + gBagPockets[POCKET_KEY_ITEMS].id = POCKET_KEY_ITEMS; gBagPockets[POCKET_POKE_BALLS].itemSlots = gSaveBlock1Ptr->bag.pokeBalls; gBagPockets[POCKET_POKE_BALLS].capacity = BAG_POKEBALLS_COUNT; + gBagPockets[POCKET_POKE_BALLS].id = POCKET_POKE_BALLS; gBagPockets[POCKET_TM_HM].itemSlots = gSaveBlock1Ptr->bag.TMsHMs; gBagPockets[POCKET_TM_HM].capacity = BAG_TMHM_COUNT; + gBagPockets[POCKET_TM_HM].id = POCKET_TM_HM; gBagPockets[POCKET_BERRIES].itemSlots = gSaveBlock1Ptr->bag.berries; gBagPockets[POCKET_BERRIES].capacity = BAG_BERRIES_COUNT; + gBagPockets[POCKET_BERRIES].id = POCKET_BERRIES; } u8 *CopyItemName(u16 itemId, u8 *dst) @@ -155,68 +186,56 @@ u8 *CopyItemNameHandlePlural(u16 itemId, u8 *dst, u32 quantity) } } -bool8 IsBagPocketNonEmpty(enum Pocket pocketId) +bool32 IsBagPocketNonEmpty(enum Pocket pocketId) { u8 i; for (i = 0; i < gBagPockets[pocketId].capacity; i++) { - if (GetBagItemId(pocketId, i) != 0) + if (GetBagItemId(pocketId, i) != ITEM_NONE) return TRUE; } return FALSE; } -bool8 CheckBagHasItem(u16 itemId, u16 count) +static bool32 NONNULL BagPocket_CheckHasItem(struct BagPocket *pocket, u16 itemId, u16 count) { - u8 i; - enum Pocket pocketId; + u16 tempItemId, tempQuantity; + // Check for item slots that contain the item + for (u32 i = 0; i < pocket->capacity && count > 0; i++) + { + BagPocket_GetSlotData(pocket, i, &tempItemId, &tempQuantity); + if (tempItemId == itemId) + count -= min(count, tempQuantity); + } + + return count == 0; +} + +bool32 CheckBagHasItem(u16 itemId, u16 count) +{ if (GetItemPocket(itemId) >= POCKETS_COUNT) return FALSE; if (InBattlePyramid() || FlagGet(FLAG_STORING_ITEMS_IN_PYRAMID_BAG) == TRUE) return CheckPyramidBagHasItem(itemId, count); - pocketId = GetItemPocket(itemId); - // Check for item slots that contain the item - for (i = 0; i < gBagPockets[pocketId].capacity; i++) - { - if (GetBagItemId(pocketId, i) == itemId) - { - u16 quantity; - // Does this item slot contain enough of the item? - quantity = GetBagItemQuantity(pocketId, i); - if (quantity >= count) - return TRUE; - count -= quantity; - // Does this item slot and all previous slots contain enough of the item? - if (count == 0) - return TRUE; - } - } - return FALSE; + + return BagPocket_CheckHasItem(&gBagPockets[GetItemPocket(itemId)], itemId, count); } -bool8 HasAtLeastOneBerry(void) +bool32 HasAtLeastOneBerry(void) { - u16 i; - - for (i = FIRST_BERRY_INDEX; i <= LAST_BERRY_INDEX; i++) - { - if (CheckBagHasItem(i, 1) == TRUE) - { - gSpecialVar_Result = TRUE; - return TRUE; - } - } gSpecialVar_Result = FALSE; - return FALSE; + + for (u32 i = FIRST_BERRY_INDEX; i <= LAST_BERRY_INDEX && gSpecialVar_Result == FALSE; i++) + gSpecialVar_Result = CheckBagHasItem(i, 1); + + return gSpecialVar_Result; } -bool8 HasAtLeastOnePokeBall(void) +bool32 HasAtLeastOnePokeBall(void) { - u16 ballId; - - for (ballId = BALL_STRANGE; ballId < POKEBALL_COUNT; ballId++) + for (u32 ballId = BALL_STRANGE; ballId < POKEBALL_COUNT; ballId++) { if (CheckBagHasItem(ballId, 1) == TRUE) return TRUE; @@ -224,7 +243,7 @@ bool8 HasAtLeastOnePokeBall(void) return FALSE; } -bool8 CheckBagHasSpace(u16 itemId, u16 count) +bool32 CheckBagHasSpace(u16 itemId, u16 count) { if (GetItemPocket(itemId) >= POCKETS_COUNT) return FALSE; @@ -235,335 +254,250 @@ bool8 CheckBagHasSpace(u16 itemId, u16 count) return GetFreeSpaceForItemInBag(itemId) >= count; } -u32 GetFreeSpaceForItemInBag(u16 itemId) +static u32 NONNULL BagPocket_GetFreeSpaceForItem(struct BagPocket *pocket, u16 itemId) { - u8 i; - enum Pocket pocketId = GetItemPocket(itemId); - u16 ownedCount; u32 spaceForItem = 0; - - if (GetItemPocket(itemId) >= POCKETS_COUNT) - return 0; + u16 tempItemId, tempQuantity; // Check space in any existing item slots that already contain this item - for (i = 0; i < gBagPockets[pocketId].capacity; i++) + for (u32 i = 0; i < pocket->capacity; i++) { - - if (GetBagItemId(pocketId, i) == itemId) - { - ownedCount = GetBagItemQuantity(pocketId, i); - spaceForItem += max(0, MAX_BAG_ITEM_CAPACITY - ownedCount); - } - else if (GetBagItemId(pocketId, i) == ITEM_NONE) - { - spaceForItem += MAX_BAG_ITEM_CAPACITY; - } + BagPocket_GetSlotData(pocket, i, &tempItemId, &tempQuantity); + if (tempItemId == ITEM_NONE || tempItemId == itemId) + spaceForItem += (tempItemId ? (MAX_BAG_ITEM_CAPACITY - tempQuantity) : MAX_BAG_ITEM_CAPACITY); } + return spaceForItem; } -static inline u32 PrepareTempPocket(struct BagPocket *tempPocket, enum Pocket pocketId) +u32 GetFreeSpaceForItemInBag(u16 itemId) { - u32 size = gBagPockets[pocketId].capacity * sizeof(struct ItemSlot); - tempPocket->itemSlots = AllocZeroed(size); - tempPocket->capacity = gBagPockets[pocketId].capacity; - memcpy(tempPocket->itemSlots, gBagPockets[pocketId].itemSlots, size); + if (GetItemPocket(itemId) >= POCKETS_COUNT) + return 0; - return size; + return BagPocket_GetFreeSpaceForItem(&gBagPockets[GetItemPocket(itemId)], itemId); } -static inline void ClearTempPocket(struct BagPocket *pocket) +static inline bool32 NONNULL CheckSlotAndUpdateCount(struct BagPocket *pocket, u16 itemId, u32 pocketPos, u32 *nextPocketPos, u16 *count, u16 *tempPocketSlotQuantities) { - Free(pocket->itemSlots); - Free(pocket); + u16 tempItemId, tempQuantity; + BagPocket_GetSlotData(pocket, pocketPos, &tempItemId, &tempQuantity); + if (tempItemId == ITEM_NONE || tempItemId == itemId) + { + // The quantity already at the slot - zero if an empty slot + if (!tempItemId) + tempQuantity = 0; + + // Record slot quantity in tempPocketSlotQuantities, adjust count + tempPocketSlotQuantities[pocketPos] = min(MAX_BAG_ITEM_CAPACITY, *count + tempQuantity); + *count -= min(*count, MAX_BAG_ITEM_CAPACITY - tempQuantity); + + // Set the starting index for the next loop to set items (shifted by one) + if (!*nextPocketPos) + *nextPocketPos = pocketPos + 1; + + return TRUE; + } + + return FALSE; } -static inline void RestorePocketAndClearTempPocket(struct BagPocket *tempPocket, enum Pocket pocketId, u32 pocketSize) +static bool32 NONNULL BagPocket_AddItem(struct BagPocket *pocket, u16 itemId, u16 count) { - memcpy(gBagPockets[pocketId].itemSlots, tempPocket->itemSlots, pocketSize); - ClearTempPocket(tempPocket); + u32 itemLookupIndex, itemAddIndex = 0; + + // First, check that there is a free slot for this item + u16 *tempPocketSlotQuantities = AllocZeroed(sizeof(u16) * pocket->capacity); + + switch (pocket->id) + { + case POCKET_TM_HM: + case POCKET_BERRIES: + for (itemLookupIndex = 0; itemLookupIndex < pocket->capacity && count > 0; itemLookupIndex++) + { + // Check if we found a slot to store the item but weren't able to reduce count to 0 + // This means that we have more than one stack's worth, which isn't allowed in these pockets + if (CheckSlotAndUpdateCount(pocket, itemId, itemLookupIndex, &itemAddIndex, &count, tempPocketSlotQuantities) && count > 0) + { + Free(tempPocketSlotQuantities); + return FALSE; + } + } + break; + default: + for (itemLookupIndex = 0; itemLookupIndex < pocket->capacity && count > 0; itemLookupIndex++) + CheckSlotAndUpdateCount(pocket, itemId, itemLookupIndex, &itemAddIndex, &count, tempPocketSlotQuantities); + } + + // If the count is still greater than zero, clearly we have not found enough slots for this... + // Otherwise, we have found slots - update the actual pockets with the updated quantities + if (count == 0) + { + for (--itemAddIndex; itemAddIndex < itemLookupIndex; itemAddIndex++) + { + if (tempPocketSlotQuantities[itemAddIndex] > 0) + BagPocket_SetSlotData(pocket, itemAddIndex, &itemId, &tempPocketSlotQuantities[itemAddIndex]); + } + } + + Free(tempPocketSlotQuantities); + return count == 0; } -bool8 AddBagItem(u16 itemId, u16 count) +bool32 AddBagItem(u16 itemId, u16 count) { - u8 i; - if (GetItemPocket(itemId) >= POCKETS_COUNT) return FALSE; // check Battle Pyramid Bag if (InBattlePyramid() || FlagGet(FLAG_STORING_ITEMS_IN_PYRAMID_BAG) == TRUE) - { return AddPyramidBagItem(itemId, count); - } - else - { - u16 ownedCount; - enum Pocket pocketId = GetItemPocket(itemId); - struct BagPocket *tempPocket = AllocZeroed(sizeof(struct BagPocket)); - u32 pocketSize = PrepareTempPocket(tempPocket, pocketId); - for (i = 0; i < gBagPockets[pocketId].capacity; i++) - { - if (GetBagItemIdPocket(tempPocket, i) == itemId) - { - ownedCount = GetBagItemQuantityPocket(tempPocket, i); - // check if won't exceed max slot capacity - if (ownedCount + count <= MAX_BAG_ITEM_CAPACITY) - { - // successfully added to already existing item's count - SetBagItemQuantityPocket(tempPocket, i, ownedCount + count); - RestorePocketAndClearTempPocket(tempPocket, pocketId, pocketSize); - return TRUE; - } - else - { - // try creating another instance of the item if possible - if (pocketId == POCKET_TM_HM || pocketId == POCKET_BERRIES) - { - ClearTempPocket(tempPocket); - return FALSE; - } - else - { - count -= MAX_BAG_ITEM_CAPACITY - ownedCount; - SetBagItemQuantityPocket(tempPocket, i, MAX_BAG_ITEM_CAPACITY); - // don't create another instance of the item if it's at max slot capacity and count is equal to 0 - if (count == 0) - { - break; - } - } - } - } - } - - // we're done if quantity is equal to 0 - if (count > 0) - { - // either no existing item was found or we have to create another instance, because the capacity was exceeded - for (i = 0; i < gBagPockets[pocketId].capacity; i++) - { - if (GetBagItemIdPocket(tempPocket, i) == ITEM_NONE) - { - SetBagItemIdPocket(tempPocket, i, itemId); - if (count > MAX_BAG_ITEM_CAPACITY) - { - // try creating a new slot with max capacity if duplicates are possible - if (pocketId == POCKET_TM_HM || pocketId == POCKET_BERRIES) - { - ClearTempPocket(tempPocket); - return FALSE; - } - count -= MAX_BAG_ITEM_CAPACITY; - SetBagItemQuantityPocket(tempPocket, i, MAX_BAG_ITEM_CAPACITY); - } - else - { - // created a new slot and added quantity - SetBagItemQuantityPocket(tempPocket, i, count); - count = 0; - break; - } - } - } - - if (count > 0) - { - ClearTempPocket(tempPocket); - return FALSE; - } - } - RestorePocketAndClearTempPocket(tempPocket, pocketId, pocketSize); - return TRUE; - } + return BagPocket_AddItem(&gBagPockets[GetItemPocket(itemId)], itemId, count); } -bool8 RemoveBagItem(u16 itemId, u16 count) +static bool32 NONNULL BagPocket_RemoveItem(struct BagPocket *pocket, u16 itemId, u16 count) { - u8 i; - u16 totalQuantity = 0; + u32 itemLookupIndex, itemRemoveIndex = 0, totalQuantity = 0; + u16 tempItemId, tempQuantity; + u16 *tempPocketSlotQuantities = AllocZeroed(sizeof(u16) * pocket->capacity); - if (GetItemPocket(itemId) >= POCKETS_COUNT || itemId == ITEM_NONE) - return FALSE; - - // check Battle Pyramid Bag - if (InBattlePyramid() || FlagGet(FLAG_STORING_ITEMS_IN_PYRAMID_BAG) == TRUE) + for (itemLookupIndex = 0; itemLookupIndex < pocket->capacity && totalQuantity < count; itemLookupIndex++) { - return RemovePyramidBagItem(itemId, count); - } - else - { - u16 ownedCount, firstStackIndex = 0; - enum Pocket pocketId = GetItemPocket(itemId); - - for (i = 0; i < gBagPockets[pocketId].capacity; i++) + BagPocket_GetSlotData(pocket, itemLookupIndex, &tempItemId, &tempQuantity); + if (tempItemId == itemId) { - if (GetBagItemId(pocketId, i) == itemId) - { - if (totalQuantity == 0) - firstStackIndex = i; - totalQuantity += GetBagItemQuantity(pocketId, i); - } + // Index for the next loop - where we should start removing items + if (!itemRemoveIndex) + itemRemoveIndex = itemLookupIndex + 1; + + // Gather quantities (+ 1 to tempPocketSlotQuantities so that even if setting to 0 we know which indices to target) + totalQuantity += tempQuantity; + tempPocketSlotQuantities[itemLookupIndex] = (tempQuantity <= count ? 0 : tempQuantity - count) + 1; } + } - if (totalQuantity < count) - return FALSE; // We don't have enough of the item - + if (totalQuantity >= count) // We have enough of the item + { if (CurMapIsSecretBase() == TRUE) { VarSet(VAR_SECRET_BASE_LOW_TV_FLAGS, VarGet(VAR_SECRET_BASE_LOW_TV_FLAGS) | SECRET_BASE_USED_BAG); VarSet(VAR_SECRET_BASE_LAST_ITEM_USED, itemId); } - for (i = firstStackIndex; i < gBagPockets[pocketId].capacity; i++) + // Update the quantities correctly with the items removed + for (--itemRemoveIndex; itemRemoveIndex < itemLookupIndex; itemRemoveIndex++) { - if (GetBagItemId(pocketId, i) == itemId) + if (tempPocketSlotQuantities[itemRemoveIndex] > 0) { - ownedCount = GetBagItemQuantity(pocketId, i); - if (ownedCount >= count) - { - SetBagItemQuantity(pocketId, i, ownedCount - count); - count = 0; - } - else - { - count -= ownedCount; - SetBagItemQuantity(pocketId, i, 0); - } - - if (GetBagItemQuantity(pocketId, i) == 0) - SetBagItemId(pocketId, i, ITEM_NONE); - - if (count == 0) - return TRUE; + tempPocketSlotQuantities[itemRemoveIndex]--; // Reverse the +1 shift + BagPocket_SetSlotData(pocket, itemRemoveIndex, &itemId, &tempPocketSlotQuantities[itemRemoveIndex]); } } - return TRUE; } + + Free(tempPocketSlotQuantities); + return totalQuantity >= count; } -static s32 FindFreePCItemSlot(void) +bool32 RemoveBagItem(u16 itemId, u16 count) { - s8 i; + if (GetItemPocket(itemId) >= POCKETS_COUNT || itemId == ITEM_NONE) + return FALSE; - for (i = 0; i < PC_ITEMS_COUNT; i++) - { - if (gSaveBlock1Ptr->pcItems[i].itemId == ITEM_NONE) - return i; - } - return -1; + // check Battle Pyramid Bag + if (InBattlePyramid() || FlagGet(FLAG_STORING_ITEMS_IN_PYRAMID_BAG) == TRUE) + return RemovePyramidBagItem(itemId, count); + + return BagPocket_RemoveItem(&gBagPockets[GetItemPocket(itemId)], itemId, count); } -u8 CountUsedPCItemSlots(void) +static u8 NONNULL BagPocket_CountUsedItemSlots(struct BagPocket *pocket) { u8 usedSlots = 0; - u8 i; + u16 tempItemId, tempQuantity; - for (i = 0; i < PC_ITEMS_COUNT; i++) + for (u32 i = 0; i < pocket->capacity; i++) { - if (gSaveBlock1Ptr->pcItems[i].itemId != ITEM_NONE) + BagPocket_GetSlotData(pocket, i, &tempItemId, &tempQuantity); + if (tempItemId) usedSlots++; } return usedSlots; } -bool8 CheckPCHasItem(u16 itemId, u16 count) +u8 CountUsedPCItemSlots(void) { - u8 i; + struct BagPocket dummyPocket = DUMMY_PC_BAG_POCKET; + return BagPocket_CountUsedItemSlots(&dummyPocket); +} - for (i = 0; i < PC_ITEMS_COUNT; i++) +static bool32 NONNULL BagPocket_CheckPocketForItemCount(struct BagPocket *pocket, u16 itemId, u16 count) +{ + u16 tempItemId, tempQuantity; + + for (u32 i = 0; i < pocket->capacity; i++) { - if (gSaveBlock1Ptr->pcItems[i].itemId == itemId && GetPCItemQuantity(&gSaveBlock1Ptr->pcItems[i].quantity) >= count) + BagPocket_GetSlotData(pocket, i, &tempItemId, &tempQuantity); + if (tempItemId == itemId && tempQuantity >= count) return TRUE; } return FALSE; } -bool8 AddPCItem(u16 itemId, u16 count) +bool32 CheckPCHasItem(u16 itemId, u16 count) { - u8 i; - s8 freeSlot; - u16 ownedCount; - struct ItemSlot *newItems; + struct BagPocket dummyPocket = DUMMY_PC_BAG_POCKET; + return BagPocket_CheckPocketForItemCount(&dummyPocket, itemId, count); +} - // Copy PC items - newItems = AllocZeroed(sizeof(gSaveBlock1Ptr->pcItems)); - memcpy(newItems, gSaveBlock1Ptr->pcItems, sizeof(gSaveBlock1Ptr->pcItems)); +bool32 AddPCItem(u16 itemId, u16 count) +{ + struct BagPocket dummyPocket = DUMMY_PC_BAG_POCKET; + return BagPocket_AddItem(&dummyPocket, itemId, count); +} - // Use any item slots that already contain this item - for (i = 0; i < PC_ITEMS_COUNT; i++) +static void NONNULL BagPocket_CompactItems(struct BagPocket *pocket) +{ + u16 itemId, quantity, zero = 0, slotCursor = 0; + for (u32 i = 0; i < pocket->capacity; i++) { - if (newItems[i].itemId == itemId) + BagPocket_GetSlotData(pocket, i, &itemId, &quantity); + if (itemId == ITEM_NONE) { - ownedCount = GetPCItemQuantity(&newItems[i].quantity); - if (ownedCount + count <= MAX_PC_ITEM_CAPACITY) - { - SetPCItemQuantity(&newItems[i].quantity, ownedCount + count); - memcpy(gSaveBlock1Ptr->pcItems, newItems, sizeof(gSaveBlock1Ptr->pcItems)); - Free(newItems); - return TRUE; - } - count += ownedCount - MAX_PC_ITEM_CAPACITY; - SetPCItemQuantity(&newItems[i].quantity, MAX_PC_ITEM_CAPACITY); - if (count == 0) - { - memcpy(gSaveBlock1Ptr->pcItems, newItems, sizeof(gSaveBlock1Ptr->pcItems)); - Free(newItems); - return TRUE; - } + if (!slotCursor) + slotCursor = i + 1; + } + else if (slotCursor > 0) + { + BagPocket_SetSlotData(pocket, slotCursor - 1, &itemId, &quantity); + BagPocket_SetSlotData(pocket, i, &zero, &zero); + slotCursor++; } } - - // Put any remaining items into a new item slot. - if (count > 0) - { - freeSlot = FindFreePCItemSlot(); - if (freeSlot == -1) - { - Free(newItems); - return FALSE; - } - else - { - newItems[freeSlot].itemId = itemId; - SetPCItemQuantity(&newItems[freeSlot].quantity, count); - } - } - - // Copy items back to the PC - memcpy(gSaveBlock1Ptr->pcItems, newItems, sizeof(gSaveBlock1Ptr->pcItems)); - Free(newItems); - return TRUE; } void RemovePCItem(u8 index, u16 count) { - gSaveBlock1Ptr->pcItems[index].quantity -= count; - if (gSaveBlock1Ptr->pcItems[index].quantity == 0) - { - gSaveBlock1Ptr->pcItems[index].itemId = ITEM_NONE; - CompactPCItems(); - } + struct BagPocket dummyPocket = DUMMY_PC_BAG_POCKET; + + // Get id, quantity at slot + u16 tempItemId, tempQuantity; + BagPocket_GetSlotData(&dummyPocket, index, &tempItemId, &tempQuantity); + + // Remove quantity + tempQuantity -= count; + BagPocket_SetSlotData(&dummyPocket, index, &tempItemId, &tempQuantity); + + // Compact if necessary + if (tempQuantity == 0) + BagPocket_CompactItems(&dummyPocket); } void CompactPCItems(void) { - u16 i; - u16 j; - - for (i = 0; i < PC_ITEMS_COUNT - 1; i++) - { - for (j = i + 1; j < PC_ITEMS_COUNT; j++) - { - if (gSaveBlock1Ptr->pcItems[i].itemId == 0) - { - struct ItemSlot temp = gSaveBlock1Ptr->pcItems[i]; - gSaveBlock1Ptr->pcItems[i] = gSaveBlock1Ptr->pcItems[j]; - gSaveBlock1Ptr->pcItems[j] = temp; - } - } - } + struct BagPocket dummyPocket = DUMMY_PC_BAG_POCKET; + BagPocket_CompactItems(&dummyPocket); } void SwapRegisteredBike(void) @@ -579,101 +513,80 @@ void SwapRegisteredBike(void) } } -static void SwapItemSlots(enum Pocket pocketId, u32 pocketPosA, u16 pocketPosB) -{ - struct ItemSlot *itemA = &gBagPockets[pocketId].itemSlots[pocketPosA], - *itemB = &gBagPockets[pocketId].itemSlots[pocketPosB], - temp; - SWAP(*itemA, *itemB, temp); -} - void CompactItemsInBagPocket(enum Pocket pocketId) { - u16 i, j; + BagPocket_CompactItems(&gBagPockets[pocketId]); +} - for (i = 0; i < gBagPockets[pocketId].capacity - 1; i++) +// Opens the possibility of sorting by other means e.g. ghoulslash's advanced sorting +static inline bool32 ItemIndexCompare(u16 itemA, u16 itemB, enum SortPocket sortPocket) +{ + switch (sortPocket) { - for (j = i + 1; j < gBagPockets[pocketId].capacity; j++) + case SORT_POCKET_BY_ITEM_ID: + return itemA > itemB; + case SORT_POCKET_TM_HM: + return GetItemTMHMIndex(itemA) > GetItemTMHMIndex(itemB); + default: + return FALSE; + } +} + +void SortPocket(enum Pocket pocketId, enum SortPocket sortPocket) +{ + u16 itemId_i, quantity_i, itemId_j, quantity_j; + struct BagPocket *pocket = &gBagPockets[pocketId]; + + for (u32 i = 0; i < pocket->capacity - 1; i++) + { + BagPocket_GetSlotData(pocket, i, &itemId_i, &quantity_i); + for (u32 j = i + 1; j < pocket->capacity; j++) { - if (GetBagItemQuantity(pocketId, i) == 0) - SwapItemSlots(pocketId, i, j); + BagPocket_GetSlotData(pocket, j, &itemId_j, &quantity_j); + if (itemId_j && (!itemId_i || ItemIndexCompare(itemId_i, itemId_j, sortPocket))) + { + BagPocket_SetSlotData(pocket, i, &itemId_j, &quantity_j); + BagPocket_SetSlotData(pocket, j, &itemId_i, &quantity_i); + itemId_i = itemId_j; + quantity_i = quantity_j; + } } } } -void SortBerriesOrTMHMs(enum Pocket pocketId) +static inline void NONNULL BagPocket_MoveItemSlot(struct BagPocket *pocket, u32 from, u32 to) { - u16 i, j; - - for (i = 0; i < gBagPockets[pocketId].capacity - 1; i++) + if (from != to) { - for (j = i + 1; j < gBagPockets[pocketId].capacity; j++) + s8 shift = (to > from) ? 1 : -1; + if (to > from) + to--; + + // Record the values at "from" + u16 fromItemId, fromQuantity, tempItemId, tempQuantity; + BagPocket_GetSlotData(pocket, from, &fromItemId, &fromQuantity); + + // Shuffle items between "to" and "from" + for (u32 i = from; i == to - shift; i += shift) { - if (GetBagItemQuantity(pocketId, i) != 0 || GetBagItemId(pocketId, i) != ITEM_NONE) - { - if (GetBagItemQuantity(pocketId, j) == 0 || GetBagItemId(pocketId, j) == ITEM_NONE) - continue; - if (pocketId == POCKET_BERRIES && GetBagItemId(pocketId, i) <= GetBagItemId(pocketId, j)) // To do - continue; - if (pocketId == POCKET_TM_HM && GetItemTMHMIndex(GetBagItemId(pocketId, i)) <= GetItemTMHMIndex(GetBagItemId(pocketId, j))) - continue; - } - SwapItemSlots(pocketId, i, j); + BagPocket_GetSlotData(pocket, i + shift, &tempItemId, &tempQuantity); + BagPocket_SetSlotData(pocket, i, &tempItemId, &tempQuantity); } + + // Move the saved "from" to "to" + BagPocket_SetSlotData(pocket, to, &fromItemId, &fromQuantity); } } void MoveItemSlotInPocket(enum Pocket pocketId, u32 from, u32 to) { - if (from != to) - { - u32 i; - s8 shift = -1; - struct BagPocket *pocket = &gBagPockets[pocketId]; - - // Record the values at "from" - u16 fromItemId = GetBagItemIdPocket(pocket, from), - fromQuantity = GetBagItemQuantityPocket(pocket, from); - - // Shuffle items between "to" and "from" - if (to > from) - { - to--; - shift = 1; - } - - for (i = from; i == to - shift; i += shift) - { - SetBagItemIdPocket(pocket, i, GetBagItemIdPocket(pocket, i + shift)); - SetBagItemQuantityPocket(pocket, i, GetBagItemQuantityPocket(pocket, i + shift)); - } - - // Move the saved "from" to "to" - SetBagItemIdPocket(pocket, to, fromItemId); - SetBagItemQuantityPocket(pocket, to, fromQuantity); - } + BagPocket_MoveItemSlot(&gBagPockets[pocketId], from, to); } void MoveItemSlotInPC(struct ItemSlot *itemSlots, u32 from, u32 to) { - if (from != to) - { - s16 i, count; - struct ItemSlot firstSlot = itemSlots[from]; - - if (to > from) - { - to--; - for (i = from, count = to; i < count; i++) - itemSlots[i] = itemSlots[i + 1]; - } - else - { - for (i = from, count = to; i > count; i--) - itemSlots[i] = itemSlots[i - 1]; - } - itemSlots[to] = firstSlot; - } + struct BagPocket dummyPocket = DUMMY_PC_BAG_POCKET; + return BagPocket_MoveItemSlot(&dummyPocket, from, to); } void ClearBag(void) @@ -681,22 +594,26 @@ void ClearBag(void) CpuFastFill(0, &gSaveBlock1Ptr->bag, sizeof(struct Bag)); } -u16 CountTotalItemQuantityInBag(u16 itemId) +static inline u16 NONNULL BagPocket_CountTotalItemQuantity(struct BagPocket *pocket, u16 itemId) { - u16 i; - u16 ownedCount = 0; - enum Pocket pocketId = GetItemPocket(itemId); + u16 tempItemId, tempQuantity, ownedCount = 0; - for (i = 0; i < gBagPockets[pocketId].capacity; i++) + for (u32 i = 0; i < pocket->capacity; i++) { - if (GetBagItemId(pocketId, i) == itemId) - ownedCount += GetBagItemQuantity(pocketId, i); + BagPocket_GetSlotData(pocket, i, &tempItemId, &tempQuantity); + if (tempItemId == itemId) + ownedCount += tempQuantity; } return ownedCount; } -static bool8 CheckPyramidBagHasItem(u16 itemId, u16 count) +u16 CountTotalItemQuantityInBag(u16 itemId) +{ + return BagPocket_CountTotalItemQuantity(&gBagPockets[GetItemPocket(itemId)], itemId); +} + +static bool32 CheckPyramidBagHasItem(u16 itemId, u16 count) { u8 i; u16 *items = gSaveBlock2Ptr->frontier.pyramidBag.itemId[gSaveBlock2Ptr->frontier.lvlMode]; @@ -722,7 +639,7 @@ static bool8 CheckPyramidBagHasItem(u16 itemId, u16 count) return FALSE; } -static bool8 CheckPyramidBagHasSpace(u16 itemId, u16 count) +static bool32 CheckPyramidBagHasSpace(u16 itemId, u16 count) { u8 i; u16 *items = gSaveBlock2Ptr->frontier.pyramidBag.itemId[gSaveBlock2Ptr->frontier.lvlMode]; @@ -748,7 +665,7 @@ static bool8 CheckPyramidBagHasSpace(u16 itemId, u16 count) return FALSE; } -bool8 AddPyramidBagItem(u16 itemId, u16 count) +bool32 AddPyramidBagItem(u16 itemId, u16 count) { u16 i; @@ -826,7 +743,7 @@ bool8 AddPyramidBagItem(u16 itemId, u16 count) } } -bool8 RemovePyramidBagItem(u16 itemId, u16 count) +bool32 RemovePyramidBagItem(u16 itemId, u16 count) { u16 i; diff --git a/src/item_menu.c b/src/item_menu.c index 647b99eb2d..d6e3598b58 100755 --- a/src/item_menu.c +++ b/src/item_menu.c @@ -964,12 +964,11 @@ static void BagMenu_MoveCursorCallback(s32 itemIndex, bool8 onInit, struct ListM static void BagMenu_ItemPrintCallback(u8 windowId, u32 itemIndex, u8 y) { - u16 itemId; - u16 itemQuantity; - int offset; - if (itemIndex != LIST_CANCEL) { + u16 itemId, itemQuantity; + s32 offset; + if (gBagMenu->toSwapPos != NOT_SWAPPING) { // Swapping items, draw cursor at original item's location @@ -979,8 +978,7 @@ static void BagMenu_ItemPrintCallback(u8 windowId, u32 itemIndex, u8 y) BagMenu_PrintCursorAtPos(y, COLORID_NONE); } - itemId = GetBagItemId(gBagPosition.pocket, itemIndex); - itemQuantity = GetBagItemQuantity(gBagPosition.pocket, itemIndex); + GetBagItemIdAndQuantity(gBagPosition.pocket, itemIndex, &itemId, &itemQuantity); // Draw HM icon if (gBagPosition.pocket == POCKET_TM_HM && GetItemTMHMIndex(itemId) > NUM_TECHNICAL_MACHINES) @@ -1133,8 +1131,10 @@ void UpdatePocketItemList(u8 pocketId) switch (pocketId) { case POCKET_TM_HM: + SortPocket(pocketId, SORT_POCKET_TM_HM); + break; case POCKET_BERRIES: - SortBerriesOrTMHMs(pocketId); + SortPocket(pocketId, SORT_POCKET_BY_ITEM_ID); break; default: CompactItemsInBagPocket(pocketId); @@ -1287,8 +1287,7 @@ static void Task_BagMenu_HandleInput(u8 taskId) BagDestroyPocketScrollArrowPair(); BagMenu_PrintCursor(tListTaskId, COLORID_GRAY_CURSOR); tListPosition = listPosition; - tQuantity = GetBagItemQuantity(gBagPosition.pocket, listPosition); - gSpecialVar_ItemId = GetBagItemId(gBagPosition.pocket, listPosition); + GetBagItemIdAndQuantity(gBagPosition.pocket, listPosition, &gSpecialVar_ItemId, (u16*)&tQuantity); sContextMenuFuncs[gBagPosition.location](taskId); break; } diff --git a/src/item_menu_icons.c b/src/item_menu_icons.c index 61413ebeca..fa769b160f 100644 --- a/src/item_menu_icons.c +++ b/src/item_menu_icons.c @@ -101,7 +101,7 @@ static const union AnimCmd *const sBagSpriteAnimTable[] = [POCKET_TM_HM] = sSpriteAnim_Bag_TMsHMs, [POCKET_BERRIES] = sSpriteAnim_Bag_Berries, [POCKET_KEY_ITEMS] = sSpriteAnim_Bag_KeyItems, - [POCKET_NONE] = sSpriteAnim_Bag_Closed, + [POCKET_DUMMY] = sSpriteAnim_Bag_Closed, }; static const union AffineAnimCmd sSpriteAffineAnim_BagNormal[] = @@ -474,7 +474,7 @@ void SetBagVisualPocketId(u8 bagPocketId, bool8 isSwitchingPockets) sprite->y2 = -5; sprite->callback = SpriteCB_BagVisualSwitchingPockets; sprite->sPocketId = bagPocketId; - StartSpriteAnim(sprite, POCKET_NONE); + StartSpriteAnim(sprite, POCKET_DUMMY); } else { diff --git a/src/party_menu.c b/src/party_menu.c index 16ea3522d7..18b577567f 100644 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -426,7 +426,6 @@ static void Task_SacredAshDisplayHPRestored(u8); static void GiveItemOrMailToSelectedMon(u8); static void DisplayItemMustBeRemovedFirstMessage(u8); static void Task_SwitchItemsFromBagYesNo(u8); -static void RemoveItemToGiveFromBag(u16); static void CB2_WriteMailToGiveMonFromBag(void); static void GiveItemToSelectedMon(u8); static void Task_UpdateHeldItemSpriteAndClosePartyMenu(u8); @@ -6850,7 +6849,7 @@ static void GiveItemOrMailToSelectedMon(u8 taskId) { if (ItemIsMail(gPartyMenu.bagItem)) { - RemoveItemToGiveFromBag(gPartyMenu.bagItem); + RemoveBagItem(gPartyMenu.bagItem, 1); sPartyMenuInternal->exitCallback = CB2_WriteMailToGiveMonFromBag; Task_ClosePartyMenu(taskId); } @@ -6869,7 +6868,7 @@ static void GiveItemToSelectedMon(u8 taskId) item = gPartyMenu.bagItem; DisplayGaveHeldItemMessage(&gPlayerParty[gPartyMenu.slotId], item, FALSE, 1); GiveItemToMon(&gPlayerParty[gPartyMenu.slotId], item); - RemoveItemToGiveFromBag(item); + RemoveBagItem(item, 1); gTasks[taskId].func = Task_UpdateHeldItemSpriteAndClosePartyMenu; } } @@ -6948,7 +6947,7 @@ static void Task_HandleSwitchItemsFromBagYesNoInput(u8 taskId) { case 0: // Yes, switch items item = gPartyMenu.bagItem; - RemoveItemToGiveFromBag(item); + RemoveBagItem(item, 1); if (AddBagItem(sPartyMenuItemId, 1) == FALSE) { ReturnGiveItemToBagOrPC(item); @@ -6984,14 +6983,6 @@ static void DisplayItemMustBeRemovedFirstMessage(u8 taskId) gTasks[taskId].func = Task_UpdateHeldItemSpriteAndClosePartyMenu; } -static void RemoveItemToGiveFromBag(u16 item) -{ - if (gPartyMenu.action == PARTY_ACTION_GIVE_PC_ITEM) // Unused, never occurs - RemovePCItem(item, 1); - else - RemoveBagItem(item, 1); -} - // Returns FALSE if there was no space to return the item // but there always should be, and the return is ignored in all uses static bool8 ReturnGiveItemToBagOrPC(u16 item) diff --git a/test/bag.c b/test/bag.c index a3fb0318dd..6d0620dd6e 100644 --- a/test/bag.c +++ b/test/bag.c @@ -30,7 +30,7 @@ TEST("TMs and HMs are sorted correctly in the bag") additem ITEM_HM02; ); - SortBerriesOrTMHMs(POCKET_TM_HM); + SortPocket(POCKET_TM_HM, SORT_POCKET_TM_HM); EXPECT_EQ(pocket->itemSlots[0].itemId, ITEM_TM01); EXPECT_EQ(pocket->itemSlots[1].itemId, ITEM_TM05); @@ -67,7 +67,7 @@ TEST("Berries are sorted correctly in the bag") additem ITEM_CHERI_BERRY; ); - SortBerriesOrTMHMs(POCKET_BERRIES); + SortPocket(POCKET_BERRIES, SORT_POCKET_BY_ITEM_ID); EXPECT_EQ(pocket->itemSlots[0].itemId, ITEM_CHERI_BERRY); EXPECT_EQ(pocket->itemSlots[1].itemId, ITEM_ORAN_BERRY); @@ -102,11 +102,17 @@ TEST("Items are correctly compacted in the bag") ); EXPECT_EQ(pocket->itemSlots[0].itemId, ITEM_NUGGET); + EXPECT_EQ(pocket->itemSlots[0].quantity, 1); EXPECT_EQ(pocket->itemSlots[1].itemId, ITEM_BIG_NUGGET); + EXPECT_EQ(pocket->itemSlots[1].quantity, 1); EXPECT_EQ(pocket->itemSlots[2].itemId, ITEM_TINY_MUSHROOM); + EXPECT_EQ(pocket->itemSlots[2].quantity, 1); EXPECT_EQ(pocket->itemSlots[3].itemId, ITEM_BIG_MUSHROOM); + EXPECT_EQ(pocket->itemSlots[3].quantity, 1); EXPECT_EQ(pocket->itemSlots[4].itemId, ITEM_PEARL); + EXPECT_EQ(pocket->itemSlots[4].quantity, 1); EXPECT_EQ(pocket->itemSlots[5].itemId, ITEM_BIG_PEARL); + EXPECT_EQ(pocket->itemSlots[5].quantity, 1); EXPECT_EQ(pocket->itemSlots[6].itemId, ITEM_NONE); // Try removing the small items, check that everything is compacted correctly @@ -120,11 +126,13 @@ TEST("Items are correctly compacted in the bag") CompactItemsInBagPocket(POCKET_ITEMS); EXPECT_EQ(pocket->itemSlots[0].itemId, ITEM_BIG_NUGGET); + EXPECT_EQ(pocket->itemSlots[0].quantity, 1); EXPECT_EQ(pocket->itemSlots[1].itemId, ITEM_BIG_MUSHROOM); + EXPECT_EQ(pocket->itemSlots[1].quantity, 1); EXPECT_EQ(pocket->itemSlots[2].itemId, ITEM_BIG_PEARL); + EXPECT_EQ(pocket->itemSlots[2].quantity, 1); EXPECT_EQ(pocket->itemSlots[3].itemId, ITEM_NONE); EXPECT_EQ(pocket->itemSlots[4].itemId, ITEM_NONE); EXPECT_EQ(pocket->itemSlots[5].itemId, ITEM_NONE); EXPECT_EQ(pocket->itemSlots[6].itemId, ITEM_NONE); - }