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)