So I’m working in an inventory system for a game, everything was good but then I wanted to make a non-stackeable and stackeable items, the problem here, is that idk how to do it? Since Items are structured with dictionaries and for example, with the non-stackeable items there is already a value with the same key so it will just overwrite it instead of making another one.
I have the same problem as this person here.
I dont know much about this but if the inventory is a GUI for each image label or text label i would put in int value in it with the amount of items that player has and a boolvalue named Stackable and if it equals false then it cant be stacked and if it is true then it can be stacked
I’m not using instance values, I’m using modules scripts and tables to manage the inventory with some functions.
but you could still use the int value if you are going to show the amount the player has so it can be edited by any script and so the player knows how much of the item they have
but with the modules i wont be of much help
If each Item is in a Specific Slot you could make a
if Module[Item].Stackable then
local CurrentAmount = tonumber(Slot.Amount.Text);
Slot.Amount.Text = tostring(CurrentAmount + Module[Item].Amount)
else
-- You create a New Slot in the Inventory
end
If you plan on doing a Minecraft-like approach, instead of using a dictionary, use an array of “slots”.
For example (just so we’re on the same page):
player.inventory = {
{
Item = "minecraft:diamond_sword",
Count = 1,
NBT = {...}
}
}
When defining a non-stackable item, simply assign its max stack size to 1. Because when you think about it, non-stackable items don’t need to be that different from regular ones, just that they cannot stack past 1; any sorting/merging logic is effectively bypassed.
As for your particular implementation, that’s up for you to decide. I can throw more ideas at the table, but you’ll have to be a little more specific
I think this is the solution! So for searching a item in the inventory I would make an extra function right? Also if you can quickly explain the logic for doing automatic stack like for example, how to make stacks depending on the amount that you are adding to the item, if so I would be very happy!
Im thinking it by just dividing the amount that is adding to the max amount for example :
120 / 64 = 1.875
then i will math.ceil the result = 2, so I will insert two items and then just going to add the amount and then resting the amount of the current stack to the adding amount so for the next stack is different.
This is what I did to make multiple stacks if the amount that you are adding is greater than the max amount :
local times = math.ceil(amount/itemD.MaxAmount)
for x = 1,times,1 do
local currentAmount = amount
local i = #inventory+1
print(amount)
table.insert(inventory,i,itemD)
if amount >= itemD.MaxAmount then
print("lol "..itemD.MaxAmount)
inventory[i].Amount = itemD.MaxAmount
elseif amount < itemD.MaxAmount then
print("what")
inventory[i].Amount = amount
end
amount-=inventory[i].Amount
end
But it sets all the items to the same last value, idk why, output :
350
lol 124
226
lol 124
102
what
--------
Id : wood_log
Amount : 102
Slot : 1
-------- (x2)
Id : wood_log
Amount : 102
Slot : 2
-------- (x2)
Id : wood_log
Amount : 102
Slot : 3
--------
(sorry for late reply)
(extra late reply, DevForum went read-only and deleted most of my progress)
Good question! The logic may seem a little daunting at first, but try your best to gain an intuition for it. It’s really easy once you know what’s going on.
Disclaimer: This isn’t a script you can copy+paste in your game and expect it to work. This is a basic expression; a framework, of a true inventory system. The design of your game is inherently yours, and it should stay that way.
In this example, the inventory is an array of 27 items. We can use a STACKS
dictionary to define stack sizes for different items.
local STACKS = {
stone = 64,
ender_pearl = 16,
diamond_sword = 1
}
local Inventory = {}
Inventory.Items = {}
for i = 1, 27 do
table.insert(Inventory.Items, { Count = 0 })
end
Now, I’ll define a helper function to merge items:
-- merges source onto dest, swap arguments for the opposite effect
function Inventory.Merge(source, dest)
if not dest.Item or (source.Item == dest.Item) then
-- either no item in dest, or both types are the same
local result = source.Count + dest.Count
local max_stack = STACKS[dest.Item]
dest.Count = math.min(result, max_stack)
source.Count = result - max_stack
if source.Count < 1 then
-- source depleted; destroy the item
-- handle this your own way, i'll just unassign its type
source.Item = nil
end
end
end
If we test this function, you can see items get properly stacked just like they do in untitled block game.
-- for example, source could be the item held at the cursor
local source = {
Item = "stone",
Count = 48
}
local dest = {
Item = "stone",
Count = 32
}
Inventory.Merge(source, dest)
print(source.Count) -- 16
print(dest.Count) -- 64
Now, items don’t get swapped yet; they always go to the inventory. But, you can implement that with a few extra checks. I’ll make a separate function for that, as swapping logic may be unintentional at times, such as when picking items off the ground.
function Inventory:Swap(slot, item)
local current = self.Items[slot] -- get the item for later
self.Items[slot] = item -- replace the item
return current -- return the old item. this goes to the cursor
end
Finally, we can step back a bit, and simulate a cursor-to-inventory interaction, such as left-clicking on items.
local function Inventory:LMB(slot, cursor)
-- cursor being the item held at the cursor, if any
local inv = self.Items[slot]
if not (inv.Item and cursor.Item) or inv.Item ~= cursor.Item then
-- if there's one or more items missing, just swap
-- if items aren't the same, swap
return self:Swap(slot, cursor)
else
-- merge from cursor
self.Merge(cursor, inv)
end
end
And that’s it! Whether your stack size is 100, 64 or 1, the same logic will still apply.
The actual networking required to make this work is for you to do. This is a formulaic expression, and will hopefully give you the intuition to create a real, and awesome, inventory system. If it’s wrong by chance, I apologize. I wrote this on a touchscreen.
I also apologize if this isn’t exactly what you needed right from the gate. I don’t feel like writing an entire functioning system, networking and all, on my phone, while mentally debugging as best as I can. Inventory systems require at least some programming knowledge as a prerequisite, so I’m assuming you have that.