# Inventory

> Everything a character owns sits in its UPC Inventory as stacks: three potions are one stack of three. With no config it is one list with no limits; a config adds slots, a grid, weight limits or bags.

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

## Set it up (5 minutes)

1. **Make a potion**

   Create an **Item Definition** (**UPC > Items > Item Definition**) `Item_MyPotion`: **Max Stack Size** 5, **Slot Tags** `UPC.Slot.Consumable`, a **Display Name**, and the demo's **BP_UPC_ItemFragment_UseEffect** in **Fragments** with **Vital Tag** `UPC.Vital.Health` and **Amount** 25. Skip Equippable: a potion is used, not held.

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

   **Category: Item**

   | Property | Value |
   | --- | --- |
   | Max Stack Size | 5 |
   | Slot Tags | UPC.Slot.Consumable |

   **Category: Display**

   | Property | Value |
   | --- | --- |
   | Display Name | Health Potion |
   | Description |  |
   | Icon | T_MyPotion_Icon |
   | Inventory Grab Sound | None |
   | Inventory Place Sound | None |

   **Category: Fragments**

   | Property | Value |
   | --- | --- |
   | Preset | None |
   | Fragments | 1 Array element |
   | Fragments > Index [0] | BP_UPC_ItemFragment_UseEffect |
   | Fragments > Index [0] > Vital Tag | UPC.Vital.Health |
   | Fragments > Index [0] > Amount | 25 |

   *No Equippable fragment, so pressing its belt slot uses it instead of drawing it. The Use Effect fragment says what using it does.*
2. **Start with three**

   On `BP_UPC_Character`'s **InventoryComponent**, add `Item_MyPotion` to **Starting Items** three times and leave **Config** alone. They join into one stack of three, and the demo belt puts it on slot 4, its consumables slot.

   **Details panel: InventoryComponent** (component, in BP_UPC_Character)

   **Category: UPC > Inventory**

   | Property | Value |
   | --- | --- |
   | Config | InventoryConfig_UPC_Simple |
   | Starting Items | 3 Array elements |
   | Starting Items > Index [0] | Item_MyPotion |
   | Starting Items > Index [1] | Item_MyPotion |
   | Starting Items > Index [2] | Item_MyPotion |

   *The demo character starts on the Simple config, which carries what the belt holds and the gear it wears. Each Starting Items entry adds one unit when play begins; three entries of one stackable item make one stack of three.*
3. **Drink one**

   Press Play, then **4** or D-pad left. The stack drops to two and Health rises by 25 up to its maximum (get hit first if Health is full); `UPC.Debug.Vitals 1` shows it. Under a style with an inventory screen, its **Consume** does the same.

