summaryrefslogtreecommitdiff
path: root/src/item.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/item.c')
-rw-r--r--src/item.c1027
1 files changed, 949 insertions, 78 deletions
diff --git a/src/item.c b/src/item.c
index 0c60c417d..975fef3ae 100644
--- a/src/item.c
+++ b/src/item.c
@@ -5,52 +5,48 @@
#include "string_util.h"
#include "text.h"
#include "event_data.h"
+#include "malloc.h"
+#include "secret_base.h"
+#include "item_menu.h"
+#include "strings.h"
+#include "load_save.h"
-extern void ApplyNewEncryptionKeyToHword(u16* hword, u32 newKey);
extern bool8 InBattlePyramid(void);
+extern u16 gUnknown_0203CF30[];
+extern const struct Item gItems[];
-extern const u8 gText_PokeBalls[];
-extern const u8 gText_Berries[];
-extern const u8 gText_Berry[];
+// this file's functions
+static bool8 CheckPyramidBagHasItem(u16 itemId, u16 count);
+static bool8 CheckPyramidBagHasSpace(u16 itemId, u16 count);
-bool8 CheckPyramidBagHasItem(u16 itemId, u16 count);
-bool8 CheckPyramidBagHasSpace(u16 itemId, u16 count);
+// EWRAM variables
+EWRAM_DATA struct BagPocket gBagPockets[POCKETS_COUNT] = {0};
-enum
-{
- ITEMS_POCKET,
- BALLS_POCKET,
- TMHM_POCKET,
- BERRIES_POCKET,
- KEYITEMS_POCKET
-};
-
-EWRAM_DATA struct BagPocket gBagPockets[5] = {};
-
-u16 GetBagItemQuantity(u16* quantity)
+// code
+static u16 GetBagItemQuantity(u16 *quantity)
{
return gSaveBlock2Ptr->encryptionKey ^ *quantity;
}
-void SetBagItemQuantity(u16* quantity, u16 newValue)
+static void SetBagItemQuantity(u16 *quantity, u16 newValue)
{
*quantity = newValue ^ gSaveBlock2Ptr->encryptionKey;
}
-u16 GetBagItemId(u16* slot)
+static u16 GetPCItemQuantity(u16 *quantity)
{
- return *slot;
+ return *quantity;
}
-void SetBagItemId(u16* slot, u16 newItemId)
+static void SetPCItemQuantity(u16 *quantity, u16 newValue)
{
- *slot = newItemId;
+ *quantity = newValue;
}
void ApplyNewEncryptionKeyToBagItems(u32 newKey)
{
u32 pocket, item;
- for (pocket = 0; pocket < 5; pocket++)
+ for (pocket = 0; pocket < POCKETS_COUNT; pocket++)
{
for (item = 0; item < gBagPockets[pocket].capacity; item++)
ApplyNewEncryptionKeyToHword(&(gBagPockets[pocket].itemSlots[item].quantity), newKey);
@@ -62,58 +58,57 @@ void ApplyNewEncryptionKeyToBagItems_(u32 newKey) // really GF?
ApplyNewEncryptionKeyToBagItems(newKey);
}
-// TODO: move those max values to defines
-
void SetBagItemsPointers(void)
{
gBagPockets[ITEMS_POCKET].itemSlots = gSaveBlock1Ptr->bagPocket_Items;
- gBagPockets[ITEMS_POCKET].capacity = 30;
+ gBagPockets[ITEMS_POCKET].capacity = BAG_ITEMS_COUNT;
gBagPockets[KEYITEMS_POCKET].itemSlots = gSaveBlock1Ptr->bagPocket_KeyItems;
- gBagPockets[KEYITEMS_POCKET].capacity = 30;
+ gBagPockets[KEYITEMS_POCKET].capacity = BAG_KEYITEMS_COUNT;
gBagPockets[BALLS_POCKET].itemSlots = gSaveBlock1Ptr->bagPocket_PokeBalls;
- gBagPockets[BALLS_POCKET].capacity = 16;
+ gBagPockets[BALLS_POCKET].capacity = BAG_POKEBALLS_COUNT;
gBagPockets[TMHM_POCKET].itemSlots = gSaveBlock1Ptr->bagPocket_TMHM;
- gBagPockets[TMHM_POCKET].capacity = 64;
+ gBagPockets[TMHM_POCKET].capacity = BAG_TMHM_COUNT;
gBagPockets[BERRIES_POCKET].itemSlots = gSaveBlock1Ptr->bagPocket_Berries;
- gBagPockets[BERRIES_POCKET].capacity = 46;
+ gBagPockets[BERRIES_POCKET].capacity = BAG_BERRIES_COUNT;
}
-void CopyItemName(u16 itemId, u8 *string)
+void CopyItemName(u16 itemId, u8 *dst)
{
- StringCopy(string, ItemId_GetItem(itemId)->name);
+ StringCopy(dst, ItemId_GetName(itemId));
}
-void CopyItemNameHandlePlural(u16 itemId, u8 *string, u32 quantity)
+void CopyItemNameHandlePlural(u16 itemId, u8 *dst, u32 quantity)
{
if (itemId == ITEM_POKE_BALL)
{
if (quantity < 2)
- StringCopy(string, ItemId_GetItem(ITEM_POKE_BALL)->name);
+ StringCopy(dst, ItemId_GetName(ITEM_POKE_BALL));
else
- StringCopy(string, gText_PokeBalls);
+ StringCopy(dst, gText_PokeBalls);
}
else
{
if (itemId >= ITEM_CHERI_BERRY && itemId <= ITEM_ENIGMA_BERRY)
- GetBerryCountString(string, gBerries[itemId - ITEM_CHERI_BERRY].name, quantity);
+ GetBerryCountString(dst, gBerries[itemId - ITEM_CHERI_BERRY].name, quantity);
else
- StringCopy(string, ItemId_GetItem(itemId)->name);
+ StringCopy(dst, ItemId_GetName(itemId));
}
}
-void GetBerryCountString(u8* dst, const u8* berryName, u32 quantity)
+void GetBerryCountString(u8 *dst, const u8 *berryName, u32 quantity)
{
- const u8* berryString;
- u8* txtPtr;
+ const u8 *berryString;
+ u8 *txtPtr;
if (quantity < 2)
berryString = gText_Berry;
else
berryString = gText_Berries;
+
txtPtr = StringCopy(dst, berryName);
*txtPtr = CHAR_SPACE;
StringCopy(txtPtr + 1, berryString);
@@ -138,21 +133,21 @@ bool8 CheckBagHasItem(u16 itemId, u16 count)
if (ItemId_GetPocket(itemId) == 0)
return FALSE;
- if (InBattlePyramid() || FlagGet(0x4004) == TRUE)
+ if (InBattlePyramid() || FlagGet(FLAG_SPECIAL_FLAG_0x4004) == TRUE)
return CheckPyramidBagHasItem(itemId, count);
pocket = ItemId_GetPocket(itemId) - 1;
- //Check for item slots that contain the item
+ // Check for item slots that contain the item
for (i = 0; i < gBagPockets[pocket].capacity; i++)
{
if (gBagPockets[pocket].itemSlots[i].itemId == itemId)
{
u16 quantity;
- //Does this item slot contain enough of the item?
+ // Does this item slot contain enough of the item?
quantity = GetBagItemQuantity(&gBagPockets[pocket].itemSlots[i].quantity);
if (quantity >= count)
return TRUE;
count -= quantity;
- //Does this item slot and all previous slots contain enough of the item?
+ // Does this item slot and all previous slots contain enough of the item?
if (count == 0)
return TRUE;
}
@@ -163,69 +158,945 @@ bool8 CheckBagHasItem(u16 itemId, u16 count)
bool8 HasAtLeastOneBerry(void)
{
u16 i;
- for (i = 0x85; i < 0xB3; i++)
+
+ for (i = FIRST_BERRY_INDEX; i < ITEM_BRIGHT_POWDER; i++)
{
if (CheckBagHasItem(i, 1) == TRUE)
{
- gSpecialVar_Result = 1;
+ gSpecialVar_Result = TRUE;
return TRUE;
}
}
- gSpecialVar_Result = 0;
+ gSpecialVar_Result = FALSE;
return FALSE;
}
-/* Refuses to match.
+#ifdef NONMATCHING
+// Refuses to match.
bool8 CheckBagHasSpace(u16 itemId, u16 count)
{
u8 i;
- u8 pocket;
- u16 slotCapacity;
- u16 quantity;
- if (ItemId_GetPocket(itemId) == 0)
+ if (ItemId_GetPocket(itemId) == POCKET_NONE)
return FALSE;
- if (InBattlePyramid() || FlagGet(0x4004) == TRUE)
+
+ if (InBattlePyramid() || FlagGet(FLAG_SPECIAL_FLAG_0x4004) == TRUE)
+ {
return CheckPyramidBagHasSpace(itemId, count);
- pocket = ItemId_GetPocket(itemId) - 1;
- if (pocket != BERRIES_POCKET)
- slotCapacity = 99;
+ }
else
- slotCapacity = 999;
+ {
+ u8 pocket;
+ u16 slotCapacity;
+ u16 ownedCount;
- //Check space in any existing item slots that already contain this item
- for (i = 0; i < gBagPockets[pocket].capacity; i++)
+ pocket = ItemId_GetPocket(itemId) - 1;
+ if (pocket != BERRIES_POCKET)
+ slotCapacity = 99;
+ else
+ slotCapacity = 999;
+
+ // Check space in any existing item slots that already contain this item
+ for (i = 0; i < gBagPockets[pocket].capacity; i++)
+ {
+ if (gBagPockets[pocket].itemSlots[i].itemId == itemId)
+ {
+ ownedCount = GetBagItemQuantity(&gBagPockets[pocket].itemSlots[i].quantity);
+ if (ownedCount + count <= slotCapacity)
+ return TRUE;
+ if (pocket == TMHM_POCKET || pocket == BERRIES_POCKET)
+ return FALSE;
+ count -= slotCapacity - ownedCount;
+ if (count == 0)
+ return TRUE;
+ }
+ }
+
+ // Check space in empty item slots
+ if (count > 0)
+ {
+ for (i = 0; i < gBagPockets[pocket].capacity; i++)
+ {
+ if (gBagPockets[pocket].itemSlots[i].itemId == 0)
+ {
+ if (count <= slotCapacity)
+ return TRUE;
+ if (pocket == TMHM_POCKET || pocket == BERRIES_POCKET)
+ return FALSE;
+ count -= slotCapacity;
+ }
+ }
+ if (count > 0)
+ return FALSE; // No more item slots. The bag is full
+ }
+
+ return TRUE;
+ }
+}
+#else
+ASM_DIRECT
+bool8 CheckBagHasSpace(u16 itemId, u16 count)
+{
+ asm_unified("push {r4-r7,lr}\n\
+ mov r7, r10\n\
+ mov r6, r9\n\
+ mov r5, r8\n\
+ push {r5-r7}\n\
+ sub sp, 0x4\n\
+ lsls r0, 16\n\
+ lsrs r0, 16\n\
+ mov r8, r0\n\
+ lsls r1, 16\n\
+ lsrs r5, r1, 16\n\
+ bl ItemId_GetPocket\n\
+ lsls r0, 24\n\
+ cmp r0, 0\n\
+ beq _080D6906\n\
+ bl InBattlePyramid\n\
+ lsls r0, 24\n\
+ cmp r0, 0\n\
+ bne _080D6838\n\
+ ldr r0, =0x00004004\n\
+ bl FlagGet\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ cmp r0, 0x1\n\
+ bne _080D684C\n\
+_080D6838:\n\
+ mov r0, r8\n\
+ adds r1, r5, 0\n\
+ bl CheckPyramidBagHasSpace\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ b _080D6916\n\
+ .pool\n\
+_080D684C:\n\
+ mov r0, r8\n\
+ bl ItemId_GetPocket\n\
+ subs r0, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r2, r0, 24\n\
+ ldr r7, =0x000003e7\n\
+ cmp r2, 0x3\n\
+ beq _080D6860\n\
+ movs r7, 0x63\n\
+_080D6860:\n\
+ movs r6, 0\n\
+ ldr r1, =gBagPockets\n\
+ lsls r4, r2, 3\n\
+ adds r0, r4, r1\n\
+ mov r9, r4\n\
+ ldrb r0, [r0, 0x4]\n\
+ cmp r6, r0\n\
+ bcs _080D68BC\n\
+ subs r0, r2, 0x2\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ mov r10, r0\n\
+_080D6878:\n\
+ adds r0, r4, r1\n\
+ ldr r1, [r0]\n\
+ lsls r0, r6, 2\n\
+ adds r1, r0, r1\n\
+ ldrh r0, [r1]\n\
+ cmp r0, r8\n\
+ bne _080D68AC\n\
+ adds r0, r1, 0x2\n\
+ str r2, [sp]\n\
+ bl GetBagItemQuantity\n\
+ lsls r0, 16\n\
+ lsrs r1, r0, 16\n\
+ adds r0, r1, r5\n\
+ ldr r2, [sp]\n\
+ cmp r0, r7\n\
+ ble _080D6914\n\
+ mov r0, r10\n\
+ cmp r0, 0x1\n\
+ bls _080D6906\n\
+ subs r0, r7, r1\n\
+ subs r0, r5, r0\n\
+ lsls r0, 16\n\
+ lsrs r5, r0, 16\n\
+ cmp r5, 0\n\
+ beq _080D6914\n\
+_080D68AC:\n\
+ adds r0, r6, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r6, r0, 24\n\
+ ldr r1, =gBagPockets\n\
+ adds r0, r4, r1\n\
+ ldrb r0, [r0, 0x4]\n\
+ cmp r6, r0\n\
+ bcc _080D6878\n\
+_080D68BC:\n\
+ cmp r5, 0\n\
+ beq _080D6914\n\
+ movs r6, 0\n\
+ ldr r3, =gBagPockets\n\
+ mov r1, r9\n\
+ adds r0, r1, r3\n\
+ ldrb r0, [r0, 0x4]\n\
+ cmp r6, r0\n\
+ bcs _080D6902\n\
+ adds r4, r3, 0\n\
+ subs r0, r2, 0x2\n\
+ lsls r0, 24\n\
+ lsrs r2, r0, 24\n\
+_080D68D6:\n\
+ adds r0, r1, r4\n\
+ ldr r1, [r0]\n\
+ lsls r0, r6, 2\n\
+ adds r0, r1\n\
+ ldrh r0, [r0]\n\
+ cmp r0, 0\n\
+ bne _080D68F2\n\
+ cmp r5, r7\n\
+ bls _080D6914\n\
+ cmp r2, 0x1\n\
+ bls _080D6906\n\
+ subs r0, r5, r7\n\
+ lsls r0, 16\n\
+ lsrs r5, r0, 16\n\
+_080D68F2:\n\
+ adds r0, r6, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r6, r0, 24\n\
+ mov r1, r9\n\
+ adds r0, r1, r3\n\
+ ldrb r0, [r0, 0x4]\n\
+ cmp r6, r0\n\
+ bcc _080D68D6\n\
+_080D6902:\n\
+ cmp r5, 0\n\
+ beq _080D6914\n\
+_080D6906:\n\
+ movs r0, 0\n\
+ b _080D6916\n\
+ .pool\n\
+_080D6914:\n\
+ movs r0, 0x1\n\
+_080D6916:\n\
+ add sp, 0x4\n\
+ pop {r3-r5}\n\
+ mov r8, r3\n\
+ mov r9, r4\n\
+ mov r10, r5\n\
+ pop {r4-r7}\n\
+ pop {r1}\n\
+ bx r1");
+}
+#endif // NONMATCHING
+
+bool8 AddBagItem(u16 itemId, u16 count)
+{
+ u8 i;
+
+ if (ItemId_GetPocket(itemId) == POCKET_NONE)
+ return FALSE;
+
+ // check Battle Pyramid Bag
+ if (InBattlePyramid() || FlagGet(FLAG_SPECIAL_FLAG_0x4004) == TRUE)
{
- if (gBagPockets[pocket].itemSlots[i].itemId == itemId)
+ return AddPyramidBagItem(itemId, count);
+ }
+ else
+ {
+ struct BagPocket *itemPocket;
+ struct ItemSlot *newItems;
+ u16 slotCapacity;
+ u16 ownedCount;
+ u8 pocket = ItemId_GetPocket(itemId) - 1;
+
+ itemPocket = &gBagPockets[pocket];
+ newItems = AllocZeroed(itemPocket->capacity * sizeof(struct ItemSlot));
+ memcpy(newItems, itemPocket->itemSlots, itemPocket->capacity * sizeof(struct ItemSlot));
+
+ if (pocket != BERRIES_POCKET)
+ slotCapacity = 99;
+ else
+ slotCapacity = 999;
+
+ for (i = 0; i < itemPocket->capacity; i++)
{
- quantity = GetBagItemQuantity(&gBagPockets[pocket].itemSlots[i].quantity);
- if (quantity + count <= slotCapacity)
- return TRUE;
- if (pocket == TMHM_POCKET || pocket == BERRIES_POCKET)
+ if (newItems[i].itemId == itemId)
+ {
+ ownedCount = GetBagItemQuantity(&newItems[i].quantity);
+ // check if won't exceed max slot capacity
+ if (ownedCount + count <= slotCapacity)
+ {
+ // successfully added to already existing item's count
+ SetBagItemQuantity(&newItems[i].quantity, ownedCount + count);
+
+ // goto SUCCESS_ADD_ITEM;
+ // is equivalent but won't match
+
+ memcpy(itemPocket->itemSlots, newItems, itemPocket->capacity * sizeof(struct ItemSlot));
+ Free(newItems);
+ return TRUE;
+ }
+ else
+ {
+ // try creating another instance of the item if possible
+ if (pocket == TMHM_POCKET || pocket == BERRIES_POCKET)
+ {
+ Free(newItems);
+ return FALSE;
+ }
+ else
+ {
+ count -= slotCapacity - ownedCount;
+ SetBagItemQuantity(&newItems[i].quantity, slotCapacity);
+ // don't create another instance of the item if it's at max slot capacity and count is equal to 0
+ if (count == 0)
+ {
+ goto SUCCESS_ADD_ITEM;
+ }
+ }
+ }
+ }
+ }
+
+ // 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 < itemPocket->capacity; i++)
+ {
+ if (newItems[i].itemId == ITEM_NONE)
+ {
+ newItems[i].itemId = itemId;
+ if (count > slotCapacity)
+ {
+ // try creating a new slot with max capacity if duplicates are possible
+ if (pocket == TMHM_POCKET || pocket == BERRIES_POCKET)
+ {
+ Free(newItems);
+ return FALSE;
+ }
+ count -= slotCapacity;
+ SetBagItemQuantity(&newItems[i].quantity, slotCapacity);
+ }
+ else
+ {
+ // created a new slot and added quantity
+ SetBagItemQuantity(&newItems[i].quantity, count);
+ goto SUCCESS_ADD_ITEM;
+ }
+ }
+ }
+
+ if (count > 0)
+ {
+ Free(newItems);
return FALSE;
- count -= slotCapacity - quantity;
+ }
+ }
+
+ SUCCESS_ADD_ITEM:
+ memcpy(itemPocket->itemSlots, newItems, itemPocket->capacity * sizeof(struct ItemSlot));
+ Free(newItems);
+ return TRUE;
+ }
+}
+
+bool8 RemoveBagItem(u16 itemId, u16 count)
+{
+ u8 i;
+ u16 totalQuantity = 0;
+
+ if (ItemId_GetPocket(itemId) == POCKET_NONE || itemId == ITEM_NONE)
+ return FALSE;
+
+ // check Battle Pyramid Bag
+ if (InBattlePyramid() || FlagGet(FLAG_SPECIAL_FLAG_0x4004) == TRUE)
+ {
+ return RemovePyramidBagItem(itemId, count);
+ }
+ else
+ {
+ u8 pocket;
+ u8 var;
+ u16 ownedCount;
+ struct BagPocket *itemPocket;
+
+ pocket = ItemId_GetPocket(itemId) - 1;
+ itemPocket = &gBagPockets[pocket];
+
+ for (i = 0; i < itemPocket->capacity; i++)
+ {
+ if (itemPocket->itemSlots[i].itemId == itemId)
+ totalQuantity += GetBagItemQuantity(&itemPocket->itemSlots[i].quantity);
+ }
+
+ if (totalQuantity < count)
+ return FALSE; // We don't have enough of the item
+
+ if (CurrentMapIsSecretBase() == TRUE)
+ {
+ VarSet(VAR_0x40EE, VarGet(VAR_0x40EE) | 0x200);
+ VarSet(VAR_0x40ED, itemId);
+ }
+
+ var = sub_81ABB2C(pocket);
+ if (itemPocket->capacity > var
+ && itemPocket->itemSlots[var].itemId == itemId)
+ {
+ ownedCount = GetBagItemQuantity(&itemPocket->itemSlots[var].quantity);
+ if (ownedCount >= count)
+ {
+ SetBagItemQuantity(&itemPocket->itemSlots[var].quantity, ownedCount - count);
+ count = 0;
+ }
+ else
+ {
+ count -= ownedCount;
+ SetBagItemQuantity(&itemPocket->itemSlots[var].quantity, 0);
+ }
+
+ if (GetBagItemQuantity(&itemPocket->itemSlots[var].quantity) == 0)
+ itemPocket->itemSlots[var].itemId = ITEM_NONE;
+
if (count == 0)
return TRUE;
}
+
+ for (i = 0; i < itemPocket->capacity; i++)
+ {
+ if (itemPocket->itemSlots[i].itemId == itemId)
+ {
+ ownedCount = GetBagItemQuantity(&itemPocket->itemSlots[i].quantity);
+ if (ownedCount >= count)
+ {
+ SetBagItemQuantity(&itemPocket->itemSlots[i].quantity, ownedCount - count);
+ count = 0;
+ }
+ else
+ {
+ count -= ownedCount;
+ SetBagItemQuantity(&itemPocket->itemSlots[i].quantity, 0);
+ }
+
+ if (GetBagItemQuantity(&itemPocket->itemSlots[i].quantity) == 0)
+ itemPocket->itemSlots[i].itemId = ITEM_NONE;
+
+ if (count == 0)
+ return TRUE;
+ }
+ }
+ return TRUE;
}
+}
- //Check space in empty item slots
- if (count > 0)
+u8 GetPocketByItemId(u16 itemId)
+{
+ return ItemId_GetPocket(itemId);
+}
+
+void ClearItemSlots(struct ItemSlot *itemSlots, u8 itemCount)
+{
+ u16 i;
+
+ for (i = 0; i < itemCount; i++)
{
- for (i = 0; i < gBagPockets[pocket].capacity; i++)
+ itemSlots[i].itemId = ITEM_NONE;
+ SetBagItemQuantity(&itemSlots[i].quantity, 0);
+ }
+}
+
+static s32 FindFreePCItemSlot(void)
+{
+ s8 i;
+
+ for (i = 0; i < PC_ITEMS_COUNT; i++)
+ {
+ if (gSaveBlock1Ptr->pcItems[i].itemId == ITEM_NONE)
+ return i;
+ }
+ return -1;
+}
+
+u8 CountUsedPCItemSlots(void)
+{
+ u8 usedSlots = 0;
+ u8 i;
+
+ for (i = 0; i < PC_ITEMS_COUNT; i++)
+ {
+ if (gSaveBlock1Ptr->pcItems[i].itemId != ITEM_NONE)
+ usedSlots++;
+ }
+ return usedSlots;
+}
+
+bool8 CheckPCHasItem(u16 itemId, u16 count)
+{
+ u8 i;
+
+ for (i = 0; i < PC_ITEMS_COUNT; i++)
+ {
+ if (gSaveBlock1Ptr->pcItems[i].itemId == itemId && GetPCItemQuantity(&gSaveBlock1Ptr->pcItems[i].quantity) >= count)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 AddPCItem(u16 itemId, u16 count)
+{
+ u8 i;
+ s8 freeSlot;
+ u16 ownedCount;
+ struct ItemSlot *newItems;
+
+ // Copy PC items
+ newItems = AllocZeroed(sizeof(gSaveBlock1Ptr->pcItems));
+ memcpy(newItems, gSaveBlock1Ptr->pcItems, sizeof(gSaveBlock1Ptr->pcItems));
+
+ // Use any item slots that already contain this item
+ for (i = 0; i < PC_ITEMS_COUNT; i++)
+ {
+ if (newItems[i].itemId == itemId)
{
- if (gBagPockets[pocket].itemSlots[i].itemId == 0)
+ ownedCount = GetPCItemQuantity(&newItems[i].quantity);
+ if (ownedCount + count <= 999)
{
- if (count <= slotCapacity)
- return TRUE;
- if (pocket == TMHM_POCKET || pocket == BERRIES_POCKET)
- return FALSE;
- count -= slotCapacity;
+ SetPCItemQuantity(&newItems[i].quantity, ownedCount + count);
+ memcpy(gSaveBlock1Ptr->pcItems, newItems, sizeof(gSaveBlock1Ptr->pcItems));
+ Free(newItems);
+ return TRUE;
+ }
+ count += ownedCount - 999;
+ SetPCItemQuantity(&newItems[i].quantity, 999);
+ if (count == 0)
+ {
+ memcpy(gSaveBlock1Ptr->pcItems, newItems, sizeof(gSaveBlock1Ptr->pcItems));
+ Free(newItems);
+ return TRUE;
}
}
- if (count > 0)
- return FALSE; //No more item slots. The bag is full
}
+ // 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)
+{
+ // UB: should use GetPCItemQuantity and SetPCItemQuantity functions
+ gSaveBlock1Ptr->pcItems[index].quantity -= count;
+ if (gSaveBlock1Ptr->pcItems[index].quantity == 0)
+ {
+ gSaveBlock1Ptr->pcItems[index].itemId = ITEM_NONE;
+ CompactPCItems();
+ }
+}
+
+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;
+ }
+ }
+ }
+}
+
+void SwapRegisteredBike(void)
+{
+ switch (gSaveBlock1Ptr->registeredItem)
+ {
+ case ITEM_MACH_BIKE:
+ gSaveBlock1Ptr->registeredItem = ITEM_ACRO_BIKE;
+ break;
+ case ITEM_ACRO_BIKE:
+ gSaveBlock1Ptr->registeredItem = ITEM_MACH_BIKE;
+ break;
+ }
+}
+
+u16 BagGetItemIdByPocketPosition(u8 pocketId, u16 pocketPos)
+{
+ return gBagPockets[pocketId - 1].itemSlots[pocketPos].itemId;
+}
+
+u16 BagGetQuantityByPocketPosition(u8 pocketId, u16 pocketPos)
+{
+ return GetBagItemQuantity(&gBagPockets[pocketId - 1].itemSlots[pocketPos].quantity);
+}
+
+static void SwapItemSlots(struct ItemSlot *a, struct ItemSlot *b)
+{
+ struct ItemSlot temp = *a;
+ *a = *b;
+ *b = temp;
+}
+
+void CompactItemsInBagPocket(struct BagPocket *bagPocket)
+{
+ u16 i, j;
+
+ for (i = 0; i < bagPocket->capacity - 1; i++)
+ {
+ for (j = i + 1; j < bagPocket->capacity; j++)
+ {
+ if (GetBagItemQuantity(&bagPocket->itemSlots[i].quantity) == 0)
+ SwapItemSlots(&bagPocket->itemSlots[i], &bagPocket->itemSlots[j]);
+ }
+ }
+}
+
+void SortBerriesOrTMHMs(struct BagPocket *bagPocket)
+{
+ u16 i, j;
+
+ for (i = 0; i < bagPocket->capacity - 1; i++)
+ {
+ for (j = i + 1; j < bagPocket->capacity; j++)
+ {
+ if (GetBagItemQuantity(&bagPocket->itemSlots[i].quantity) != 0)
+ {
+ if (GetBagItemQuantity(&bagPocket->itemSlots[j].quantity) == 0)
+ continue;
+ if (bagPocket->itemSlots[i].itemId <= bagPocket->itemSlots[j].itemId)
+ continue;
+ }
+ SwapItemSlots(&bagPocket->itemSlots[i], &bagPocket->itemSlots[j]);
+ }
+ }
+}
+
+void MoveItemSlotInList(struct ItemSlot* itemSlots_, u32 from, u32 to_)
+{
+ // dumb assignments needed to match
+ struct ItemSlot *itemSlots = itemSlots_;
+ u32 to = 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;
+ }
+}
+
+void ClearBag(void)
+{
+ u16 i;
+
+ for (i = 0; i < POCKETS_COUNT; i++)
+ {
+ ClearItemSlots(gBagPockets[i].itemSlots, gBagPockets[i].capacity);
+ }
+}
+
+u16 CountTotalItemQuantityInBag(u16 itemId)
+{
+ u16 i;
+ u16 ownedCount = 0;
+ struct BagPocket *bagPocket = &gBagPockets[ItemId_GetPocket(itemId) - 1];
+
+ for (i = 0; i < bagPocket->capacity; i++)
+ {
+ if (bagPocket->itemSlots[i].itemId == itemId)
+ ownedCount += GetBagItemQuantity(&bagPocket->itemSlots[i].quantity);
+ }
+
+ return ownedCount;
+}
+
+static bool8 CheckPyramidBagHasItem(u16 itemId, u16 count)
+{
+ u8 i;
+ u16 *items = gSaveBlock2Ptr->pyramidBag.itemId[gSaveBlock2Ptr->frontierChosenLvl];
+ u8 *quantities = gSaveBlock2Ptr->pyramidBag.quantity[gSaveBlock2Ptr->frontierChosenLvl];
+
+ for (i = 0; i < PYRAMID_BAG_ITEMS_COUNT; i++)
+ {
+ if (items[i] == itemId)
+ {
+ if (quantities[i] >= count)
+ return TRUE;
+
+ count -= quantities[i];
+ if (count == 0)
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static bool8 CheckPyramidBagHasSpace(u16 itemId, u16 count)
+{
+ u8 i;
+ u16 *items = gSaveBlock2Ptr->pyramidBag.itemId[gSaveBlock2Ptr->frontierChosenLvl];
+ u8 *quantities = gSaveBlock2Ptr->pyramidBag.quantity[gSaveBlock2Ptr->frontierChosenLvl];
+
+ for (i = 0; i < PYRAMID_BAG_ITEMS_COUNT; i++)
+ {
+ if (items[i] == itemId || items[i] == ITEM_NONE)
+ {
+ if (quantities[i] + count <= 99)
+ return TRUE;
+
+ count = (quantities[i] + count) - 99;
+ if (count == 0)
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+bool8 AddPyramidBagItem(u16 itemId, u16 count)
+{
+ u16 i;
+
+ u16 *items = gSaveBlock2Ptr->pyramidBag.itemId[gSaveBlock2Ptr->frontierChosenLvl];
+ u8 *quantities = gSaveBlock2Ptr->pyramidBag.quantity[gSaveBlock2Ptr->frontierChosenLvl];
+
+ u16 *newItems = Alloc(PYRAMID_BAG_ITEMS_COUNT * sizeof(u16));
+ u8 *newQuantities = Alloc(PYRAMID_BAG_ITEMS_COUNT * sizeof(u8));
+
+ memcpy(newItems, items, PYRAMID_BAG_ITEMS_COUNT * sizeof(u16));
+ memcpy(newQuantities, quantities, PYRAMID_BAG_ITEMS_COUNT * sizeof(u8));
+
+ for (i = 0; i < PYRAMID_BAG_ITEMS_COUNT; i++)
+ {
+ if (newItems[i] == itemId && newQuantities[i] < 99)
+ {
+ newQuantities[i] += count;
+ if (newQuantities[i] > 99)
+ {
+ count = newQuantities[i] - 99;
+ newQuantities[i] = 99;
+ }
+ else
+ {
+ count = 0;
+ }
+
+ if (count == 0)
+ break;
+ }
+ }
+
+ if (count > 0)
+ {
+ for (i = 0; i < PYRAMID_BAG_ITEMS_COUNT; i++)
+ {
+ if (newItems[i] == ITEM_NONE)
+ {
+ newItems[i] = itemId;
+ newQuantities[i] = count;
+ if (newQuantities[i] > 99)
+ {
+ count = newQuantities[i] - 99;
+ newQuantities[i] = 99;
+ }
+ else
+ {
+ count = 0;
+ }
+
+ if (count == 0)
+ break;
+ }
+ }
+ }
+
+ if (count == 0)
+ {
+ memcpy(items, newItems, PYRAMID_BAG_ITEMS_COUNT * sizeof(u16));
+ memcpy(quantities, newQuantities, PYRAMID_BAG_ITEMS_COUNT * sizeof(u8));
+ Free(newItems);
+ Free(newQuantities);
+ return TRUE;
+ }
+ else
+ {
+ Free(newItems);
+ Free(newQuantities);
+ return FALSE;
+ }
+}
+
+bool8 RemovePyramidBagItem(u16 itemId, u16 count)
+{
+ u16 i;
+
+ u16 *items = gSaveBlock2Ptr->pyramidBag.itemId[gSaveBlock2Ptr->frontierChosenLvl];
+ u8 *quantities = gSaveBlock2Ptr->pyramidBag.quantity[gSaveBlock2Ptr->frontierChosenLvl];
+
+ i = gUnknown_0203CF30[3] + gUnknown_0203CF30[4];
+ if (items[i] == itemId && quantities[i] >= count)
+ {
+ quantities[i] -= count;
+ if (quantities[i] == 0)
+ items[i] = ITEM_NONE;
+ return TRUE;
+ }
+ else
+ {
+ u16 *newItems = Alloc(PYRAMID_BAG_ITEMS_COUNT * sizeof(u16));
+ u8 *newQuantities = Alloc(PYRAMID_BAG_ITEMS_COUNT * sizeof(u8));
+
+ memcpy(newItems, items, PYRAMID_BAG_ITEMS_COUNT * sizeof(u16));
+ memcpy(newQuantities, quantities, PYRAMID_BAG_ITEMS_COUNT * sizeof(u8));
+
+ for (i = 0; i < PYRAMID_BAG_ITEMS_COUNT; i++)
+ {
+ if (newItems[i] == itemId)
+ {
+ if (newQuantities[i] >= count)
+ {
+ newQuantities[i] -= count;
+ count = 0;
+ if (newQuantities[i] == 0)
+ newItems[i] = ITEM_NONE;
+ }
+ else
+ {
+ count -= newQuantities[i];
+ newQuantities[i] = 0;
+ newItems[i] = ITEM_NONE;
+ }
+
+ if (count == 0)
+ break;
+ }
+ }
+
+ if (count == 0)
+ {
+ memcpy(items, newItems, PYRAMID_BAG_ITEMS_COUNT * sizeof(u16));
+ memcpy(quantities, newQuantities, PYRAMID_BAG_ITEMS_COUNT * sizeof(u8));
+ Free(newItems);
+ Free(newQuantities);
+ return TRUE;
+ }
+ else
+ {
+ Free(newItems);
+ Free(newQuantities);
+ return FALSE;
+ }
+ }
+}
+
+static u16 SanitizeItemId(u16 itemId)
+{
+ if (itemId >= ITEM_LAST_ID + 1)
+ return ITEM_NONE;
+ else
+ return itemId;
+}
+
+const u8 *ItemId_GetName(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].name;
+}
+
+u16 ItemId_GetId(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].itemId;
+}
+
+u16 ItemId_GetPrice(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].price;
+}
+
+u8 ItemId_GetHoldEffect(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].holdEffect;
+}
+
+u8 ItemId_GetHoldEffectParam(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].holdEffectParam;
+}
+
+const u8 *ItemId_GetDescription(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].description;
+}
+
+u8 ItemId_GetImportance(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].importance;
+}
+
+// unused
+u8 ItemId_GetUnknownValue(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].unk19;
+}
+
+u8 ItemId_GetPocket(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].pocket;
+}
+
+u8 ItemId_GetType(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].type;
+}
+
+ItemUseFunc ItemId_GetFieldFunc(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].fieldUseFunc;
+}
+
+u8 ItemId_GetBattleUsage(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].battleUsage;
+}
+
+ItemUseFunc ItemId_GetBattleFunc(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].battleUseFunc;
+}
+
+u8 ItemId_GetSecondaryId(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].secondaryId;
+}