Questlight Studio
Docs / Items, inventory and economy

8. Items, inventory and economy

In short: One item system serves every battle mode and exploration. Items are data assets in four kinds (consumables, equipment, key items, documents). The party carries them in a shared grid or in per-character bags, and money, shops, inns, chests and loot tables are built from the same data and the same Conditions and Effects language as dialogs and quests.

8.1 Basics

8.1.1 The four kinds of item

KindAsset classWhat it is for
ConsumableURSEConsumableDataUsed up: potions, bombs, cures, manuals. Its effect is an ability (Use Ability).
EquipmentURSEEquipmentDataWorn or wielded. Gives stats, affinities, tags and abilities while equipped.
Key itemURSEItemDataStory and puzzle items. Never used up by accident, never sold, never discarded.
DocumentURSEDocumentDataA readable note or book, with one or more pages of text.

All kinds share one asset type, so there is one ID space for saves and one place to look items up.

Fields every item has (URSEItemData):

  • Description and an Icon (or Item Mesh, which the icon tools frame for you).
  • Max Stack (0 means the project default, 99).
  • Buy Price, Sell Price Override (-1 = automatic) and Sellable. A price of 0 means the item has no value: a shop can only sell it with a price override, and the party cannot sell it.
  • Grid Size (cells), Rarity (Item.Rarity.* tag), Category (Item.Category.* tag) and Weight for the grid inventory.

8.1.2 Make your first consumable

  1. RPG Saga Engine → Studio → Content → New item (pick a family such as potion, status cure or bomb), or make the data asset by hand in the Content Browser (Miscellaneous → Data Asset, class RSEConsumableData).
  2. Set the Use Ability. Either pick an existing ability (a heal, a bomb) or make a new one. The ability's Tactics Rules give the item its range, area and Action Point cost in grid battles, and its ATB Rules give it a scope in classic battles. That is how a bomb has an area on the grid and hits a row in ATB.
  3. Tick Usable In Battle (default on). To allow use from the party menu, open the use ability's Field Rules and tick Usable In Field.
  4. Set Buy Price. Optionally add the item to a shop and a loot table.

The plugin ships examples in /RPGSagaEngine/Data/Items/: DA_Item_Potion, DA_Item_Ether, DA_Item_Bomb, DA_Item_Antidote, DA_Item_RevivalPlume, DA_Item_ManualBerserkSlash (teaches an ability), DA_Key_SpireKey (a key item), DA_Doc_FieldGuide (a document) and a full set of DA_Equip_* equipment.

8.1.3 Equipment

An equipment item has a Slot Type (Equip.Slot.*) and an Equipment Type (Equip.Type.*). Classes list the types they may use. While worn it gives:

  • Modifiers (stat modifiers), Affinities (element weakness, resistance, immunity, absorb) and Granted Tags (traits such as status immunities, and the type tag itself, so a shield lets its wearer use shield abilities);
  • Granted Abilities: abilities usable only while it is worn.

Other fields: Two Handed (weapons that also occupy the off-hand slot), Mastery Abilities and Mastery Rate (the item teaches an ability for good after enough use), Bag Size Bonus and Carry Capacity Bonus (a backpack in the per-character inventory), Appearance Part and Weapon Presentation (how it looks on the body, see Weapons), and Action Weapon for action battles.

The slots a character has are a list in Project Settings → RPG Saga Engine → Items → Equipment Slots. Each slot has an id (Weapon, OffHand, Accessory1...), a name, the slot type it accepts, and optional body part and attach settings for the paperdoll. You can start from an Equipment Slot Set preset (use Apply To Project), or let a Game Foundation preset write the list for you.

