# Tut 0x030 ## Inventories Many gamemode bases try to build an inventory system into the gamemode, leaving the developer with few ways to actually use the system more than "put item in, take item out". Artery somewhat forces you to build your own inventories to use. In this tutorial, we'll build a simple rougelike inventory, where we expect items to have a "weight", and we can carry as many items as we want, as long as we don't exceed our "max weight". Inventories and items in Artery are just tables, as per usual in lua. They have a few required fields each. On the left, under "Classes" (all the way at the bottom!), open invtbl and itemtbl in new tabs. ## A simple inventory You can see all the fields needed for an inventory, so let's get started. Recall that function tbl:func_name(one) ... end is the same as function tbl.func_name(self,one) ... end lua will automatically create the variable "self" in the first example garrysmod/addons/artery_rougelite/data/artery/global/rougeinv.lua local inventory_registry = nrequire("inventory.lua") local item_registry = nrequire("item.lua") local inv = {} inv.items = {} --A table of all the items we have inv.maxweight = 100 --The maximum weight of all our items inv.weight = 0 --The current weight of all our items. --Technically we could calculate the weight based on the "items" table, -- but that might start taking a long time if we have a lot of low-weight items. --Returns a position for an item, or nil if we don't have room function inv:FindPlaceFor(item) --Make sure we won't be over weight when we add the item if self.weight + item.weight > self.maxweight then return nil end --[[ ALWAYS return a table position, even if you only need a number. This is the same as return { [1] = #self.items + 1 } ]] return {#self.items + 1} end function inv:CanFitIn(position,item) --Check that we won't be over weight if self.weight + item.weight > self.maxweight then return false end --And make sure we don't already have an item in that position if self.items[position[1]] ~= nil then return false end --If we won't go over weight, and the position isn't already used, we can fit it! return true end --Put something into our inventory function inv:Put(position,item) self.items[position[1]] = item self.weight = self.weight + item.weight end --This one is a bit complicated --ptr can be either a string, or a function that takes 1 argument, -- and returns true when given an object we should return. --this function returns a POSITION that can be given back to get, remove, ect. -- the object. function inv:Has(ptr) --Look for an item with the given name if type(ptr) == "string" then for k,v in pairs(self.items) do if v.Name == ptr then return {k} end end elseif type(ptr) == "function" then for k,v in pairs(self.items) do if ptr(v) then return {k} end end end return nil end --Removes an item from our inventory, returns the item we removed function inv:Remove(position) local item = self.items[position[1]] self.weight = self.weight - item.weight self.items[position[1]] = nil return item end --Gets the item in a given position function inv:Get(position) return self.items[position[1]] end --Creates a string that this inventory can be re-created with function inv:Serialize() local ser = {} for k,v in pairs(self.items) do ser[k] = { v.Name, v:Serialize() --Take advantage of the fact that all items must also have a -- Serialize() method } end return util.TableToJSON(ser) end --Re-creates this inventory from the data created by Serialize() function inv:DeSerialize(data) local self_copy = table.Copy(self) local json = util.JSONToTable(data) for k,v in pairs(json) do local item_name = v[1] local item_data = v[2] local item = item_registry.GetItemFromData(item_name,item_data) self_copy.items[k] = item end for k,v in pair(self_copy.items) do self_copy.weight = self_copy.weight + v.weight end return self_copy end --Don't forget to register it with the gamemode! inventory_registry.RegisterInventory(inv) That was a bit long, but we're done! This is the absolute minimum needed to create an Artery inventory. Now you can go in-game and use the console command `artery_printinventories`, and in that list, you will see your newly made inventory! Next tutorial: @{tut040_items.md} Further reading: @{tut031_metatables.md}