# Items and inventory

> Define your game's items, categories and equipment slots, give the player a bag with limits, and place pickups and containers in your levels.

Source: https://feather-engine.com/docs/gameplay/items-and-inventory/

Feather's item system is generic enough for any game. Your project defines its own item
categories and equipment slots, and items carry whatever custom properties your game needs —
weight, rarity, durability, a recipe. The player's bag can be limited by count or by a summed
property such as weight. Consumables heal and cure statuses, equipment protects against damage
kinds, and tools cast elements where the player aims.

Items in the world are picked up with **Interact**. Containers — chests, stashes, shops — hold
items too. The inventory, container and status screens are UI templates, so you can restyle them.

## What's included

- An item library with ready-made presets: `apple`, `potion`, `antidote`, `wood`, `gem`, `key`,
  `flame_tunic`, `rubber_cloak`, `snow_boots`, `iron_helm`, `fire_rod`, `torch`, `ice_rod`,
  `storm_rod`, `water_flask`, `oil_flask`, `shovel`, `earth_staff`, `leveller` and `smoke_bomb`.
- Categories and equipment slots you name yourself.
- Consumables, equipment with resistances and status immunity, and tools that cast elements,
  spill liquids, reshape the ground or burst into smoke.
- Starting items, a carry limit by item count or by a property, and an on-screen status bar.
- Pickup and container components for scene objects.
- A spreadsheet-style **Item manager** with JSON import and export.

## Create items

1. Open **Window → World & terrain** and select the **Items** tab.
2. Under **Item library**, start from a preset or create an item, then edit its fields and custom
   properties.
3. Under **Inventory**, set the key that opens the screen, the carry limits, your categories and
   equipment slots, and the items the player starts with.
4. To edit many items at once, open **Window → Item manager**. It shows every item as a sortable,
   searchable table with a column per custom property, and imports and exports JSON.

### Item fields

| Field | Description | Default |
| --- | --- | --- |
| `id` | Stable ID used by pickups, doors, scripts and saves | — |
| `name`, `description` | Shown on the inventory screen | — |
| `category` | One of the project's categories | Materials |
| `stack` | Most in one stack, and in one bag, 1–9999 | 99 |
| `value` | Worth, for shops and scripts | 0 |
| `icon` | A Phosphor icon name, such as `apple`, `key`, `sword` or `flask` | `package` |
| `color` | Icon colour | — |
| `heal` | Health restored when used, 0–100,000 | 0 |
| `cures` | Statuses it ends: `burning`, `wet`, `shocked`, `chilled` | None |
| `consumed` | Using it uses one up | Off |
| `slot` | Equipment slot it is worn in | None |
| `resist` | Damage multiplier per damage kind while worn, 0–10; 0 is immune, and the lowest worn value wins | None |
| `immune` | Statuses it keeps off while worn | None |
| `properties` | Any custom data: weight, rarity, damage… | None |
| `cast` | Makes the item a tool; see below | None |

### Tools

While a tool is worn, the **Use tool** action (C) casts it where the player aims: a fire rod
lights the grass, a torch sets what it touches alight, a water flask puts fires out.

| Field | Description | Default |
| --- | --- | --- |
| `kind` | Damage kind: `physical`, `blunt`, `explosive`, `fire`, `electric`, `ice` or `water` | fire |
| `amount`, `radius` | Damage at the centre and its reach, 0.1–30 m | 12, 1.5 m |
| `range` | Distance from the camera, 0.5–200 m | 20 m |
| `cooldown` | Seconds between uses, 0–60 | 0.6 s |
| `ammo` | An item each use costs | None |
| `effect`, `sound` | Played where it lands | None |
| `fluid`, `fluid_volume` | A liquid spilled where it lands, up to 100 m³ | None |
| `terrain`, `terrain_depth` | `dig`, `raise`, `flatten` or `smooth` the ground, up to 10 m | none, 0.5 m |
| `smoke` | Diameter of a smoke cloud where it lands, up to 15 m | 0 |

