Introduction

The documentation for newer versions of the asset has been moved to a new location! Click here to be redirected.

New versions of exINV are released for Game Maker: Studio 2 only. For the GMS 1 version, please refer to the legacy documentation

About

exINV is a general purpose inventory system that provides ready to use assets to manage an item database, multiple inventories and a comprehensive user interface built on top of that, including features like crafting and equipment selection and saving / loading mechanisms.

exINV can be seen as a collection of three main modules: Database system, Inventory system and User Interface & Logic (UI).

It is important to understand that while the Database system & the Inventory system are generic enough to be used as they are in any project, the UI and its logic may differ greatly from one project to another, depending on the desired result.
The UI and the other modules are, however, totally decoupled. This means that you can safely import all the scripts into any project and they'll work out of the box, since they do not reference any pre-defined object.
The provided UI instead is a structured and commented example built on top of that; you will need to edit and adapt it to your needs, or simply start from scratch and build your own.

Getting started

Before integrating the asset into an existing project, you are strongly encouraged to test it out by importing everything into a blank project, and running the demo to get a feel of what you can do and expect beforehand.

Integrating exINV into your existing project requires a few steps, described below:

1. Importing the "ex" folders

While you may not need everything included in the package, it is strongly suggested to work in a subtractive way, by adding all ex folders from the package resource tree to your game, and edit / remove what you don't need afterwards. All the assets in those folders are namespaced so you should not find any name clash with your current resources.

The few assets outside of those folders are part of the demo. You are encouraged look at them, but are not meant to be imported directly into your project.

2. Initializing the system

The first thing you have to do is initialize the inventory system. You should only do that once, ideally at game start. In the demo project this is done in obj_init_rm_controller, in your project you should add this code in your game initialization routine. Note that you need to provide the full sandbox path to your CSV files.

//initialize and load the sample database csv files
ex_init();
ex_db_load("ex/inv_armor.csv","ex/inv_food.csv","ex/inv_potions.csv","ex/inv_weapons.csv");

//(optional) initialize the crafting system
ex_craft_init();

3. Creating an inventory

Once the system is initialized, you may start creating inventories.

//create an inventory with 30 slots
global.inv_player = ex_inv_create(30);

4. Inserting items

Items are identified by a unique item key (as string). This and the other item properties are defined in the item database loaded in step 2.

//add a bow and some arrows
ex_item_add(global.inv_player,"weapon_fire_arrow",64);
ex_item_add(global.inv_player,"weapon_wooden_bow",1);

5. Displaying the inventory

So far we loaded the item database, created an inventory, and added some items in it. But this is all handled in memory, if you try to run the code above, you will not see anything graphically. This is because inventory managament and UI are decoupled and mostly independent.
The next step therefore is to display the inventory we just created, by creating an instance of a panel that is able to diplay that specific inventory.

//display the inventory using the obj_inv_panel_backpack object
//at position 32,32 on the inventory_panels layer
ex_ui_panel_show_layer(global.inv_player,obj_inv_panel_backpack,32,32,"inventory_panels");

You are strongly encouraged to look at the provided demo and go through every event of obj_inv_controller, since this is where most of the above (and a lot more) is defined, and use that to build your own.

It is also worth noting that inventories (as created by ex_inv_create()) are to be treated exactly like data structures. This means that inventory data is persistent across room changes, and needs to be released from the memory when not needed anymore by using ex_inv_destroy().
You should therefore avoid creating new player inventories from scratch in every room, just be sure to do so in the first room of a new game and use panel objects to display them in one or more rooms.

6. Customize

The next step is to customize the inventory system to your needs. Some obvious things you may want to change are:

  • Modify the item database defined in the included CSV files
  • Edit the default sprites
  • Extend the crafting system and define the recipes
  • Edit the behavior of the default panels

Database system

Introduction

The database stores a collection of all the items in your inventory system along with their properties, and allows a fast and easy access to this data. It is worth noting that database data should be considered read-only. If you feel the need to change or give specific items some individual attributes at runtime, you can do that using tags (see related section).

Data files

