5 Item Automatically Goes to PC if Bag is Full
Manectric-Rang edited this page 2024-01-28 19:22:31 +01:00

By devolov

Goal: Make items found in the overworld or by an NPC go to the PC if the bag is full. This will not happen if the item is a key item or you're in the battle pyramid.

----------------------------- asm/macros/event.inc -----------------------------
index 76dc9a839..ac3bd3e62 100644
@@ -1734,8 +1734,16 @@
	.macro bufferitemnameplural stringVarId:req, item:req, quantity:req
	.byte 0xe2
	stringvar \stringVarId
	.2byte \item
	.2byte \quantity
	.endm
 
+	@ Checks if the player has enough space in their PC to hold quantity more of the specified item. Sets VAR_RESULT to
+	@ TRUE if there is room, or FALSE is there is no room.
+	.macro checkpcspace itemId:req, quantity=1
+	.byte 0xe3
+	.2byte \itemId
+	.2byte \quantity
+	.endm
+
 @ Supplementary
 
 	.macro goto_if_unset flag:req, dest:req
 	checkflag \flag
-------------------------- data/script_cmd_table.inc --------------------------
index 7578b6832..41e233e71 100644
@@ -227,7 +227,8 @@ gScriptCmdTable::
 	.4byte ScrCmd_warpwhitefade             @ 0xe0
 	.4byte ScrCmd_buffercontestname         @ 0xe1
 	.4byte ScrCmd_bufferitemnameplural      @ 0xe2
+	.4byte ScrCmd_checkpcspace              @ 0xe3
 
 gScriptCmdTableEnd::
 	.4byte ScrCmd_nop
------------------------- data/scripts/obtain_item.inc -------------------------
index e982858e7..8ef9833fa 100644
@@ -1,18 +1,30 @@
 .set ITEMID, VAR_0x8000
 .set AMOUNT, VAR_0x8001
 
 Std_ObtainItem::
+	copyvar VAR_0x8004, ITEMID
+	copyvar VAR_0x8005, AMOUNT
 	additem ITEMID, AMOUNT
 	copyvar VAR_0x8007, VAR_RESULT
+	call_if_eq VAR_0x8007, FALSE, EventScript_TryAddItemToPCObtain
 	call EventScript_ObtainItemMessage
 	return
 
+EventScript_TryAddItemToPCObtain::
+	checkitemtype VAR_0x8004 @ Don't add if it's a key item
+	goto_if_eq VAR_RESULT, POCKET_KEY_ITEMS, EventScript_TryAddItemToPCObtainContinue
+	addpcitem VAR_0x8004, VAR_0x8005
+	goto_if_eq VAR_RESULT, FALSE, EventScript_TryAddItemToPCObtainContinue
+	setvar VAR_0x8007, 2  @ (0= full, 1= in pocket, 2=in PC) 
+EventScript_TryAddItemToPCObtainContinue::
+	return
+
 EventScript_ObtainItemMessage::
 	bufferitemnameplural STR_VAR_2, ITEMID, AMOUNT
 	checkitemtype ITEMID
 	call EventScript_BufferPocketNameAndTryFanfare
-	call_if_eq VAR_0x8007, TRUE, EventScript_ObtainedItem
+	call_if_ne VAR_0x8007, FALSE, EventScript_ObtainedItem
 	call_if_eq VAR_0x8007, FALSE, EventScript_NoRoomForItem
 	return
 
 EventScript_BufferPocketNameAndTryFanfare::
@@ -25,35 +37,35 @@ EventScript_BufferPocketNameAndTryFanfare::
 	end
 
 EventScript_BufferItemsPocket::
 	bufferstdstring STR_VAR_3, STDSTRING_ITEMS
-	call_if_eq VAR_0x8007, TRUE, EventScript_PlayFanfareObtainedItem
+	call_if_ne VAR_0x8007, FALSE, EventScript_PlayFanfareObtainedItem
 	return
 
 EventScript_BufferKeyItemsPocket::
 	bufferstdstring STR_VAR_3, STDSTRING_KEYITEMS
