# Bags and Banks

> A bag is an item that opens a container of its own, in a backpack or on a bag bar. A bank or a stash keeps items off the character until the player stands at it.

Markdown version of https://rigbak.com/docs/universal-player-combat/inventory-bags, a page of the Universal Player Combat documentation. Link that page when citing it.

## Set it up (5 minutes)

1. **Give the character a pouch**

   On `BP_UPC_Character`'s **InventoryComponent**, set **Config** to `InventoryConfig_UPC_SurvivalGrid` (its Key Items list has **Opens Bags** ticked), and add `Item_UPC_HipPouch` to **Starting Items**; the case's filter keeps pouches out, so it lands in Key Items. If you cleared the belt's Filters in [Use Only Part of the Inventory](https://rigbak.com/docs/universal-player-combat/inventory-pick-what-you-need), restore them (Weapon, Consumable.Potion, Off Hand, Consumable) or the pouch also takes a belt slot.

   In **BP_UPC_Character**, under UPC > Inventory, set:

   | Property | Value |
   | --- | --- |
   | Config | InventoryConfig_UPC_SurvivalGrid (replaces InventoryConfig_UPC_Simple) |
2. **Print a container's size when it changes**

   Press **+** beside the component's **On Capacity Changed**:

   Blueprint graph, nodes in reading order:

   - **Comment box: BP_UPC_Character · print a container's size when it changes**

     - **On Capacity Changed (InventoryComponent)** (event); outputs: Container
     - **Get Container Size** (pure function); inputs: Target, Container; outputs: Return Value
     - **To String (IntPoint)** (pure function); inputs: In Int Point; outputs: Return Value
     - **Print String** (function); inputs: In String
3. **Press Play**

   The screen prints `X=6 Y=1`: the pouch opened its own container, six cells by one. Press **I** to see them under the case and drop an item there.

---

## Make a bag

