How to make a Crates Cash

Hey everyone :wave:

I’m making an RP themed game, and I really want to make Crates like this where the Crates will get Money and also Tools, but I have a problem where when I open the Crates and get Money… The money doesn’t add to the Leaderstats. so what should I do??

Example of Crates that I want to make

I got the Model Crates from this Video

you can open this File Studio
Case.rbxl (132.3 KB)

2 Likes

honestly its pretty easy. can i see the script? i cant really help without it. also, some models on the internet can be outdated or just straight up wrong. i know theres a link but it would be easier if i just had the money adding script. I don’t have time to watch the video but the title say to check the description for new versions. Try that.

1 Like

LocalScript

--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()


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)

SCRIPT

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 = {}

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:Clone().Parent = plr:WaitForChild("StarterGear")
			
			if plr.Character then
				foundItem:Clone().Parent = plr:WaitForChild("Backpack")
			end
		end
	end
end)


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("StarterGear")
			if plr.Character then
				itemChosen:Clone().Parent = plr:WaitForChild("Backpack")
			end
		end
	end
end)