CCCPaste

Cp&Summit System

-- Checkpoints&Summit System By KitooStudioLite
-- Pasang Di SSS ( Script )

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local DataStoreService = game:GetService("DataStoreService")

local Config = require(ReplicatedStorage:WaitForChild("Config"))

-- DataStore
local CheckpointData = DataStoreService:GetDataStore("SummitStoreV1")

-- RemoteEvent
local REMOTE_EVENT_NAME = "RunControlCommand"
local RunCommandEvent = ReplicatedStorage:FindFirstChild(REMOTE_EVENT_NAME)
if not RunCommandEvent then
    RunCommandEvent = Instance.new("RemoteEvent")
    RunCommandEvent.Name = REMOTE_EVENT_NAME
    RunCommandEvent.Parent = ReplicatedStorage
end

-- Admin check
local function isAdmin(player)
    local name = player.Name:lower()
    for _, v in ipairs(Config.OwnerUsernames) do
        if name == v:lower() then return true end
    end
    for _, v in ipairs(Config.AdminUsernames) do
        if name == v:lower() then return true end
    end
    return false
end

-- Workspace references
local checkpointsFolder = workspace:WaitForChild("Checkpoints")
local summitPart = workspace:WaitForChild("Summit")
local fallFolder = workspace:WaitForChild("FallParts")
local START_SPAWN_LOCATION = Vector3.new(0, 20, 0)

-- Load checkpoints
local checkpoints = {}
for _, cp in ipairs(checkpointsFolder:GetChildren()) do
    if cp:IsA("BasePart") then
        table.insert(checkpoints, cp)
    end
end
table.sort(checkpoints, function(a,b)
    local n1 = tonumber(a.Name:match("%d+")) or 0
    local n2 = tonumber(b.Name:match("%d+")) or 0
    return n1 < n2
end)

-- Warna checkpoint
local COLOR_PASSED = Color3.fromRGB(0,255,0)
local COLOR_UNPASSED = Color3.fromRGB(255,0,0)

-- Teleport function
local function teleportToCheckpoint(player)
    local cpIndex = player:GetAttribute("Checkpoint") or 0
    local pos = START_SPAWN_LOCATION
    if cpIndex > 0 and checkpoints[cpIndex] then
        pos = checkpoints[cpIndex].Position + Vector3.new(0,3,0)
    end
    local char = player.Character
    if char and char:FindFirstChild("HumanoidRootPart") then
        char:SetPrimaryPartCFrame(CFrame.new(pos))
    end
end

-- Setup player
local function setupPlayer(player)
    local leaderstats = Instance.new("Folder")
    leaderstats.Name = "leaderstats"
    leaderstats.Parent = player

    local cpStat = Instance.new("IntValue")
    cpStat.Name = "Checkpoint"
    cpStat.Value = 0
    cpStat.Parent = leaderstats

    local summitStat = Instance.new("NumberValue")
    summitStat.Name = "Summit"
    summitStat.Value = 0
    summitStat.Parent = leaderstats

    -- Load DataStore
    local data
    local success, err = pcall(function()
        data = CheckpointData:GetAsync(player.UserId)
    end)

    local lastCP = 0
    local totalSummit = 0
    if success and data then
        lastCP = data.LastCheckpoint or 0
        totalSummit = data.TotalSummit or 0
    end

    cpStat.Value = lastCP
    summitStat.Value = totalSummit
    player:SetAttribute("Checkpoint", lastCP)

    -- Set checkpoint colors
    for i, cp in ipairs(checkpoints) do
        cp.BrickColor = BrickColor.new(i <= lastCP and COLOR_PASSED or COLOR_UNPASSED)
    end

    player.CharacterAdded:Connect(function(char)
        char:WaitForChild("HumanoidRootPart",5)
        local cpIndex = player:GetAttribute("Checkpoint") or 0
        local pos = cpIndex > 0 and checkpoints[cpIndex].Position + Vector3.new(0,3,0) or START_SPAWN_LOCATION
        char:MoveTo(pos)
    end)
