-- src/ServerScriptService/AchievementManager.server.lua local Players = game:GetService("Players") local ReplicatedStorage = game:GetService("ReplicatedStorage") local NotificationEvent = ReplicatedStorage:WaitForChild("Events"):WaitForChild("NotificationEvent") -- Achievement definitions local Achievements = { {id = "first_chop", title = "First Swing", description = "Chop your first tree segment", stat = "WoodChopped", target = 1}, {id = "chop_100", title = "Century Cutter", description = "Chop 100 tree segments", stat = "WoodChopped", target = 100}, {id = "chop_500", title = "Lumber Legend", description = "Chop 500 tree segments", stat = "WoodChopped", target = 500}, {id = "chop_1000", title = "Timber Titan", description = "Chop 1000 tree segments", stat = "WoodChopped", target = 1000}, {id = "earn_1000", title = "First Thousand", description = "Earn $1,000 total", stat = "TotalEarned", target = 1000}, {id = "earn_10000", title = "Money Bags", description = "Earn $10,000 total", stat = "TotalEarned", target = 10000}, {id = "earn_100000", title = "Timber Mogul", description = "Earn $100,000 total", stat = "TotalEarned", target = 100000}, {id = "build_1", title = "First Foundation", description = "Build your first structure", stat = "TotalBuilt", target = 1}, {id = "build_25", title = "Master Builder", description = "Build 25 structures", stat = "TotalBuilt", target = 25}, } -- Track awarded achievements per player local playerAchievements = {} -- [userId] = {achievementId = true, ...} local function checkAchievements(player) local data = _G.GetPlayerData(player) if not data then return end if not playerAchievements[player.UserId] then playerAchievements[player.UserId] = {} end local leaderstats = player:FindFirstChild("leaderstats") for _, achievement in ipairs(Achievements) do if playerAchievements[player.UserId][achievement.id] then continue end local currentValue = 0 -- Check leaderstats if leaderstats then local stat = leaderstats:FindFirstChild(achievement.stat) if stat then currentValue = stat.Value end end -- Check player data if data[achievement.stat] then currentValue = data[achievement.stat] end if currentValue >= achievement.target then playerAchievements[player.UserId][achievement.id] = true NotificationEvent:FireClient(player, "Achievement", achievement.title .. " - " .. achievement.description) end end end -- Expose for other managers _G.CheckAchievements = function(player) checkAchievements(player) end _G.GetPlayerAchievements = function(player) return playerAchievements[player.UserId] or {} end -- Periodic check task.spawn(function() while true do task.wait(10) for _, player in ipairs(Players:GetPlayers()) do pcall(function() checkAchievements(player) end) end end end) Players.PlayerRemoving:Connect(function(player) playerAchievements[player.UserId] = nil end)