-	call_if_eq VAR_0x8007, TRUE, EventScript_PlayFanfareObtainedItem
+	call_if_ne VAR_0x8007, FALSE, EventScript_PlayFanfareObtainedItem
 	return
 
 EventScript_BufferPokeballsPocket::
 	bufferstdstring STR_VAR_3, STDSTRING_POKEBALLS
-	call_if_eq VAR_0x8007, TRUE, EventScript_PlayFanfareObtainedItem
+	call_if_ne VAR_0x8007, FALSE, EventScript_PlayFanfareObtainedItem
 	return
 
 EventScript_BufferTMHMsPocket::
 	bufferstdstring STR_VAR_3, STDSTRING_TMHMS
-	call_if_eq VAR_0x8007, TRUE, EventScript_PlayFanfareObtainedTMHM
+	call_if_ne VAR_0x8007, FALSE, EventScript_PlayFanfareObtainedTMHM
 	return
 
 EventScript_BufferBerriesPocket::
 	bufferstdstring STR_VAR_3, STDSTRING_BERRIES
-	call_if_eq VAR_0x8007, TRUE, EventScript_PlayFanfareObtainedItem
+	call_if_ne VAR_0x8007, FALSE, EventScript_PlayFanfareObtainedItem
 	return
 
 EventScript_ObtainedItem::
 	message gText_ObtainedTheItem
 	waitfanfare
-	msgbox gText_PutItemInPocket, MSGBOX_DEFAULT
+	call EventScript_PutItemMsg
 	setvar VAR_RESULT, TRUE
 	return
 
 EventScript_NoRoomForItem::
@@ -99,19 +111,37 @@ Std_FindItem::
 	copyvar VAR_0x8004, ITEMID
 	copyvar VAR_0x8005, AMOUNT
 	checkitemspace ITEMID, AMOUNT
 	copyvar VAR_0x8007, VAR_RESULT
+	call_if_eq VAR_0x8007, FALSE, EventScript_CheckPCSpace
 	bufferitemnameplural STR_VAR_2, ITEMID, AMOUNT
 	checkitemtype ITEMID
 	call EventScript_BufferPocketNameAndTryFanfare
-	call_if_eq VAR_0x8007, TRUE, EventScript_PickUpItem
+	call_if_ne VAR_0x8007, FALSE, EventScript_PickUpItem
 	call_if_eq VAR_0x8007, FALSE, EventScript_NoRoomToPickUpItem
 	release
 	return
 
+EventScript_CheckPCSpace::
+	checkitemtype VAR_0x8004 @ Don't add if it's a key item
+	goto_if_eq VAR_RESULT, POCKET_KEY_ITEMS, EventScript_CheckPCSpaceContinue
+	pyramid_inchallenge
+	copyvar VAR_0x8004, ITEMID  @ pyramid_inchallenge modifies VAR_0x8004
+	goto_if_eq VAR_RESULT, TRUE, EventScript_CheckPCSpaceContinue
+	checkpcspace VAR_0x8004, VAR_0x8005
+	goto_if_eq VAR_RESULT, FALSE, EventScript_CheckPCSpaceContinue
+	setvar VAR_0x8007, 2  @ (0= full, 1= in pocket, 2=in PC) 
+EventScript_CheckPCSpaceContinue::
+	return
+
 EventScript_PickUpItem::
 	removeobject VAR_LAST_TALKED
+	goto_if_eq VAR_0x8007, 2, EventScript_PickUpItemPCAdd
 	additem VAR_0x8004, VAR_0x8005
+	goto EventScript_PickUpItemContinueAdd
+EventScript_PickUpItemPCAdd::
+	addpcitem VAR_0x8004, VAR_0x8005
+EventScript_PickUpItemContinueAdd::
 	specialvar VAR_RESULT, BufferTMHMMoveName
 	copyvar VAR_0x8008, VAR_RESULT
 	call_if_eq VAR_0x8008, TRUE, EventScript_FoundTMHM
 	call_if_eq VAR_0x8008, FALSE, EventScript_FoundItem