Database data is stored in one or more CSV files located in the included files of your project. You can load multiple files at one using ex_db_load(file1,file2,...). Each file can define different properties for the items it contains, but there are some requirements:

  • The first row holds the attribute names.
  • The second row holds the type for each attribute, that is either string, real, or asset. string and real are self explanatory, asset instead means that the column holds an asset name (like a sprite or object name).
  • You are required to define an attribute named key of type string, holding a unique (among all files!) identifier per item.
  • You are required to define an attribute named stack_size of type real, holding the maximum stack size for the item (1 for non stackable items)

Please refer to the included files for an example of all of the above.

Database structure

The database itself holds the items defined in the CSV as ds_maps, accessed by their key.
Along with the database, a ds_list of all keys is also generated and accessible with ex_db_keys(). This can be useful for example when you need to get a random item, as it's enough to get a random element from the list.

Scripts reference

ex_db_get(key)

Returns a ds_map holding all the data of the item with the specified key.

var item = ex_db_get("weapon_fire_arrow"); //get the fire arrow item data
var item_name = item[? "name"]; //get the name property of the item
ex_db_keys()

Returns a ds_list where all database keys are stored. This can be useful for example for selecting a random item, or determining the size of the database.

var keys = ex_db_keys();
var keys_count = ds_list_size(keys);
var random_item_key = keys[| irandom(keys_count)-1];
ex_db_load(file1,file2,...)

Loads data from one or more CSV files (as described above) into the database.

ex_db_load("inv_armor.csv","inv_food.csv","inv_potions.csv","inv_weapons.csv");

Inventory system

Introduction

An inventory is a special data structure holding a predefined number of slots. Like regular data structures, they are kept in memory as long as the program is running or the inventory explicitly destroyed with ex_inv_destroy();

While inventories are meant to be displayed and interact with the player input, in exINV they are not tied to a visual representation, since that's the UI role. You can create and perform all kind of operations on inventories without ever displaying them.

The only exception to the above is represented by the script ex_inv_updated, which is called every time an inventory changes, and includes the code required to update the UI objects accordingly (if present).

Inventories

The following scripts exist to deal with inventories.

Scripts reference

ex_inv_clear(inv)

Clears an inventory by deleting all its contents, but does NOT destroy the inventory iteself.

inv {integer} inventory to clear

ex_inv_clear(global.inv_player);
ex_inv_count(inv,key)

Returns the amount of items matching the provided key.

inv {integer} inventory
key {string} key of the items to count

returns {integer} number of items matching the key

var amount = ex_inv_count(global.inv_player,"food_cheese");
ex_inv_create(size)

Creates a new empty inventory having the specified number of slot

size {integer} number of slots

returns {integer} the inventory id

global.inv_player = ex_inv_create(30);
ex_inv_destroy(inv)

Destroys an inventory and all its contents. This generates an inventory_destroyed event for the related UI panels, automatically closing them.

inv {integer} inventory to destroy

ex_inv_destroy(global.inv_player);
ex_inv_max_size(inv)

Returns the total number of slots of an inventory, either empty or full. Use ex_inv_size to get only the number of non-empty slots.

inv {integer} inventory

returns {integer} total number of slots

var free_slots = ex_inv_max_size(global.inv_player) - ex_inv_size(global.inv_player);
ex_inv_read(data)

Creates and returns an inventory from a string generated using ex_inv_write.

data {string} string containing inventory data

returns {integer} the inventory id

//replace the player inventory with some previously saved data
ex_inv_destroy(global.inv_player);
global.inv_player = ex_inv_read(save_data);
ex_inv_resize(inv,new_size)

Resizes an inventory by adding or removing slots according to the new size. Items in extra slots are removed.
This function generates an inventory_resized event on its open UI panels. By default panels create or destroy the slot instances according to the new size, but you should probably override this event in your panel objects according to the behavior you expect.

inv {integer} inventory to resize
new_size {integer} new size

//resize the player inventory to 8 slots
ex_inv_resize(global.inv_player,8);
ex_inv_size(inv)

Returns the number non-empty of slots of an inventory. Use ex_inv_max_size instead if you need the amount of (either empty or filled) slots of an inventory.

inv {integer} inventory

returns {integer} number of non empty slots

var free_slots = ex_inv_max_size(global.inv_player) - ex_inv_size(global.inv_player);
ex_inv_sort(inv,sort_by,order)

Sorts the inventory base on a specific attribute. When sorting, items will always have higher priority over empty slots.
sort_by can either be an item attribute as defined in the database like "name" or "key", or a meta value like the stack amount. In the first case, you just pass the attribute as a string. In the second, you'll need to use a value from the EX_COLS enum. The most useful are:

