Inventory #

Players can obtain weapons and utility items via an Inventory system in Squad Alpha by Say Games.
Players can obtain weapons and utility items via an Inventory system in Squad Alpha by Say Games.

The Inventory meta-system in Hiro enables players to collect, upgrade, and consume items in your game. These in-game items can be anything from a piece of equipment like a sword or chestplate, to a cosmetic item like a flag or costume, to a power up like a spawner or boost.

Inventory items can be purchased from the virtual store, or earned through gameplay.

Customization parameters #

The following JSON represents the customization parameters you can use to configure the default user experience for the inventory system.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
{
  "items": {
    "iron_sword": {
      "name": "Iron Sword",
      "description": "A sharp sword made of iron.",
      "category": "weapons",
      "item_sets": ["common_weapons"],
      "max_count": 99,
      "stackable": false,
      "consumable": false,
      "string_properties": {
        "equipment_slot": "right_hand"
      },
      "numeric_properties": {
        "rank": 1
      }
    },
    "health_potion": {
      "name": "Health Potion",
      "description": "A vial of red liquid used for healing.",
      "category": "potions",
      "max_count": 99,
      "stackable": true,
      "consumable": true,
      "consume_reward": {
        "guaranteed": {
          "energies": {
            "health": {
              "min": 100
            }
          }
        }
      }
    },
    "small_crafting_bag": {
      "name": "Small Crafting Bag",
      "description": "A small bag of miscellaneous crafting materials.",
      "category": "loot_bags",
      "max_count": 99,
      "stackable": false,
      "consumable": true,
      "consume_reward": {
        "max_rolls": 2,
        "weighted": [
          {
            "items": {
              "leather_scraps": {
                "min": 1,
                "max": 5
              }
            },
            "weight": 50
          },
          {
            "items": {
              "bronze_nails": {
                "min": 5,
                "max": 100,
                "multiple": 5
              }
            },
            "weight": 50
          }
        ]
      }
    }
  }
}

The JSON schema defines several objects which define the various items and item sets that will be available in your game. You can configure as few or as many of each as needed for your desired gameplay.

items #

The items object is structured as follows:

PropertyDescription
nameThe name for this item.
descriptionThe description for this item.
categoryThe category for this item.
item_setsAn array of string values that indicate which item sets this item belongs to.
max_countThe maximum number of this item a user can own.
stackableA bool value indicating whether this item can stack.
consumableA bool value indicating whether this item can be consumed.
consume_rewardA reward object that defines what rewards a user can or will receive for consuming the item.
string_propertiesA map of string values that define item specific metadata.
numeric_propertiesA map of number values that define item specific metadata.

Item definitions #

Item categories #

Every item definition has a category property. This is a simple string property that defines which broad collection the item belongs to and is useful for listing items. For example, you may wish to separate your items into categories such as weapons, armor, and potions.

Item sets #

Item definitions can optionally define an array of item_sets that they belong to. Item sets differ from categories in that an item can belong to multiple sets at once. These item sets can be used as tags for the items in your game such as rare and sword.

Item sets are used in the reward system to allow users to be rewarded with a random item that belongs to specific sets (see example below).

Item rewards #

A powerful feature of the Inventory system is the ability for game designers to add consume rewards to item definitions. When a user consumes the item, they will be granted the reward accordingly. Due to the power and flexibility of the Hiro reward system, this allows game designers the opportunity to create all manner of consumables.

Consider the following scenarios and associated item definitions:

A potion that restores 50 health

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
{
  "health_potion": {
    "name": "Health Potion",
    "description": "A vial of red liquid used for healing.",
    "category": "potions",
    "max_count": 99,
    "stackable": true,
    "consumable": true,
    "consume_reward": {
      "guaranteed": {
        "energies": {
          "health": {
            "min": 100
          }
        }
      }
    }
  }
}

A coin pouch that rewards between 100 and 500 gold coins in multiples of 10

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
{
  "coin_pouch": {
    "name": "Coin Pouch",
    "description": "A small pouch of gold coins.",
    "category": "bags",
    "max_count": 99,
    "stackable": true,
    "consumable": true,
    "consume_reward": {
      "guaranteed": {
        "currencies": {
          "coins": {
            "min": 100,
            "max": 500,
            "multiple": 10
          }
        }
      }
    }
  }
}

A loot chest that rewards a sword and a random rare weapon

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{
  "loot_chest": {
    "name": "Loot Chest",
    "description": "A shiny chest full of treasure.",
    "category": "chests",
    "max_count": 99,
    "stackable": false,
    "consumable": true,
    "consume_reward": {
      "guaranteed": {
        "items": {
          "bronze_sword": {
            "min": 1
          }
        },
        "item_sets": [
          {
            "set": ["rare", "weapon"],
            "min": 1
          }
        ]
      }
    }
  }
}

