Goofy Clone Issue

Hi everyone I’m currently working on a Crate System and my Problem is every time I buy a crate it duplicates itself in the Inventory.I tried solving the issue by deleting 2 :Clone() Codes and it worked…
that’s what I thought it only works for the first time.If there is an easier way to let only one Tool appear in my Inventory pls tell me here are some pics and scripts:(pls tell me if there is an easier way)

These are the :Clone() Code things I want to delete:


This is what happens if I delete the two :Clone() things

and this is the issue Line:

Here is the CratesServer Script

--Variables
local rs = game:GetService("ReplicatedStorage")
local remotes = rs:WaitForChild("RemoteEvents")
local items = rs:WaitForChild("Items")
local crates = rs:WaitForChild("Crates")

local rnd = Random.new()

local playersUnboxing = {}


--Data handling
local dss = game:GetService("DataStoreService")
local ds = dss:GetDataStore("UNBOXING SYSTEM DATA")


function saveData(plr:Player)

	if not plr:FindFirstChild("DATA FAILED TO LOAD") then
		
		local cash = plr.leaderstats.Cash.Value
		
		local inventory = {}
		for _, item in pairs(plr.StarterGear:GetChildren()) do
			table.insert(inventory, item.Name)
		end
		if playersUnboxing[plr] then
			table.insert(inventory, playersUnboxing[plr])
		end
		
		local compiledData = {
			Cash = cash;
			Inventory = inventory;
		}

		local success, err = nil, nil
		while not success do
			success, err = pcall(function()
				ds:SetAsync(plr.UserId, compiledData)
			end)
			if err then
				warn(err)
			end
			task.wait(0.02)
		end
	end
end


game.Players.PlayerRemoving:Connect(saveData)
game:BindToClose(function()
	for _, plr in pairs(game.Players:GetPlayers()) do
		saveData(plr)
	end
end)

game.Players.PlayerAdded:Connect(function(plr)

	local dataFailedWarning = Instance.new("StringValue")
	dataFailedWarning.Name = "DATA FAILED TO LOAD"
	dataFailedWarning.Parent = plr

	local success, plrData = nil, nil
	while not success do
		success, plrData = pcall(function()
			return ds:GetAsync(plr.UserId)
		end)
		task.wait(0.02)
	end
	dataFailedWarning:Destroy()

	if not plrData then
		plrData = {
			Cash = 30000;
			Inventory = {};
		}
	end
	
	local ls = Instance.new("Folder")
	ls.Name = "leaderstats"
	ls.Parent = plr
	
	local cashValue = Instance.new("IntValue")
	cashValue.Name = "Cash"
	cashValue.Value = plrData.Cash
	cashValue.Parent = ls

	for _, itemName in pairs(plrData.Inventory) do
		local foundItem = items:FindFirstChild(itemName, true)
		
		if foundItem and foundItem.Parent.Parent == items then
			foundItem.Parent = plr:WaitForChild("Inventory")
			
			if plr.Character then
				foundItem.Parent = plr:WaitForChild("Inventory")
			end
		end
	end
end)


