2017-09-03 00:47:51 +02:00
# include "global.h"
# include "item.h"
2018-01-19 19:49:08 +01:00
# include "berry.h"
2017-09-03 13:33:13 +02:00
# include "string_util.h"
# include "text.h"
# include "event_data.h"
2019-09-09 03:07:54 +02:00
# include "malloc.h"
2018-04-29 13:36:26 +02:00
# include "secret_base.h"
# include "item_menu.h"
2018-04-29 14:21:59 +02:00
# include "strings.h"
# include "load_save.h"
2018-12-03 13:37:32 +01:00
# include "item_use.h"
2018-11-18 17:52:22 +01:00
# include "battle_pyramid.h"
2018-08-30 20:10:57 +02:00
# include "battle_pyramid_bag.h"
2018-12-03 13:37:32 +01:00
# include "constants/items.h"
# include "constants/hold_effects.h"
2020-01-08 10:26:26 +01:00
# include "constants/tv.h"
2017-09-03 00:47:51 +02:00
2018-04-29 14:21:59 +02:00
extern u16 gUnknown_0203CF30 [ ] ;
2017-09-03 00:47:51 +02:00
2018-04-29 13:36:26 +02:00
// this file's functions
2019-07-19 02:46:00 +02:00
# if !defined(NONMATCHING) && MODERN
# define static
# endif
2018-04-29 13:36:26 +02:00
static bool8 CheckPyramidBagHasItem ( u16 itemId , u16 count ) ;
static bool8 CheckPyramidBagHasSpace ( u16 itemId , u16 count ) ;
2018-04-29 14:21:59 +02:00
// EWRAM variables
EWRAM_DATA struct BagPocket gBagPockets [ POCKETS_COUNT ] = { 0 } ;
2017-09-03 00:47:51 +02:00
2018-12-03 13:37:32 +01:00
// rodata
# include "data/text/item_descriptions.h"
# include "data/items.h"
2018-04-29 14:21:59 +02:00
// code
static u16 GetBagItemQuantity ( u16 * quantity )
2017-09-03 00:47:51 +02:00
{
return gSaveBlock2Ptr - > encryptionKey ^ * quantity ;
}
2018-04-29 14:21:59 +02:00
static void SetBagItemQuantity ( u16 * quantity , u16 newValue )
2017-09-03 00:47:51 +02:00
{
* quantity = newValue ^ gSaveBlock2Ptr - > encryptionKey ;
}
2018-04-29 14:21:59 +02:00
static u16 GetPCItemQuantity ( u16 * quantity )
2017-09-03 00:47:51 +02:00
{
2018-04-29 13:36:26 +02:00
return * quantity ;
2017-09-03 00:47:51 +02:00
}
2018-04-29 14:21:59 +02:00
static void SetPCItemQuantity ( u16 * quantity , u16 newValue )
2017-09-03 00:47:51 +02:00
{
2018-04-29 13:36:26 +02:00
* quantity = newValue ;
2017-09-03 00:47:51 +02:00
}
2017-11-27 21:20:10 +01:00
void ApplyNewEncryptionKeyToBagItems ( u32 newKey )
2017-09-03 00:47:51 +02:00
{
u32 pocket , item ;
2018-04-29 13:36:26 +02:00
for ( pocket = 0 ; pocket < POCKETS_COUNT ; pocket + + )
2017-09-03 00:47:51 +02:00
{
2017-09-03 13:33:13 +02:00
for ( item = 0 ; item < gBagPockets [ pocket ] . capacity ; item + + )
2017-11-27 21:20:10 +01:00
ApplyNewEncryptionKeyToHword ( & ( gBagPockets [ pocket ] . itemSlots [ item ] . quantity ) , newKey ) ;
2017-09-03 00:47:51 +02:00
}
}
2017-11-27 21:20:10 +01:00
void ApplyNewEncryptionKeyToBagItems_ ( u32 newKey ) // really GF?
2017-09-03 00:47:51 +02:00
{
2017-11-27 21:20:10 +01:00
ApplyNewEncryptionKeyToBagItems ( newKey ) ;
2017-09-03 00:47:51 +02:00
}
void SetBagItemsPointers ( void )
{
2017-09-03 13:33:13 +02:00
gBagPockets [ ITEMS_POCKET ] . itemSlots = gSaveBlock1Ptr - > bagPocket_Items ;
2018-04-29 13:36:26 +02:00
gBagPockets [ ITEMS_POCKET ] . capacity = BAG_ITEMS_COUNT ;
2017-09-03 00:47:51 +02:00
2017-09-03 13:33:13 +02:00
gBagPockets [ KEYITEMS_POCKET ] . itemSlots = gSaveBlock1Ptr - > bagPocket_KeyItems ;
2018-04-29 13:36:26 +02:00
gBagPockets [ KEYITEMS_POCKET ] . capacity = BAG_KEYITEMS_COUNT ;
2017-09-03 00:47:51 +02:00
2017-09-03 13:33:13 +02:00
gBagPockets [ BALLS_POCKET ] . itemSlots = gSaveBlock1Ptr - > bagPocket_PokeBalls ;
2018-04-29 13:36:26 +02:00
gBagPockets [ BALLS_POCKET ] . capacity = BAG_POKEBALLS_COUNT ;
2017-09-03 13:33:13 +02:00
gBagPockets [ TMHM_POCKET ] . itemSlots = gSaveBlock1Ptr - > bagPocket_TMHM ;
2018-04-29 13:36:26 +02:00
gBagPockets [ TMHM_POCKET ] . capacity = BAG_TMHM_COUNT ;
2017-09-03 13:33:13 +02:00
gBagPockets [ BERRIES_POCKET ] . itemSlots = gSaveBlock1Ptr - > bagPocket_Berries ;
2018-04-29 13:36:26 +02:00
gBagPockets [ BERRIES_POCKET ] . capacity = BAG_BERRIES_COUNT ;
2017-09-03 13:33:13 +02:00
}
2018-04-29 14:21:59 +02:00
void CopyItemName ( u16 itemId , u8 * dst )
2017-09-03 13:33:13 +02:00
{
2018-04-29 14:21:59 +02:00
StringCopy ( dst , ItemId_GetName ( itemId ) ) ;
2017-09-03 13:33:13 +02:00
}
2017-09-03 00:47:51 +02:00
2018-04-29 14:21:59 +02:00
void CopyItemNameHandlePlural ( u16 itemId , u8 * dst , u32 quantity )
2017-09-03 13:33:13 +02:00
{
2017-09-13 11:16:26 +02:00
if ( itemId = = ITEM_POKE_BALL )
2017-09-03 13:33:13 +02:00
{
if ( quantity < 2 )
2018-04-29 14:21:59 +02:00
StringCopy ( dst , ItemId_GetName ( ITEM_POKE_BALL ) ) ;
2017-09-03 13:33:13 +02:00
else
2018-04-29 14:21:59 +02:00
StringCopy ( dst , gText_PokeBalls ) ;
2017-09-03 13:33:13 +02:00
}
else
{
2018-01-19 19:49:08 +01:00
if ( itemId > = ITEM_CHERI_BERRY & & itemId < = ITEM_ENIGMA_BERRY )
2018-04-29 14:21:59 +02:00
GetBerryCountString ( dst , gBerries [ itemId - ITEM_CHERI_BERRY ] . name , quantity ) ;
2017-09-03 13:33:13 +02:00
else
2018-04-29 14:21:59 +02:00
StringCopy ( dst , ItemId_GetName ( itemId ) ) ;
2017-09-03 13:33:13 +02:00
}
}
2017-09-03 00:47:51 +02:00
2018-04-29 13:36:26 +02:00
void GetBerryCountString ( u8 * dst , const u8 * berryName , u32 quantity )
2017-09-03 13:33:13 +02:00
{
2018-04-29 13:36:26 +02:00
const u8 * berryString ;
u8 * txtPtr ;
2017-09-03 13:33:13 +02:00
if ( quantity < 2 )
2017-09-20 21:38:05 +02:00
berryString = gText_Berry ;
2017-09-03 13:33:13 +02:00
else
2017-09-20 21:38:05 +02:00
berryString = gText_Berries ;
2018-04-29 13:36:26 +02:00
2017-09-03 13:33:13 +02:00
txtPtr = StringCopy ( dst , berryName ) ;
* txtPtr = CHAR_SPACE ;
StringCopy ( txtPtr + 1 , berryString ) ;
2017-09-03 00:47:51 +02:00
}
2017-09-03 13:33:13 +02:00
bool8 IsBagPocketNonEmpty ( u8 pocket )
{
u8 i ;
for ( i = 0 ; i < gBagPockets [ pocket - 1 ] . capacity ; i + + )
{
if ( gBagPockets [ pocket - 1 ] . itemSlots [ i ] . itemId ! = 0 )
return TRUE ;
}
return FALSE ;
}
bool8 CheckBagHasItem ( u16 itemId , u16 count )
{
u8 i ;
u8 pocket ;
if ( ItemId_GetPocket ( itemId ) = = 0 )
return FALSE ;
2019-10-18 01:22:03 +02:00
if ( InBattlePyramid ( ) | | FlagGet ( FLAG_STORING_ITEMS_IN_PYRAMID_BAG ) = = TRUE )
2017-09-03 13:33:13 +02:00
return CheckPyramidBagHasItem ( itemId , count ) ;
pocket = ItemId_GetPocket ( itemId ) - 1 ;
2018-04-29 13:36:26 +02:00
// Check for item slots that contain the item
2017-09-03 13:33:13 +02:00
for ( i = 0 ; i < gBagPockets [ pocket ] . capacity ; i + + )
{
if ( gBagPockets [ pocket ] . itemSlots [ i ] . itemId = = itemId )
{
u16 quantity ;
2018-04-29 14:21:59 +02:00
// Does this item slot contain enough of the item?
2017-09-03 13:33:13 +02:00
quantity = GetBagItemQuantity ( & gBagPockets [ pocket ] . itemSlots [ i ] . quantity ) ;
if ( quantity > = count )
return TRUE ;
count - = quantity ;
2018-04-29 14:21:59 +02:00
// Does this item slot and all previous slots contain enough of the item?
2017-09-03 13:33:13 +02:00
if ( count = = 0 )
return TRUE ;
}
}
return FALSE ;
}
bool8 HasAtLeastOneBerry ( void )
{
u16 i ;
2018-04-29 13:36:26 +02:00
for ( i = FIRST_BERRY_INDEX ; i < ITEM_BRIGHT_POWDER ; i + + )
2017-09-03 13:33:13 +02:00
{
if ( CheckBagHasItem ( i , 1 ) = = TRUE )
{
2018-04-29 13:36:26 +02:00
gSpecialVar_Result = TRUE ;
2017-09-03 13:33:13 +02:00
return TRUE ;
}
}
2018-04-29 13:36:26 +02:00
gSpecialVar_Result = FALSE ;
2017-09-03 13:33:13 +02:00
return FALSE ;
}
bool8 CheckBagHasSpace ( u16 itemId , u16 count )
{
2020-09-05 18:28:02 +02:00
u8 i , pocket ;
u16 slotCapacity , ownedCount ;
2017-09-03 13:33:13 +02:00
2018-04-29 13:36:26 +02:00
if ( ItemId_GetPocket ( itemId ) = = POCKET_NONE )
2017-09-03 13:33:13 +02:00
return FALSE ;
2018-04-29 13:36:26 +02:00
2020-09-05 18:28:02 +02:00
if ( InBattlePyramid ( ) | | ( FlagGet ( FLAG_STORING_ITEMS_IN_PYRAMID_BAG ) = = TRUE ) )
2018-04-29 13:36:26 +02:00
{
2017-09-03 13:33:13 +02:00
return CheckPyramidBagHasSpace ( itemId , count ) ;
2018-04-29 13:36:26 +02:00
}
2017-09-03 13:33:13 +02:00
2020-09-05 18:28:02 +02:00
pocket = ItemId_GetPocket ( itemId ) - 1 ;
if ( pocket ! = BERRIES_POCKET )
slotCapacity = MAX_BAG_ITEM_CAPACITY ;
else
slotCapacity = MAX_BERRY_CAPACITY ;
2018-04-29 13:36:26 +02:00
2020-09-05 18:28:02 +02:00
// 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 )
2018-04-29 13:36:26 +02:00
{
2020-09-05 18:28:02 +02:00
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 )
break ; //Should just be "return TRUE", since setting count to 0 means all the remaining checks until return will be false anyway, but that doesn't match
2018-04-29 13:36:26 +02:00
}
2020-09-05 18:28:02 +02:00
}
2018-04-29 13:36:26 +02:00
2020-09-05 18:28:02 +02:00
// Check space in empty item slots
if ( count > 0 ) //if (count !=0) also works here; both match
{
for ( i = 0 ; i < gBagPockets [ pocket ] . capacity ; i + + )
2018-04-29 13:36:26 +02:00
{
2020-09-05 18:28:02 +02:00
if ( gBagPockets [ pocket ] . itemSlots [ i ] . itemId = = 0 )
2018-04-29 13:36:26 +02:00
{
2020-09-05 18:28:02 +02:00
if ( count > slotCapacity )
2018-04-29 13:36:26 +02:00
{
if ( pocket = = TMHM_POCKET | | pocket = = BERRIES_POCKET )
return FALSE ;
count - = slotCapacity ;
}
2020-09-05 18:28:02 +02:00
else
{
count = 0 ; //Should just be "return TRUE", since setting count to 0 means all the remaining checks until return will be false anyway, but that doesn't match
break ;
}
2018-04-29 13:36:26 +02:00
}
}
2020-09-05 18:28:02 +02:00
if ( count > 0 ) //if (count !=0) also works here; both match
return FALSE ; // No more item slots. The bag is full
2018-04-29 13:36:26 +02:00
}
2020-09-05 18:28:02 +02:00
return TRUE ;
2018-04-29 13:36:26 +02:00
}
bool8 AddBagItem ( u16 itemId , u16 count )
{
u8 i ;
if ( ItemId_GetPocket ( itemId ) = = POCKET_NONE )
return FALSE ;
// check Battle Pyramid Bag
2019-10-18 01:22:03 +02:00
if ( InBattlePyramid ( ) | | FlagGet ( FLAG_STORING_ITEMS_IN_PYRAMID_BAG ) = = TRUE )
2017-09-03 13:33:13 +02:00
{
2018-04-29 13:36:26 +02:00
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 )
2020-01-26 10:02:15 +01:00
slotCapacity = MAX_BAG_ITEM_CAPACITY ;
2018-04-29 13:36:26 +02:00
else
2020-01-26 10:02:15 +01:00
slotCapacity = MAX_BERRY_CAPACITY ;
2018-04-29 13:36:26 +02:00
for ( i = 0 ; i < itemPocket - > capacity ; i + + )
2017-09-03 13:33:13 +02:00
{
2018-04-29 13:36:26 +02:00
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 ) ;
2017-09-03 13:33:13 +02:00
return FALSE ;
2018-04-29 13:36:26 +02:00
}
}
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
2019-10-18 01:22:03 +02:00
if ( InBattlePyramid ( ) | | FlagGet ( FLAG_STORING_ITEMS_IN_PYRAMID_BAG ) = = TRUE )
2018-04-29 13:36:26 +02:00
{
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
2019-04-05 23:11:24 +02:00
if ( CurMapIsSecretBase ( ) = = TRUE )
2018-04-29 13:36:26 +02:00
{
2020-01-08 10:26:26 +01:00
VarSet ( VAR_SECRET_BASE_LOW_TV_FLAGS , VarGet ( VAR_SECRET_BASE_LOW_TV_FLAGS ) | SECRET_BASE_USED_BAG ) ;
2019-02-28 05:54:51 +01:00
VarSet ( VAR_SECRET_BASE_LAST_ITEM_USED , itemId ) ;
2018-04-29 13:36:26 +02:00
}
2018-12-15 19:08:13 +01:00
var = GetItemListPosition ( pocket ) ;
2018-04-29 13:36:26 +02:00
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 ;
2017-09-03 13:33:13 +02:00
if ( count = = 0 )
return TRUE ;
}
2018-04-29 13:36:26 +02:00
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 ;
2017-09-03 13:33:13 +02:00
}
2018-04-29 13:36:26 +02:00
}
2017-09-03 13:33:13 +02:00
2018-04-29 13:36:26 +02:00
u8 GetPocketByItemId ( u16 itemId )
{
return ItemId_GetPocket ( itemId ) ;
}
void ClearItemSlots ( struct ItemSlot * itemSlots , u8 itemCount )
{
u16 i ;
for ( i = 0 ; i < itemCount ; i + + )
2017-09-03 13:33:13 +02:00
{
2018-04-29 13:36:26 +02:00
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 )
2017-09-03 13:33:13 +02:00
{
2018-04-29 13:36:26 +02:00
ownedCount = GetPCItemQuantity ( & newItems [ i ] . quantity ) ;
2020-01-26 10:02:15 +01:00
if ( ownedCount + count < = MAX_PC_ITEM_CAPACITY )
2017-09-03 13:33:13 +02:00
{
2018-04-29 13:36:26 +02:00
SetPCItemQuantity ( & newItems [ i ] . quantity , ownedCount + count ) ;
memcpy ( gSaveBlock1Ptr - > pcItems , newItems , sizeof ( gSaveBlock1Ptr - > pcItems ) ) ;
Free ( newItems ) ;
return TRUE ;
}
2020-01-26 10:02:15 +01:00
count + = ownedCount - MAX_PC_ITEM_CAPACITY ;
SetPCItemQuantity ( & newItems [ i ] . quantity , MAX_PC_ITEM_CAPACITY ) ;
2018-04-29 13:36:26 +02:00
if ( count = = 0 )
{
memcpy ( gSaveBlock1Ptr - > pcItems , newItems , sizeof ( gSaveBlock1Ptr - > pcItems ) ) ;
Free ( newItems ) ;
return TRUE ;
2017-09-03 13:33:13 +02:00
}
}
}
2018-04-29 13:36:26 +02:00
// 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 ) ;
2017-09-03 13:33:13 +02:00
return TRUE ;
2018-04-29 13:36:26 +02:00
}
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 )
{
2018-08-30 15:01:07 +02:00
struct ItemSlot temp ;
2018-08-30 21:28:03 +02:00
SWAP ( * a , * b , temp ) ;
2018-04-29 13:36:26 +02:00
}
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 ;
2018-08-25 19:59:47 +02:00
u16 * items = gSaveBlock2Ptr - > frontier . pyramidBag . itemId [ gSaveBlock2Ptr - > frontier . lvlMode ] ;
u8 * quantities = gSaveBlock2Ptr - > frontier . pyramidBag . quantity [ gSaveBlock2Ptr - > frontier . lvlMode ] ;
2018-04-29 13:36:26 +02:00
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 ;
2018-08-25 19:59:47 +02:00
u16 * items = gSaveBlock2Ptr - > frontier . pyramidBag . itemId [ gSaveBlock2Ptr - > frontier . lvlMode ] ;
u8 * quantities = gSaveBlock2Ptr - > frontier . pyramidBag . quantity [ gSaveBlock2Ptr - > frontier . lvlMode ] ;
2018-04-29 13:36:26 +02:00
for ( i = 0 ; i < PYRAMID_BAG_ITEMS_COUNT ; i + + )
{
if ( items [ i ] = = itemId | | items [ i ] = = ITEM_NONE )
{
2020-01-26 10:02:15 +01:00
if ( quantities [ i ] + count < = MAX_BAG_ITEM_CAPACITY )
2018-04-29 13:36:26 +02:00
return TRUE ;
2020-01-26 10:02:15 +01:00
count = ( quantities [ i ] + count ) - MAX_BAG_ITEM_CAPACITY ;
2018-04-29 13:36:26 +02:00
if ( count = = 0 )
return TRUE ;
}
}
return FALSE ;
}
2018-04-29 14:21:59 +02:00
bool8 AddPyramidBagItem ( u16 itemId , u16 count )
2018-04-29 13:36:26 +02:00
{
u16 i ;
2018-08-25 19:59:47 +02:00
u16 * items = gSaveBlock2Ptr - > frontier . pyramidBag . itemId [ gSaveBlock2Ptr - > frontier . lvlMode ] ;
u8 * quantities = gSaveBlock2Ptr - > frontier . pyramidBag . quantity [ gSaveBlock2Ptr - > frontier . lvlMode ] ;
2018-04-29 13:36:26 +02:00
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 + + )
{
2020-01-26 10:02:15 +01:00
if ( newItems [ i ] = = itemId & & newQuantities [ i ] < MAX_BAG_ITEM_CAPACITY )
2018-04-29 13:36:26 +02:00
{
newQuantities [ i ] + = count ;
2020-01-26 10:02:15 +01:00
if ( newQuantities [ i ] > MAX_BAG_ITEM_CAPACITY )
2018-04-29 13:36:26 +02:00
{
2020-01-26 10:02:15 +01:00
count = newQuantities [ i ] - MAX_BAG_ITEM_CAPACITY ;
newQuantities [ i ] = MAX_BAG_ITEM_CAPACITY ;
2018-04-29 13:36:26 +02:00
}
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 ;
2020-01-26 10:02:15 +01:00
if ( newQuantities [ i ] > MAX_BAG_ITEM_CAPACITY )
2018-04-29 13:36:26 +02:00
{
2020-01-26 10:02:15 +01:00
count = newQuantities [ i ] - MAX_BAG_ITEM_CAPACITY ;
newQuantities [ i ] = MAX_BAG_ITEM_CAPACITY ;
2018-04-29 13:36:26 +02:00
}
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 ;
}
}
2018-04-29 14:21:59 +02:00
bool8 RemovePyramidBagItem ( u16 itemId , u16 count )
2018-04-29 13:36:26 +02:00
{
u16 i ;
2018-08-25 19:59:47 +02:00
u16 * items = gSaveBlock2Ptr - > frontier . pyramidBag . itemId [ gSaveBlock2Ptr - > frontier . lvlMode ] ;
u8 * quantities = gSaveBlock2Ptr - > frontier . pyramidBag . quantity [ gSaveBlock2Ptr - > frontier . lvlMode ] ;
2018-04-29 13:36:26 +02:00
2018-08-30 20:10:57 +02:00
i = gPyramidBagCursorData . cursorPosition + gPyramidBagCursorData . scrollPosition ;
2018-04-29 13:36:26 +02:00
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 )
{
2018-07-07 14:24:19 +02:00
if ( itemId > = ITEMS_COUNT )
2018-04-29 13:36:26 +02:00
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 ;
}