--!strict
-- ============================================
-- DONATION GUI CLIENT - LOCAL SCRIPT
-- Interface de donation avec produits
-- ============================================
-- EMPLACEMENT: StarterPlayer > StarterPlayerScripts > DonationSystem > DonationGuiClient
-- Services
local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local MarketplaceService = game:GetService("MarketplaceService")
local TweenService = game:GetService("TweenService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- MANDATORY: Mobile Platform Detection
if not UserInputService.TouchEnabled then
warn("DonationGui requires mobile platform - initialization aborted")
return
end
local player = Players.LocalPlayer
local playerGui = player:WaitForChild("PlayerGui")
-- RemoteEvents
local donationSystemFolder = ReplicatedStorage:WaitForChild("DonationSystem")
local donationPurchasedEvent = donationSystemFolder:WaitForChild("DonationPurchased") :: RemoteEvent
-- ============================================
-- TYPES & CONFIGS
-- ============================================
type DonationTier = {
Name: string,
Robux: number,
ProductId: number,
Icon: string,
Color: Color3,
GradientColor: Color3
}
local TWEEN_FAST = TweenInfo.new(0.3, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
local TWEEN_SMOOTH = TweenInfo.new(0.5, Enum.EasingStyle.Cubic, Enum.EasingDirection.Out)
local TWEEN_BOUNCE = TweenInfo.new(0.6, Enum.EasingStyle.Back, Enum.EasingDirection.Out)
-- Configuration des produits (DOIT CORRESPONDRE au serveur!)
local donationTiers: {DonationTier} = {
{
Name = "STARTER",
Robux = 10,
ProductId = 1234567890, -- ⚠️ REMPLACER
Icon = "🥉",
Color = Color3.fromRGB(205, 127, 50),
GradientColor = Color3.fromRGB(184, 115, 51)
},
{
Name = "SUPPORTER",
Robux = 50,
ProductId = 1234567891, -- ⚠️ REMPLACER
Icon = "🥈",
Color = Color3.fromRGB(192, 192, 192),
GradientColor = Color3.fromRGB(169, 169, 169)
},
{
Name = "PREMIUM",
Robux = 100,
ProductId = 1234567892, -- ⚠️ REMPLACER
Icon = "🥇",
Color = Color3.fromRGB(255, 215, 0),
GradientColor = Color3.fromRGB(218, 165, 32)
},
{
Name = "ELITE",
Robux = 250,
ProductId = 1234567893, -- ⚠️ REMPLACER
Icon = "💎",
Color = Color3.fromRGB(0, 191, 255),
GradientColor = Color3.fromRGB(30, 144, 255)
},
{
Name = "LEGENDARY",
Robux = 500,
ProductId = 1234567894, -- ⚠️ REMPLACER
Icon = "👑",
Color = Color3.fromRGB(138, 43, 226),
GradientColor = Color3.fromRGB(75, 0, 130)
},
{
Name = "MYTHIC",
Robux = 1000,
ProductId = 1234567895, -- ⚠️ REMPLACER
Icon = "⭐",
Color = Color3.fromRGB(255, 105, 180),
GradientColor = Color3.fromRGB(255, 20, 147)
}
}
-- ============================================
-- GUI CONSTRUCTION
-- ============================================
local donateGui = Instance.new("ScreenGui")
donateGui.Name = "DonationGui"
donateGui.ResetOnSpawn = false
donateGui.ZIndexBehavior = Enum.ZIndexBehavior.Sibling
donateGui.ScreenInsets = Enum.ScreenInsets.DeviceSafeInsets
donateGui.Parent = playerGui
-- Overlay
local overlay = Instance.new("Frame")
overlay.Name = "Overlay"
overlay.Size = UDim2.fromScale(1, 1)
overlay.BackgroundColor3 = Color3.fromRGB(0, 0, 0)
overlay.BackgroundTransparency = 1
overlay.BorderSizePixel = 0
overlay.Visible = false
overlay.ZIndex = 1
overlay.Parent = donateGui
-- Toggle Button
local toggleButton = Instance.new("TextButton")
toggleButton.Name = "ToggleButton"
toggleButton.AnchorPoint = Vector2.new(0, 0)
toggleButton.Position = UDim2.fromScale(0.02, 0.12)
toggleButton.Size = UDim2.fromScale(0.2, 0.09)
toggleButton.BackgroundColor3 = Color3.fromRGB(139, 69, 255)
toggleButton.BorderSizePixel = 0
toggleButton.Font = Enum.Font.GothamBold
toggleButton.Text = "💎 DONATE"
toggleButton.TextColor3 = Color3.fromRGB(255, 255, 255)
toggleButton.TextScaled = true
toggleButton.ZIndex = 2
toggleButton.Parent = donateGui
local toggleGradient = Instance.new("UIGradient")
toggleGradient.Color = ColorSequence.new{
ColorSequenceKeypoint.new(0, Color3.fromRGB(139, 69, 255)),
ColorSequenceKeypoint.new(1, Color3.fromRGB(88, 44, 204))
}
toggleGradient.Rotation = 45
toggleGradient.Parent = toggleButton
local toggleCorner = Instance.new("UICorner")
toggleCorner.CornerRadius = UDim.new(0.25, 0)
toggleCorner.Parent = toggleButton
local togglePadding = Instance.new("UIPadding")
togglePadding.PaddingLeft = UDim.new(0.1, 0)
togglePadding.PaddingRight = UDim.new(0.1, 0)
togglePadding.PaddingTop = UDim.new(0.2, 0)
togglePadding.PaddingBottom = UDim.new(0.2, 0)
togglePadding.Parent = toggleButton
local toggleStroke = Instance.new("UIStroke")
toggleStroke.Color = Color3.fromRGB(255, 255, 255)
toggleStroke.Transparency = 0.7
toggleStroke.Thickness = 2
toggleStroke.Parent = toggleButton
-- MainFrame (MANDATORY: 0.5, 0.5)
local mainFrame = Instance.new("Frame")
mainFrame.Name = "MainFrame"
mainFrame.AnchorPoint = Vector2.new(0.5, 0.5)
mainFrame.Position = UDim2.fromScale(0.5, 0.5)
mainFrame.Size = UDim2.fromScale(0.5, 0.5)
mainFrame.BackgroundColor3 = Color3.fromRGB(25, 25, 35)
mainFrame.BorderSizePixel = 0
mainFrame.Visible = false
mainFrame.ZIndex = 2
mainFrame.Parent = donateGui
local mainGradient = Instance.new("UIGradient")
mainGradient.Color = ColorSequence.new{
ColorSequenceKeypoint.new(0, Color3.fromRGB(30, 30, 45)),
ColorSequenceKeypoint.new(1, Color3.fromRGB(20, 20, 30))
}
mainGradient.Rotation = 135
mainGradient.Parent = mainFrame
local mainCorner = Instance.new("UICorner")
mainCorner.CornerRadius = UDim.new(0.05, 0)
mainCorner.Parent = mainFrame
local mainStroke = Instance.new("UIStroke")
mainStroke.Color = Color3.fromRGB(139, 69, 255)
mainStroke.Transparency = 0.5
mainStroke.Thickness = 3
mainStroke.Parent = mainFrame
local aspectRatio = Instance.new("UIAspectRatioConstraint")
aspectRatio.AspectRatio = 0.75
aspectRatio.Parent = mainFrame
-- Header
local header = Instance.new("Frame")
header.Name = "Header"
header.Size = UDim2.fromScale(1, 0.15)
header.Position = UDim2.fromScale(0, 0)
header.BackgroundColor3 = Color3.fromRGB(139, 69, 255)
header.BorderSizePixel = 0
header.ZIndex = 3
header.Parent = mainFrame
local headerGradient = Instance.new("UIGradient")
headerGradient.Color = ColorSequence.new{
ColorSequenceKeypoint.new(0, Color3.fromRGB(139, 69, 255)),
ColorSequenceKeypoint.new(1, Color3.fromRGB(88, 44, 204))
}
headerGradient.Rotation = 90
headerGradient.Parent = header
local headerCorner = Instance.new("UICorner")
headerCorner.CornerRadius = UDim.new(0.05, 0)
headerCorner.Parent = header
-- Title
local titleLabel = Instance.new("TextLabel")
titleLabel.Name = "Title"
titleLabel.Size = UDim2.fromScale(0.75, 1)
titleLabel.Position = UDim2.fromScale(0, 0)
titleLabel.BackgroundTransparency = 1
titleLabel.Font = Enum.Font.GothamBold
titleLabel.Text = "✨ SUPPORT THE GAME"
titleLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
titleLabel.TextScaled = true
titleLabel.ZIndex = 4
titleLabel.Parent = header
local titlePadding = Instance.new("UIPadding")
titlePadding.PaddingLeft = UDim.new(0.08, 0)
titlePadding.PaddingTop = UDim.new(0.15, 0)
titlePadding.PaddingBottom = UDim.new(0.15, 0)
titlePadding.Parent = titleLabel
-- Close Button
local closeButton = Instance.new("TextButton")
closeButton.Name = "CloseButton"
closeButton.AnchorPoint = Vector2.new(1, 0.5)
closeButton.Position = UDim2.fromScale(0.95, 0.5)
closeButton.Size = UDim2.fromScale(0.15, 0.7)
closeButton.BackgroundColor3 = Color3.fromRGB(255, 70, 70)
closeButton.BorderSizePixel = 0
closeButton.Font = Enum.Font.GothamBold
closeButton.Text = "✕"
closeButton.TextColor3 = Color3.fromRGB(255, 255, 255)
closeButton.TextScaled = true
closeButton.ZIndex = 5
closeButton.Parent = header
local closeCorner = Instance.new("UICorner")
closeCorner.CornerRadius = UDim.new(0.5, 0)
closeCorner.Parent = closeButton
-- Subtitle
local subtitle = Instance.new("TextLabel")
subtitle.Name = "Subtitle"
subtitle.Size = UDim2.fromScale(0.9, 0.08)
subtitle.Position = UDim2.fromScale(0.05, 0.17)
subtitle.BackgroundTransparency = 1
subtitle.Font = Enum.Font.Gotham
subtitle.Text = "Your support helps us create amazing content! 💙"
subtitle.TextColor3 = Color3.fromRGB(200, 200, 220)
subtitle.TextScaled = true
subtitle.TextWrapped = true
subtitle.ZIndex = 3
subtitle.Parent = mainFrame
-- ScrollingFrame
local scrollFrame = Instance.new("ScrollingFrame")
scrollFrame.Name = "ProductScroll"
scrollFrame.Position = UDim2.fromScale(0.05, 0.27)
scrollFrame.Size = UDim2.fromScale(0.9, 0.68)
scrollFrame.BackgroundColor3 = Color3.fromRGB(35, 35, 50)
scrollFrame.BackgroundTransparency = 0.3
scrollFrame.BorderSizePixel = 0
scrollFrame.ScrollBarThickness = 4
scrollFrame.ScrollBarImageColor3 = Color3.fromRGB(139, 69, 255)
scrollFrame.CanvasSize = UDim2.fromScale(0, 0)
scrollFrame.AutomaticCanvasSize = Enum.AutomaticSize.Y
scrollFrame.ScrollingDirection = Enum.ScrollingDirection.Y
scrollFrame.ZIndex = 3
scrollFrame.Parent = mainFrame
local scrollCorner = Instance.new("UICorner")
scrollCorner.CornerRadius = UDim.new(0.04, 0)
scrollCorner.Parent = scrollFrame
local listLayout = Instance.new("UIListLayout")
listLayout.SortOrder = Enum.SortOrder.LayoutOrder
listLayout.Padding = UDim.new(0.025, 0)
listLayout.HorizontalAlignment = Enum.HorizontalAlignment.Center
listLayout.Parent = scrollFrame
local listPadding = Instance.new("UIPadding")
listPadding.PaddingTop = UDim.new(0.02, 0)
listPadding.PaddingBottom = UDim.new(0.02, 0)
listPadding.PaddingLeft = UDim.new(0.03, 0)
listPadding.PaddingRight = UDim.new(0.03, 0)
listPadding.Parent = scrollFrame
-- Notification
local notificationFrame = Instance.new("Frame")
notificationFrame.Name = "Notification"
notificationFrame.AnchorPoint = Vector2.new(0.5, 0)
notificationFrame.Position = UDim2.fromScale(0.5, -0.2)
notificationFrame.Size = UDim2.fromScale(0.8, 0.12)
notificationFrame.BackgroundColor3 = Color3.fromRGB(50, 200, 100)
notificationFrame.BorderSizePixel = 0
notificationFrame.ZIndex = 10
notificationFrame.Parent = donateGui
local notifCorner = Instance.new("UICorner")
notifCorner.CornerRadius = UDim.new(0.2, 0)
notifCorner.Parent = notificationFrame
local notifLabel = Instance.new("TextLabel")
notifLabel.Size = UDim2.fromScale(1, 1)
notifLabel.BackgroundTransparency = 1
notifLabel.Font = Enum.Font.GothamBold
notifLabel.Text = "✓ Purchase Successful!"
notifLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
notifLabel.TextScaled = true
notifLabel.ZIndex = 11
notifLabel.Parent = notificationFrame
local notifPadding = Instance.new("UIPadding")
notifPadding.PaddingLeft = UDim.new(0.05, 0)
notifPadding.PaddingRight = UDim.new(0.05, 0)
notifPadding.PaddingTop = UDim.new(0.2, 0)
notifPadding.PaddingBottom = UDim.new(0.2, 0)
notifPadding.Parent = notifLabel
-- ============================================
-- HELPER FUNCTIONS
-- ============================================
local function showNotification(message: string, isSuccess: boolean)
notificationFrame.BackgroundColor3 = isSuccess
and Color3.fromRGB(50, 200, 100)
or Color3.fromRGB(220, 53, 69)
notifLabel.Text = isSuccess and `✓ {message}` or `✕ {message}`
local slideIn = TweenService:Create(
notificationFrame,
TWEEN_BOUNCE,
{Position = UDim2.fromScale(0.5, 0.05)}
)
slideIn:Play()
slideIn.Completed:Wait()
task.wait(2)
local slideOut = TweenService:Create(
notificationFrame,
TWEEN_FAST,
{Position = UDim2.fromScale(0.5, -0.2)}
)
slideOut:Play()
end
local function createProductButton(tier: DonationTier, index: number): Frame
local container = Instance.new("Frame")
container.Name = tier.Name
container.Size = UDim2.fromScale(0.94, 0.16)
container.BackgroundColor3 = Color3.fromRGB(45, 45, 65)
container.BorderSizePixel = 0
container.LayoutOrder = index
container.ZIndex = 4
local containerCorner = Instance.new("UICorner")
containerCorner.CornerRadius = UDim.new(0.12, 0)
containerCorner.Parent = container
local containerStroke = Instance.new("UIStroke")
containerStroke.Color = tier.Color
containerStroke.Transparency = 0.6
containerStroke.Thickness = 2
containerStroke.Parent = container
local iconLabel = Instance.new("TextLabel")
iconLabel.Name = "Icon"
iconLabel.Size = UDim2.fromScale(0.2, 0.8)
iconLabel.Position = UDim2.fromScale(0.05, 0.1)
iconLabel.BackgroundTransparency = 1
iconLabel.Font = Enum.Font.GothamBold
iconLabel.Text = tier.Icon
iconLabel.TextScaled = true
iconLabel.ZIndex = 5
iconLabel.Parent = container
local nameLabel = Instance.new("TextLabel")
nameLabel.Name = "TierName"
nameLabel.Size = UDim2.fromScale(0.45, 0.4)
nameLabel.Position = UDim2.fromScale(0.28, 0.15)
nameLabel.BackgroundTransparency = 1
nameLabel.Font = Enum.Font.GothamBold
nameLabel.Text = tier.Name
nameLabel.TextColor3 = tier.Color
nameLabel.TextScaled = true
nameLabel.TextXAlignment = Enum.TextXAlignment.Left
nameLabel.ZIndex = 5
nameLabel.Parent = container
local priceLabel = Instance.new("TextLabel")
priceLabel.Name = "Price"
priceLabel.Size = UDim2.fromScale(0.45, 0.3)
priceLabel.Position = UDim2.fromScale(0.28, 0.55)
priceLabel.BackgroundTransparency = 1
priceLabel.Font = Enum.Font.Gotham
priceLabel.Text = `{tier.Robux} Robux`
priceLabel.TextColor3 = Color3.fromRGB(200, 200, 220)
priceLabel.TextScaled = true
priceLabel.TextXAlignment = Enum.TextXAlignment.Left
priceLabel.ZIndex = 5
priceLabel.Parent = container
local purchaseButton = Instance.new("TextButton")
purchaseButton.Name = "PurchaseButton"
purchaseButton.AnchorPoint = Vector2.new(1, 0.5)
purchaseButton.Position = UDim2.fromScale(0.95, 0.5)
purchaseButton.Size = UDim2.fromScale(0.22, 0.6)
purchaseButton.BackgroundColor3 = tier.Color
purchaseButton.BorderSizePixel = 0
purchaseButton.Font = Enum.Font.GothamBold
purchaseButton.Text = "BUY"
purchaseButton.TextColor3 = Color3.fromRGB(255, 255, 255)
purchaseButton.TextScaled = true
purchaseButton.ZIndex = 6
purchaseButton.Parent = container
local buttonGradient = Instance.new("UIGradient")
buttonGradient.Color = ColorSequence.new{
ColorSequenceKeypoint.new(0, tier.Color),
ColorSequenceKeypoint.new(1, tier.GradientColor)
}
buttonGradient.Rotation = 90
buttonGradient.Parent = purchaseButton
local buttonCorner = Instance.new("UICorner")
buttonCorner.CornerRadius = UDim.new(0.25, 0)
buttonCorner.Parent = purchaseButton
purchaseButton.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.Touch then
TweenService:Create(purchaseButton, TweenInfo.new(0.1), {Size = UDim2.fromScale(0.2, 0.55)}):Play()
end
end)
purchaseButton.InputEnded:Connect(function(input)
if input.UserInputType == Enum.UserInputType.Touch then
TweenService:Create(purchaseButton, TweenInfo.new(0.1), {Size = UDim2.fromScale(0.22, 0.6)}):Play()
end
end)
purchaseButton.MouseButton1Click:Connect(function()
purchaseButton.Text = "..."
local success, result = pcall(function()
MarketplaceService:PromptProductPurchase(player, tier.ProductId)
end)
task.wait(0.5)
purchaseButton.Text = "BUY"
if success then
showNotification("Purchase prompted!", true)
else
showNotification("Purchase failed!", false)
warn(`Purchase error: {result}`)
end
end)
return container
end
-- Populate products
for index, tier in donationTiers do
local productButton = createProductButton(tier, index)
productButton.Parent = scrollFrame
end
-- ============================================
-- TOGGLE FUNCTIONALITY
-- ============================================
local function toggleMainFrame()
if mainFrame.Visible then
local fadeTween = TweenService:Create(overlay, TWEEN_FAST, {BackgroundTransparency = 1})
local slideTween = TweenService:Create(mainFrame, TWEEN_SMOOTH, {Position = UDim2.fromScale(0.5, 1.5)})
fadeTween:Play()
slideTween:Play()
slideTween.Completed:Wait()
mainFrame.Visible = false
overlay.Visible = false
mainFrame.Position = UDim2.fromScale(0.5, 0.5)
toggleButton.Text = "💎 DONATE"
else
overlay.Visible = true
mainFrame.Visible = true
mainFrame.Position = UDim2.fromScale(0.5, -0.5)
local fadeTween = TweenService:Create(overlay, TWEEN_SMOOTH, {BackgroundTransparency = 0.5})
local slideTween = TweenService:Create(mainFrame, TWEEN_BOUNCE, {Position = UDim2.fromScale(0.5, 0.5)})
fadeTween:Play()
slideTween:Play()
toggleButton.Text = "✕ CLOSE"
end
end
toggleButton.MouseButton1Click:Connect(toggleMainFrame)
closeButton.MouseButton1Click:Connect(toggleMainFrame)
overlay.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.Touch then
toggleMainFrame()
end
end)
-- Pulse animation
task.spawn(function()
while true do
if not mainFrame.Visible then
TweenService:Create(toggleButton, TweenInfo.new(1, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut), {
Size = UDim2.fromScale(0.22, 0.095)
}):Play()
task.wait(1)
TweenService:Create(toggleButton, TweenInfo.new(1, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut), {
Size = UDim2.fromScale(0.2, 0.09)
}):Play()
task.wait(1)
else
task.wait(0.5)
end
end
end)
-- Listen for donations from other players
donationPurchasedEvent.OnClientEvent:Connect(function(userId, username, amount)
if userId == player.UserId then
showNotification(`Merci pour votre donation de {amount} Robux! 💎`, true)
end
end)
print("✅ DonationGui initialized successfully")