Owning an item does not put it in hand: the [Quick Bar](https://rigbak.com/docs/universal-player-combat/quick-bar) draws owned items from its slots and an [inventory screen](https://rigbak.com/docs/universal-player-combat/inventory-screens) equips them.

---

## Add, spend and count

These run on the server, which in single player is your one machine.

| Node | Does |
| --- | --- |
| **Add Item Definition** | Adds **Stack Count** units, topping up existing stacks first; under a Config only what fits. Returns the stack the last units landed in (eight potions at Max Stack Size 5 make stacks of 5 and 3 and return the second). |
| **Add Item Stack** | Adds units as stacks of their own, **Stat Tags** as each new stack's state ([stat tags](https://rigbak.com/docs/universal-player-combat/inventory#per-item-state-stat-tags)). |
| **Remove Item Instance** | Removes one stack. |
| **Consume Item** | Spends **Count** units of an item carried and in reach, all or none (false when too few). |
| **Consume Item Instance** | Spends **Count** units from one stack, all or none. |

| Node | Answers |
| --- | --- |
| **Get Item Count** | Carried units of an item across every stack (banks excluded). |
| **Get Item Stack Count** | Units in one stack, or 0. |
| **Get All Items** | Every stack, in no set order. |
| **Find First Item by Definition** | First stack of an item, or nothing. |
| **Get Weight** | Weight carried (Weight fragment times count); name a container in **Scope** for that one alone. |
| **Is Item Carried And In Reach** | Whether the character can draw, belt or use a stack now. |

**On Item Added**, **On Item Removed** and **On Item Count Changed** report changes. On Item Count Changed carries the item's total (what Get Item Count answers) and fires alone for a merge into an existing stack, so a count display listens to it: with stacks of 5 and 2 potions, spending one fires it with 6. A screen laying out containers reads the events on [Inventory Screens](https://rigbak.com/docs/universal-player-combat/inventory-screens#read-the-inventory).

---

## Use an item

A belt slot holding an item with no Equippable uses it, and so does a screen's **Consume** (**Request Use Item**). Both send the gameplay event `UPC.Event.UseItem` on the server with the item as **Optional Object**; the ability it triggers decides what using means. The **Consume Item** node only removes units.

The demo's `GA_UPC_UseItem` (granted by `AbilitySet_UPC_Default`) spends one unit and applies the item's **BP_UPC_ItemFragment_UseEffect** (its **Vital Tag** changes by its **Amount**). For other items (a spell scroll), duplicate `GA_UPC_UseItem` (`Demo/Abilities`), change what its event graph applies, and add the copy to an Ability Set the character carries ([Input](https://rigbak.com/docs/universal-player-combat/input#abilities-that-answer-a-key)). Every granted ability triggered by the event answers it, so make each graph act only on its own items and end at once for others. The copy keeps an **Ability Triggers** row on `UPC.Event.UseItem`, **Net Execution Policy** **Server Only**, and no input; its graph reads the item from the event's **Optional Object**.

---

## Per-item state: stat tags

State belonging to one owned stack (a sword's durability, a wand's charges) lives on it as **stat tags**: counted gameplay tags describing every unit in the stack. Two wands carrying `MyGame.Stat.Charges` at 3 are two wands of three charges each.

| Node | Does |
| --- | --- |
| **Add Stat Tag Stack**, **Remove Stat Tag Stack** | Raise or lower a tag's count, on the server. |
| **Get Stat Tag Stack Count**, **Has Stat Tag**, **Has Any Stat Tags**, **Get Stat Tags** | Read them (a tooltip). |
| **On Stat Tag Changed** | The tag and its new count (0 when removed). Call Get Stat Tags once after binding, since the starting state arrives first. |

A stack with stat tags never joins another (a worn sword stays apart from a new one), and a split stack carries them on both halves. Drops and [saves](https://rigbak.com/docs/universal-player-combat/inventory-saving) keep them.

---

## Pick a style

Set **InventoryComponent**'s **Config**. The four ready styles ship in `Demo/Items/Inventory`, each but Simple with its own screen.

| You want | Set up | Page |
| --- | --- | --- |
| Only what the belt holds and worn gear, no inventory screen (the demo player's style) | `InventoryConfig_UPC_Simple` | [Use Only Part of the Inventory](https://rigbak.com/docs/universal-player-combat/inventory-pick-what-you-need#a-belt-and-nothing-else) |
| A small case where items turn to fit, key items, a stash | `InventoryConfig_UPC_SurvivalGrid` | [Survival Grid](https://rigbak.com/docs/universal-player-combat/inventory-survival-grid) |
| A backpack with weight tiers that slow, pouches, worn gear, a stash | `InventoryConfig_UPC_PartyRPG` | [Party RPG](https://rigbak.com/docs/universal-player-combat/inventory-party-rpg) |
| One sorted list, weight that slows past a limit, categories | `InventoryConfig_UPC_OpenWorldList` | [Open World List](https://rigbak.com/docs/universal-player-combat/inventory-open-world-list) |
| A belt and nothing else | No config, and the belt's **Auto Populate from Inventory** | [Use Only Part of the Inventory](https://rigbak.com/docs/universal-player-combat/inventory-pick-what-you-need) |
| Numbered slots, caps per item kind, a hard weight cap | A config of your own | [Containers and Rules](https://rigbak.com/docs/universal-player-combat/inventory-containers) |
| A bag bar and a bank | A container that opens bags, and storage off the character | [Bags and Banks](https://rigbak.com/docs/universal-player-combat/inventory-bags) |
| Herbs mixed, rounds loaded into a magazine, a key opening a box | A Combine Set on the config | [Combines](https://rigbak.com/docs/universal-player-combat/inventory-combines) |
| A chest every nearby player sees | `BP_UPC_LootChest` | [Loot Chests](https://rigbak.com/docs/universal-player-combat/loot-chests) |
| The inventory in your save game | **Export Snapshot**, **Import Snapshot** | [Saving the Inventory](https://rigbak.com/docs/universal-player-combat/inventory-saving) |
| Rules, combines or item data of your own | A Blueprint subclass | [Inventory Rules and Combines in Blueprint](https://rigbak.com/docs/universal-player-combat/inventory-blueprint) |

**Switch styles in play** with **Set Config**, on the server. A container both configs list, such as a stash, keeps its items; every other item is placed again as an add would place it. An item in hand stays in hand. The belt follows the config's **Belt Slots** and **Has Belt** ([Quick Bar](https://rigbak.com/docs/universal-player-combat/quick-bar#a-belt-an-inventory-config-names)).

---

## Debug it

Setup problems, such as a starting item with no room, log as warnings under `LogUPCInventory`. `Log LogUPCInventory Verbose` names each request the server turned down, and `Log LogUPCEquipment Verbose` why the belt left an item off a slot.

<details>
<summary>How stacks fill and leave (Advanced)</summary>

- An add tops up stacks of the same item to its **Max Stack Size**, then opens new ones. An item with a Max Stack Size of 1, such as a sword, takes a stack per unit.
- With no Config every add fits. Under a Config an add takes only the units that fit, and a pickup leaves the rest on the ground.
- **Starting Items** adds one unit per element at Begin Play on the server, merging as any add does. Under a Config, one that finds no room is skipped with a warning.
- **Add Item Definition** skips stacks carrying stat tags, and returns nothing off the server, with no item, or with a Stack Count below 1.
- **Add Item Stack** splits into stacks of at most Max Stack Size, and with Stat Tags gives each new stack exactly those tags, each describing every unit, so a stack split in two carries them twice.
- **Consume Item** spends in inventory order, plain stacks before ones carrying stat tags. A stack spent to zero is removed.
- A pickup adds through Add Item Stack when the world item carries stat tags, else through Add Item Definition ([Pickups, Drops and Holders](https://rigbak.com/docs/universal-player-combat/pickups-drops-holders)).
- **Set Config** places a stack that fits nowhere past the end of the first carried container that takes new items, and logs a warning.
- When a drawn item's stack leaves the inventory, by a drop, a consume or a remove, the item leaves the hand at once, with no animation. Its belt slot takes another carried stack of the same item in reach when the belt's **Refill Item Kinds** lists the item (consumables by default), or clears ([Quick Bar](https://rigbak.com/docs/universal-player-combat/quick-bar#fill-the-belt)).

</details>

<details>
<summary>The demo</summary>

- **`LVL_UPC_Demo`**: the player takes swords and the shield off the weapon rack, and three potions, a ring and a necklace out of the [loot chest](https://rigbak.com/docs/universal-player-combat/loot-chests) (**E** opens the inventory screen beside it, **F** takes everything). The player starts on Simple, which carries what the belt holds and the gear it wears: a sword, a second sword or the shield, and the potions, with the ring and the necklace kept in its Worn slots. Simple opens no inventory screen, so **E** at the chest shows none. To play under another style, set its config on `BP_UPC_Character`'s **InventoryComponent**.
- **`LVL_UPC_Wardrobe`** (also via the **Wardrobe** plate in the start room): a pad per demo weapon and worn item, walked onto to equip and again to put away (under Simple, again takes the item back out of the inventory), sending the requests a screen does ([Inventory Screens](https://rigbak.com/docs/universal-player-combat/inventory-screens#equip-from-the-inventory)). Three style pads behind the spawn switch to the survival grid, party RPG or open world list, and a fourth, Belt Only, in the front corner by the shield's pad switches back to Simple, each with a starter kit (Simple's wears a cape); disconnect **Remove All Items** in `BP_UPC_InventoryStylePad`'s **Apply Style** to keep your items across a switch.

</details>

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

The server makes every change. The inventory replicates to its owning player only, so its nodes read it and its events fire on the server and that player's machine; elsewhere it reads as empty. Other players see what a character holds through its equipment. A [loot chest](https://rigbak.com/docs/universal-player-combat/loot-chests) is the exception: its items reach every nearby player.

- Counts are not predicted; the player's count follows the server's about a round trip later.
- On the owner's machine, **On Item Removed** can fire before the rest of the same update has arrived; read counts from **On Item Count Changed**, which fires once it has settled. Stat tags reach the owner the same way.
- A player's machine changes nothing itself: a screen sends requests, and the server carries them out or turns them down ([Inventory Screens](https://rigbak.com/docs/universal-player-combat/inventory-screens)).
- The config **Set Config** applies reaches the owner with the new places, and containers that come and go fire **On Capacity Changed** there as on the server.

</details>

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

- `UUPCInventoryComponent` keeps its stacks in a FastArray of `UUPCInventoryItemInstance` subobjects, replicated `COND_OwnerOnly`; `UUPCWorldInventoryComponent` replicates the same list to every machine.
- A new owned item runs `OnInstanceCreated(UUPCInventoryItemInstance*)` on every fragment its item uses, to seed starting stat tags (a C++ virtual on `UUPCItemFragment`; no shipped fragment seeds anything). `AddItemStack` with explicit Stat Tags skips the seeding.
- `UUPCInventoryItemInstance::FindFragmentByClass<T>()` reads a fragment of the item a stack holds. Quantity lives only on the stack's count; stat tags never hold a count of units.

</details>

---

Previous page: [Pickups, Drops and Holders](https://rigbak.com/docs/universal-player-combat/pickups-drops-holders). Next page: [Use Only Part of the Inventory](https://rigbak.com/docs/universal-player-combat/inventory-pick-what-you-need)