EX_COLS.index - Sorts by slot index
EX_COLS.key - Sorts by item key
EX_COLS.amount - Sorts by stack amount

inv {integer} inventory to sort
sort_by {integer|string} sort attribute
order {boolean} if true, sorts in ascending order, descending otherwise

//sort the player inventory by item name
ex_inv_sort(global.player_inv,"name",true);
ex_inv_updated(event,[affected_slots])

This script gets called whenever an inventory changes in some way. You should not call this script directly.
If you are implementing your own UI on top of exinv, you should adapt this script to suit your needs.

event {integer} update event (from EX_EVENTS enum)
[affected_slots] {ds_list} list of slots affected by the update (only for EX_EVENTS.slots_updated)

ex_inv_write(inv)

Returns a JSON encoded string of the specified inventory. You can use the output of this function to serialize the inventory to file, and read it back using ex_inv_read.

inv {integer} inventory to encode

returns {string} a JSON string representation of the provided inventory

//save the equipment inventory to file

var data = ex_inv_write(equipment_inv);

var file = file_text_open_write("equipment.inv");
file_text_write_string(file,data);
file_text_close(file);

Inventory items

An item in an inventory slot is a collection of 6 values, all of which can be accessed using an appropriate function:

  • index: the slot index (number) where the item is stored (starts at 0, being the first slot)
  • amount: the amount of items in the slot (stack). Default: 0
  • key: the key of the item. Default: ""
  • item: a reference to the item data (a ds_map) in the database. Default: -1
  • stack_id: a string used to test item stacking (more on that in the tags section). Default: ""
  • tags: a ds_map holding the specific item tags (if any). Default: -1

You can access those properties at any time using the ex_item_get_* functions.

It is important to note that every item of the same type (that is, having the same key), references the same data in the database. You should not change the item data in any way, as this would change the database directly. If you want to give an item some extra attributes, you should use tags.

Scripts reference

ex_item_get_amount(inv,slot)
ex_item_get_item(inv,slot)
ex_item_get_key(inv,slot)
ex_item_get_stack_id(inv,slot)
ex_item_get_tags(inv,slot)

Returns an attribute at the given slot index of the specified inventory.

inv {integer} inventory
slot {integer} slot index

returns the attribute at the specified slot

var item = ex_item_get_item(global.inv_player,0);
if(item >= 0) {
show_debug_message("Name of the item in slot 0: " + item[? "name"]); }
else {
show_debug_message("The slot is empty!"); }
ex_item_add(inv,key,amount,[slot],[tags])

Inserts an item into an inventory in the first available slot(s), or in the specific slot. If a slot is specified and the item you are trying to add can not be stacked, the items are not added ( or only partially if reaching stack limit).

inv {integer} inventory
key {string} key of the item to insert
amount {integer} amount of items to insert
[slot] {integer} (optional) slot to insert the item(s) into. Default: -1
[tags] {ds_map} (optional) a ds_map holding the item tags.

returns {integer} the number of items inserted (same as amount given enough space in the inventory or slot)

IMPORTANT: you can optionally assign tags to an item directly, by passing a ds_map to this function. if you do that, the inventory always stores a copy of the ds_map. You are free to edit or destroy this map afterwards without affecting the inventory.

//add 16 carrots to slot 3 of the player inventory
var n = ex_item_add(global.player_inv,"food_carrot",16,3);
show_debug_message(string(n) + " carrots have been inserted in slot 3 of the toolbar!");
ex_item_clear(inv,slot)

Clears (removes) the content of a slot

inv {integer} inventory
slot {integer} slot index

//clear slot 0 of the player inventory
ex_item_clear(global.inv_player,0);
ex_item_copy(inv1,slot1,inv2,amount,[slot2])

Adds an item to an inventory or slot by copying the contents from another inventory. Tags are copied as well. inv1 and inv2 do not necessarily need to be different, it is possible to copy items from one slot to another on the same inventory.

inv1 {integer} inventory to copy the item from
slot1 {integer} slot index in inv1
inv2 {integer} inventory to copy the item to
amount {integer} amount to copy. If set to -1, all items in slot 1 are copied
[slot2] {integer} (optional) slot index in inv2. If omitted, the item will be copied in the first available slot.

returns {integer} the amount of items actually copied.