A loot chest that rewards a weighted random currency

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{
  "currency_chest": {
    "name": "Currency Chest",
    "description": "A shiny chest full of unknown currency.",
    "category": "chests",
    "max_count": 99,
    "stackable": false,
    "consumable": true,
    "consume_reward": {
      "max_rolls": 1,
      "weighted": [
        {
          "currencies": {
            "coins": {
              "min": 100
            }
          },
          "weight": 80
        },
        {
          "currencies": {
            "gems": {
              "min": 10,
              "max": 20,
              "multiple": 5
            }
          },
          "weight": 20
        }
      ]
    }
  }
}

Item instances #

When a user is granted an item, whether from a Store Purchase, as a Reward, or any other means, it is stored as an item instance inside their inventory. The inventory itself is stored inside the Storage Engine under a special collection/key for that user.

A user’s inventory has the following JSON schema.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{
  "2cb9c733-a2c8-498f-aaed-8ba24a989c45": {
    "item_id": "iron_sword",
    "owned_time": 1674300933,
    "update_time": 1687347732,
    "count": 1,
    "string_properties": {
      "equipment_slot": "right_hand",
      "gem_slot_1": "strength_ruby",
      "gem_slot_2": "dexterity_emerald"
    },
    "numeric_properties": {
      "rank": 3,
      "monsters_defeated": 435
    }
  },
  "e264eaa7-6bc0-4a78-99ed-18fdadf3afea": {
    "item_id": "potion",
    "owned_time": 1654334562,
    "update_time": 1654338987,
    "count": 12,
    "string_properties": {},
    "numeric_properties": {}
  }
}

The inventory is a map of item instance IDs and the associated item instance data, where each item instance has the following structure.

PropertyDescription
item_idThe ID of the item definition this is an instance of.
owned_timeThe time that this item was acquired.
update_timeThe time that this item was last updated.
countHow many of this item the user currently has.
string_propertiesA map of string values that define item instance specific metadata.
numeric_propertiesA map of number values that define item instance specific metadata.

Item properties #

Each item instance will copy across any properties that are defined in the string_properties and numeric_properties of the item definition by default.

Because item instances have their own metadata, this allows you to build systems where a user can customize, rank up, or modify the items they own. For example, you may have a weapon rank system that allows your players to “level up” their weapons, or a “gem slot” system that allows players to improve the stats of their items by socketing various gems to them, or perhaps you just want to keep track of how many monsters a user has defeated with a particular weapon as shown in the example above.

Item stacking #

Where an item is granted that is defined as stackable, the inventory system will first check to see if the user currently has an item instance for that item ID. If they do, the count property of that particular instance will be increased accordingly. If they don’t, or if the item is not stackable, a new item instance will be generated instead and added to the user’s inventory.

Interacting with the Inventory system #

Listing the available items #

You can list the available items in the inventory system.

1
2
3
4
5
6
7
8
var result = await inventorySystem.ListAsync();

foreach (var itemKvp in result.Items)
{
    var id = itemKvp.Key;
    var item = itemKvp.Value;
    Debug.Log($"Item {id}: {item.Name} - {item.Description}");
}

Listing the user’s inventory #

You can list a user’s inventory.

1
2
3
4
5
6
7
8
var result = await inventorySystem.ListInventoryAsync();

foreach (var itemKvp in result.Items)
{
    var id = itemKvp.Key;
    var item = itemKvp.Value;
    Debug.Log($"Item {id}: {item.Name} - {item.Description}");
}

You can also filter the inventory by categories.

1
2
3
var category = "<category1>";

var inventory = await inventorySystem.ListInventoryAsync(category);

Granting inventory items #

You can grant inventory items to the user.

1
2
3
4
5
6
7
var items = new Dictionary<string, long>
{
    { "<itemId1>", 1 },
    { "<itemId2>", 10 }
};

await inventorySystem.GrantItemsAsync(items);

Consuming items #

You can consume items for a user that have the consumable flag. You can specify whether or not the user is allowed to overconsume (use more than they have).

Setting overconsume to true can be useful when handling multiple device scenarios. This allows consumption of the item, even if the local device’s resource data is out of sync. However, once the item reaches zero, further consumption is prevented, irrespective of the overconsume setting. This provides developers flexibility in managing inventory inconsistencies across devices.
1
2
3
4
5
6
7
8
9
var toConsume = new Dictionary<string, long>
{
    {"<consumableId1>", 2},
    {"<consumableId2>", 1}
};

var overconsume = false;

await inventorySystem.ConsumeAsync(toConsume, overconsume);

Refreshing the inventory system #

You can refresh the inventory system’s data.

1
await inventorySystem.RefreshAsync();