|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>Ultimate Roblox Cookie Clicker Guide</title> |
|
<script src="https://cdn.tailwindcss.com"></script> |
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> |
|
<style> |
|
|
|
.gradient-bg { background: linear-gradient(135deg, #f6d365 0%, #fda085 100%); } |
|
.cookie-btn { transition: all 0.2s ease; transform-style: preserve-3d; } |
|
.cookie-btn:hover { transform: scale(1.05) rotate(5deg); box-shadow: 0 10px 20px rgba(0,0,0,0.2); } |
|
.cookie-btn:active { transform: scale(0.95); } |
|
.progress-bar { transition: width 0.5s ease; } |
|
.skin-card { transition: all 0.3s ease; } |
|
.skin-card:hover { transform: translateY(-5px); box-shadow: 0 10px 25px rgba(0,0,0,0.1); } |
|
.monster-hunger { animation: pulse 2s infinite; } |
|
@keyframes pulse { |
|
0% { transform: scale(1); } |
|
50% { transform: scale(1.05); } |
|
100% { transform: scale(1); } |
|
} |
|
.tooltip { |
|
position: relative; |
|
} |
|
.tooltip-text { |
|
visibility: hidden; |
|
width: 200px; |
|
background-color: #555; |
|
color: #fff; |
|
text-align: center; |
|
border-radius: 6px; |
|
padding: 5px; |
|
position: absolute; |
|
z-index: 1; |
|
bottom: 125%; |
|
left: 50%; |
|
margin-left: -100px; |
|
opacity: 0; |
|
transition: opacity 0.3s; |
|
} |
|
.tooltip:hover .tooltip-text { |
|
visibility: visible; |
|
opacity: 1; |
|
} |
|
.code-tab { |
|
display: none; |
|
} |
|
.code-tab.active { |
|
display: block; |
|
} |
|
</style> |
|
</head> |
|
<body class="gradient-bg min-h-screen font-sans"> |
|
<div class="container mx-auto px-4 py-8"> |
|
|
|
<header class="text-center mb-12"> |
|
<h1 class="text-5xl font-bold text-white mb-4">Ultimate Roblox Cookie Clicker Guide</h1> |
|
<p class="text-xl text-white opacity-90">Create a feature-packed cookie clicking game with achievements, skins, global leaderboards, and Cookie Monster!</p> |
|
</header> |
|
|
|
|
|
<nav class="bg-white rounded-lg shadow-lg p-4 mb-8"> |
|
<ul class="flex flex-wrap justify-center gap-4"> |
|
<li><a href="#basic-setup" class="px-4 py-2 bg-amber-500 text-white rounded-lg hover:bg-amber-600 transition">Basic Setup</a></li> |
|
<li><a href="#cookie-design" class="px-4 py-2 bg-amber-500 text-white rounded-lg hover:bg-amber-600 transition">Cookie Design</a></li> |
|
<li><a href="#achievements" class="px-4 py-2 bg-amber-500 text-white rounded-lg hover:bg-amber-600 transition">Achievements</a></li> |
|
<li><a href="#skins" class="px-4 py-2 bg-amber-500 text-white rounded-lg hover:bg-amber-600 transition">Skins</a></li> |
|
<li><a href="#leaderboard" class="px-4 py-2 bg-amber-500 text-white rounded-lg hover:bg-amber-600 transition">Leaderboard</a></li> |
|
<li><a href="#cookie-monster" class="px-4 py-2 bg-amber-500 text-white rounded-lg hover:bg-amber-600 transition">Cookie Monster</a></li> |
|
</ul> |
|
</nav> |
|
|
|
|
|
<main class="bg-white rounded-lg shadow-xl p-8"> |
|
|
|
<section id="basic-setup" class="mb-12"> |
|
<h2 class="text-3xl font-bold text-amber-800 mb-6 border-b-2 border-amber-200 pb-2">1. Basic Game Setup</h2> |
|
|
|
<div class="grid md:grid-cols-2 gap-8"> |
|
|
|
<div class="bg-amber-50 p-6 rounded-lg border-l-4 border-amber-400"> |
|
<h3 class="text-xl font-semibold text-amber-700 mb-4">Creating the Base Game</h3> |
|
<div class="mb-6"> |
|
<h4 class="font-medium text-gray-800 mb-2">Detailed Steps:</h4> |
|
<ol class="list-decimal pl-5 space-y-3 text-gray-700"> |
|
<li> |
|
<strong>Create a new Roblox place:</strong> |
|
<ul class="list-disc pl-5 mt-1 text-sm"> |
|
<li>Open Roblox Studio</li> |
|
<li>Select "Baseplate" as your starting template</li> |
|
<li>Save your place with a descriptive name</li> |
|
</ul> |
|
</li> |
|
<li> |
|
<strong>Set up the GUI structure:</strong> |
|
<ul class="list-disc pl-5 mt-1 text-sm"> |
|
<li>In Explorer, go to StarterGui</li> |
|
<li>Insert a ScreenGui (rename to "MainGUI")</li> |
|
<li>Add a Frame inside (set Size to 1,1 scale)</li> |
|
<li>Configure background transparency (0.5-0.8)</li> |
|
</ul> |
|
</li> |
|
<li> |
|
<strong>Cookie display setup:</strong> |
|
<ul class="list-disc pl-5 mt-1 text-sm"> |
|
<li>Add TextLabel for cookie count</li> |
|
<li>Set font to "Gotham Black" (size 24-36)</li> |
|
<li>Position at top-center of screen</li> |
|
<li>Add shadow effect with TextStroke</li> |
|
</ul> |
|
</li> |
|
<li> |
|
<strong>Cookie button creation:</strong> |
|
<ul class="list-disc pl-5 mt-1 text-sm"> |
|
<li>Insert ImageButton (200x200 pixels)</li> |
|
<li>Upload cookie image (PNG with transparency)</li> |
|
<li>Add hover/click effects (scale, rotation)</li> |
|
<li>Center on screen with AutoButtonColor=false</li> |
|
</ul> |
|
</li> |
|
</ol> |
|
</div> |
|
|
|
<div class="p-4 bg-gray-100 rounded"> |
|
<div class="flex border-b border-gray-300 mb-3"> |
|
<button class="code-tab-btn px-4 py-2 font-medium text-amber-700 border-b-2 border-amber-500" data-tab="basic-local">LocalScript</button> |
|
<button class="code-tab-btn px-4 py-2 font-medium text-gray-600" data-tab="basic-server">ServerScript</button> |
|
</div> |
|
|
|
<div id="basic-local" class="code-tab active"> |
|
<h4 class="font-medium text-gray-800 mb-2">LocalScript for Click Handling:</h4> |
|
<pre class="bg-gray-800 text-green-300 p-3 rounded text-sm overflow-x-auto"> |
|
local Players = game:GetService("Players") |
|
local player = Players.LocalPlayer |
|
local cookieButton = script.Parent.CookieButton |
|
local cookieCount = script.Parent.CookieCount |
|
|
|
-- Initialize cookie value (will be synced with server) |
|
local cookies = 0 |
|
|
|
-- Create a remote event for server communication |
|
local remoteEvent = Instance.new("RemoteEvent") |
|
remoteEvent.Name = "CookieClickEvent" |
|
remoteEvent.Parent = game.ReplicatedStorage |
|
|
|
-- Click handler with visual feedback |
|
cookieButton.MouseButton1Click:Connect(function() |
|
-- Visual feedback |
|
cookieButton:TweenSize(UDim2.new(0.9, 0, 0.9, 0), "Out", "Quad", 0.1) |
|
task.wait(0.1) |
|
cookieButton:TweenSize(UDim2.new(1, 0, 1, 0), "Out", "Elastic", 0.5) |
|
|
|
-- Play sound if available |
|
if cookieButton:FindFirstChild("ClickSound") then |
|
cookieButton.ClickSound:Play() |
|
end |
|
|
|
-- Fire to server |
|
remoteEvent:FireServer() |
|
end) |
|
|
|
-- Update display when cookies change |
|
local function updateDisplay(newCount) |
|
cookies = newCount |
|
cookieCount.Text = "Cookies: " .. formatNumber(cookies) |
|
end |
|
|
|
-- Helper function to format large numbers |
|
local function formatNumber(num) |
|
if num >= 1000000 then |
|
return string.format("%.1fM", num/1000000) |
|
elseif num >= 1000 then |
|
return string.format("%.1fK", num/1000) |
|
end |
|
return tostring(num) |
|
end |
|
|
|
-- Listen for server updates |
|
game.ReplicatedStorage:WaitForChild("CookieUpdate").OnClientEvent:Connect(updateDisplay)</pre> |
|
</div> |
|
|
|
<div id="basic-server" class="code-tab"> |
|
<h4 class="font-medium text-gray-800 mb-2">Server-Side Cookie Management:</h4> |
|
<pre class="bg-gray-800 text-green-300 p-3 rounded text-sm overflow-x-auto"> |
|
local Players = game:GetService("Players") |
|
local ServerStorage = game:GetService("ServerStorage") |
|
local ReplicatedStorage = game:GetService("ReplicatedStorage") |
|
|
|
-- Create remote events |
|
local clickEvent = Instance.new("RemoteEvent") |
|
clickEvent.Name = "CookieClickEvent" |
|
clickEvent.Parent = ReplicatedStorage |
|
|
|
local updateEvent = Instance.new("RemoteEvent") |
|
updateEvent.Name = "CookieUpdate" |
|
updateEvent.Parent = ReplicatedStorage |
|
|
|
-- Player data management |
|
local playerData = {} |
|
|
|
local function onPlayerAdded(player) |
|
-- Initialize player data |
|
playerData[player] = { |
|
cookies = 0, |
|
clickMultiplier = 1, |
|
autoClickers = {} |
|
} |
|
|
|
-- Create leaderstats |
|
local leaderstats = Instance.new("Folder") |
|
leaderstats.Name = "leaderstats" |
|
leaderstats.Parent = player |
|
|
|
local cookiesStat = Instance.new("IntValue") |
|
cookiesStat.Name = "Cookies" |
|
cookiesStat.Value = 0 |
|
cookiesStat.Parent = leaderstats |
|
|
|
-- Send initial data to client |
|
updateEvent:FireClient(player, 0) |
|
end |
|
|
|
-- Handle cookie clicks |
|
clickEvent.OnServerEvent:Connect(function(player) |
|
local data = playerData[player] |
|
if not data then return end |
|
|
|
-- Calculate cookies to add (with multiplier) |
|
local cookiesToAdd = 1 * data.clickMultiplier |
|
|
|
-- Update player data |
|
data.cookies = data.cookies + cookiesToAdd |
|
player.leaderstats.Cookies.Value = data.cookies |
|
|
|
-- Update client |
|
updateEvent:FireClient(player, data.cookies) |
|
end) |
|
|
|
-- Clean up when player leaves |
|
local function onPlayerRemoving(player) |
|
playerData[player] = nil |
|
end |
|
|
|
-- Connect events |
|
Players.PlayerAdded:Connect(onPlayerAdded) |
|
Players.PlayerRemoving:Connect(onPlayerRemoving)</pre> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="bg-amber-50 p-6 rounded-lg border-l-4 border-amber-400"> |
|
<h3 class="text-xl font-semibold text-amber-700 mb-4">Auto-Clicker Upgrades</h3> |
|
|
|
<div class="mb-6"> |
|
<h4 class="font-medium text-gray-800 mb-2">Upgrade System Design:</h4> |
|
<ul class="list-disc pl-5 space-y-2 text-gray-700"> |
|
<li><strong>Upgrade Types:</strong> |
|
<ul class="list-disc pl-5 mt-1 text-sm"> |
|
<li>Click Multipliers (2x, 5x, 10x)</li> |
|
<li>Auto-Clickers (Grandma, Oven, Factory)</li> |
|
<li>Temporary Boosts (30min 2x cookies)</li> |
|
</ul> |
|
</li> |
|
<li><strong>Cost Scaling:</strong> |
|
<ul class="list-disc pl-5 mt-1 text-sm"> |
|
<li>Base cost * (1.15^owned)</li> |
|
<li>Example: First grandma costs 10, next 11.5, then 13.2, etc.</li> |
|
</ul> |
|
</li> |
|
<li><strong>Visual Feedback:</strong> |
|
<ul class="list-disc pl-5 mt-1 text-sm"> |
|
<li>Highlight affordable upgrades</li> |
|
<li>Show purchase confirmation</li> |
|
<li>Visual effect on purchase</li> |
|
</ul> |
|
</li> |
|
</ul> |
|
</div> |
|
|
|
<div class="p-4 bg-gray-100 rounded"> |
|
<div class="flex border-b border-gray-300 mb-3"> |
|
<button class="code-tab-btn px-4 py-2 font-medium text-amber-700 border-b-2 border-amber-500" data-tab="upgrade-client">Client UI</button> |
|
<button class="code-tab-btn px-4 py-2 font-medium text-gray-600" data-tab="upgrade-server">Server Logic</button> |
|
</div> |
|
|
|
<div id="upgrade-client" class="code-tab active"> |
|
<h4 class="font-medium text-gray-800 mb-2">Upgrade Shop UI:</h4> |
|
<pre class="bg-gray-800 text-green-300 p-3 rounded text-sm overflow-x-auto"> |
|
-- In a LocalScript connected to your upgrade buttons |
|
local ReplicatedStorage = game:GetService("ReplicatedStorage") |
|
local upgradeEvent = ReplicatedStorage:WaitForChild("UpgradeEvent") |
|
local updateEvent = ReplicatedStorage:WaitForChild("CookieUpdate") |
|
|
|
local upgrades = { |
|
{ |
|
name = "Grandma", |
|
desc = "Bakes 0.2 cookies per second", |
|
baseCost = 10, |
|
owned = 0, |
|
rate = 0.2, |
|
button = script.Parent.GrandmaButton |
|
}, |
|
-- Add more upgrades |
|
} |
|
|
|
-- Initialize UI |
|
local function updateUpgradeUI() |
|
for _, upgrade in pairs(upgrades) do |
|
local cost = math.floor(upgrade.baseCost * (1.15 ^ upgrade.owned)) |
|
upgrade.button.Text = string.format("%s\nCost: %d\nOwned: %d", |
|
upgrade.name, cost, upgrade.owned) |
|
|
|
-- Grey out if unaffordable |
|
if playerCookies < cost then |
|
upgrade.button.BackgroundColor3 = Color3.fromRGB(200, 200, 200) |
|
else |
|
upgrade.button.BackgroundColor3 = Color3.fromRGB(100, 200, 100) |
|
end |
|
end |
|
end |
|
|
|
-- Handle purchases |
|
for _, upgrade in pairs(upgrades) do |
|
upgrade.button.MouseButton1Click:Connect(function() |
|
local cost = math.floor(upgrade.baseCost * (1.15 ^ upgrade.owned)) |
|
if playerCookies >= cost then |
|
upgradeEvent:FireServer(upgrade.name) |
|
else |
|
-- Play error sound |
|
end |
|
end |
|
end |
|
|
|
-- Update when cookies change |
|
updateEvent.OnClientEvent:Connect(function(cookies) |
|
playerCookies = cookies |
|
updateUpgradeUI() |
|
end)</pre> |
|
</div> |
|
|
|
<div id="upgrade-server" class="code-tab"> |
|
<h4 class="font-medium text-gray-800 mb-2">Server Upgrade Handling:</h4> |
|
<pre class="bg-gray-800 text-green-300 p-3 rounded text-sm overflow-x-auto"> |
|
local ReplicatedStorage = game:GetService("ReplicatedStorage") |
|
local upgradeEvent = Instance.new("RemoteEvent") |
|
upgradeEvent.Name = "UpgradeEvent" |
|
upgradeEvent.Parent = ReplicatedStorage |
|
|
|
-- Define server-side upgrade data |
|
local upgradeData = { |
|
["Grandma"] = { |
|
baseCost = 10, |
|
rate = 0.2, |
|
type = "auto" |
|
}, |
|
["2x Multiplier"] = { |
|
baseCost = 100, |
|
multiplier = 2, |
|
type = "click" |
|
} |
|
} |
|
|
|
-- Handle upgrade purchases |
|
upgradeEvent.OnServerEvent:Connect(function(player, upgradeName) |
|
local data = playerData[player] |
|
if not data or not upgradeData[upgradeName] then return end |
|
|
|
local upgrade = upgradeData[upgradeName] |
|
local owned = data.upgrades[upgradeName] or 0 |
|
local cost = math.floor(upgrade.baseCost * (1.15 ^ owned)) |
|
|
|
if data.cookies >= cost then |
|
-- Deduct cookies |
|
data.cookies = data.cookies - cost |
|
player.leaderstats.Cookies.Value = data.cookies |
|
|
|
-- Apply upgrade |
|
if upgrade.type == "auto" then |
|
table.insert(data.autoClickers, { |
|
name = upgradeName, |
|
rate = upgrade.rate, |
|
nextTick = time() + 1 |
|
}) |
|
elseif upgrade.type == "click" then |
|
data.clickMultiplier = data.clickMultiplier * upgrade.multiplier |
|
end |
|
|
|
-- Update client |
|
ReplicatedStorage.CookieUpdate:FireClient(player, data.cookies) |
|
end |
|
end) |
|
|
|
-- Auto-clicker processing |
|
local function processAutoClickers() |
|
while true do |
|
local currentTime = time() |
|
for player, data in pairs(playerData) do |
|
for _, clicker in pairs(data.autoClickers) do |
|
if currentTime >= clicker.nextTick then |
|
data.cookies = data.cookies + clicker.rate |
|
player.leaderstats.Cookies.Value = data.cookies |
|
clicker.nextTick = currentTime + 1 |
|
end |
|
end |
|
end |
|
wait(0.1) |
|
end |
|
end |
|
|
|
-- Start the auto-clicker loop |
|
spawn(processAutoClickers)</pre> |
|
</div> |
|
</div> |
|
|
|
<div class="mt-4 p-3 bg-amber-100 rounded border-l-4 border-amber-500"> |
|
<h4 class="font-medium text-amber-800 mb-2">Pro Tip:</h4> |
|
<p class="text-sm text-amber-700">Use a ModuleScript to store all upgrade data for easy maintenance. This allows you to balance game economics without touching the core logic.</p> |
|
</div> |
|
</div> |
|
</div> |
|
</section> |
|
|
|
|
|
<section id="cookie-design" class="mb-12"> |
|
<h2 class="text-3xl font-bold text-amber-800 mb-6 border-b-2 border-amber-200 pb-2">2. Creating an Appealing Cookie</h2> |
|
|
|
<div class="grid md:grid-cols-2 gap-8"> |
|
|
|
<div class="bg-amber-50 p-6 rounded-lg"> |
|
<h3 class="text-xl font-semibold text-amber-700 mb-4">Advanced Visual Design</h3> |
|
|
|
<div class="mb-6 grid grid-cols-2 gap-4"> |
|
<div class="bg-white p-4 rounded-lg shadow"> |
|
<h4 class="font-medium text-gray-800 mb-2">Particle Effects</h4> |
|
<ul class="list-disc pl-5 text-sm space-y-1"> |
|
<li>Cookie crumbs on click</li> |
|
<li>Golden sparkles for critical clicks</li> |
|
<li>Steam effect for hot cookies</li> |
|
<li>Trail effect when dragging</li> |
|
</ul> |
|
</div> |
|
<div class="bg-white p-4 rounded-lg shadow"> |
|
<h4 class="font-medium text-gray-800 mb-2">Sound Design</h4> |
|
<ul class="list-disc pl-5 text-sm space-y-1"> |
|
<li>Crunch sound on click</li> |
|
<li>Cha-ching for purchases</li> |
|
<li>Positive ding for achievements</li> |
|
<li>Background bakery music</li> |
|
</ul> |
|
</div> |
|
<div class="bg-white p-4 rounded-lg shadow"> |
|
<h4 class="font-medium text-gray-800 mb-2">Animation Types</h4> |
|
<ul class="list-disc pl-5 text-sm space-y-1"> |
|
<li>Squish on click</li> |
|
<li>Rotation when idle</li> |
|
<li>Bounce when cookies added</li> |
|
<li>Celebration for milestones</li> |
|
</ul> |
|
</div> |
|
<div class="bg-white p-4 rounded-lg shadow"> |
|
<h4 class="font-medium text-gray-800 mb-2">Visual Feedback</h4> |
|
<ul class="list-disc pl-5 text-sm space-y-1"> |
|
<li>Floating +1 cookies</li> |
|
<li>Screen shake on big clicks</li> |
|
<li>Color pulses for bonuses</li> |
|
<li>Glow effects for active boosts</li> |
|
</ul> |
|
</div> |
|
</div> |
|
|
|
<div class="flex justify-center space-x-6"> |
|
<div class="text-center"> |
|
<div class="w-24 h-24 rounded-full bg-amber-200 border-4 border-amber-400 mx-auto mb-2 flex items-center justify-center"> |
|
<i class="fas fa-cookie-bite text-amber-700 text-3xl"></i> |
|
</div> |
|
<p class="text-sm font-medium">Default Cookie</p> |
|
</div> |
|
<div class="text-center"> |
|
<div class="w-24 h-24 rounded-full bg-blue-200 border-4 border-blue-400 mx-auto mb-2 flex items-center justify-center relative"> |
|
<i class="fas fa-cookie-bite text-blue-700 text-3xl"></i> |
|
<div class="absolute -inset-1 rounded-full border-2 border-white animate-ping opacity-75"></div> |
|
</div> |
|
<p class="text-sm font-medium">Animated Cookie</p> |
|
</div> |
|
<div class="text-center"> |
|
<div class="w-24 h-24 rounded-full bg-purple-200 border-4 border-purple-400 mx-auto mb-2 flex items-center justify-center"> |
|
<i class="fas fa-cookie-bite text-purple-700 text-3xl"></i> |
|
<div class="absolute inset-0 rounded-full bg-white opacity-20 animate-pulse"></div> |
|
</div> |
|
<p class="text-sm font-medium">Glowing Cookie</p> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="bg-amber-50 p-6 rounded-lg"> |
|
<h3 class="text-xl font-semibold text-amber-700 mb-4">Advanced Effects Implementation</h3> |
|
|
|
<div class="mb-6"> |
|
<h4 class="font-medium text-gray-800 mb-2">Particle System Setup:</h4> |
|
<pre class="bg-gray-800 text-green-300 p-3 rounded text-sm overflow-x-auto"> |
|
-- Create particle emitter for cookie |
|
local particleEmitter = Instance.new("ParticleEmitter") |
|
particleEmitter.Name = "CookieParticles" |
|
particleEmitter.Parent = cookieButton |
|
|
|
-- Configure particles |
|
particleEmitter.Texture = "rbxassetid://242842629" -- Crumb texture |
|
particleEmitter.LightEmission = 0.5 |
|
particleEmitter.Size = NumberSequence.new({ |
|
NumberSequenceKeypoint.new(0, 0.5), |
|
NumberSequenceKeypoint.new(1, 0) |
|
}) |
|
particleEmitter.Transparency = NumberSequence.new({ |
|
NumberSequenceKeypoint.new(0, 0), |
|
NumberSequenceKeypoint.new(1, 1) |
|
}) |
|
particleEmitter.Lifetime = NumberRange.new(0.5, 1) |
|
particleEmitter.Rate = 0 -- We'll emit manually |
|
particleEmitter.Speed = NumberRange.new(20, 50) |
|
particleEmitter.SpreadAngle = Vector2.new(45, 45) |
|
particleEmitter.Rotation = NumberRange.new(0, 360) |
|
|
|
-- Emit particles on click |
|
cookieButton.MouseButton1Click:Connect(function() |
|
particleEmitter:Emit(10) -- Emit 10 particles |
|
|
|
-- Also emit golden particles for critical clicks |
|
if math.random() < 0.1 then -- 10% chance |
|
local goldenEmitter = cookieButton:FindFirstChild("GoldenParticles") |
|
if goldenEmitter then |
|
goldenEmitter:Emit(20) |
|
end |
|
end |
|
end)</pre> |
|
</div> |
|
|
|
<div> |
|
<h4 class="font-medium text-gray-800 mb-2">Advanced Click Animation:</h4> |
|
<pre class="bg-gray-800 text-green-300 p-3 rounded text-sm overflow-x-auto"> |
|
local UserInputService = game:GetService("UserInputService") |
|
local TweenService = game:GetService("TweenService") |
|
|
|
-- Click animation with squash effect |
|
cookieButton.MouseButton1Down:Connect(function() |
|
-- Squash vertically, stretch horizontally |
|
local squashTween = TweenService:Create( |
|
cookieButton, |
|
TweenInfo.new(0.1, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), |
|
{Size = UDim2.new(1.1, 0, 0.9, 0)} |
|
) |
|
squashTween:Play() |
|
end) |
|
|
|
-- Release animation with bounce |
|
cookieButton.MouseButton1Up:Connect(function() |
|
-- First return to normal size quickly |
|
local returnTween = TweenService:Create( |
|
cookieButton, |
|
TweenInfo.new(0.1, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), |
|
{Size = UDim2.new(1, 0, 1, 0)} |
|
) |
|
returnTween:Play() |
|
|
|
-- Then add a little bounce |
|
task.wait(0.1) |
|
local bounceTween = TweenService:Create( |
|
cookieButton, |
|
TweenInfo.new(0.3, Enum.EasingStyle.Elastic, Enum.EasingDirection.Out, 0, false, 0), |
|
{Size = UDim2.new(1.05, 0, 1.05, 0)} |
|
) |
|
bounceTween:Play() |
|
end) |
|
|
|
-- Drag effect (cookie follows mouse slightly) |
|
local dragConnection |
|
cookieButton.MouseEnter:Connect(function() |
|
dragConnection = UserInputService.InputChanged:Connect(function(input) |
|
if input.UserInputType == Enum.UserInputType.MouseMovement then |
|
local mousePos = game:GetService("Players").LocalPlayer:GetMouse() |
|
local buttonPos = cookieButton.AbsolutePosition |
|
local center = buttonPos + cookieButton.AbsoluteSize/2 |
|
|
|
-- Calculate offset from center |
|
local offset = (mousePos - center) / 10 -- Divide to reduce movement |
|
|
|
-- Apply offset with tween for smooth movement |
|
TweenService:Create( |
|
cookieButton, |
|
TweenInfo.new(0.2, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), |
|
{Position = UDim2.new(0.5, offset.X, 0.5, offset.Y)} |
|
):Play() |
|
end |
|
end) |
|
end) |
|
|
|
cookieButton.MouseLeave:Connect(function() |
|
if dragConnection then |
|
dragConnection:Disconnect() |
|
-- Return to center |
|
TweenService:Create( |
|
cookieButton, |
|
TweenInfo.new(0.5, Enum.EasingStyle.Elastic, Enum.EasingDirection.Out), |
|
{Position = UDim2.new(0.5, 0, 0.5, 0)} |
|
):Play() |
|
end |
|
end)</pre> |
|
</div> |
|
</div> |
|
</div> |
|
</section> |
|
|
|
|
|
<section id="achievements" class="mb-12"> |
|
<h2 class="text-3xl font-bold text-amber-800 mb-6 border-b-2 border-amber-200 pb-2">3. Advanced Achievements System</h2> |
|
|
|
<div class="grid md:grid-cols-2 gap-8"> |
|
|
|
<div class="bg-amber-50 p-6 rounded-lg"> |
|
<h3 class="text-xl font-semibold text-amber-700 mb-4">Achievement Types & Progression</h3> |
|
|
|
<div class="mb-6"> |
|
<h4 class="font-medium text-gray-800 mb-2">Achievement Categories:</h4> |
|
<div class="grid grid-cols-2 gap-4"> |
|
<div class="bg-white p-3 rounded shadow"> |
|
<h5 class="font-semibold text-amber-600">Milestones</h5> |
|
<ul class="text-sm mt-1 space-y-1"> |
|
<li>Bake 100 cookies</li> |
|
<li>Bake 1,000 cookies</li> |
|
<li>Bake 1,000,000 cookies</li> |
|
</ul> |
|
</div> |
|
<div class="bg-white p-3 rounded shadow"> |
|
<h5 class="font-semibold text-amber-600">Upgrades</h5> |
|
<ul class="text-sm mt-1 space-y-1"> |
|
<li>Purchase first upgrade</li> |
|
<li>Own 10 grandmas</li> |
|
<li>Max out all upgrades</li> |
|
</ul> |
|
</div> |
|
<div class="bg-white p-3 rounded shadow"> |
|
<h5 class="font-semibold text-amber-600">Special</h5> |
|
<ul class="text-sm mt-1 space-y-1"> |
|
<li>Critical click (1% chance)</li> |
|
<li>Feed Cookie Monster 10 times</li> |
|
<li>Play for 24 hours total</li> |
|
</ul> |
|
</div> |
|
<div class="bg-white p-3 rounded shadow"> |
|
<h5 class="font-semibold text-amber-600">Secret</h5> |
|
<ul class="text-sm mt-1 space-y-1"> |
|
<li>Click 100 times in 10 seconds</li> |
|
<li>Find hidden cookie</li> |
|
<li>Bake negative cookies</li> |
|
</ul> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<div> |
|
<h4 class="font-medium text-gray-800 mb-2">Reward Structure:</h4> |
|
<div class="bg-white p-4 rounded-lg shadow"> |
|
<div class="flex items-center mb-3"> |
|
<div class="w-10 h-10 rounded-full bg-yellow-100 flex items-center justify-center mr-3"> |
|
<i class="fas fa-coins text-yellow-600"></i> |
|
</div> |
|
<div> |
|
<h5 class="font-semibold">Cookie Rewards</h5> |
|
<p class="text-xs text-gray-600">Instant cookie bonuses</p> |
|
</div> |
|
</div> |
|
<div class="flex items-center mb-3"> |
|
<div class="w-10 h-10 rounded-full bg-blue-100 flex items-center justify-center mr-3"> |
|
<i class="fas fa-tachometer-alt text-blue-600"></i> |
|
</div> |
|
<div> |
|
<h5 class="font-semibold">Permanent Multipliers</h5> |
|
<p class="text-xs text-gray-600">Increase cookie production</p> |
|
</div> |
|
</div> |
|
<div class="flex items-center"> |
|
<div class="w-10 h-10 rounded-full bg-purple-100 flex items-center justify-center mr-3"> |
|
<i class="fas fa-palette text-purple-600"></i> |
|
</div> |
|
<div> |
|
<h5 class="font-semibold">Exclusive Skins</h5> |
|
<p class="text-xs text-gray-600">Unique visual customization</p> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="bg-amber-50 p-6 rounded-lg"> |
|
<h3 class="text-xl font-semibold text-amber-700 mb-4">Achievement System Implementation</h3> |
|
|
|
<div class="mb-6"> |
|
<h4 class="font-medium text-gray-800 mb-2">Achievement Data Structure:</h4> |
|
<pre class="bg-gray-800 text-green-300 p-3 rounded text-sm overflow-x-auto"> |
|
-- In a ModuleScript called "AchievementData" |
|
local AchievementData = {} |
|
|
|
AchievementData.list = { |
|
{ |
|
id = "first_cookie", |
|
name = "First Cookie", |
|
desc = "Bake your first cookie", |
|
goal = 1, |
|
reward = {type = "cookies", amount = 10}, |
|
icon = "rbxassetid://123456", |
|
category = "milestone", |
|
hidden = false |
|
}, |
|
{ |
|
id = "cookie_tycoon", |
|
name = "Cookie Tycoon", |
|
desc = "Bake 1,000,000 cookies", |
|
goal = 1000000, |
|
reward = {type = "skin", id = "golden_cookie"}, |
|
icon = "rbxassetid://654321", |
|
category = "milestone", |
|
hidden = false |
|
}, |
|
{ |
|
id = "critical_click", |
|
name = "Critical Click!", |
|
desc = "Get a critical click (1% chance)", |
|
goal = 1, |
|
reward = {type = "multiplier", amount = 0.1}, |
|
icon = "rbxassetid://789012", |
|
category = "special", |
|
hidden = true |
|
} |
|
-- Add more achievements |
|
} |
|
|
|
return AchievementData</pre> |
|
</div> |
|
|
|
<div> |
|
<h4 class="font-medium text-gray-800 mb-2">Achievement Tracking System:</h4> |
|
<pre class="bg-gray-800 text-green-300 p-3 rounded text-sm overflow-x-auto"> |
|
-- Server-side achievement tracking |
|
local AchievementData = require(script.Parent.AchievementData) |
|
local ReplicatedStorage = game:GetService("ReplicatedStorage") |
|
local Players = game:GetService("Players") |
|
|
|
local achievementEvent = Instance.new("RemoteEvent") |
|
achievementEvent.Name = "AchievementEvent" |
|
achievementEvent.Parent = ReplicatedStorage |
|
|
|
local playerAchievements = {} |
|
|
|
local function onPlayerAdded(player) |
|
-- Initialize player's achievement progress |
|
playerAchievements[player] = {} |
|
|
|
for _, achievement in pairs(AchievementData.list) do |
|
playerAchievements[player][achievement.id] = { |
|
progress = 0, |
|
unlocked = false |
|
} |
|
end |
|
|
|
-- Set up stat tracking |
|
player:SetAttribute("TotalClicks", 0) |
|
player:SetAttribute("CriticalClicks", 0) |
|
end |
|
|
|
local function checkAchievement(player, achievementId, progress) |
|
local achievement = AchievementData.list[achievementId] |
|
if not achievement or playerAchievements[player][achievementId].unlocked then |
|
return |
|
end |
|
|
|
-- Update progress |
|
playerAchievements[player][achievementId].progress = progress |
|
|
|
-- Check if achievement is completed |
|
if progress >= achievement.goal then |
|
playerAchievements[player][achievementId].unlocked = true |
|
giveReward(player, achievement.reward) |
|
achievementEvent:FireClient(player, achievementId) |
|
end |
|
end |
|
|
|
-- Example of tracking cookie milestones |
|
local function onCookiesChanged(player, cookies) |
|
for _, achievement in pairs(AchievementData.list) do |
|
if achievement.category == "milestone" and string.find(achievement.desc, "Bake") then |
|
checkAchievement(player, achievement.id, cookies) |
|
end |
|
end |
|
end |
|
|
|
-- Example of tracking critical clicks |
|
local function onCriticalClick(player) |
|
player:SetAttribute("CriticalClicks", player:GetAttribute("CriticalClicks") + 1) |
|
|
|
for _, achievement in pairs(AchievementData.list) do |
|
if achievement.id == "critical_click" then |
|
checkAchievement(player, achievement.id, 1) |
|
end |
|
end |
|
end |
|
|
|
Players.PlayerAdded:Connect(onPlayerAdded)</pre> |
|
</div> |
|
</div> |
|
</div> |
|
</section> |
|
|
|
|
|
<section id="skins" class="mb-12"> |
|
<h2 class="text-3xl font-bold text-amber-800 mb-6 border-b-2 border-amber-200 pb-2">4. Advanced Skin System</h2> |
|
|
|
<div class="grid md:grid-cols-2 gap-8"> |
|
|
|
<div class="bg-amber-50 p-6 rounded-lg"> |
|
<h3 class="text-xl font-semibold text-amber-700 mb-4">Skin Shop Architecture</h3> |
|
|
|
<div class="mb-6"> |
|
<h4 class="font-medium text-gray-800 mb-2">Skin Types:</h4> |
|
<div class="grid grid-cols-3 gap-3 mb-4"> |
|
<div class="bg-white p-3 rounded text-center shadow"> |
|
<div class="w-12 h-12 rounded-full bg-amber-100 mx-auto mb-2 flex items-center justify-center"> |
|
<i class="fas fa-cookie text-amber-600"></i> |
|
</div> |
|
<p class="text-xs font-medium">Cookie Skins</p> |
|
</div> |
|
<div class="bg-white p-3 rounded text-center shadow"> |
|
<div class="w-12 h-12 rounded-full bg-blue-100 mx-auto mb-2 flex items-center justify-center"> |
|
<i class="fas fa-user text-blue-600"></i> |
|
</div> |
|
<p class="text-xs font-medium">Character Skins</p> |
|
</div> |
|
<div class="bg-white p-3 rounded text-center shadow"> |
|
<div class="w-12 h-12 rounded-full bg-purple-100 mx-auto mb-2 flex items-center justify-center"> |
|
<i class="fas fa-utensils text-purple-600"></i> |
|
</div> |
|
<p class="text-xs font-medium">Baker Tools</p> |
|
</div> |
|
</div> |
|
|
|
<h4 class="font-medium text-gray-800 mb-2">Unlock Methods:</h4> |
|
<div class="bg-white p-4 rounded-lg shadow"> |
|
<div class="flex items-center mb-3"> |
|
<div class="w-8 h-8 rounded-full bg-green-100 flex items-center justify-center mr-3"> |
|
<i class="fas fa-coins text-green-600 text-sm"></i> |
|
</div> |
|
<div> |
|
<h5 class="font-semibold">Cookie Purchase</h5> |
|
<p class="text-xs text-gray-600">Earned through normal gameplay</p> |
|
</div> |
|
</div> |
|
<div class="flex items-center mb-3"> |
|
<div class="w-8 h-8 rounded-full bg-yellow-100 flex items-center justify-center mr-3"> |
|
<i class="fas fa-trophy text-yellow-600 text-sm"></i> |
|
</div> |
|
<div> |
|
<h5 class="font-semibold">Achievement Reward</h5> |
|
<p class="text-xs text-gray-600">Complete special challenges</p> |
|
</div> |
|
</div> |
|
<div class="flex items-center"> |
|
<div class="w-8 h-8 rounded-full bg-red-100 flex items-center justify-center mr-3"> |
|
<i class="fas fa-gem text-red-600 text-sm"></i> |
|
</div> |
|
<div> |
|
<h5 class="font-semibold">Premium Currency</h5> |
|
<p class="text-xs text-gray-600">Optional real-money purchases</p> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<div> |
|
<h4 class="font-medium text-gray-800 mb-2">Skin Rarity System:</h4> |
|
<div class="grid grid-cols-4 gap-2 text-xs text-center"> |
|
<div class="bg-gray-100 p-2 rounded">Common</div> |
|
<div class="bg-blue-100 p-2 rounded">Uncommon</div> |
|
<div class="bg-purple-100 p-2 rounded">Rare</div> |
|
<div class="bg-yellow-100 p-2 rounded">Legendary</div> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="bg-amber-50 p-6 rounded-lg"> |
|
<h3 class="text-xl font-semibold text-amber-700 mb-4">Skin System Implementation</h3> |
|
|
|
<div class="mb-6"> |
|
<h4 class="font-medium text-gray-800 mb-2">Skin Data Module:</h4> |
|
<pre class="bg-gray-800 text-green-300 p-3 rounded text-sm overflow-x-auto"> |
|
-- In a ModuleScript called "SkinData" |
|
local SkinData = {} |
|
|
|
SkinData.cookieSkins = { |
|
{ |
|
id = "classic", |
|
name = "Classic Cookie", |
|
texture = "rbxassetid://123456", |
|
price = 0, |
|
rarity = "common", |
|
ownedByDefault = true |
|
}, |
|
{ |
|
id = "golden", |
|
name = "Golden Cookie", |
|
texture = "rbxassetid://234567", |
|
price = 10000, |
|
rarity = "rare", |
|
unlockMethod = "purchase" |
|
}, |
|
{ |
|
id = "dragon", |
|
name = "Dragon Cookie", |
|
texture = "rbxassetid://345678", |
|
unlockMethod = "achievement", |
|
achievementId = "dragon_slayer", |
|
rarity = "legendary" |
|
} |
|
} |
|
|
|
SkinData.characterSkins = { |
|
-- Similar structure for character skins |
|
} |
|
|
|
return SkinData</pre> |
|
</div> |
|
|
|
<div> |
|
<h4 class="font-medium text-gray-800 mb-2">Skin Management System:</h4> |
|
<pre class="bg-gray-800 text-green-300 p-3 rounded text-sm overflow-x-auto"> |
|
local ReplicatedStorage = game:GetService("ReplicatedStorage") |
|
local Players = game:GetService("Players") |
|
local SkinData = require(script.Parent.SkinData) |
|
|
|
local skinEvent = Instance.new("RemoteEvent") |
|
skinEvent.Name = "SkinEvent" |
|
skinEvent.Parent = ReplicatedStorage |
|
|
|
local playerSkins = {} |
|
|
|
local function onPlayerAdded(player) |
|
-- Initialize player's skin data |
|
playerSkins[player] = { |
|
equippedCookie = "classic", |
|
equippedCharacter = "baker", |
|
ownedSkins = {} |
|
} |
|
|
|
-- Grant default skins |
|
for _, skin in pairs(SkinData.cookieSkins) do |
|
if skin.ownedByDefault then |
|
table.insert(playerSkins[player].ownedSkins, { |
|
type = "cookie", |
|
id = skin.id |
|
}) |
|
end |
|
end |
|
|
|
-- Load saved data from DataStore |
|
-- (Implementation similar to previous data saving examples) |
|
end |
|
|
|
-- Handle skin purchases |
|
skinEvent.OnServerEvent:Connect(function(player, action, skinType, skinId) |
|
if action == "purchase" then |
|
local skin = SkinData[skinType.."Skins"][skinId] |
|
if not skin or skin.unlockMethod ~= "purchase" then return end |
|
|
|
-- Check if player can afford |
|
if player.leaderstats.Cookies.Value >= skin.price then |
|
player.leaderstats.Cookies.Value = player.leaderstats.Cookies.Value - skin.price |
|
table.insert(playerSkins[player].ownedSkins, { |
|
type = skinType, |
|
id = skinId |
|
}) |
|
|
|
-- Notify client of successful purchase |
|
skinEvent:FireClient(player, "purchased", skinType, skinId) |
|
end |
|
elseif action == "equip" then |
|
-- Check if player owns this skin |
|
local ownsSkin = false |
|
for _, ownedSkin in pairs(playerSkins[player].ownedSkins) do |
|
if ownedSkin.type == skinType and ownedSkin.id == skinId then |
|
ownsSkin = true |
|
break |
|
end |
|
end |
|
|
|
if ownsSkin then |
|
playerSkins[player]["equipped"..skinType:sub(1,1):upper()..skinType:sub(2)] = skinId |
|
skinEvent:FireClient(player, "equipped", skinType, skinId) |
|
end |
|
end |
|
end) |
|
|
|
-- Grant achievement skins |
|
local function onAchievementUnlocked(player, achievementId) |
|
for _, skin in pairs(SkinData.cookieSkins) do |
|
if skin.unlockMethod == "achievement" and skin.achievementId == achievementId then |
|
table.insert(playerSkins[player].ownedSkins, { |
|
type = "cookie", |
|
id = skin.id |
|
}) |
|
skinEvent:FireClient(player, "unlocked", "cookie", skin.id) |
|
end |
|
end |
|
end |
|
|
|
Players.PlayerAdded:Connect(onPlayerAdded)</pre> |
|
</div> |
|
</div> |
|
</div> |
|
</section> |
|
|
|
|
|
<section id="leaderboard" class="mb-12"> |
|
<h2 class="text-3xl font-bold text-amber-800 mb-6 border-b-2 border-amber-200 pb-2">5. Global Leaderboard with Countries</h2> |
|
|
|
<div class="grid md:grid-cols-2 gap-8"> |
|
|
|
<div class="bg-amber-50 p-6 rounded-lg"> |
|
<h3 class="text-xl font-semibold text-amber-700 mb-4">Leaderboard Features</h3> |
|
|
|
<div class="mb-6"> |
|
<h4 class="font-medium text-gray-800 mb-2">Filtering Options:</h4> |
|
<div class="bg-white p-4 rounded-lg shadow mb-4"> |
|
<div class="flex flex-wrap gap-2"> |
|
<button class="px-3 py-1 bg-amber-500 text-white rounded-full text-xs">Global</button> |
|
<button class="px-3 py-1 bg-white border border-amber-300 rounded-full text-xs">United States</button> |
|
<button class="px-3 py-1 bg-white border border-amber-300 rounded-full text-xs">United Kingdom</button> |
|
<button class="px-3 py-1 bg-white border border-amber-300 rounded-full text-xs">Canada</button> |
|
<button class="px-3 py-1 bg-white border border-amber-300 rounded-full text-xs">Australia</button> |
|
<button class="px-3 py-1 bg-white border border-amber-300 rounded-full text-xs">Japan</button> |
|
</div> |
|
</div> |
|
|
|
<h4 class="font-medium text-gray-800 mb-2">Time Frames:</h4> |
|
<div class="bg-white p-4 rounded-lg shadow"> |
|
<div class="flex gap-2"> |
|
<button class="px-3 py-1 bg-amber-500 text-white rounded-full text-xs">All-Time</button> |
|
<button class="px-3 py-1 bg-white border border-amber-300 rounded-full text-xs">Daily</button> |
|
<button class="px-3 py-1 bg-white border border-amber-300 rounded-full text-xs">Weekly</button> |
|
<button class="px-3 py-1 bg-white border border-amber-300 rounded-full text-xs">Monthly</button> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<div> |
|
<h4 class="font-medium text-gray-800 mb-2">Player Badges:</h4> |
|
<div class="flex flex-wrap gap-2"> |
|
<div class="w-8 h-8 rounded-full bg-yellow-100 flex items-center justify-center"> |
|
<i class="fas fa-crown text-yellow-600 text-xs"></i> |
|
</div> |
|
<div class="w-8 h-8 rounded-full bg-silver-100 flex items-center justify-center"> |
|
<i class="fas fa-medal text-gray-600 text-xs"></i> |
|
</div> |
|
<div class="w-8 h-8 rounded-full bg-amber-100 flex items-center justify-center"> |
|
<i class="fas fa-award text-amber-600 text-xs"></i> |
|
</div> |
|
<div class="w-8 h-8 rounded-full bg-blue-100 flex items-center justify-center"> |
|
<i class="fas fa-flag text-blue-600 text-xs"></i> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="bg-amber-50 p-6 rounded-lg"> |
|
<h3 class="text-xl font-semibold text-amber-700 mb-4">Leaderboard Implementation</h3> |
|
|
|
<div class="mb-6"> |
|
<h4 class="font-medium text-gray-800 mb-2">Country Detection:</h4> |
|
<pre class="bg-gray-800 text-green-300 p-3 rounded text-sm overflow-x-auto"> |
|
-- Server script to detect player country |
|
local HttpService = game:GetService("HttpService") |
|
local Players = game:GetService("Players") |
|
|
|
local function getPlayerCountry(player) |
|
-- Try to get from saved data first |
|
local success, savedCountry = pcall(function() |
|
return DataStore:GetAsync("PlayerCountry_"..player.UserId) |
|
end) |
|
|
|
if success and savedCountry then |
|
return savedCountry |
|
end |
|
|
|
-- Fallback to IP detection (requires HTTP enabled) |
|
local ip = player:GetRemote("GetRemoteEvent").InvokeClient(player, "GetIP") |
|
|
|
if ip then |
|
local success, geoData = pcall(function() |
|
return HttpService:JSONDecode(HttpService:GetAsync( |
|
"http://ip-api.com/json/"..ip.."?fields=countryCode" |
|
)) |
|
end) |
|
|
|
if success and geoData.countryCode then |
|
-- Save for future sessions |
|
pcall(function() |
|
DataStore:SetAsync("PlayerCountry_"..player.UserId, geoData.countryCode) |
|
end) |
|
return geoData.countryCode |
|
end |
|
end |
|
|
|
return "Unknown" |
|
end |
|
|
|
Players.PlayerAdded:Connect(function(player) |
|
player:SetAttribute("Country", getPlayerCountry(player)) |
|
end)</pre> |
|
</div> |
|
|
|
<div> |
|
<h4 class="font-medium text-gray-800 mb-2">Global Data Handling:</h4> |
|
<pre class="bg-gray-800 text-green-300 p-3 rounded text-sm overflow-x-auto"> |
|
-- Using DataStores for global leaderboard |
|
local DataStoreService = game:GetService("DataStoreService") |
|
local leaderboardStore = DataStoreService:GetOrderedDataStore("GlobalLeaderboard") |
|
|
|
local function updateGlobalLeaderboard(player, cookies) |
|
-- Update all-time leaderboard |
|
pcall(function() |
|
leaderboardStore:SetAsync(tostring(player.UserId), cookies) |
|
end) |
|
|
|
-- Update daily leaderboard (with today's date as key) |
|
local today = os.date("%Y-%m-%d") |
|
local dailyKey = "daily_"..today.."_"..player.UserId |
|
pcall(function() |
|
leaderboardStore:SetAsync(dailyKey, cookies) |
|
end) |
|
end |
|
|
|
-- Function to get leaderboard data |
|
local function getLeaderboardData(scope, country) |
|
-- scope can be "alltime", "daily", "weekly", "monthly" |
|
-- country can be country code or "Global" |
|
|
|
local data = {} |
|
local keyPrefix = "" |
|
|
|
if scope == "daily" then |
|
keyPrefix = "daily_"..os.date("%Y-%m-%d").."_" |
|
elseif scope == "weekly" then |
|
-- Similar implementation for weekly |
|
end |
|
|
|
-- Get top 100 entries |
|
local success, pages = pcall(function() |
|
if country == "Global" then |
|
return leaderboardStore:GetSortedAsync(false, 100, keyPrefix) |
|
else |
|
-- Filter by country would require additional data structure |
|
-- This is a simplified version |
|
return leaderboardStore:GetSortedAsync(false, 100) |
|
end |
|
end) |
|
|
|
if success then |
|
for _, entry in ipairs(pages:GetCurrentPage()) do |
|
local userId = entry.key:gsub(keyPrefix, "") |
|
table.insert(data, { |
|
userId = userId, |
|
cookies = entry.value |
|
}) |
|
end |
|
end |
|
|
|
return data |
|
end |
|
|
|
-- Example of player data saving |
|
game.Players.PlayerRemoving:Connect(function(player) |
|
updateGlobalLeaderboard(player, player.leaderstats.Cookies.Value) |
|
end)</pre> |
|
</div> |
|
</div> |
|
</div> |
|
</section> |
|
|
|
|
|
<section id="cookie-monster" class="mb-12"> |
|
<h2 class="text-3xl font-bold text-amber-800 mb-6 border-b-2 border-amber-200 pb-2">6. Cookie Monster Game Mechanic</h2> |
|
|
|
<div class="grid md:grid-cols-2 gap-8"> |
|
|
|
<div class="bg-amber-50 p-6 rounded-lg"> |
|
<h3 class="text-xl font-semibold text-amber-700 mb-4">Cookie Monster Features</h3> |
|
|
|
<div class="mb-6"> |
|
<h4 class="font-medium text-gray-800 mb-2">Monster States:</h4> |
|
<div class="grid grid-cols-3 gap-3 text-center text-xs"> |
|
<div class="bg-green-100 p-3 rounded"> |
|
<div class="w-12 h-12 mx-auto mb-2 bg-green-200 rounded-full flex items-center justify-center"> |
|
<i class="fas fa-smile text-green-600"></i> |
|
</div> |
|
<p>Happy (0-30%)</p> |
|
</div> |
|
<div class="bg-yellow-100 p-3 rounded"> |
|
<div class="w-12 h-12 mx-auto mb-2 bg-yellow-200 rounded-full flex items-center justify-center"> |
|
<i class="fas fa-meh text-yellow-600"></i> |
|
</div> |
|
<p>Hungry (31-70%)</p> |
|
</div> |
|
<div class="bg-red-100 p-3 rounded"> |
|
<div class="w-12 h-12 mx-auto mb-2 bg-red-200 rounded-full flex items-center justify-center"> |
|
<i class="fas fa-angry text-red-600"></i> |
|
</div> |
|
<p>Enraged (71-100%)</p> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<div> |
|
<h4 class="font-medium text-gray-800 mb-2">Feeding Mechanics:</h4> |
|
<ul class="list-disc pl-5 space-y-2 text-gray-700"> |
|
<li><strong>Basic Feed:</strong> 50 cookies - reduces hunger by 25%</li> |
|
<li><strong>Special Feed:</strong> 200 cookies - reduces hunger by 60%</li> |
|
<li><strong>Golden Feed:</strong> 1000 cookies - resets hunger to 0%</li> |
|
<li><strong>Auto-Feeder:</strong> Upgrade that automatically feeds when hunger reaches 50%</li> |
|
</ul> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="bg-amber-50 p-6 rounded-lg"> |
|
<h3 class="text-xl font-semibold text-amber-700 mb-4">Cookie Monster Implementation</h3> |
|
|
|
<div class="mb-6"> |
|
<h4 class="font-medium text-gray-800 mb-2">Monster State Management:</h4> |
|
<pre class="bg-gray-800 text-green-300 p-3 rounded text-sm overflow-x-auto"> |
|
-- Server-side monster manager |
|
local monster = { |
|
hunger = 0, -- 0-100 |
|
lastFed = os.time(), |
|
hungerRate = 0.1, -- % per minute |
|
state = "happy", |
|
rampageThreshold = 90, |
|
isRampaging = false, |
|
rampageEndTime = 0 |
|
} |
|
|
|
-- Update hunger over time |
|
local function updateHunger() |
|
while true do |
|
local timePassed = os.time() - monster.lastFed |
|
monster.hunger = math.min(100, monster.hunger + (monster.hungerRate * (timePassed/60))) |
|
|
|
-- Update state |
|
if monster.hunger <= 30 then |
|
monster.state = "happy" |
|
elseif monster.hunger <= 70 then |
|
monster.state = "hungry" |
|
else |
|
monster.state = "angry" |
|
end |
|
|
|
-- Check for rampage |
|
if monster.hunger >= monster.rampageThreshold and not monster.isRampaging then |
|
startRampage() |
|
end |
|
|
|
-- Increase hunger rate over time (gets harder) |
|
monster.hungerRate = monster.hungerRate * 1.0001 |
|
|
|
-- Broadcast update to all players |
|
for _, player in ipairs(game.Players:GetPlayers()) do |
|
ReplicatedStorage.MonsterUpdate:FireClient(player, { |
|
hunger = monster.hunger, |
|
state = monster.state, |
|
isRampaging = monster.isRampaging, |
|
timeLeft = monster.rampageEndTime - os.time() |
|
}) |
|
end |
|
|
|
wait(60) -- Update every minute |
|
end |
|
end |
|
|
|
-- Start the hunger update loop |
|
spawn(updateHunger)</pre> |
|
</div> |
|
|
|
<div> |
|
<h4 class="font-medium text-gray-800 mb-2">Rampage System:</h4> |
|
<pre class="bg-gray-800 text-green-300 p-3 rounded text-sm overflow-x-auto"> |
|
local function startRampage() |
|
monster.isRampaging = true |
|
monster.rampageEndTime = os.time() + 300 -- 5 minutes to stop |
|
|
|
-- Alert all players |
|
for _, player in ipairs(game.Players:GetPlayers()) do |
|
ReplicatedStorage.RampageAlert:FireClient(player, true) |
|
end |
|
|
|
-- Start countdown |
|
local countdown = 300 -- 5 minutes |
|
while countdown > 0 and monster.isRampaging do |
|
countdown = countdown - 1 |
|
|
|
-- Update players every second |
|
for _, player in ipairs(game.Players:GetPlayers()) do |
|
ReplicatedStorage.MonsterUpdate:FireClient(player, { |
|
hunger = monster.hunger, |
|
state = monster.state, |
|
isRampaging = monster.isRampaging, |
|
timeLeft = countdown |
|
}) |
|
end |
|
|
|
-- Check if hunger was reduced below threshold |
|
if monster.hunger < monster.rampageThreshold then |
|
monster.isRampaging = false |
|
break |
|
end |
|
|
|
wait(1) |
|
end |
|
|
|
if monster.isRampaging then |
|
-- Monster eats all cookies |
|
for _, player in ipairs(game.Players:GetPlayers()) do |
|
player.leaderstats.Cookies.Value = 0 |
|
ReplicatedStorage.CookieUpdate:FireClient(player, 0) |
|
end |
|
|
|
-- Play animation/sound |
|
for _, player in ipairs(game.Players:GetPlayers()) do |
|
ReplicatedStorage.RampageEffect:FireClient(player) |
|
end |
|
end |
|
|
|
-- Reset monster |
|
monster.isRampaging = false |
|
monster.hunger = 0 |
|
monster.lastFed = os.time() |
|
|
|
-- Alert players rampage is over |
|
for _, player in ipairs(game.Players:GetPlayers()) do |
|
ReplicatedStorage.RampageAlert:FireClient(player, false) |
|
end |
|
end |
|
|
|
-- Handle feeding |
|
ReplicatedStorage.FeedMonster.OnServerEvent:Connect(function(player, feedType) |
|
local cost = 0 |
|
local reduction = 0 |
|
|
|
if feedType == "basic" then |
|
cost = 50 |
|
reduction = 25 |
|
elseif feedType == "special" then |
|
cost = 200 |
|
reduction = 60 |
|
elseif feedType == "golden" then |
|
cost = 1000 |
|
reduction = 100 |
|
end |
|
|
|
if player.leaderstats.Cookies.Value >= cost then |
|
player.leaderstats.Cookies.Value = player.leaderstats.Cookies.Value - cost |
|
monster.hunger = math.max(0, monster.hunger - reduction) |
|
monster.lastFed = os.time() |
|
|
|
-- Check if rampage was stopped |
|
if monster.isRampaging and monster.hunger < monster.rampageThreshold then |
|
monster.isRampaging = false |
|
end |
|
end |
|
end)</pre> |
|
</div> |
|
</div> |
|
</div> |
|
</section> |
|
|
|
|
|
<section class="bg-amber-100 rounded-lg p-6 border-l-4 border-amber-500"> |
|
<h2 class="text-2xl font-bold text-amber-800 mb-4">Complete Implementation Roadmap</h2> |
|
|
|
<div class="grid md:grid-cols-3 gap-6"> |
|
<div class="bg-white p-4 rounded-lg shadow"> |
|
<h3 class="font-semibold text-amber-700 mb-3">Phase 1: Core Gameplay</h3> |
|
<ul class="list-disc pl-5 space-y-2 text-sm"> |
|
<li>Basic clicking mechanic</li> |
|
<li>Auto-clicker upgrades</li> |
|
<li>Simple cookie design</li> |
|
<li>Local leaderboard</li> |
|
</ul> |
|
</div> |
|
<div class="bg-white p-4 rounded-lg shadow"> |
|
<h3 class="font-semibold text-amber-700 mb-3">Phase 2: Progression</h3> |
|
<ul class="list-disc pl-5 space-y-2 text-sm"> |
|
<li>Achievements system</li> |
|
<li>Skin customization</li> |
|
<li>Global leaderboard</li> |
|
<li>Country selection</li> |
|
</ul> |
|
</div> |
|
<div class="bg-white p-4 rounded-lg shadow"> |
|
<h3 class="font-semibold text-amber-700 mb-3">Phase 3: Advanced Features</h3> |
|
<ul class="list-disc pl-5 space-y-2 text-sm"> |
|
<li>Cookie Monster mechanic</li> |
|
<li>Special events</li> |
|
<li>Social features</li> |
|
<li>Premium currency</li> |
|
</ul> |
|
</div> |
|
</div> |
|
|
|
<div class="mt-6 bg-white p-4 rounded-lg shadow"> |
|
<h3 class="font-semibold text-amber-700 mb-3">Optimization Checklist</h3> |
|
<div class="grid grid-cols-2 gap-4"> |
|
<div> |
|
<h4 class="font-medium text-gray-800 mb-2">Performance:</h4> |
|
<ul class="list-disc pl-5 space-y-1 text-sm"> |
|
<li>Use ValueObjects for frequently updated values</li> |
|
<li>Limit particle effects</li> |
|
<li>Optimize DataStore calls</li> |
|
</ul> |
|
</div> |
|
<div> |
|
<h4 class="font-medium text-gray-800 mb-2">Security:</h4> |
|
<ul class="list-disc pl-5 space-y-1 text-sm"> |
|
<li>Server-side validation</li> |
|
<li>Anti-exploit checks</li> |
|
<li>DataStore backup system</li> |
|
</ul> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<div class="mt-6 text-center"> |
|
<button class="cookie-btn px-6 py-3 bg-amber-500 text-white rounded-full text-lg font-bold shadow-lg hover:bg-amber-600"> |
|
<i class="fas fa-rocket mr-2"></i> Launch Your Cookie Empire! |
|
</button> |
|
</div> |
|
</section> |
|
</main> |
|
|
|
|
|
<footer class="mt-12 text-center text-white opacity-80 text-sm"> |
|
<p>© 2023 Ultimate Roblox Cookie Clicker Guide. All rights reserved.</p> |
|
<p class="mt-2">Created with <i class="fas fa-heart text-red-400"></i> for Roblox developers</p> |
|
</footer> |
|
</div> |
|
|
|
<script> |
|
|
|
document.querySelectorAll('.code-tab-btn').forEach(btn => { |
|
btn.addEventListener('click', function() { |
|
const tabId = this.getAttribute('data-tab'); |
|
const container = this.closest('.bg-gray-100'); |
|
|
|
|
|
container.querySelectorAll('.code-tab-btn').forEach(t => { |
|
t.classList.remove('border-b-2', 'border-amber-500', 'text-amber-700'); |
|
t.classList.add('text-gray-600'); |
|
}); |
|
|
|
|
|
container.querySelectorAll('.code-tab').forEach(t => { |
|
t.classList.remove('active'); |
|
}); |
|
|
|
|
|
this.classList.add('border-b-2', 'border-amber-500', 'text-amber-700'); |
|
this.classList.remove('text-gray-600'); |
|
document.getElementById(tabId).classList.add('active'); |
|
}); |
|
}); |
|
|
|
|
|
document.querySelectorAll('.cookie-btn').forEach(btn => { |
|
btn.addEventListener('click', function() { |
|
this.classList.add('animate-bounce'); |
|
setTimeout(() => { |
|
this.classList.remove('animate-bounce'); |
|
}, 1000); |
|
}); |
|
}); |
|
</script> |
|
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=DiamondVi/cookie-1" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
|
</html> |