//copy the contents of slot 0 of the player inventory to the toolbar
ex_item_copy(global.inv_player,0,global.inv_toolbar,-1);
ex_item_find(inv,key,find_type)

Returns the index of the first slot holding an item with the specified key.

When multiple copies of the item having the specified key are present, the result depends on the find type applied. Find types are defined in the EX_FIND enum, as follows:

EX_FIND.first: returns the first slot index found
EX_FIND.last: returns the last slot index found
EX_FIND.low: returns the slot index having the lowest amount of items in the stack
EX_FIND.high: returns the slot index having the highest amount of items in the stack

inv {integer} inventory
key {string} key of the item to look for
find_type {integer} type of search operation defined by the EX_FIND enum

returns {integer} the slot index if found, or -1 if nothing is found.

//print the index of the first slot in the toolbar having carrots
var slot = ex_item_find(global.inv_toolbar,"food_carrot",EX_FIND.first);
if(slot >= 0) {
show_debug_message("Found some carrots in slot " + string(slot)); }
else {
show_debug_message("No carrots found"); }
ex_item_move(inv1,slot1,inv2,amount,[slot2])

Moves a specific amount of items (or stack) in a slot to another inventory (or another slot in the same inventory).

inv1 {integer} inventory to move the item from
slot1 {integer} slot index in inv1
inv2 {integer} inventory to move the item to
amount {integer} amount to move. If set to -1, all items in slot 1 are moved
[slot2] {integer} (optional) slot index in inv2. If omitted, the item will be moved in the first available slot.

returns {integer} the amount if items actually moved.

//move all items in slot 0 of the toolbar to the player inventory
ex_item_move(global.inv_toolbar,0,global.inv_player,-1);
ex_item_remove(inv,key,amount,[slot])

Removes item(s) from an inventory, or a specific slot

inv {integer} inventory
key {string} key of the item(s) to remove
amount {integer} amount of items to remove. If set to -1, removes all items from a slot (if specified), or all items having that specific key in the inventory.
[slot] {integer} (optional) slot to remove the item(s) from

returns {integer} the amount if items actually removed

var n = ex_item_remove(global.inv_player,"food_carrot",8);
show_debug_message(string(n) + " carrots have been removed from the inventory!");
ex_item_set(inv,key,amount,slot,[tags])

Inserts an item into an inventory slot, replacing any previous content.

inv {integer} inventory
key {string} key of the item to set
amount {integer} amount of items to add
slot {integer} slot to set items into
[tags] {ds_map} (optional) a ds_map holding the item tags.

returns {integer} the amount if items actually inserted

IMPORTANT: you can optionally assign tags to the item directly, by passing a ds_map to this function. If you do that, the inventory always stores a copy of the ds_map. You are free to edit or destroy this map afterwards without affecting the inventory.

//replace the contents of the first slot of the toolbar with a carrot
ex_item_set(global.inv_toolbar,"item_carrot",1,0);
ex_item_switch(inv1,slot1,inv2,slot2)

Swaps the items of the specified slots (either in the same inventory or different ones)

inv1 {integer} first inventory
slot1 {integer} slot in the first inventory
inv2 {integer} second inventory
slot2 {integer} slot in the second inventory

//switch the first two slots in the toolbar
ex_item_switch(global.inv_toolbar,0,global.inv_toolbar,1);
ex_item_test(inv,key,amount,[slot],[tags])

Returns the items that would be added by calling ex_item_add() with the same arguments, but doesn't actually add them to the inventory.

inv {integer} inventory
key {string} key of the item to test
amount {integer} amount of items to test
[slot] {integer} (optional) slot to test the item(s) insertion. Default: -1
[tags] {ds_map} (optional) a ds_map holding the item tags.

returns {integer} the number of items that would be inserted by ex_item_add

ex_item_test_ext(inv1,slot1,inv2,amount,[slot2])

Returns the items that would be added by calling ex_item_copy() with the same arguments, but doesn't actually add them to the inventory.

inv1 {integer} inventory to copy the item from
slot1 {integer} slot index in inv1
inv2 {integer} inventory to copy the item to
amount {integer} amount to copy. If set to -1, all items in slot 1 are copied
[slot2] {integer} (optional) slot index in inv2. If omitted, the item will be copied in the first available slot.

returns {integer} the number of items that would be inserted by ex_item_copy