--Unboxing a crate
remotes:WaitForChild("BuyCrate").OnServerEvent:Connect(function(plr, crateName)
	
	local plrCash = plr.leaderstats.Cash
	
	if crates:FindFirstChild(crateName) and not playersUnboxing[plr] then
		local crateProperties = require(crates[crateName])
		
		if plrCash.Value >= crateProperties["Price"] then
			plrCash.Value -= crateProperties["Price"]
			
			local chances = crateProperties["Chances"]
			local plrChance = rnd:NextNumber() * 100
			
			local n = 0
			local rarityChosen = nil
			
			for rarity, chance in pairs(chances) do	
				n += chance
				if plrChance <= n then
					rarityChosen = rarity
					break
				end
			end
			
			local unboxableItems = crateProperties["Items"]
			
			for i = #unboxableItems, 2, -1 do
				local j = rnd:NextInteger(1, i)
				unboxableItems[i], unboxableItems[j] = unboxableItems[j], unboxableItems[i]
			end
			
			local itemChosen = nil
			
			for _, itemName in pairs(unboxableItems) do
				if items:FindFirstChild(itemName, true).Parent.Name == rarityChosen then
					itemChosen = items:FindFirstChild(itemName, true)
					break
				end
			end
			playersUnboxing[plr] = itemChosen.Name
			
			local unboxTime = rnd:NextNumber(3, 7)
			remotes:WaitForChild("CrateOpened"):FireClient(plr, crateName, itemChosen, unboxTime)
			
			local timeStarted = tick()
			while true do
				if (tick() - timeStarted >= unboxTime) or (not plr.Character) then
					break
				end
				game:GetService("RunService").Heartbeat:Wait()
			end
			
			playersUnboxing[plr] = nil
			
			itemChosen:Clone().Parent = plr:WaitForChild("Inventory")
			if plr.Character then
				itemChosen:Clone().Parent = plr:WaitForChild("Inventory")
			end
		end
	end
end)
















Here’s the CratesClient Script:

–Variables
local rs = game:GetService(“ReplicatedStorage”)
local remotes = rs:WaitForChild(“RemoteEvents”)
local rarityProperties = rs:WaitForChild(“RarityProperties”)
local items = rs:WaitForChild(“Items”)
local crates = rs:WaitForChild(“Crates”)

local shopGui = script.Parent:WaitForChild(“CrateShopGui”);shopGui.Enabled = true
local openShopBtn = shopGui:WaitForChild(“OpenButton”);openShopBtn.Visible = true
local shopFrame = shopGui:WaitForChild(“CrateShopFrame”);shopFrame.Visible = false
local closeShopBtn = shopFrame:WaitForChild(“CloseButton”)
local cratesList = shopFrame:WaitForChild(“CratesList”)
local selectedCrate = shopFrame:WaitForChild(“SelectedCrate”);selectedCrate.Visible = false

local openedGui = script.Parent:WaitForChild(“OpenedCrateGui”);openedGui.Enabled = false
local openedFrame = openedGui:WaitForChild(“CrateFrame”);openedFrame.Visible = false
local closeOpenedBtn = openedFrame:WaitForChild(“ContinueButton”)
local openedItemsFrame = openedFrame:WaitForChild(“ItemsFrame”)

local crateButtonTemplate = script:WaitForChild(“CrateShopButton”)
local selectedCrateItemTemplate = script:WaitForChild(“SelectedCrateItemFrame”)
local openingCrateItemTemplate = script:WaitForChild(“OpeningCrateItemFrame”)

local rnd = Random.new()

–Open and close buttons
openShopBtn.MouseButton1Click:Connect(function()
if openedFrame.Visible == false then
shopFrame.Visible = not shopFrame.Visible
end
end)

closeShopBtn.MouseButton1Click:Connect(function()
shopFrame.Visible = false
end)

closeOpenedBtn.MouseButton1Click:Connect(function()
openedFrame.Visible = false
openedGui.Enabled = false

for _, child in pairs(openedItemsFrame.ItemsContainer:GetChildren()) do
	if child:IsA("Frame") then
		child:Destroy()
	end
end

end)

–Setting up crates shop
local crateButtons = {}

for _, crate in pairs(crates:GetChildren()) do

local crateProperties = require(crate)

local newBtn = crateButtonTemplate:Clone()
newBtn.Name = crate.Name
newBtn.CrateName.Text = crate.Name
newBtn.CrateImage.Image = crateProperties["Image"]