See [Combat](/docs/gameplay/combat/#damage-kinds-and-statuses) for damage kinds and statuses.

## Inventory settings

| Field | Description | Range | Default |
| --- | --- | --- | --- |
| `enabled` | The inventory screen and HUD | On/off | On |
| `key` | Opens and closes the screen | Key name | Tab |
| `start` | Items the player starts with, `{id: count}` | 1–9999 each | None |
| `capacity` | Different items the player can carry; 0 is no limit | 0–10,000 | 0 |
| `limit` | Caps a summed property, `{property, max}`, such as weight | — | None |
| `status_bar` | Health and statuses on screen | On/off | On |
| `categories` | Your categories, in screen order | Up to 32 | Materials, Food, Potions, Keys, Weapons, Armor, Accessories, Quest |
| `equip_slots` | Your equipment slots, one item each | Up to 16 | head, body, legs, hands, weapon, shield, accessory |

Rename a category or slot with `inventory.rename` and every item using it follows.

## Pickups and containers

To place an item in the world:

1. Select an object and choose **Details → Add Component → Pickup**.
2. Choose the **Item** and **Count**. Leave **Prompt** empty to show "Pick up" and the item name.
3. In Play, the player presses **Interact** to take it, and the object disappears.

To add a chest or stash:

1. Choose **Details → Add Component → Container**.
2. Set the **Title** (empty uses the object's name), the **Prompt** (default "Open") and the
   number of different items it can hold (0 is any).
3. Under **Inside**, choose **Put an item in** to add starting contents.

A door can be locked with an item, such as a key; see [Interaction](/docs/gameplay/interaction/).
What everyone carries is kept in saves.

## Extend it

| Function | Description |
| --- | --- |
| `give_item(id[, count])` | Adds items; returns how many fit |
| `take_item(id[, count])` | Removes items; returns whether the player had them |
| `item_count(id)`, `has_item(id)` | What the player carries |
| `use_item(id)` | Eats, drinks or wears an item |
| `equip_item(id)`, `unequip_item(slot)`, `equipped(slot)` | Equipment |
| `inventory()` | The player's items as a map |
| `carried_total(property)` | Sum of a property across the bag, such as weight |
| `item_info(id)`, `item_property(id, key)` | Item data and custom properties |
| `items_in_category(category)` | Item IDs in a category |
| `open_inventory()`, `close_inventory()` | Show or hide the inventory screen |
| `give_to(bag, id, count)`, `take_from(bag, id, count)` | Change a container's contents |
| `move_item(from, to, id, count)` | Moves items between bags; `"player"` is the player |
| `bag_items(bag)` | A container's contents as a map |
| `open_container(bag, title)`, `close_container()` | Show a container screen |

A container placed in a level is the bag `"object:<id>"`. Any other name creates a bag for a shop or
a stash.

| Hook | Runs when |
| --- | --- |
| `on_item(id, count)` | The player gains or loses an item; `count` is how many they have now |
| `on_use_item(id)` | The player uses an item |
| `on_equip(slot, id)` | The player wears an item; `id` is empty when the slot is emptied |

```rust
// A world script: a shop. Object 12, the trader, has an interaction prompt.
fn start() {
    give_to("trader", "potion", 5);
    give_to("trader", "torch", 2);
}

fn on_interact(id) {
    if id == "12" {
        open_container("trader", "Trader");
    }
}
```

## Limits

- Up to 32 categories and 16 equipment slots, each 1–32 characters.
- An item can't be removed while a pickup or locked door uses it.
- `item.batch` changes up to 5,000 items in one undo step.

## Automate it

```bash
# A healing herb from the potion preset
feather-cli --connect .feather-session.json command item.upsert \
  --json '{"preset":"potion","value":{"id":"herb","name":"Healing herb","heal":15,"properties":{"weight":0.1}}}'

# A 30 kg weight limit and a starting kit
feather-cli --connect .feather-session.json command inventory.set \
  --json '{"patch":{"limit":{"property":"weight","max":30},"start":{"herb":3,"torch":1}}}'

# Turn object 12 into a pickup for two herbs
feather-cli --connect .feather-session.json command scene.update \
  --json '{"id":12,"patch":{"pickup":{"item":"herb","count":2}}}'
```

`item.get` returns the library, the presets, which pickups and doors use each item, and the
categories and slots. `item.batch` imports a whole table in one validated step.