Equipment results are explicit. Equip returns Ok, Unknown Slot, Wrong Slot, Class Cannot Use, Not In Inventory, Locked (a guest's fixed equipment) or Blocked By Two Handed.

8.1.4 Documents and key items

A document shows its pages when the player reads it from the inventory. A key item is used on the thing in front of the player ("Use on door") or combined with another key item. The puzzles that react to them are in Exploration.

8.1.5 Money, shops, inns and chests

  • Money is one currency with the name, symbol and format you choose.
  • A shop (URSEShopData) lists stock. Each entry can override the price, limit the quantity forever, and appear only while story conditions hold ("after the smith joined").
  • An inn restores the party for a price.
  • A chest is an actor with items, money, an optional key and an "opened" flag saved with the story.
  • Loot tables (URSELootTable) give enemies and encounters their drops.

Shops, loot tables and chests are plain data and actors, described below. A shop is opened by the Open Shop story effect, for example from an NPC's dialog.

8.2 How it works

8.2.1 The flow

Items (data) ──► Inventory (RSECore: stacks, grid layouts, containers)
                  │              │
 Party state ◄────┘              └──► Loot distribution rule ──► who receives what
 (money, equipment, shop stock)
Economy rules (RSECore) ──► Shop / Inn / Chest / Battle loot
Screens (RSE): inventory, shop, chest, reward feed
  • RSECore holds the rules: stacks, equipment checks, prices, buying and selling, loot rolls, distribution. They are headless and tested.
  • RSE holds the screens (inventory board, shop, party menu) and the world actors (chest, stash point).
  • Every inventory change is a serializable command (FRSEInventoryCommand): Move In Grid, Equip, Unequip, Use Item, Sort Container, Discard, Transfer, Auto Distribute, Give Money. The host validates and applies it. That is why co-op works without extra code.

8.2.2 Inventory modes

Project Settings → RPG Saga Engine → Inventory Rules → Mode:

ModeBehaviorBest for
Shared (default)One party inventory, shown as a grid with tabs. Everyone uses it.Classic JRPG, ATB, Tactics
Per CharacterEach member carries a bag. A large shared stash opens at save points (or rest places, or anywhere, by Stash Access). Key items and documents stay shared.Live-field and action games

The mode can change at any time, in either direction. A profile or a Game Foundation preset can set it. Per Character to Shared merges every bag, the stash and the pending loot. Shared to Per Character distributes the items by the distribution rule (Migration: Distribute) or puts everything in the stash (All To Stash). Equipment worn never moves. Nothing is lost.

In Per Character, loot that nobody can carry waits in a Pending Loot tab until taken or distributed (Overflow), and you can add weight: Use Weight gives each member a Carry Capacity (base plus a stat plus equipment), with Overweight Rule Display Only or Block Adding.

8.2.3 Who receives loot

Everything the party gains passes one settle step with a source (battle, chest, pickup, quest, shop, story). A distribution rule only ranks the receivers. The framework fills the best receiver, then the others, then the stash, then the Overflow rule. Built-in rules:

RuleBehavior
Smart (default)Equipment goes to the member who gains most from it (weighted stat changes, with Stat Weights and Minimum Upgrade). Consumables are balanced, steered by Role Rules (ethers to mages). Deterministic.
PickerWhoever picked it up (the leader for battle rewards).
Round RobinNext member for each stack.
All To StashEverything goes to the stash.

A different rule can be set globally, per chest (Loot Rule) or per encounter. You can write your own (see Advanced).

8.2.4 Battle loot and money

On victory the rules roll the loot table of every defeated enemy, in battle order, then the encounter's own loot (Encounter Loot) and its Reward Items. Each entry rolls on its own, so several can drop. The dice come from a stream derived from the battle's seed, so the same battle always drops the same things. The simulator rolls loot exactly like the game.

One battle never gives more money than Battle Money Cap allows for the level of its strongest defeated enemy (a curve you edit). This keeps a late boss's loot table from paying a fortune when used on an early enemy.

8.3 Key classes and assets

Class / assetModuleRole
URSEItemDataRSECoreBase item; also the key item class.
URSEConsumableDataRSECoreConsumable with a Use Ability.
URSEEquipmentDataRSECoreEquipment.
URSEDocumentDataRSECoreReadable document.
URSESaveItemDataRSEA consumable that saves the game anywhere allowed (see Save and load).
URSEEquipmentSlotSetRSECoreAn editor-only preset of equipment slots (classic JRPG set, action-RPG set). Apply To Project writes it into Items → Equipment Slots.
FRSEInventory, FRSEItemStackRSECoreThe shared inventory: stacks of soft item references.
URSEInventorySubsystemRSECoreReceives and applies inventory commands. Fires On Command Applied.
URSEInventoryPermissionPolicyRSECoreWho may do what in co-op.
URSELootDistributionRuleRSECoreBase of distribution rules (URSELootRule_Smart, _Picker, _RoundRobin, _AllToStash).
URSEShopDataRSECoreA shop's stock and rules.
URSELootTableRSECoreMoney range and weighted drops.
ARSEChestRSEA chest actor.
URSEStashPointComponentRSEMarks an actor (inn, camp) as a place that opens the stash.
URSEBlueprintLibrary_ItemsRSECoreGive, take, count items, money, shop and inn functions.

8.4 Settings

Project Settings → RPG Saga Engine:

GroupKey settings (defaults)
ItemsDefault Max Stack (99), Equipment Slots, Off Hand Slot Id, Starting Items, Rarity Tiers and Default Rarity, Stash Tabs (grid containers with filters), Sort Order, Max Item Grid Size (4x4), Allow Discard (off), Permission Policy Class.
Inventory RulesMode (Shared), Shared Kinds, Migration (Distribute), the Bag, Stash and Pending Loot containers, Stash Access (Save Points) and Stash Access Radius, Money Mode, weight options, Distribution Rule, Auto Distribute Rule, Overflow (Pending Loot), Stat Weights, Role Rules. A rules-profile section.
EconomyCurrency Name, Currency Symbol, Money Format ({Amount}, {Symbol}, {Name}), Max Money, Starting Money (200), Sell Ratio (0.5), Buy Price Multiplier (1), Default Inn Cost (50), Inn Revives KO (on), Cap Battle Money and the Battle Money Cap curve. Sell ratio, price multiplier and inn settings can change per profile. The currency, cap and starting money are global.
Inventory UI, Economy UIThe screens' look and behavior (RSE).

The complete lists are in Appendix B.

8.5 Blueprint usage

All nodes below are in the RPG Saga | Items and RPG Saga | Economy categories.

Give the player an item when an NPC dialog ends:

  1. In the dialog, add the story effect Give Item (Item = DA_Item_Potion, Count = 3). No Blueprint needed. Use the Has Item and Take Item conditions and effects the same way.
  2. From Blueprint instead: Event → Give Item (Item = DA_Item_Potion, Count = 3). The node returns how many were added, capped by the stack limit.

Check a key item before opening a door:

  1. Has Item (Item = DA_Key_SpireKey) → Branch.
  2. True: Take Item (if the key is used up), then open the door.

Open a shop and buy:

  1. Dialog effect Open Shop (Shop = DA_Shop_Starter_Z1). The screen opens after the running dialog ends.
  2. Scripted purchases: Can Buy (Shop, Entry Index) → Buy (Shop, Entry Index, Count). Both return a result: Ok, Not Enough Money, Out Of Stock, Unavailable, Inventory Full, Not Sellable or Not Enough Items. Get Buy Price, Get Stock Left and Get Max Buy Count feed a custom shop UI.

Money and inns: Get Money, Add Money, Spend Money, Get Inn Cost and Rest At Inn. In story data use the Has Money condition and the Give Money, Take Money and Rest At Inn effects. Gate the inn choice with Has Money.

Equipment: the party library offers Get Equipment, Get Equipped Item, Can Equip, Equip, Unequip, Get Equip Candidates and Preview Equip (the stats before and after).

React to changes: bind to the inventory subsystem's On Command Applied.

For a full list see Appendix A.

8.6 C++ usage

#include "Items/RSEBlueprintLibrary_Items.h"

// Reward the player and report what happened.
const int32 Added = URSEBlueprintLibrary_Items::GiveItem(this, PotionAsset, 3);

if (URSEBlueprintLibrary_Items::HasItem(this, KeyAsset))
{
    URSEBlueprintLibrary_Items::TakeItem(this, KeyAsset, 1);
}

const ERSEShopResult Result = URSEBlueprintLibrary_Items::Buy(this, ShopAsset, /*EntryIndex*/ 0, /*Count*/ 1);

Equipment changes go through the party library (URSEBlueprintLibrary_Party::Equip, which returns ERSEEquipResult). If you write your own inventory screen, send FRSEInventoryCommand structs through URSEInventorySubsystem::SubmitCommand. Never write the party state directly.

Extension points:

  • URSELootDistributionRule: override RankTargets (a BlueprintNativeEvent) to decide who receives items.
  • URSEInventoryPermissionPolicy: override CanIssue, CanChangeEquipment, CanIssuePartyCommand and CanUseContainer.
  • A new item kind of behavior: make a consumable whose use ability has a Custom effect.

8.7 Advanced

8.7.1 Grid containers and stash tabs

The shared inventory is drawn as a grid. Stash Tabs is a list of container definitions (id, name, icon, grid size, filter). An item appears in the first tab whose filter accepts it, so every item always has a place. A filter matches item kinds and a gameplay tag query over rarity, category, slot and equipment type. A container with Max Height 0 grows as needed. A bounded container (a chest) leaves items it cannot fit unplaced. Sort Order lists the keys auto-sort compares (kind, rarity, category, equip slot, size, name).

8.7.2 Writing a distribution rule

Create a Blueprint class derived from RSE Loot Distribution Rule, override Rank Targets, and pick it in Inventory Rules → Distribution Rule. The input is the party state and a query (the items and their source). The output is a ranked list of containers. Do not fill containers yourself. The framework fills them in order and handles overflow.

8.7.3 Co-op

Each inventory change is a serializable command that the host validates and applies. Pickups To Picker In Coop sends what a player picks up to that player's member first. With Per Character inventory and the default policy, a guest may take items only from the bag of the member they play (see Co-op and online).

8.7.4 Save and migration

Inventory state, grid layouts, shop purchases and money are part of the party save section, so old saves load into the mode in use and distribute as described above. See Save and load.

8.7.5 Content from spreadsheets

Items, shops and loot tables import from spreadsheets (Configurator → Tools → Content Import) and appear in the AI prompt packs. See Editor tools.

8.7.6 Performance

The inventory board draws without per-frame rebuilds. It refreshes when a command is applied. Item icons can be a live 3D preview (Inventory UI settings, CVars RSE.Inventory.LivePreview, RSE.Inventory.PreviewScale, RSE.Inventory.PreviewRate). See Appendix C.

8.7.7 Development commands

In development builds: RSE.Items.Give, RSE.Items.List, RSE.Items.Reset, RSE.Economy.Money, RSE.Economy.OpenShop, RSE.Economy.Rest and RSE.Inventory.ForceStashAccess (stash everywhere). Appendix C lists the arguments.

8.8 Troubleshooting

SymptomCause and fix
A shop will not sell my itemIts Buy Price is 0 and the entry has no Price Override. Set one.
The player cannot sell an itemKey items and documents never sell. Check Sellable and a non-zero price.
An item vanished from the sale listWorn equipment is not in the inventory. Unequip it first.
Equip returns Class Cannot UseThe class does not list the item's Equipment Type.
Equip returns Wrong SlotSlot Type does not match any slot's Accepts Slot Type in Items → Equipment Slots.
A consumable cannot be used from the menuThe use ability's Field Rules → Usable In Field is off, or the target filter does not allow an ally.
The player cannot discard itemsItems → Allow Discard is off (the default). Key items and documents can never be discarded.
A chest stays closedIts Opened Flag is missing, a Required Key is not held, a condition fails, or the stack limit would be exceeded.
Loot went to the wrong member (Per Character)The distribution rule decides. Check Stat Weights, Role Rules and the encounter's or chest's Loot Rule.
Money from a battle is lower than the tableCap Battle Money limits it by the strongest defeated enemy's level. Adjust the curve or turn it off.
The stash will not openStash Access is Save Points and the player is outside Stash Access Radius. Add a RSE Stash Point component to an inn or camp, or change the access.

8.9 See also