newBtn.MouseButton1Click:Connect(function()
	
	if selectedCrate.CrateName.Text ~= crate.Name then
		
		selectedCrate.CrateName.Text = crate.Name
		selectedCrate.CrateImage.Image = crateProperties["Image"]
		selectedCrate.UnboxButton.Text = "$" .. crateProperties["Price"]
		
		local rarities = {}
		for rarityName, chance in pairs(crateProperties["Chances"]) do
			table.insert(rarities, {rarityName, chance})
		end
		table.sort(rarities, function(a, b)
			return rarityProperties[a[1]].Order.Value <rarityProperties[b[1]].Order.Value
		end)
		
		local raritiesText = ""
		for _, rarity in pairs(rarities) do
			local color = rarityProperties[rarity[1]].Color.Value
			color = {R = math.round(color.R*255); G = math.round(color.G*255); B = math.round(color.B*255)}
			raritiesText = raritiesText .. '<font color="rgb(' .. color.R .. ',' .. color.G .. ',' .. color.B .. ')">' .. rarity[1] .. ': <b>' .. rarity[2] .. '%</b></font><br />'
		end
		selectedCrate.RaritiesText.RichText = true
		selectedCrate.RaritiesText.Text = raritiesText
		
		for _, child in pairs(selectedCrate.ItemsList:GetChildren()) do
			if child:IsA("Frame") then
				child:Destroy()
			end
		end
		
		local unboxableItems = crateProperties["Items"]
		table.sort(unboxableItems, function(a, b)
			return 
				(rarityProperties[items:FindFirstChild(a, true).Parent.Name].Order.Value < rarityProperties[items:FindFirstChild(b, true).Parent.Name].Order.Value)
				or (rarityProperties[items:FindFirstChild(a, true).Parent.Name].Order.Value == rarityProperties[items:FindFirstChild(b, true).Parent.Name].Order.Value)
				and (a < b)
		end)
		
		for _, unboxableItemName in pairs(unboxableItems) do
			local newItemFrame = selectedCrateItemTemplate:Clone()
			newItemFrame.ItemName.Text = unboxableItemName
			newItemFrame.ItemName.TextColor3 = rarityProperties[items:FindFirstChild(unboxableItemName, true).Parent.Name].Color.Value
			
			local itemModel = Instance.new("Model")
			
			for _, child in pairs(items:FindFirstChild(unboxableItemName, true):GetChildren()) do
				if not (child:IsA("Script") or child:IsA("LocalScript") or child:IsA("ModuleScript") or child:IsA("Sound")) then
					child:Clone().Parent = itemModel
				end
			end
			
			itemModel:PivotTo(CFrame.new() * CFrame.Angles(math.rad(-39), 0, 0))
			
			itemModel.Parent = newItemFrame.ItemImage
			
			local currentCamera = Instance.new("Camera")
			currentCamera.CFrame = CFrame.new(Vector3.new(-itemModel:GetExtentsSize().Y*0.7, 0, 0), itemModel:GetPivot().Position + Vector3.new(0, -0.1, 0))
			currentCamera.Parent = newItemFrame.ItemImage
			newItemFrame.ItemImage.CurrentCamera = currentCamera
			
			newItemFrame.Parent = selectedCrate.ItemsList
		end
		
		selectedCrate.Visible = true
	end
end)

table.insert(crateButtons, {newBtn, crateProperties["Price"]})

end

table.sort(crateButtons, function(a, b)
return (a[2] < b[2]) or (a[2] == b[2] and a[1].Name < b[1].Name)
end)

for _, crateButton in pairs(crateButtons) do
crateButton[1].Parent = cratesList
end

–Purchasing crates
selectedCrate.UnboxButton.MouseButton1Click:Connect(function()
if selectedCrate.Visible == true and game.Players.LocalPlayer.leaderstats.Cash.Value >= tonumber(string.sub(selectedCrate.UnboxButton.Text, 2, -1)) then
remotes:WaitForChild(“BuyCrate”):FireServer(selectedCrate.CrateName.Text)
end
end)

–Unboxing crates
function lerp(a, b, t)
return a + (b-a) * t
end

function tweenGraph(x, pow)
x = math.clamp(x, 0, 1)
return 1 - (1-x)^pow
end

