# Inventory Rules and Combines in Blueprint

> Write your own inventory rules, combines and item fragments in Blueprint with no C++, copying from the seven the demo ships.

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

## Set it up (5 minutes)

1. **Make the class**

   An item fragment is a block of settings an item definition carries (a weight, a gold value). Create `BP_MyGoldValue`, a Blueprint child of **UPC Item Fragment**.
2. **Give it settings**

   Add an integer variable, `Value`, with **Instance Editable** and **Blueprint Read Only** ticked (all characters holding the item read the same fragment, so validation warns about a variable a graph could change).
3. **Put it on an item**

   In an item definition add a **Fragments** element, pick `BP_MyGoldValue` and set Value to 150.
4. **Read it**

   On an owned item, call **Find Fragment by Class** with `BP_MyGoldValue`, then **Is Valid** and **Value**. To check it, give `BP_UPC_Character` the item in **Starting Items**, and on its Event Begin Play call **Get All Items** on its **InventoryComponent**, loop, and print Value: 150. (The demo's Valuables rule reads `BP_UPC_ItemFragment_GoldValue`, not this class.)

A rule or a combine starts the same way, from the parent **UPC Inventory Rule** or **UPC Inventory Combine**, overriding its functions from the **Functions** list's **Override** menu; or duplicate the closest demo Blueprint. All characters share one copy, so it answers only from what its functions receive.

---

## The demo's seven

All sit in `Demo/Items/Inventory/Blueprints`.

| Blueprint | Parent | Does | Used by |
| --- | --- | --- | --- |
| `BP_UPC_InventoryRule_UniqueKeyItems` | Rule | One of each key item | [Survival Grid](https://rigbak.com/docs/universal-player-combat/inventory-survival-grid) |
| `BP_UPC_InventoryRule_Valuables` | Rule | Tags a character carrying an item worth a gold threshold | [Open World List](https://rigbak.com/docs/universal-player-combat/inventory-open-world-list) |
| `BP_UPC_Combine_LoadHolder` | Combine | Loose units into a holder (rounds into a magazine, arrows into a quiver) | Demo Combine Set |
| `BP_UPC_Combine_CoatWeapon` | Combine | Poison coats a weapon for three strikes | Demo Combine Set |
| `BP_UPC_ItemFragment_GoldValue` | Fragment | Gold value per unit | Valuables rule |
| `BP_UPC_ItemFragment_Holder` | Fragment | What a holder takes, how much, and the stat counting its load | Load Holder; the demo screens' load |
| `BP_UPC_ItemFragment_UseEffect` | Fragment | A resource tag (health) and the amount a use changes it | Demo use ability ([Use an item](https://rigbak.com/docs/universal-player-combat/inventory#use-an-item)) |

---

## Rules

A rule goes on a config's **Carry Rules** or a container's **Rules** ([Containers and Rules](https://rigbak.com/docs/universal-player-combat/inventory-containers)) and overrides one or both functions:

- **Get Units Accepted** gets a **Context**, an **Item** (definition) and a **Count**, and returns how many units it admits. A pickup adds the units its preview answered, so a rule admitting 3 of 10 must admit 3 of 3.
- **Get Status Tags** gets the Context and returns the tags the contents put on the character.

| Context field | Holds |
| --- | --- |
| **Inventory** | The inventory being judged. |
| **Scope** | The container judged, or empty for everything carried (a carry rule). Pass it unchanged to **Get Weight** or **Get Category Count** so one rule works in either place. |
| **Departing Item**, **Departing Units** | A definition leaving in the same change (a swap) and its units; judge as if gone. |
| **Arriving With** | Items arriving beside Item (what a bag holds); judge as if in. A carry rule ignoring it judges a bag without its items. |

**Unique Key Items**, Get Units Accepted, with **Key Item Tag** `UPC.Slot.KeyItem`:

1. **Has Tag** on Item's **Slot Tags** (the kinds its definition says it is) with Key Item Tag, not exact. Any other item passes: return **Count**.
2. **Get Item Count** of Item on the context's Inventory. When **Departing Item** == Item, subtract **Departing Units**.
3. The room is 1 minus that, clamped between 0 and Count. Below Count, return the room with **Out Reason** `UPC.Inventory.Refused.NotAdmitted`; otherwise Count.

Put the rule in the **Carry Rules** of the config that should limit keys (the demo's survival grid lists it there). To judge a bag carrying a key too, add the key units in **Arriving With** to step 2's count.

With no key carried, the room is 1 and a key comes in. A second copy finds 1 carried, room 0, and stays out. A swap of the carried key for a stash copy counts 1 minus the 1 departing, so the stash's copy comes in.

**Valuables**, Get Status Tags, with **Threshold** 100 and **Status Tag** `UPC.State.CarryingValuables`:

1. **Get All Items** on the context's Inventory, into a **For Each Loop**.
2. Skip an item that fails **Is Item Carried And In Reach**, or whose **Find Fragment by Class** with `BP_UPC_ItemFragment_GoldValue` is not valid.
3. As soon as one item's fragment **Value** is at least Threshold, return Status Tag in a container (**Make Gameplay Tag Container from Tag**); after the loop, an empty one. Put the rule in the config's **Carry Rules**.

The inventory runs every rule again after each change of its own (an add, a move, a removal). A change to something outside the inventory that a rule reads, such as a strength attribute or a quest flag, runs nothing by itself: the code making it calls **Refresh Limits** on the inventory so the rules and status tags update.

---

## Combines

A combine goes in a Combine Set's **Combines**; [Combines](https://rigbak.com/docs/universal-player-combat/inventory-combines#a-combine-of-your-own) explains its three functions and builds a magazine. The demo's two:

| Combine | Matches | Get Units | Apply Unit |
| --- | --- | --- | --- |
| Load Holder | The item a holder **Holds**, dropped onto an item carrying the Holder fragment | The least of the units dragged, the units in the stack and the room under the holder's **Capacity**, else `Refused.Full` | Moves one unit into the holder's **Stat Tag** count |
| Coat Weapon | **Poison** onto an item whose Slot Tags fall under **Weapon Tags** | 1, or 0 with `Refused.NotAdmitted` while the weapon holds **Poisoned Tag** | Consumes one poison and gives the weapon **Strikes** stacks of Poisoned Tag, for your own damage code to spend |

The **Holder** fragment names what a holder takes (**Holds**), its **Capacity** per unit and the stat counting its load (**Stat Tag**): the demo magazine holds 15 rounds in `UPC.Inventory.Stat.Loaded`. Load Holder reads nothing else, so a quiver from the fragment holding `Item_UPC_Arrow` loads with nothing more to set.

<details>
<summary>Rules and fragments in detail (Advanced)</summary>

- The server keeps the union of the rules' tags on the character, so Valuables' tag comes and goes with the necklace.
- Each combine's **Unit Timing** sits on its class defaults, and each Combine Set entry can change it: Load Holder takes 0.3 seconds a unit, Coat Weapon 1.5 seconds a coat. Coat Weapon's **Weapon Tags** is `UPC.Slot.Weapon` and its **Poisoned Tag** `UPC.Inventory.Stat.Poisoned`.

</details>

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

- The server judges every request with these Blueprints, and the owning player's machine runs them over its copy, so a screen shows a refusal early. **Apply Unit** runs on the server only; rule status tags reach every machine through the character's ability system.

</details>

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

- A rule overrides `UUPCInventoryRule::GetUnitsAccepted_Implementation` and `GetStatusTags_Implementation`; a combine overrides `UUPCInventoryCombine::Matches_Implementation`, `GetUnits_Implementation` and `ApplyUnit_Implementation`.
- A C++ fragment subclasses `UUPCItemFragment` and can seed an owned item's stat tags in `OnInstanceCreated`, which a Blueprint fragment cannot.

</details>

---

Previous page: [Saving the Inventory](https://rigbak.com/docs/universal-player-combat/inventory-saving). Next page: [Combat Styles](https://rigbak.com/docs/universal-player-combat/combat-styles)
