Item Stacking Problem

I am working on a Inventory System using ProfileService

The problem is when I give the player items greater than stack limit it does not stack properly.
Here’s a video showing the problem: https://www.youtube.com/watch?v=31QAaaF4m2Y

It works when I give the player items less than the stack limit, but when I give more it doesn’t work.

My code:

local function GetItems(inventory, itemName)
	local itemsFound = {}
	local amountOfItems = 0
	if type(inventory) == "table" then
		for _, itemTable in ipairs(inventory) do
			print(itemTable, itemTable.Name)
			if type(itemTable) == "table" and itemTable.Name == itemName then
				table.insert(itemsFound, itemTable)
				amountOfItems += itemTable.Amount
			end
		end
	end
	return amountOfItems, itemsFound
end

local function FixStacks(inventory, itemsFound, itemInstance, amountOfItems)
	local amountRemoved = 0
	local stackCapacity = itemInstance.Value
	for _, itemTable in ipairs(itemsFound) do
		if itemTable.Amount > stackCapacity then
			amountRemoved += itemTable.Amount - stackCapacity
			itemTable.Amount = stackCapacity
		end
		itemTable = itemTable.Amount <= stackCapacity and itemTable.Amount or stackCapacity
	end
	if amountRemoved > 0 then
		local amountLeftOver = amountRemoved - math.floor(amountRemoved / stackCapacity)
		for i = 1, math.floor(amountRemoved / stackCapacity) do
			table.insert(inventory, {
				["ID"] = HttpService:GenerateGUID(false),
				["Name"] = itemInstance.Name,
				["Image"] = itemInstance.Image.Texture,
				["Amount"] = stackCapacity
			})
		end
		table.insert(inventory, {
			["ID"] = HttpService:GenerateGUID(false),
			["Name"] = itemInstance.Name,
			["Image"] = itemInstance.Image.Texture,
			["Amount"] = stackCapacity
		})
	end
end

local function GiveItem(player, profile, itemName, amount)
	if typeof(player) == "Instance" and player:IsDescendantOf(Players) and type(profile) == "table" and type(profile.Data) == "table" and type(profile.Data.Inventory) == "table" then
		if type(itemName) == "string" and Items:FindFirstChild(itemName) and Items:FindFirstChild(itemName):IsA("IntValue") then
			local itemInstance = Items:FindFirstChild(itemName)
			amount = math.floor(amount)
			amount = amount >= 1 and amount or 1
			table.insert(profile.Data.Inventory, {
				["ID"] = HttpService:GenerateGUID(false),
				["Name"] = itemName,
				["Image"] = itemInstance.Image.Texture,
				["Amount"] = amount or 1
			})
			local amountOfItems, itemsFound = GetItems(profile.Data.Inventory, itemName)
			FixStacks(profile.Data.Inventory, itemsFound, itemInstance, amountOfItems)
			UpdateInventory:FireClient(player, profile.Data.Inventory)
		end
	end
end

Screenshot_616

I got the FixStacks function giving the right amount of items now but it creates too many stacks.
New FixStacks Code:

local function FixStacks(inventory, itemsFound, itemInstance, amountOfItems)
	local stackCapacity = itemInstance.Value
	for _, itemTable in ipairs(itemsFound) do
		if itemTable.Amount > stackCapacity then
			local amountRemoved = itemTable.Amount - stackCapacity
			itemTable.Amount = stackCapacity
			while amountRemoved > 0 do
				local stackToAdd = math.min(stackCapacity, amountRemoved)
				table.insert(inventory, {
					["ID"] = HttpService:GenerateGUID(false),
					["Name"] = itemInstance.Name,
					["Image"] = itemInstance.Image.Texture,
					["Amount"] = stackToAdd
				})
				amountRemoved = amountRemoved - stackToAdd
			end
		end
	end
end

What I have now:


What I want:

Ok figured it out now! :tada:

local function GetItems(inventory, itemName)
	local itemsFound = {}
	local amountOfItems = 0
	local firstEmptySlot = 1
	if type(inventory) == "table" and Items:FindFirstChild(itemName) then
		for index, itemTable in next, inventory do
			if type(itemTable) == "table" and itemTable.Name == itemName then
				table.insert(itemsFound, itemTable)
				amountOfItems += itemTable.Amount
				if firstEmptySlot == 1 and itemTable.Amount < Items:FindFirstChild(itemName).Value then
					firstEmptySlot = index
				end
			end
		end
	end
	return amountOfItems, itemsFound, firstEmptySlot
end

local function FixStacks(inventory, itemsFound, itemInstance, amountOfItems)
	local stackCapacity = itemInstance.Value
	for _, itemTable in ipairs(itemsFound) do
		if itemTable.Amount > stackCapacity then
			local amountRemoved = itemTable.Amount - stackCapacity
			itemTable.Amount = stackCapacity
			while amountRemoved > 0 do
				local stackToAdd = math.min(stackCapacity, amountRemoved)
				table.insert(inventory, {
					["ID"] = HttpService:GenerateGUID(false),
					["Name"] = itemInstance.Name,
					["Image"] = itemInstance.Image.Texture,
					["Amount"] = stackToAdd
				})
				amountRemoved = amountRemoved - stackToAdd
			end
			local newAmountOfItems, newItemsFound = GetItems(inventory, itemInstance.Name)
			if #newItemsFound > 0 then
				FixStacks(inventory, newItemsFound, itemInstance, newAmountOfItems)
			end
		end
	end
end

local function GiveItem(player, profile, itemName, amount)
	if typeof(player) == "Instance" and player:IsDescendantOf(Players) and type(profile) == "table" and type(profile.Data) == "table" and type(profile.Data.Inventory) == "table" then
		if type(itemName) == "string" and Items:FindFirstChild(itemName) and Items:FindFirstChild(itemName):IsA("IntValue") then
			local itemInstance = Items:FindFirstChild(itemName)
			amount = math.floor(amount)
			amount = amount >= 1 and amount or 1
			local amountOfItems, itemsFound, firstEmptySlot = GetItems(profile.Data.Inventory, itemName)
			if amountOfItems <= 0 then
				table.insert(profile.Data.Inventory, {
					["ID"] = HttpService:GenerateGUID(false),
					["Name"] = itemName,
					["Image"] = itemInstance.Image.Texture,
					["Amount"] = amount or 1
				})
			else
				itemsFound[firstEmptySlot].Amount += amount
			end
			amountOfItems, itemsFound, firstEmptySlot = GetItems(profile.Data.Inventory, itemName)
			FixStacks(profile.Data.Inventory, itemsFound, itemInstance, amountOfItems)
			UpdateInventory:FireClient(player, profile.Data.Inventory)
		end
	end
end

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.