end

Players.PlayerAdded:Connect(setupPlayer)

Players.PlayerRemoving:Connect(function(player)
    local summitVal = player.leaderstats:FindFirstChild("Summit")
    local cpVal = player:GetAttribute("Checkpoint")
    if summitVal and cpVal ~= nil then
        pcall(function()
            CheckpointData:SetAsync(player.UserId,{
                LastCheckpoint = cpVal,
                TotalSummit = summitVal.Value
            })
        end)
    end
end)

-- Checkpoint touched
for i, cp in ipairs(checkpoints) do
    cp.Touched:Connect(function(hit)
        local player = Players:GetPlayerFromCharacter(hit.Parent)
        if not player then return end

        local currentCP = player:GetAttribute("Checkpoint") or 0
        if currentCP == i-1 then
            player:SetAttribute("Checkpoint", i)
            player.leaderstats.Checkpoint.Value = i
            cp.BrickColor = BrickColor.new(COLOR_PASSED)

            -- Notification
            RunCommandEvent:FireClient(player,"TouchNotification","✅ Checkpoint #"..i.." diamankan!")

            pcall(function()
                CheckpointData:SetAsync(player.UserId,{
                    LastCheckpoint = i,
                    TotalSummit = player.leaderstats.Summit.Value
                })
            end)
        end
    end)
end

-- Summit touched
summitPart.Touched:Connect(function(hit)
    local player = Players:GetPlayerFromCharacter(hit.Parent)
    if not player then return end

    local totalCP = #checkpoints
    local currentCP = player:GetAttribute("Checkpoint") or 0
    if currentCP == totalCP then
        player.leaderstats.Summit.Value += 1
        player:SetAttribute("Checkpoint",0)
        player.leaderstats.Checkpoint.Value = 0

        for _, cp in ipairs(checkpoints) do
            cp.BrickColor = BrickColor.new(COLOR_UNPASSED)
        end

        RunCommandEvent:FireClient(player,"TouchNotification","🏔️ Anda mencapai Summit! (+1)")

        pcall(function()
            CheckpointData:SetAsync(player.UserId,{
                LastCheckpoint = 0,
                TotalSummit = player.leaderstats.Summit.Value
            })
        end)
    end
end)

-- Fall parts teleport
for _, part in ipairs(fallFolder:GetChildren()) do
    if part:IsA("BasePart") then
        part.Touched:Connect(function(hit)
            local player = Players:GetPlayerFromCharacter(hit.Parent)
            if not player then return end
            teleportToCheckpoint(player)
        end)
    end
end

-- Admin adjust summit
RunCommandEvent.OnServerEvent:Connect(function(player,command,targetName,amount)
    if not isAdmin(player) then
        RunCommandEvent:FireClient(player,"Notification","❌ Gagal: Bukan admin",Color3.fromRGB(255,0,0))
        return
    end

    if command == "AdjustSummit" and type(amount) == "number" then
        local target = Players:FindFirstChild(targetName)
        if not target then
            RunCommandEvent:FireClient(player,"Notification","⚠️ Pemain "..targetName.." tidak ditemukan",Color3.fromRGB(255,0,0))
            return
        end

        local stat = target.leaderstats:FindFirstChild("Summit")
        if stat then
            stat.Value += amount
            pcall(function()
                CheckpointData:SetAsync(target.UserId,{
                    LastCheckpoint = target:GetAttribute("Checkpoint"),
                    TotalSummit = stat.Value
                })
            end)

            local action = amount >= 0 and "ditambahkan" or "dikurangi"
            RunCommandEvent:FireClient(player,"Notification",
                string.format("✅ Summit %s %.1f untuk %s (Total: %.1f)", action, math.abs(amount), targetName, stat.Value),
                Color3.fromRGB(0,200,0))
        else
            RunCommandEvent:FireClient(player,"Notification","❌ Leaderstat 'Summit' tidak ditemukan",Color3.fromRGB(255,0,0))
        end
    end
end)