Tags

As mentioned in the previous sections, item properties in the database are to be considered immutable. An item having a certain key shares the same attributes as all the other items having that same key.
It is common though for specific items to have some unique and independent properties that need to be set at runtime: that's where tags come into play. Tags can be assigned to any item or stack in a specific slot and allow defining any number of attributes specific to that item or stack.

While there are some functions allowing tags manipulation, it is worth keeping in mind that tags for a specific slot are stored in a ds_map. When getting the tags of a slot using ex_item_get_tags(), you are in fact returning a ds_map (or -1 if no tags are set) and you free to read them as you normally would using ds_map functions and accessors. You should definitely avoid though altering the ds_map directly in any way, due to stacking.

Tags vs stacking

In short, two items having the same key but with different tags will not stack, ever. If both items have no tags, or the tags happen to be exactly equal, they will stack as usual (if the item is stackable to begin with).

It may be worth knowing how the above works in practice, since comparing ds_maps is a slow process and you may be concerned about performance.
Whenever you set or change the tags of an item using the tag scripts, the contents of the ds_map are serialized in a string, hashed using MD5 and the result is stored in the stack_id property of the inventory slot. This property is then used to tell when to stack or not stack items when moving them around.
You are free to change how the stack id is generated by editing the _ex_prv_generate_stack_id script.

Scripts reference

ex_tag_delete(inv,slot,tag)

Deletes the tag from the item (or stack) in the given slot

inv {integer} inventory
slot {integer} slot index
tag {string} tag to remove

ex_tag_delete(global.inv_player,0,"fire_damage");
ex_tag_exists(inv,slot,tag)

Returns true if the tag exists for the item (or stack) in the specified slot

inv {integer} inventory
slot {integer} slot index
tag {string} tag

returns {boolean}

if(ex_tag_exists(global.inv_player,0,"fire_damage")) {
var fd = ex_tag_get(global.inv_player,0,"fire_damage");
show_debug_message("Fire damage: " + string(fd));
}
ex_tag_get(inv,slot,tag)

Returns the value of the specified tag.

inv {integer} inventory
slot {integer} slot index
tag {string} tag to return

returns the tag value

//get a tag holding the item durability. Ff the item is worn out, it is removed from the inventory.
var durability = ex_tag_get(global.inv_toolbar,0,"durability");
if(durability <= 0) {
ex_item_clear(global.inv_toolbar,0); }
ex_tag_set(inv,slot,tag,value)

Sets the value for the specified tag, creating the tag if it doesn't exist, or replacing the value of the existing tag.

inv {integer} inventory
slot {integer} slot index
tag {string} tag
value {any} value

var durability = ex_tag_get(global.inv_toolbar,0,"durability");
ex_tag_set(global.inv_toolbar,0,"durability",durability-1);
ex_tags_replace(inv,slot,tags)

Replaces ALL the tags of an item (or stack) in a slot with the values in the provided ds_map

inv {integer} inventory
slot {integer} slot index
tags {ds_map|integer} new tags as ds_map, or -1 to remove the current tags

ex_tags_size(inv,slot)

Returns the number of tags for the item in the given slot

inv {integer} inventory
slot {integer} slot index

returns {integer} number of tags for the item

User Interface

Introduction

The user interface determines how inventories are displayed to the user, and all the logic that handles how the inventory behaves when the user interacts with them.

As such, while the inventory system and database system are generally project agnostic, the UI is instead an opinionated resource, and differs greatly from game to game, not just in appearance but in functionality too. exINV provides a flexible base for you to work on top, with some common inventories like crafting, player inventory, toolbar and equipment management, but it's up to the programmer to refine or rewrite this part based on his needs.

It is important to understand that the inventory itself and the UI are decoupled, meaning that there is no reference to objects or instances inside ex_inv scripts, with the notable exception of ex_inv_updated . This is the script that ties UI and inventories, and is in charge of notifying the UI that something changed inside the inventories.

The UI is managed and displayed by using 3 main objects, found in the ex/core/ folder: Panels (obj_inv_panel), Slots (obj_inv_slot), Mouse, (obj_inv_mouse).

Panels

Panels are containers that handle the general logic of an inventory and its appearance, and are in charge of maintaing a number of slot instances associated with the inventory.

