Help with a more modular inventory system

Before you say anything, yes i’ve already googled, and nothing has what I’m looking for,
All of those systems use stackables only which is not what I’m looking for.

I’m currently using an OOP inventory system, where each item is represented with a number, just like every other system. ["Item"] = 1, this works fine for stackable items such as gold or resources, but becomes a problem for things like RPG games, where players can have multiple different items of the same type with different attributes, such as two longswords, but only one has a poison attribute. A simple solution seems to be to just turn them into tables such as

Backpack = {
			CommonTestItem = {
				OnFire = false,	
			},
			LegendaryTestItem = {
				OnFire = true,	
			},
		},

This would be fine until you have two of the same items, such as two “CommonTestItems”, both with different or the same attributes, since they have the same name they will be overwritten when a new one is added/updated. I’m just looking for a push in the right direction.

This is my current inventory system which works fine for now, it’s just missing a MAJOR feature of most RPG games.


--// SERVICES //--
local REPLICATED_STORAGE = game:GetService("ReplicatedStorage")

--// CONSTANTS //--
local Inventory = {}
Inventory.__index = Inventory

local ClientAssets = REPLICATED_STORAGE:WaitForChild("ClientAssets")
local InventoryFramework = ClientAssets:WaitForChild("InventoryFramework")
local Remotes = InventoryFramework:WaitForChild("Remotes")

--// VARIABLES //--

--// FUNCTIONS //--
function Inventory:RemoveItem(v1, v2)
	if not v1 or not self.Backpack[v1] then
		return
	end
	if v2 < 1 then
		v2 = nil
	end
	if self.Backpack[v1] - (v2 or 1) < 0 then
		self.Backpack[v1] = nil
	else
		self.Backpack[v1] = self.Backpack[v1] - v2 or 1
	end
end

function Inventory:AddItem(v1, v2)
	if not v1 then
		return
	end
	if not self.Backpack[v1] then
		self.Backpack[v1] = v2 or 1
	else
		self.Backpack[v1] = self.Backpack[v1] + v2 or 1
	end
end

function Inventory.new(Player)
	if not Player then
		return
	end
	
	local newInventory = {
		RightHand = "",
		LeftHand = "",
		Head = "",
		Torso = "",
		Hotbar = {},
		Backpack = {
			CommonTestItem = {
				OnFire = false,	
			},
			LegendaryTestItem = {
				OnFire = true,	
			},
		},
	}
	setmetatable(newInventory, Inventory)
	
	_G.Inventories[Player.Name] = newInventory
	
	return newInventory
end

local function GetData(Player)
	if _G.Inventories[Player.Name] then
		return _G.Inventories[Player.Name]
	end
	return nil
end

--// EVENTS //--
Remotes:WaitForChild("getInventoryData").OnServerInvoke = GetData

return Inventory

I’d just create new tables for each physical item they have in their inventory, and you can define the fields that make up each item in the table, like so:

local newItem = {
rarity = "Legendary";
onFire = true;

itemID = 0;
}

And for cases where you need to determine which item is being equipped currently by the player, you could incorporate a simple ID system that stores a unique identifying value for each item in those tables, by generating a random number making sure it doesn’t currently exist as an item ID. (if needed)

This is probably how I’d do it. Store one table for every unique object the player obtains, that can have statistics that differ between items.

Thank you!
I just found out about GUIDs right as you posted this, and it mostly solved my issue, and you mentioning unique IDs for each item gave me an idea that I should have thought of earlier.

1 Like