Bag refactor 2 (#7166)

This commit is contained in:
Nephrite 2025-07-11 12:50:38 +03:00 committed by GitHub
parent cb606cee6a
commit 7d5a949b71
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 367 additions and 443 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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