# Inventory and equipment (inventory.* kits) What the player carries and wears. Readable offline: `gripforge docs inventory`, or the MCP tool `gripforge_docs` (topic `inventory`). ## What it is for | Kit | What it adds | | --- | --- | | `inventory.basic` | item slots with stacks, pick-ups in the world through the interaction prompt, use and drop, item rewards, and the verbs to give, take and check items | | `inventory.equipment` | what the player wears: slots, gear as data, stats of the worn pieces applied to combat, carry weight | Money has its own kit (see the Economy guide); shops, crafting and containers build on this inventory. ## Turn it on ```text gripforge_gamekit_install { project_id: "gkp_…", id: "inventory.basic" } gripforge_gamekit_configure { project_id: "gkp_…", id: "inventory.basic", config: { "slots": 20, "stack": 50 } } gripforge_gamekit_install { project_id: "gkp_…", id: "inventory.equipment" } ``` `inventory.basic` requires `input.actions` and `game.engine`; `inventory.equipment` requires `inventory.basic`. ## Settings and defaults | Kit | Key | Default | Meaning | | --- | --- | --- | --- | | `inventory.basic` | `slots` | 12 | inventory slots, one stack of one item each | | `inventory.basic` | `stack` | 99 | maximum units per stack (1 for a non-stackable item) | | `inventory.basic` | `dropOnDeath` | `false` | drop every held item as pick-ups when the player dies | | `inventory.equipment` | `slots` | head, chest, hands, feet, weapon, offhand, ring, amulet | your own list, for instance `["armor", "primary", "charm"]` | | `inventory.equipment` | `maxWeight` | 0 | carry weight of the worn gear (0: unlimited) | | `inventory.equipment` | `overloadSlow` | 0.4 | share of walking speed lost above `maxWeight` | | `inventory.equipment` | `autoEquip` | `false` | a picked-up piece is worn at once when its slot is free | All of them, and the collections below, are moddable. ## Items, pick-ups, gear Items are the documents of the `items` collection: `{ id, name, stackable?, icon? }`. Without the collection any item id is accepted (stackable, named after its id); with it, unknown ids are refused. Gear is the `equipment` collection: ```json { "items": [{ "id": "iron_helmet", "name": "Iron Helmet", "stackable": false }], "equipment": [{ "id": "iron_helmet", "name": "Iron Helmet", "slot": "head", "weight": 5, "stats": { "armor": 12 } }] } ``` - `give` tops up the stacks in slot order, then opens stacks in free slots. `take` is all or nothing. `use` consumes one unit unless `{ keep: true }`. `drop` spawns a pick-up at the player's feet. - A pick-up is any entity with the component `inventory.pickup = { item, count? }`; interacting gives the units (it disappears when everything fitted, `inventory.full` is emitted when nothing did). With `game.engine` content the archetype components are `pickup { item, count? }` and `container { items, money?, personal? }` (a chest: using it gives its items and money once, or once per player with `personal`). - Equipping takes one unit from the inventory and wears it; the piece that was there goes back. The worn stats are summed: `armor` reduces incoming damage by armor / (armor + 100), `damage_add` and `damage_mult` raise outgoing damage, `health_max` adds maximum health, `move_mult` scales walking; other stats (`stamina_max`, `mana_max`...) are read by other kits. ## Services, verbs, events, variables - `inventory.items`: `items()`, `count(item)`, `has(item, n?)`, `give(item, n?)` (units added), `take(item, n?)`, `use(item, { keep? })`, `drop(item, n?)`, `slots()`. - `inventory.equipment`: `slots()`, `equipped()`, `equippedIn(slot)`, `gear()`, `canEquip(id)`, `equip(id)`, `unequip(slot)`, `stats()`, `stat(name)`, `weight()`. - Verbs: `give_item`, `take_item`, `has_item`, `equip_item`, `unequip_slot`, `equipped`. In scripts: `{ "give_item": "cellar_key" }`, `{ "take_item": { "item": "arrow", "count": 3 } }`. - Events: `inventory.changed { item, count, delta }`, `inventory.used`, `inventory.full`, `inventory.picked`, `inventory.looted`, `equipment.changed`, `equipment.refused`, `equipment.stats`. - Variables: `inventory.used` (slots in use), `inventory.count.`, `equipment.weight`, `equipment.armor`, `equipment.overloaded`. - Mission `rewards.items` land here, once, just before `mission.completed`. The stacks and the worn gear are saved. ## Hooks and modding | Hook | Payload | What a tap may do | | --- | --- | --- | | `inventory.give` | `{ item, count }` | change `count`, cancel | | `inventory.pickup` | `{ item, count, pickup }` | change `count`, cancel (the pick-up stays) | | `inventory.use` | `{ item, keep }` | set `keep`, cancel | | `inventory.drop` | `{ item, count }` | lower `count`, cancel (a quest item) | | `equipment.equip` | `{ item, slot, previous }` | cancel (`equipment.refused` carries the reason) | | `equipment.unequip` | `{ slot, item, returned }` | set `returned: false`, cancel (a cursed ring) | ```json { "id": "keep_key", "hook": "inventory.drop", "match": { "item": "cellar_key" }, "cancel": true } ``` ## Engines `inventory.basic` is the same Rust logic on the web and in the native player, delivered to Godot and Unity as files and to Unreal through the shared kit library. `inventory.equipment` runs on the web and in the native player. The hooks run in those two; the older engine scripts keep the behaviour without taps. ## When it does not do what you expect | Symptom | Cause and fix | | --- | --- | | `give` adds nothing | the item id is not in the `items` collection (when it exists), or every slot is full | | A worn piece cannot be sold or dropped | by design: the inventory counts it as worn, unequip it first | | Equipping is refused | the piece's `slot` is not among the configured slots, or a tap cancelled `equipment.equip` | | Armor does nothing | `inventory.equipment` is installed but `combat.core` is not | | The player walks slowly | the worn weight is above `maxWeight` (`equipment.overloaded`) |