Give an item a **Container** fragment and **Max Stack Size** 1. **Definition** is the container it opens (own layout, rules, Access Tag); **Container Tag** names it (`UPC.Inventory.Container.Bag` by default, apart from the config's container tags). The bag opens in any container with **Opens Bags** ticked and stays closed elsewhere.

**Details panel: Container** (instanced object, in Item_UPC_Pouch)

**Category: Container**

| Property | Value |
| --- | --- |
| Definition | Container_UPC_Pouch |
| Container Tag | UPC.Inventory.Container.Bag |

*The party RPG's pouch: in the backpack, which opens bags, it opens an eight slot container of its own.*

---

## Where a bag's items go

- **A bag keeps what it holds wherever it goes.** Closed in storage, a chest or on the ground, it keeps its items in place, out of reach until it opens. Game code removing or consuming the bag spills them into other containers (Bags in detail, below).
- **A stack dropped on an open bag goes inside** (**Can Place** answers **Into Bag**). A bag dropped on a bag trades places, so a bag bar reorders by drag.
- **A bag holding items never goes inside another bag** (`UPC.Inventory.Refused.BagNotEmpty`): bags stay one level deep.
- **An item on the belt or in hand steps out** of a bag that closes or leaves, into the carried containers. Drop a pouch holding a belted potion and a herb: the herb leaves in the pouch, the potion stays with the character.
- **A closed bag's items count as carried while the bag is** (weight included) though out of reach until it opens. A pouch moved to the stash is closed and the stash is not carried, so its herb adds no weight.
- **A bag on the belt or in hand stays open**, items in reach, even when **Belt Space** or **Equipped Space** **Frees Its Place** takes it out of the container that opened it.

---

## A bag bar

For an MMO bag bar, a Slots container holds the bags that open, and the container they sit in stops opening them:

1. Copy `InventoryConfig_UPC_SurvivalGrid` and its `Container_UPC_KeyItems` (an MMO's backpack would be the container bags sit in).
2. In your Key Items copy, untick **Opens Bags** and point the copied config's Key Items row at it.
3. Add a bar row after it: a Slots container with **Opens Bags** ticked and **Takes New Items** unticked (`UPC.Inventory.Container.BagBar` is a ready row tag).
4. Set the copy as the character's **Config**. It has no screen row, so **I** opens the open world list; the key below needs no screen.

**Details panel: Container_MyBagBar** (data asset, in Content Browser)

**Category: Display**

| Property | Value |
| --- | --- |
| Display Name | Bag Bar |
| Icon | None |

**Category: Layout**

| Property | Value |
| --- | --- |
| Layout | Slots |
| Slot Count | 4 |
| Capacity Tag | None |

**Category: Rules**

| Property | Value |
| --- | --- |
| Rules | 0 Array elements |

**Category: Access**

| Property | Value |
| --- | --- |
| Carried | true |
| Takes New Items | false |
| Access Tag | None |

**Category: Bags**

| Property | Value |
| --- | --- |
| Opens Bags | true |

*Four slots for bags. A bag placed here opens its own container, which adds fill right after the backpack.*

A screen moves a bag onto the bar with **Request Move**, and **On Capacity Changed** fires as its container opens. The demo screens show no bag bar, so a key stands in for the drag. The destination names the bar by tag alone: **Providing Item** stays empty for a config-listed container and names the bag only for a bag's own container ([Read bags in a screen](https://rigbak.com/docs/universal-player-combat/inventory-bags#read-bags-in-a-screen)).

Blueprint graph, nodes in reading order:

- **Comment box: BP_UPC_Character · B puts the pouch on the bag bar**

  - **B** (event); outputs: Pressed, Released, Key
  - **Inventory Component** (variable)
  - **Find First Item by Definition** (pure function); inputs: Target, Item Def = Item_UPC_HipPouch; outputs: Return Value
  - **Make UPC Container Id** (make struct); inputs: Tag = UPC.Inventory.Container.BagBar, Providing Item; outputs: UPC Container Id
  - **Make UPC Inventory Placement** (make struct); inputs: Container, Position = 0, Rotated; outputs: UPC Inventory Placement
  - **Request Move** (function; Target is UPC Inventory); inputs: Target, Item, Count = 1, Destination

---

## A bank or a stash

A bank or stash is a container of the player's inventory with **Carried** and **Takes New Items** off and an **Access Tag** (the demo's **Stash** uses `UPC.State.AtStash`). The character reaches it only while holding that tag, so grant it on the server while the character stands at the bank and remove it on leaving. The demo's `BP_UPC_StorageBox` does this with `GE_UPC_StorageAccess` while the character stands in its zone. The box holds nothing: the stash belongs to the player's inventory and stays across inventory styles ([Survival Grid Inventory](https://rigbak.com/docs/universal-player-combat/inventory-survival-grid)).

**Details panel: Container_UPC_Stash** (data asset, in Content Browser)

**Category: Display**

| Property | Value |
| --- | --- |
| Display Name | Stash |
| Icon | None |

**Category: Layout**

| Property | Value |
| --- | --- |
| Layout | Slots |
| Slot Count | 30 |

**Category: Rules**

| Property | Value |
| --- | --- |
| Rules | 0 Array elements |

**Category: Access**

| Property | Value |
| --- | --- |
| Carried | false |
| Takes New Items | false |
| Access Tag | UPC.State.AtStash |

**Category: Bags**

| Property | Value |
| --- | --- |
| Opens Bags | false |

*The stash every demo style lists: thirty slots off the character that a player fills by moving items in, reached only while the character holds UPC.State.AtStash.*

---

## Read bags in a screen

A bag's container goes by a **UPC Container Id**: its **Tag** plus **Providing Item** (the bag), so two pouches of one kind stay apart; a gameplay tag wired into a container pin converts automatically. **Get Containers** lists each open bag right after the container it sits in, the order a pickup fills them. **Get Container Opened By** answers a bag's container for a bag bar slot (false while closed).

---

## Debug it

- A bag whose Container Tag a config row uses opens nothing, and `LogUPCInventory` warns once.
- Saving a bag item fails for a Max Stack Size above 1, no Container Tag, or a Definition that opens bags.

<details>
<summary>Bags in detail (Advanced)</summary>

- A bag's items are in reach only while the bag is open, in reach, and its container's Access Tag allows. Moves, uses, draws, consumes, sorts, transfers and adds skip a closed bag's items.
- A bag inside a bag never opens, and a bag never goes into its own container (`OutOfBounds`).
- A drop on a closed bag is a drop on a plain item. Into Bag goes to the bag's first free place, judged by its container's rules and the carry rules.
- **Remove Item Instance**, **Consume Item** or **Consume Item Instance** on a bag spills its contents: each stack moves whole, stat tags and belt slot kept, to where an add would put it, else past the end of the first carried container taking new items, with a warning. Nothing drops into the world. **Take Item Out** moves a bag elsewhere with its items.
- The carry rules judge a bag arriving from storage together with its items, so a full pouch too heavy to carry stays in the stash with `TooHeavy`.
- **Request Transfer** and **Request Take All** move a bag and its items to or from a chest whole or not at all; in the chest the bag is closed and the chest lists the bag alone.
- A drop, a rack's Put Back and **Take Item Out** take a bag out with its items; picking it up restores them in place (**Can Add Bag With Items** answers first).
- A spilled stack from the belt or hand goes only to a carried container. Where no container opens bags (the open world list), a bag's items stay out of reach.

</details>

<details>
<summary>What runs where (Multiplayer)</summary>

- A bag's items reach the owning player's machine only; a chest's or a dropped bag's reach every machine near it. Items can arrive before the bag; each announces its add once the bag has arrived.

</details>

<details>
<summary>C++</summary>

- `UUPCItemFragment_Container` makes an item a bag; `UUPCContainerDefinition::bOpensBags` makes a container open bags.
- `FUPCContainerId` holds `Tag` and `ProvidingItem`; `UUPCInventoryStatics` adds the tag conversion and the equality node.
- `UUPCInventoryComponent::GetContainerOpenedBy(Bag, OutContainer)` and `GetContainers()` are the queries a bag bar screen reads; `TakeItemOut(Item, Count, OutBagItems)` hands a bag's items back as `FUPCInventorySnapshot` rows for whatever takes the bag.

</details>

---

Previous page: [Containers and Rules](https://rigbak.com/docs/universal-player-combat/inventory-containers). Next page: [Combines](https://rigbak.com/docs/universal-player-combat/inventory-combines)