obj_inv_panel defines the shared default logic of ALL of your inventories. In general, you do not want create instances of obj_inv_panel directly; instead, every inventory should have its own panel object, as a child of obj_inv_panel, that overrides / defines its specific behavior. Knowing how inheritance works in Game Maker is fundamental to customize and create panels.

Showing / hiding panels

The following scripts are available to show / hide panels:

ex_ui_panel_hide(panel)

Hides (destroys) a specific panel instance or object.

panel {object|instance} either an instance of a panel (to close that specific instance), or an object, closing ALL panel instances belonging to that object.

ex_ui_panel_show_depth(inv,panel_obj,x,y,depth)

Displays a panel at the specified coordinates at the specified depth.

inv {integer} inventory id
panel_obj {object} panel to show
x {integer} x position of the panel
y {integer} y position of the panel
depth {integer} depth at which the panel is instantiated

returns {instance} The panel instance

ex_ui_panel_show_layer(inv,panel_obj,x,y,layer)

Displays a panel at the specified coordinates on the specified layer.

inv {integer} inventory id
panel_obj {object} panel to show
x {integer} x position of the panel
y {integer} y position of the panel
layer {string} layer where the panel is instantiated

returns {instance} The panel instance

 

It is worth noting that when opening / closing panels we are in fact creating and destroying instances of the specific panel objects, without affecting the inventory data.

Opening a panel returns the panel instance, that by default lets you access the following variables:

inv: The inventory id referenced by the panel
slots: An array of slot instances that matches the size of the slots in inv

Defining new panels

The minimum requirement when creating a new panel object is to implement the "create slot" event (event user 0). This event is in charge of creating the right amount of slots in the right position.

The folder ex/panels/ provides a few useful examples you can use to build your own logic. The most basic one being obj_inv_panel_backpack, that simply implements the create slots event.
More complex examples are provided, like the equipment panel, where restrictions are applied to specific slots in order to allow only the right type of item for each armor piece.

Panels events

Panels work by defining an implementation for specific events. Those are defined by the INV_PANEL_EVENTS enum (in the create event) which references user events that get triggered automatically at specific times. A panel needing a specific action for an event should override the default event, replacing the default behavior defined by obj_inv_panel (if present).

Create slots event (event_user_0): Called right after the panel is created. Slot instances have to be created in this event.
Inventory refresh event (event_user_1): Called once after the inventory changes in some way. This is used for example in obj_inv_panel_equipment to update the armor rating whenever something some equipment is added / removed to the inventory
Inventory resized event (event_user_2): Called when the inventory gets resized by ex_inv_resize(). By default, destroys all the current slots and calls the create slots event again.
Inventory Destroyed event (event_user_3): Called when the inventory gets destroyed by ex_inv_destroy(). By default, destroys the panel instance and the slots.
Slot updated event (event_user_4): Called when a slot is updated. In this event, you can use other to refer to the specific slot.
Slot left pressed (event_user_5): Called when a slot is left clicked. In this event, you can use other to refer to the specific slot.
Slot right pressed (event_user_6): Called when a slot is right clicked. In this event, you can use other to refer to the specific slot.

Extending panels events

Panel events are meant to be extended based on the functionalities you need. If, for example, you want something to happen when the middle mouse button is pressed on a slot, you'll have to:

  • 1. add the event to the INV_PANEL_EVENTS enum in obj_inv_panel create event.
  • 2. Add a middle mouse pressed event to obj_inv_slot that calls the event for the panel: with(panel) {event_user(INV_PANEL_EVENTS.slot_middle_pressed)}
  • 3. Add the event user associated to the event number defined in step 1 to obj_inv_panel, and add the code that should be executed when this event gets called. If the code is not common to all or most of the panels, leave it blank and implement it in the specific panels that need it.

Slots

Panels hold a collection of obj_inv_slot instances visually representing the items of the inventory, and also in charge of detecting the user interaction (left click, right click, etc.).

Slot instances are generally created in the "create slot event" of the panel, using one of the following scripts:

ex_ui_slot_create(panel,index,x,y,depth_or_layer,slot_object)

Creates and returns a slot for the specified panel.

panel {instance} the panel instance the slot is associated to
index {integer} index of the slot referenced in the inventory (starting at 0)
x {integer} x position of the slot relative to the panel
y {integer} y position of the slot relative to the panel
depth_or_layer {integer|string} depht (as a real) or layer (as a string) where the slot instance is created slot_object {object} slot object to instantiate. Usually obj_inv_slot, but you may define different kinds of slot objects if you need to.

