UI/UX
Shop UI
Split this at the SPLIT line. Paste the top into StarterPlayerScripts as a LocalScript and the bottom into ServerScriptService as a Script. The window prompts game pass and developer product purchases. Replace the ids.
-- LOCAL SCRIPT. Paste into StarterPlayer > StarterPlayerScripts.
-- Replace the ids. 0 hides that button's purchase prompt.
local Players = game:GetService("Players")
local MarketplaceService = game:GetService("MarketplaceService")
local GAMEPASSES = {
{ name = "Auto Collect", id = 0 },
}
local PRODUCTS = {
{ name = "100 Coins", id = 0 },
}
local player = Players.LocalPlayer
local playerGui = player:WaitForChild("PlayerGui")
local gui = Instance.new("ScreenGui")
gui.Name = "ShopUi"
gui.ResetOnSpawn = false
gui.Parent = playerGui
local toggle = Instance.new("TextButton")
toggle.Size = UDim2.fromOffset(88, 36)
toggle.Position = UDim2.fromOffset(16, 16)
toggle.BackgroundColor3 = Color3.fromRGB(99, 102, 241)
toggle.Text = "Shop"
toggle.TextColor3 = Color3.new(1, 1, 1)
toggle.Font = Enum.Font.GothamBold
toggle.TextSize = 16
toggle.Parent = gui
local panel = Instance.new("Frame")
panel.Size = UDim2.fromOffset(280, 220)
panel.Position = UDim2.fromOffset(16, 60)
panel.BackgroundColor3 = Color3.fromRGB(19, 22, 28)
panel.Visible = false
panel.Parent = gui
local layout = Instance.new("UIListLayout")
layout.Padding = UDim.new(0, 8)
layout.Parent = panel
local padding = Instance.new("UIPadding")
padding.PaddingTop = UDim.new(0, 12)
padding.PaddingLeft = UDim.new(0, 12)
padding.PaddingRight = UDim.new(0, 12)
padding.Parent = panel
local function addButton(text: string, callback: () -> ())
local button = Instance.new("TextButton")
button.Size = UDim2.new(1, 0, 0, 36)
button.BackgroundColor3 = Color3.fromRGB(30, 35, 48)
button.Text = text
button.TextColor3 = Color3.new(1, 1, 1)
button.Font = Enum.Font.GothamMedium
button.TextSize = 15
button.Parent = panel
button.MouseButton1Click:Connect(callback)
end
for _, pass in ipairs(GAMEPASSES) do
addButton(pass.name, function()
if pass.id ~= 0 then
MarketplaceService:PromptGamePassPurchase(player, pass.id)
end
end)
end
for _, product in ipairs(PRODUCTS) do
addButton(product.name, function()
if product.id ~= 0 then
MarketplaceService:PromptProductPurchase(player, product.id)
end
end)
end
toggle.MouseButton1Click:Connect(function()
panel.Visible = not panel.Visible
end)
-- SPLIT
-- SERVER SCRIPT. Paste into ServerScriptService.
-- Keep only one ProcessReceipt handler in the whole game.
-- PRODUCT_REWARDS maps a developer product id to the coins it grants.
local Players = game:GetService("Players")
local MarketplaceService = game:GetService("MarketplaceService")
local PRODUCT_REWARDS = {
[0] = 100,
}
local function getCash(player: Player): IntValue
local leaderstats = player:FindFirstChild("leaderstats")
if not leaderstats then
leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
end
local cash = leaderstats:FindFirstChild("Cash")
if not cash then
cash = Instance.new("IntValue")
cash.Name = "Cash"
cash.Value = 0
cash.Parent = leaderstats
end
return cash :: IntValue
end
MarketplaceService.ProcessReceipt = function(receipt)
local reward = PRODUCT_REWARDS[receipt.ProductId]
if not reward or receipt.ProductId == 0 then
return Enum.ProductPurchaseDecision.NotProcessedYet
end
local player = Players:GetPlayerByUserId(receipt.PlayerId)
if not player then
return Enum.ProductPurchaseDecision.NotProcessedYet
end
getCash(player).Value += reward
return Enum.ProductPurchaseDecision.PurchaseGranted
end