@@ -119,9 +149,9 @@ EventScript_PickUpItem::
 	waitmessage
 	bufferitemnameplural STR_VAR_2, VAR_0x8004, VAR_0x8005
 	pyramid_inchallenge
 	goto_if_eq VAR_RESULT, TRUE, EventScript_PutBattlePyramidItemInBag
-	msgbox gText_PutItemInPocket, MSGBOX_DEFAULT
+	call EventScript_PutItemMsg
 	return
 
 EventScript_PutBattlePyramidItemInBag::
 	msgbox gText_PlayerPutItemInBag, MSGBOX_DEFAULT
@@ -146,15 +176,25 @@ EventScript_HiddenItemScript::
 	lockall
 	waitse
 	additem VAR_0x8005
 	copyvar VAR_0x8007, VAR_RESULT
+	call_if_eq VAR_0x8007, FALSE, EventScript_TryAddItemToPCHidden
 	bufferitemnameplural STR_VAR_2, VAR_0x8005, 1
 	checkitemtype VAR_0x8005
 	call EventScript_BufferPocketNameAndTryFanfare
-	goto_if_eq VAR_0x8007, TRUE, EventScript_PickUpHiddenItem
+	goto_if_ne VAR_0x8007, FALSE, EventScript_PickUpHiddenItem
 	goto_if_eq VAR_0x8007, FALSE, EventScript_NoRoomForHiddenItem
 	end
 
+EventScript_TryAddItemToPCHidden::
+	checkitemtype VAR_0x8005 @ Don't add if it's a key item
+	goto_if_eq VAR_RESULT, POCKET_KEY_ITEMS, EventScript_TryAddHiddenItemToPCContinue
+	addpcitem VAR_0x8005
+	goto_if_eq VAR_RESULT, FALSE, EventScript_TryAddHiddenItemToPCContinue
+	setvar VAR_0x8007, 2  @ (0= full, 1= in pocket, 2=in PC) 
+EventScript_TryAddHiddenItemToPCContinue::
+	return
+
 EventScript_PickUpHiddenItem::
 	copyvar VAR_0x8008, VAR_0x8004
 	copyvar VAR_0x8004, VAR_0x8005
 	specialvar VAR_RESULT, BufferTMHMMoveName
@@ -177,16 +217,25 @@ EventScript_PutHiddenItemInPocket::
 	waitmessage
 	waitfanfare
 	bufferitemnameplural STR_VAR_2, VAR_0x8004, 1
 	copyvar VAR_0x8004, VAR_0x8008
-	msgbox gText_PutItemInPocket, MSGBOX_DEFAULT
+	call EventScript_PutItemMsg
 	special TryPutTreasureInvestigatorsOnAir
 	special SetHiddenItemFlag
 	releaseall
 	end
 
+EventScript_PutItemMsg::
+	goto_if_eq VAR_0x8007, 2, EventScript_PutItemPCMsg
+	msgbox gText_PutItemInPocket, MSGBOX_DEFAULT
+	goto EventScript_PutItemContinueMsg
+EventScript_PutItemPCMsg::
+	msgbox gText_PutItemInPC, MSGBOX_DEFAULT
+EventScript_PutItemContinueMsg::
+	return
+
 EventScript_NoRoomForHiddenItem::
 	msgbox gText_PlayerFoundOneItem, MSGBOX_DEFAULT
-	msgbox gText_TooBadBagIsFull, MSGBOX_DEFAULT
+	msgbox gText_TooBadBagAndPCAreFull, MSGBOX_DEFAULT
 	setvar VAR_RESULT, 0
 	releaseall
 	end
-------------------------- data/text/obtain_item.inc --------------------------
index 37788a8ff..0e5d85cda 100644
@@ -7,15 +7,23 @@ gText_TheBagIsFull::
 gText_PutItemInPocket::
 	.string "{PLAYER} put away the {STR_VAR_2}\n"
 	.string "in the {STR_VAR_3} POCKET.$"
 