returns {instance} The slot instance

ex_ui_slots_build(panel,slot_object,columns,distance,[x_offset],[y_offset],[depth_or_layer])

Automatically generates ALL the slots for a panel, arranging them in a grid layout.

panel {instance} the panel instance the slots are associated to
slot_object {object} slot object used to instantiate. Usually obj_inv_slot, but you may define different kinds of slot objects if you need to.
columns {integer} how many slots per row to generate, before going to the next row
distance {integer} distance between slots in pixels (from origin to origin)
[x_offset] {integer} (optional) x position of the first slot relative to panel origin. Default: 0
[y_offset] {integer} (optional) y position of the first slot relative to panel origin. Default: 0
[depth_or_layer] {integer|string} (optional) depht (as a real) or layer (as a string) where the slot instances are created

returns {instance} The slot instance

 

Slot instances are automatically updated to reflect the contents of the inventory slot they are linked to. You are able to access the following variables:

item: Reference to the database ds_map holding the item properties (-1 if empty)
key: Key of the item currently in the slot ("" if empty)
amount: Number of items in the slot (stack)
index: Index of the slot in the inventory
tags: Tags ds_map associated to the inventory item (-1 if no tags defined or slot empty)
rel_x: x position of the slot relative to the panel
rel_y: y position of the slot relative to the panel
panel: Rerefence to the panel instance holding the slot instance
inv: Reference to the inventory

It is important to understand that slots are slaves with respect to inventory data, changing for example the item, amount or key variables of the slot instance will do absolutely nothing to the inventory itself.
Slots are automatically updated whenever the inventory changes.

Mouse

While not required, by default exINV assumes that the UI is managed by the player using the mouse, in charge of temporarily holding the items being moved around.
obj_inv_mouse defines all the required logic to handle this.

obj_inv_mouse is in fact programmed as a regular panel having a single slot. This means that, if you want to use the mouse in your game, you are in charge of creating (and destroying) the mouse inventory yourself using ex_inv_create(1);. Like other panels, you are also supposed to open / close the mouse panel whenever necessary.

Inventory controller

Unlike previous versions of exINV, in the current version the use of an inventory controller is not enforced anymore.
You are still encouraged to create one such object to manage all the high level logic though, and in fact the ex/demo/ folder includes an example implementation (obj_inv_controller) that does all the heavy lifting of creating, opening, closing and positioning of the UI panels in the room.

Other functionalities

Crafting system

Crafting is a broad term referring to in game item creation, generally by consuming other items. There is no single crafting system nor implementation that fits every game, therefore the provided cafting system is simply an example of how this can be achieved using exINV.

Crafting recipes are defined at game start by the script ex_craft_init(), which generates a recipes database, each recipe holding the required items and the resulting item (as well as its quantity).

The panel obj_inv_panel_craft is in charge of checking the recipes and eventually produce the resulting item, by consuming the recipe items.
It defines 4 slots that are dedicated to ingredients, and a special slot where the resulting items are generated. The panel defines a very specific logic for the result slot, prohibiting anything from being inserted there and consuming ingredients when the player actually get something out of it.

obj_inv_panel_craft also generates and keeps an updated ds_list of item keys based on the 4 ingredient slots, which is then sorted and compared to all recipe ingredient lists whenever an item is inserted or removed from the ingredient slots. By sorting both recipe and ingredients lists, we ensure that the order of the items plays no role in determining if a recipe is valid.

Keep in mind that this approach is relatively simple, but also limited in scope. It does not consider, in contrast for example with minecraft, the number of ingredient items in the same slot, nor the position in the crafting grid

Equipment

The equipment panel included in the package is a special example showing how you can easily arrange inventory slots in a non grid layout while maintaining all the default functionalities, and also work on top of that setup in order to restrict the slots to specific item types.

The above has been achieved by keeping each slot instance in a variable, used in turn to test the contents before inserting an item. The actual testing of the items against the slot is defined in the script ex_equipment_allowed, which should be adapted in order to reflect the logic you require.

Previous versions

exINV 1.3.0 documentation
exINV 1.4.0 documentation

Credits

Contact me on the YoYoGames forums or by email at simoneguerra<at>ekalia.com