remotes:WaitForChild(“CrateOpened”).OnClientEvent:Connect(function(crateName, itemChosen, unboxTime)

local crateProperties = require(crates[crateName])

local numItems = rnd:NextInteger(20, 100)
local chosenPosition = rnd:NextInteger(15, numItems-5)

for i = 1, numItems do
	
	local rarityChosen = itemChosen.Parent.Name
	local randomItemChosen = itemChosen
	
	if i ~= chosenPosition then
		local rndChance = rnd:NextNumber() * 100
		local n = 0
		
		for rarity, chance in pairs(crateProperties["Chances"]) do	
			n += chance
			if rndChance <= n then
				rarityChosen = rarity
				break
			end
		end

		local unboxableItems = crateProperties["Items"]
		for i = #unboxableItems, 2, -1 do
			local j = rnd:NextInteger(1, i)
			unboxableItems[i], unboxableItems[j] = unboxableItems[j], unboxableItems[i]
		end
		
		for _, itemName in pairs(unboxableItems) do
			if items:FindFirstChild(itemName, true).Parent.Name == rarityChosen then
				randomItemChosen = items:FindFirstChild(itemName, true)
				break
			end
		end
	end
	
	local newItemFrame = openingCrateItemTemplate:Clone()
	newItemFrame.ItemName.Text = randomItemChosen.Name
	newItemFrame.ItemName.TextColor3 = rarityProperties[rarityChosen].Color.Value
	
	local itemModel = Instance.new("Model")

	for _, child in pairs(randomItemChosen:GetChildren()) do
		if not (child:IsA("Script") or child:IsA("LocalScript") or child:IsA("ModuleScript") or child:IsA("Sound")) then
			child:Clone().Parent = itemModel
		end
	end

	itemModel:PivotTo(CFrame.new() * CFrame.Angles(math.rad(-39), 0, 0))

	itemModel.Parent = newItemFrame.ItemImage

	local currentCamera = Instance.new("Camera")
	currentCamera.CFrame = CFrame.new(Vector3.new(-itemModel:GetExtentsSize().Y*0.7, 0, 0), itemModel:GetPivot().Position + Vector3.new(0, -0.1, 0))
	currentCamera.Parent = newItemFrame.ItemImage
	newItemFrame.ItemImage.CurrentCamera = currentCamera
	
	newItemFrame.Parent = openedItemsFrame.ItemsContainer
end

openedItemsFrame.ItemsContainer.Position = UDim2.new(0, 0, 0.5, 0)

local cellSize = openingCrateItemTemplate.Size.X.Scale
local padding = openedItemsFrame.ItemsContainer.UIListLayout.Padding.Scale
local pos1 = 0.5 - cellSize/2
local nextOffset = -cellSize - padding

local posFinal = pos1 + (chosenPosition-1) * nextOffset
local rndOffset = rnd:NextNumber(-cellSize/2, cellSize/2)
posFinal += rndOffset

local timeOpened = tick()

openedFrame.CrateName.Text = crateName
shopFrame.Visible = false
closeOpenedBtn.Visible = false
openedFrame.Visible = true
openedGui.Enabled = true

local pow = rnd:NextNumber(2, 10)
local lastSlot = 0

while true do
	local timeSinceOpened = tick() - timeOpened
	local x = timeSinceOpened / unboxTime
	
	local t = tweenGraph(x, pow)
	local newXPos = lerp(0, posFinal, t)
	
	local currentSlot = math.abs(math.floor((newXPos+rndOffset)/cellSize))+1
	if currentSlot ~= lastSlot then
		script.TickSound:Play()
		lastSlot = currentSlot
	end
	
	openedItemsFrame.ItemsContainer.Position = UDim2.new(newXPos, 0, 0.5, 0)
	
	if x >= 1 then
		break
	end
	
	game:GetService("RunService").Heartbeat:Wait()
end

closeOpenedBtn.Visible = true

end)

local clonedItem = itemChosen:Clone()
clonedItem.Parent = plr:WaitForChild("Inventory")
if plr.Character then
    clonedItem.Parent = plr:WaitForChild("Inventory")
end

By cloning the item only once and then assigning it to a variable, you can ensure that only one instance of the item is added to the inventory.

1 Like

finally bro thank you very much

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