+gText_PutItemInPC::
+	.string "{PLAYER} put away the {STR_VAR_2}\n"
+	.string "in the PC since bag is full.$"
+
 gText_PlayerFoundOneItem::
 	.string "{PLAYER} found one {STR_VAR_2}!$"
 
 gText_TooBadBagIsFull::
 	.string "Too bad!\n"
 	.string "The BAG is full…$"
 
+gText_TooBadBagAndPCAreFull::
+	.string "Too bad!\n"
+	.string "The BAG and PC are full…$"
+
 gText_PlayerPutItemInBag::
 	.string "{PLAYER} put away the {STR_VAR_2}\n"
 	.string "in the BAG.$"
 
-------------------------------- include/item.h --------------------------------
index 794137115..223c41630 100644
@@ -46,8 +46,9 @@ bool8 AddBagItem(u16 itemId, u16 count);
 bool8 RemoveBagItem(u16 itemId, u16 count);
 u8 GetPocketByItemId(u16 itemId);
 void ClearItemSlots(struct ItemSlot *itemSlots, u8 itemCount);
 u8 CountUsedPCItemSlots(void);
+bool8 CheckPCHasSpace(u16 itemId, u16 count);
 bool8 CheckPCHasItem(u16 itemId, u16 count);
 bool8 AddPCItem(u16 itemId, u16 count);
 void RemovePCItem(u8 index, u16 count);
 void CompactPCItems(void);
---------------------------------- src/item.c ----------------------------------
index 938825f57..208faf1fd 100644
@@ -486,8 +486,56 @@ bool8 CheckPCHasItem(u16 itemId, u16 count)
     }
     return FALSE;
 }
 
+
+bool8 CheckPCHasSpace(u16 itemId, u16 count)
+{
+    u8 i;
+    u16 ownedCount = 0;
+
+    if (InBattlePyramid() || FlagGet(FLAG_STORING_ITEMS_IN_PYRAMID_BAG) == TRUE)
+    {
+        return FALSE;
+    }
+
+    for (i = 0; i < PC_ITEMS_COUNT; i++)  // Get owned count
+    {
+        if (gSaveBlock1Ptr->pcItems[i].itemId == itemId)
+            ownedCount = GetPCItemQuantity(&gSaveBlock1Ptr->pcItems[i].quantity);
+    }
+
+    if (ownedCount + count <= MAX_PC_ITEM_CAPACITY)  // If there's room in already existing slot
+    {
+        return TRUE;
+    }
+
+    // Check space in empty item slots
+    if (count > 0)
+    {
+        for (i = 0; i < PC_ITEMS_COUNT; i++)
+        {
+            if (gSaveBlock1Ptr->pcItems[i].itemId == ITEM_NONE)
+            {
+                if (count > PC_ITEMS_COUNT)
+                {
+                    count -= PC_ITEMS_COUNT;
+                }
+                else
+                {
+                    count = 0; //should be return TRUE, but that doesn't match
+                    break;
+                }
+            }
+        }
+        if (count > 0)
+            return FALSE; // No more item slots. The bag is full
+    }
+
+    return TRUE;
+}
+
+
 bool8 AddPCItem(u16 itemId, u16 count)
 {
     u8 i;
     s8 freeSlot;
--------------------------------- src/scrcmd.c ---------------------------------
index 3ef4b8208..353167754 100644
@@ -510,8 +510,17 @@ bool8 ScrCmd_checkitemspace(struct ScriptContext *ctx)
     gSpecialVar_Result = CheckBagHasSpace(itemId, (u8)quantity);
     return FALSE;
 }
 
+bool8 ScrCmd_checkpcspace(struct ScriptContext *ctx)
+{
+    u16 itemId = VarGet(ScriptReadHalfword(ctx));
+    u32 quantity = VarGet(ScriptReadHalfword(ctx));
+
+    gSpecialVar_Result = CheckPCHasSpace(itemId, (u8)quantity);
+    return FALSE;
+}
+
 bool8 ScrCmd_checkitem(struct ScriptContext *ctx)
 {
     u16 itemId = VarGet(ScriptReadHalfword(ctx));
     u32 quantity = VarGet(ScriptReadHalfword(ctx));