Simple TP Checkpoint UI
Key RequiredUniversal

Simple TP Checkpoint UI

Universal Scriptiloveaiscriptsiloveaiscripts 93 views 637 executesUpdated Jul 9, 2026
Unrated
00
Lua Script•673 lines (22998 chars)
-- Checkpoint System + Speed Changer LocalScript
-- Place in: StarterPlayer > StarterPlayerScripts

local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local TweenService = game:GetService("TweenService")

local player = Players.LocalPlayer
local playerGui = player:WaitForChild("PlayerGui")
local character = player.Character or player.CharacterAdded:Wait()
local rootPart = character:WaitForChild("HumanoidRootPart")

local checkpoints = {}
local idCounter = 0
local MAX_CHECKPOINTS = 20
local MAX_SPEED = 100000
local DEFAULT_SPEED = 16
local isCollapsed = false

-- Billboard tuning: fixed WORLD size so labels never grow, and hide when too far
local BILLBOARD_WORLD_WIDTH = 3.2   -- scale units (world-anchored size)
local BILLBOARD_WORLD_HEIGHT = 0.8
local BILLBOARD_MAX_DISTANCE = 350  -- beyond this, label stops rendering

local checkpointFolder = workspace:FindFirstChild("PlayerCheckpoints")
if not checkpointFolder then
	checkpointFolder = Instance.new("Folder")
	checkpointFolder.Name = "PlayerCheckpoints"
	checkpointFolder.Parent = workspace
end

-- ══════════════════════════════════════════
--              UI CONSTRUCTION
-- ══════════════════════════════════════════

local screenGui = Instance.new("ScreenGui")
screenGui.Name = "CheckpointSystemGui"
screenGui.ResetOnSpawn = false
screenGui.ZIndexBehavior = Enum.ZIndexBehavior.Sibling
screenGui.Parent = playerGui

local mainFrame = Instance.new("Frame")
mainFrame.Name = "MainFrame"
mainFrame.Size = UDim2.new(0, 310, 0, 510)
mainFrame.Position = UDim2.new(0, 20, 0.5, -255)
mainFrame.BackgroundColor3 = Color3.fromRGB(15, 15, 20)
mainFrame.BorderSizePixel = 0
mainFrame.ClipsDescendants = true
mainFrame.Parent = screenGui

local mainCorner = Instance.new("UICorner")
mainCorner.CornerRadius = UDim.new(0, 12)
mainCorner.Parent = mainFrame

local mainStroke = Instance.new("UIStroke")
mainStroke.Color = Color3.fromRGB(80, 130, 255)
mainStroke.Thickness = 1.5
mainStroke.Transparency = 0.4
mainStroke.Parent = mainFrame

-- ── Header bar ──────────────────────────────
local header = Instance.new("Frame")
header.Name = "Header"
header.Size = UDim2.new(1, 0, 0, 48)
header.BackgroundColor3 = Color3.fromRGB(25, 30, 50)
header.BorderSizePixel = 0
header.Parent = mainFrame

local headerCorner = Instance.new("UICorner")
headerCorner.CornerRadius = UDim.new(0, 12)
headerCorner.Parent = header

local headerFix = Instance.new("Frame")
headerFix.Size = UDim2.new(1, 0, 0, 12)
headerFix.Position = UDim2.new(0, 0, 1, -12)
headerFix.BackgroundColor3 = Color3.fromRGB(25, 30, 50)
headerFix.BorderSizePixel = 0
headerFix.Parent = header

local accentLine = Instance.new("Frame")
accentLine.Size = UDim2.new(0, 4, 0, 28)
accentLine.Position = UDim2.new(0, 14, 0.5, -14)
accentLine.BackgroundColor3 = Color3.fromRGB(80, 130, 255)
accentLine.BorderSizePixel = 0
accentLine.Parent = header

local accentCorner2 = Instance.new("UICorner")
accentCorner2.CornerRadius = UDim.new(0, 2)
accentCorner2.Parent = accentLine

local titleLabel = Instance.new("TextLabel")
titleLabel.Size = UDim2.new(1, -160, 1, 0)
titleLabel.Position = UDim2.new(0, 28, 0, 0)
titleLabel.BackgroundTransparency = 1
titleLabel.Text = "CHECKPOINTS"
titleLabel.TextColor3 = Color3.fromRGB(220, 230, 255)
titleLabel.TextSize = 14
titleLabel.Font = Enum.Font.GothamBold
titleLabel.TextXAlignment = Enum.TextXAlignment.Left
titleLabel.Parent = header

local countLabel = Instance.new("TextLabel")
countLabel.Name = "CountLabel"
countLabel.Size = UDim2.new(0, 44, 1, 0)
countLabel.Position = UDim2.new(1, -120, 0, 0)
countLabel.BackgroundTransparency = 1
countLabel.Text = "0/20"
countLabel.TextColor3 = Color3.fromRGB(80, 130, 255)
countLabel.TextSize = 12
countLabel.Font = Enum.Font.GothamMedium
countLabel.TextXAlignment = Enum.TextXAlignment.Right
countLabel.Parent = header

-- Collapse toggle button
local toggleBtn = Instance.new("TextButton")
toggleBtn.Name = "ToggleBtn"
toggleBtn.Size = UDim2.new(0, 30, 0, 30)
toggleBtn.Position = UDim2.new(1, -72, 0.5, -15)
toggleBtn.BackgroundColor3 = Color3.fromRGB(40, 50, 80)
toggleBtn.BorderSizePixel = 0
toggleBtn.Text = "-"
toggleBtn.TextColor3 = Color3.fromRGB(150, 170, 255)
toggleBtn.TextSize = 18
toggleBtn.Font = Enum.Font.GothamBold
toggleBtn.Parent = header

local toggleCorner = Instance.new("UICorner")
toggleCorner.CornerRadius = UDim.new(0, 7)
toggleCorner.Parent = toggleBtn

-- X = SELF DESTRUCT button
local closeBtn = Instance.new("TextButton")
closeBtn.Name = "CloseBtn"
closeBtn.Size = UDim2.new(0, 30, 0, 30)
closeBtn.Position = UDim2.new(1, -36, 0.5, -15)
closeBtn.BackgroundColor3 = Color3.fromRGB(120, 20, 20)
closeBtn.BorderSizePixel = 0
closeBtn.Text = "X"
closeBtn.TextColor3 = Color3.fromRGB(255, 90, 90)
closeBtn.TextSize = 14
closeBtn.Font = Enum.Font.GothamBold
closeBtn.Parent = header

local closeCorner = Instance.new("UICorner")
closeCorner.CornerRadius = UDim.new(0, 7)
closeCorner.Parent = closeBtn

-- ── Content area ─────────────────────────────
local contentFrame = Instance.new("Frame")
contentFrame.Name = "Content"
contentFrame.Size = UDim2.new(1, 0, 1, -48)
contentFrame.Position = UDim2.new(0, 0, 0, 48)
contentFrame.BackgroundTransparency = 1
contentFrame.Parent = mainFrame

-- ── Speed Changer Section ────────────────────
local speedSection = Instance.new("Frame")
speedSection.Size = UDim2.new(1, -24, 0, 72)
speedSection.Position = UDim2.new(0, 12, 0, 10)
speedSection.BackgroundColor3 = Color3.fromRGB(18, 22, 40)
speedSection.BorderSizePixel = 0
speedSection.Parent = contentFrame

local speedSectionCorner = Instance.new("UICorner")
speedSectionCorner.CornerRadius = UDim.new(0, 10)
speedSectionCorner.Parent = speedSection

local speedSectionStroke = Instance.new("UIStroke")
speedSectionStroke.Color = Color3.fromRGB(255, 150, 50)
speedSectionStroke.Thickness = 1
speedSectionStroke.Transparency = 0.5
speedSectionStroke.Parent = speedSection

local speedTitleLabel = Instance.new("TextLabel")
speedTitleLabel.Size = UDim2.new(1, -12, 0, 22)
speedTitleLabel.Position = UDim2.new(0, 12, 0, 6)
speedTitleLabel.BackgroundTransparency = 1
speedTitleLabel.Text = "SPEED CHANGER  (max: 100000)"
speedTitleLabel.TextColor3 = Color3.fromRGB(255, 150, 50)
speedTitleLabel.TextSize = 10
speedTitleLabel.Font = Enum.Font.GothamBold
speedTitleLabel.TextXAlignment = Enum.TextXAlignment.Left
speedTitleLabel.Parent = speedSection

local speedInputBox = Instance.new("TextBox")
speedInputBox.Name = "SpeedInput"
speedInputBox.Size = UDim2.new(1, -108, 0, 32)
speedInputBox.Position = UDim2.new(0, 12, 0, 32)
speedInputBox.BackgroundColor3 = Color3.fromRGB(22, 26, 42)
speedInputBox.BorderSizePixel = 0
speedInputBox.PlaceholderText = "Enter speed..."
speedInputBox.PlaceholderColor3 = Color3.fromRGB(80, 90, 120)
speedInputBox.Text = tostring(DEFAULT_SPEED)
speedInputBox.TextColor3 = Color3.fromRGB(255, 200, 100)
speedInputBox.TextSize = 13
speedInputBox.Font = Enum.Font.GothamBold
speedInputBox.TextXAlignment = Enum.TextXAlignment.Center
speedInputBox.ClearTextOnFocus = false
speedInputBox.Parent = speedSection

local speedInputCorner = Instance.new("UICorner")
speedInputCorner.CornerRadius = UDim.new(0, 7)
speedInputCorner.Parent = speedInputBox

local speedInputStroke = Instance.new("UIStroke")
speedInputStroke.Color = Color3.fromRGB(255, 150, 50)
speedInputStroke.Thickness = 1
speedInputStroke.Transparency = 0.6
speedInputStroke.Parent = speedInputBox

local applySpeedBtn = Instance.new("TextButton")
applySpeedBtn.Name = "ApplySpeedBtn"
applySpeedBtn.Size = UDim2.new(0, 82, 0, 32)
applySpeedBtn.Position = UDim2.new(1, -94, 0, 32)
applySpeedBtn.BackgroundColor3 = Color3.fromRGB(200, 100, 20)
applySpeedBtn.BorderSizePixel = 0
applySpeedBtn.Text = "Apply"
applySpeedBtn.TextColor3 = Color3.fromRGB(255, 255, 255)
applySpeedBtn.TextSize = 13
applySpeedBtn.Font = Enum.Font.GothamBold
applySpeedBtn.Parent = speedSection

local applySpeedCorner = Instance.new("UICorner")
applySpeedCorner.CornerRadius = UDim.new(0, 7)
applySpeedCorner.Parent = applySpeedBtn

-- ── Separator ────────────────────────────────
local sep1 = Instance.new("Frame")
sep1.Size = UDim2.new(1, -24, 0, 1)
sep1.Position = UDim2.new(0, 12, 0, 92)
sep1.BackgroundColor3 = Color3.fromRGB(40, 50, 80)
sep1.BorderSizePixel = 0
sep1.Parent = contentFrame

-- ── Checkpoint Name Input ────────────────────
local inputSection = Instance.new("Frame")
inputSection.Size = UDim2.new(1, -24, 0, 44)
inputSection.Position = UDim2.new(0, 12, 0, 104)
inputSection.BackgroundColor3 = Color3.fromRGB(22, 26, 42)
inputSection.BorderSizePixel = 0
inputSection.Parent = contentFrame

local inputCorner = Instance.new("UICorner")
inputCorner.CornerRadius = UDim.new(0, 8)
inputCorner.Parent = inputSection

local inputStroke = Instance.new("UIStroke")
inputStroke.Color = Color3.fromRGB(50, 70, 130)
inputStroke.Thickness = 1
inputStroke.Parent = inputSection

local nameInput = Instance.new("TextBox")
nameInput.Name = "NameInput"
nameInput.Size = UDim2.new(1, -16, 1, 0)
nameInput.Position = UDim2.new(0, 12, 0, 0)
nameInput.BackgroundTransparency = 1
nameInput.PlaceholderText = "Enter checkpoint name..."
nameInput.PlaceholderColor3 = Color3.fromRGB(70, 80, 110)
nameInput.Text = ""
nameInput.TextColor3 = Color3.fromRGB(200, 210, 255)
nameInput.TextSize = 13
nameInput.Font = Enum.Font.Gotham
nameInput.TextXAlignment = Enum.TextXAlignment.Left
nameInput.ClearTextOnFocus = false
nameInput.Parent = inputSection

-- ── Create Checkpoint Button ─────────────────
local createBtn = Instance.new("TextButton")
createBtn.Name = "CreateBtn"
createBtn.Size = UDim2.new(1, -24, 0, 38)
createBtn.Position = UDim2.new(0, 12, 0, 158)
createBtn.BackgroundColor3 = Color3.fromRGB(60, 110, 255)
createBtn.BorderSizePixel = 0
createBtn.Text = "+ Create Checkpoint at My Position"
createBtn.TextColor3 = Color3.fromRGB(255, 255, 255)
createBtn.TextSize = 13
createBtn.Font = Enum.Font.GothamBold
createBtn.Parent = contentFrame

local createCorner = Instance.new("UICorner")
createCorner.CornerRadius = UDim.new(0, 8)
createCorner.Parent = createBtn

-- ── Separator + List title ───────────────────
local sep2 = Instance.new("Frame")
sep2.Size = UDim2.new(1, -24, 0, 1)
sep2.Position = UDim2.new(0, 12, 0, 208)
sep2.BackgroundColor3 = Color3.fromRGB(40, 50, 80)
sep2.BorderSizePixel = 0
sep2.Parent = contentFrame

local listTitle = Instance.new("TextLabel")
listTitle.Size = UDim2.new(1, -24, 0, 24)
listTitle.Position = UDim2.new(0, 12, 0, 214)
listTitle.BackgroundTransparency = 1
listTitle.Text = "SAVED CHECKPOINTS"
listTitle.TextColor3 = Color3.fromRGB(60, 80, 130)
listTitle.TextSize = 10
listTitle.Font = Enum.Font.GothamBold
listTitle.TextXAlignment = Enum.TextXAlignment.Left
listTitle.Parent = contentFrame

-- ── Scrolling checkpoint list ─────────────────
local scrollFrame = Instance.new("ScrollingFrame")
scrollFrame.Name = "CheckpointList"
scrollFrame.Size = UDim2.new(1, -24, 1, -244)
scrollFrame.Position = UDim2.new(0, 12, 0, 242)
scrollFrame.BackgroundTransparency = 1
scrollFrame.BorderSizePixel = 0
scrollFrame.ScrollBarThickness = 3
scrollFrame.ScrollBarImageColor3 = Color3.fromRGB(60, 100, 220)
scrollFrame.CanvasSize = UDim2.new(0, 0, 0, 0)
scrollFrame.Parent = contentFrame

local listLayout = Instance.new("UIListLayout")
listLayout.FillDirection = Enum.FillDirection.Vertical
listLayout.HorizontalAlignment = Enum.HorizontalAlignment.Center
listLayout.SortOrder = Enum.SortOrder.LayoutOrder
listLayout.Padding = UDim.new(0, 6)
listLayout.Parent = scrollFrame

-- ══════════════════════════════════════════
--           DRAGGING LOGIC
-- ══════════════════════════════════════════

local dragging = false
local dragStartPos = nil
local frameStartPos = nil

header.InputBegan:Connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		dragging = true
		dragStartPos = input.Position
		frameStartPos = mainFrame.Position
		input.Changed:Connect(function()
			if input.UserInputState == Enum.UserInputState.End then
				dragging = false
			end
		end)
	end
end)

UserInputService.InputChanged:Connect(function(input)
	if dragging and input.UserInputType == Enum.UserInputType.MouseMovement then
		local delta = input.Position - dragStartPos
		mainFrame.Position = UDim2.new(
			frameStartPos.X.Scale,
			frameStartPos.X.Offset + delta.X,
			frameStartPos.Y.Scale,
			frameStartPos.Y.Offset + delta.Y
		)
	end
end)

UserInputService.InputEnded:Connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		dragging = false
	end
end)

-- ══════════════════════════════════════════
--           CHECKPOINT FUNCTIONS
-- ══════════════════════════════════════════

local function updateCount()
	countLabel.Text = #checkpoints .. "/20"
end

local function updateScrollCanvas()
	scrollFrame.CanvasSize = UDim2.new(0, 0, 0, listLayout.AbsoluteContentSize.Y + 10)
end

local function createCheckpointEntry(id, name, position)
	local entry = Instance.new("Frame")
	entry.Name = "Entry_" .. id
	entry.Size = UDim2.new(1, -4, 0, 52)
	entry.BackgroundColor3 = Color3.fromRGB(22, 28, 48)
	entry.BorderSizePixel = 0
	entry.LayoutOrder = id
	entry.Parent = scrollFrame

	local entryCorner = Instance.new("UICorner")
	entryCorner.CornerRadius = UDim.new(0, 8)
	entryCorner.Parent = entry

	local entryStroke = Instance.new("UIStroke")
	entryStroke.Color = Color3.fromRGB(40, 60, 120)
	entryStroke.Thickness = 1
	entryStroke.Parent = entry

	local dot = Instance.new("Frame")
	dot.Size = UDim2.new(0, 8, 0, 8)
	dot.Position = UDim2.new(0, 12, 0.5, -4)
	dot.BackgroundColor3 = Color3.fromRGB(80, 150, 255)
	dot.BorderSizePixel = 0
	dot.Parent = entry

	local dotCorner = Instance.new("UICorner")
	dotCorner.CornerRadius = UDim.new(1, 0)
	dotCorner.Parent = dot

	local nameLabel = Instance.new("TextLabel")
	nameLabel.Size = UDim2.new(1, -90, 0, 22)
	nameLabel.Position = UDim2.new(0, 28, 0, 7)
	nameLabel.BackgroundTransparency = 1
	nameLabel.Text = name
	nameLabel.TextColor3 = Color3.fromRGB(210, 225, 255)
	nameLabel.TextSize = 13
	nameLabel.Font = Enum.Font.GothamMedium
	nameLabel.TextXAlignment = Enum.TextXAlignment.Left
	nameLabel.TextTruncate = Enum.TextTruncate.AtEnd
	nameLabel.Parent = entry

	local posLabel = Instance.new("TextLabel")
	posLabel.Size = UDim2.new(1, -90, 0, 18)
	posLabel.Position = UDim2.new(0, 28, 0, 28)
	posLabel.BackgroundTransparency = 1
	posLabel.Text = string.format("X:%.0f Y:%.0f Z:%.0f", position.X, position.Y, position.Z)
	posLabel.TextColor3 = Color3.fromRGB(60, 80, 130)
	posLabel.TextSize = 10
	posLabel.Font = Enum.Font.Gotham
	posLabel.TextXAlignment = Enum.TextXAlignment.Left
	posLabel.Parent = entry

	local tpBtn = Instance.new("TextButton")
	tpBtn.Size = UDim2.new(0, 34, 0, 34)
	tpBtn.Position = UDim2.new(1, -80, 0.5, -17)
	tpBtn.BackgroundColor3 = Color3.fromRGB(30, 60, 130)
	tpBtn.BorderSizePixel = 0
	tpBtn.Text = "TP"
	tpBtn.TextColor3 = Color3.fromRGB(120, 170, 255)
	tpBtn.TextSize = 11
	tpBtn.Font = Enum.Font.GothamBold
	tpBtn.Parent = entry

	local tpCorner = Instance.new("UICorner")
	tpCorner.CornerRadius = UDim.new(0, 6)
	tpCorner.Parent = tpBtn

	local delBtn = Instance.new("TextButton")
	delBtn.Size = UDim2.new(0, 34, 0, 34)
	delBtn.Position = UDim2.new(1, -40, 0.5, -17)
	delBtn.BackgroundColor3 = Color3.fromRGB(100, 25, 35)
	delBtn.BorderSizePixel = 0
	delBtn.Text = "X"
	delBtn.TextColor3 = Color3.fromRGB(255, 100, 120)
	delBtn.TextSize = 13
	delBtn.Font = Enum.Font.GothamBold
	delBtn.Parent = entry

	local delCorner = Instance.new("UICorner")
	delCorner.CornerRadius = UDim.new(0, 6)
	delCorner.Parent = delBtn

	tpBtn.MouseButton1Click:Connect(function()
		local char = player.Character
		if char then
			local root = char:FindFirstChild("HumanoidRootPart")
			if root then
				root.CFrame = CFrame.new(position + Vector3.new(0, 3, 0))
			end
		end
	end)

	tpBtn.MouseEnter:Connect(function() tpBtn.BackgroundColor3 = Color3.fromRGB(50, 100, 200) end)
	tpBtn.MouseLeave:Connect(function() tpBtn.BackgroundColor3 = Color3.fromRGB(30, 60, 130) end)
	delBtn.MouseEnter:Connect(function() delBtn.BackgroundColor3 = Color3.fromRGB(160, 40, 55) end)
	delBtn.MouseLeave:Connect(function() delBtn.BackgroundColor3 = Color3.fromRGB(100, 25, 35) end)

	delBtn.MouseButton1Click:Connect(function()
		for i, cp in ipairs(checkpoints) do
			if cp.id == id then
				if cp.sphere and cp.sphere.Parent then
					cp.sphere:Destroy()
				end
				table.remove(checkpoints, i)
				break
			end
		end
		entry:Destroy()
		updateCount()
		updateScrollCanvas()
	end)

	updateScrollCanvas()
end

local function createSphere(name, position)
	local sphere = Instance.new("Part")
	sphere.Name = "Checkpoint_" .. name
	sphere.Shape = Enum.PartType.Ball
	sphere.Size = Vector3.new(6, 6, 6)
	sphere.Position = position
	sphere.Anchored = true
	sphere.CanCollide = false
	sphere.CastShadow = false
	sphere.Material = Enum.Material.Neon
	sphere.Color = Color3.fromRGB(60, 120, 255)
	sphere.Transparency = 0.55

	local billboard = Instance.new("BillboardGui")
	-- LOCKED WORLD SIZE: using SCALE units makes the label a fixed size in the
	-- world (it shrinks naturally as you move away instead of ballooning).
	billboard.Size = UDim2.new(BILLBOARD_WORLD_WIDTH, 0, BILLBOARD_WORLD_HEIGHT, 0)
	billboard.StudsOffset = Vector3.new(0, 4.5, 0)
	billboard.AlwaysOnTop = false
	billboard.MaxDistance = BILLBOARD_MAX_DISTANCE  -- stops rendering when too far
	billboard.LightInfluence = 0
	billboard.Parent = sphere

	local billboardLabel = Instance.new("TextLabel")
	billboardLabel.Size = UDim2.new(1, 0, 1, 0)
	billboardLabel.BackgroundColor3 = Color3.fromRGB(10, 15, 35)
	billboardLabel.BackgroundTransparency = 0.3
	billboardLabel.Text = name
	billboardLabel.TextColor3 = Color3.fromRGB(180, 210, 255)
	billboardLabel.TextScaled = true  -- text fills the fixed-size frame
	billboardLabel.Font = Enum.Font.GothamBold
	billboardLabel.Parent = billboard

	-- Constrain text so it never blows up past a max pixel size
	local textConstraint = Instance.new("UITextSizeConstraint")
	textConstraint.MaxTextSize = 18
	textConstraint.MinTextSize = 6
	textConstraint.Parent = billboardLabel

	local bbCorner = Instance.new("UICorner")
	bbCorner.CornerRadius = UDim.new(0, 6)
	bbCorner.Parent = billboardLabel

	sphere.Parent = checkpointFolder
	return sphere
end

local function addCheckpoint(name, position)
	if #checkpoints >= MAX_CHECKPOINTS then
		countLabel.TextColor3 = Color3.fromRGB(255, 80, 80)
		task.delay(1, function()
			countLabel.TextColor3 = Color3.fromRGB(80, 130, 255)
		end)
		return
	end
	idCounter = idCounter + 1
	local id = idCounter
	local sphere = createSphere(name, position)
	table.insert(checkpoints, { id = id, name = name, position = position, sphere = sphere })
	createCheckpointEntry(id, name, position)
	updateCount()
end

-- ══════════════════════════════════════════
--           SPEED CHANGER LOGIC
-- ══════════════════════════════════════════

local function applySpeed()
	local char = player.Character
	if not char then return end
	local humanoid = char:FindFirstChildOfClass("Humanoid")
	if not humanoid then return end

	local raw = tonumber(speedInputBox.Text)
	if not raw then
		speedInputBox.Text = tostring(humanoid.WalkSpeed)
		return
	end

	local clamped = math.clamp(math.floor(raw), 0, MAX_SPEED)
	humanoid.WalkSpeed = clamped
	speedInputBox.Text = tostring(clamped)

	TweenService:Create(speedSectionStroke, TweenInfo.new(0.15), {
		Color = Color3.fromRGB(80, 255, 120), Transparency = 0,
	}):Play()
	task.delay(0.6, function()
		TweenService:Create(speedSectionStroke, TweenInfo.new(0.4), {
			Color = Color3.fromRGB(255, 150, 50), Transparency = 0.5,
		}):Play()
	end)
end

applySpeedBtn.MouseButton1Click:Connect(applySpeed)
speedInputBox.FocusLost:Connect(function(enterPressed)
	if enterPressed then applySpeed() end
end)
applySpeedBtn.MouseEnter:Connect(function() applySpeedBtn.BackgroundColor3 = Color3.fromRGB(240, 130, 30) end)
applySpeedBtn.MouseLeave:Connect(function() applySpeedBtn.BackgroundColor3 = Color3.fromRGB(200, 100, 20) end)

player.CharacterAdded:Connect(function(newChar)
	character = newChar
	rootPart = newChar:WaitForChild("HumanoidRootPart")
	local humanoid = newChar:WaitForChild("Humanoid")
	humanoid.WalkSpeed = math.clamp(tonumber(speedInputBox.Text) or DEFAULT_SPEED, 0, MAX_SPEED)
end)

-- ══════════════════════════════════════════
--           BUTTON EVENTS
-- ══════════════════════════════════════════

createBtn.MouseButton1Click:Connect(function()
	local char = player.Character
	if not char then return end
	local root = char:FindFirstChild("HumanoidRootPart")
	if not root then return end
	local rawName = nameInput.Text
	local cpName = (rawName ~= "" and rawName) or ("Checkpoint " .. (idCounter + 1))
	addCheckpoint(cpName, root.Position)
	nameInput.Text = ""
end)

createBtn.MouseEnter:Connect(function() createBtn.BackgroundColor3 = Color3.fromRGB(80, 130, 255) end)
createBtn.MouseLeave:Connect(function() createBtn.BackgroundColor3 = Color3.fromRGB(60, 110, 255) end)

-- ── Collapse toggle ───────────────────────────
local collapsedHeight = 48
local expandedHeight = 510

toggleBtn.MouseButton1Click:Connect(function()
	isCollapsed = not isCollapsed
	if isCollapsed then
		mainFrame:TweenSize(UDim2.new(0, 310, 0, collapsedHeight), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.2, true)
		toggleBtn.Text = "+"
		contentFrame.Visible = false
	else
		contentFrame.Visible = true
		mainFrame:TweenSize(UDim2.new(0, 310, 0, expandedHeight), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.2, true)
		toggleBtn.Text = "-"
	end
end)

-- ── X = SELF DESTRUCT (deletes everything) ────
closeBtn.MouseButton1Click:Connect(function()
	for _, cp in ipairs(checkpoints) do
		if cp.sphere and cp.sphere.Parent then
			cp.sphere:Destroy()
		end
	end
	checkpoints = {}

	if checkpointFolder and checkpointFolder.Parent then
		checkpointFolder:Destroy()
	end

	TweenService:Create(mainFrame, TweenInfo.new(0.3, Enum.EasingStyle.Quad), {
		BackgroundTransparency = 1,
		Size = UDim2.new(0, 310, 0, 0),
	}):Play()

	task.delay(0.35, function()
		screenGui:Destroy()
	end)
end)

closeBtn.MouseEnter:Connect(function() closeBtn.BackgroundColor3 = Color3.fromRGB(180, 30, 30) end)
closeBtn.MouseLeave:Connect(function() closeBtn.BackgroundColor3 = Color3.fromRGB(120, 20, 20) end)

-- ── F5 shortcut ───────────────────────────────
UserInputService.InputBegan:Connect(function(input, gameProcessed)
	if gameProcessed then return end
	if input.KeyCode == Enum.KeyCode.F5 then
		local char = player.Character
		if not char then return end
		local root = char:FindFirstChild("HumanoidRootPart")
		if not root then return end
		local rawName = nameInput.Text
		local cpName = (rawName ~= "" and rawName) or ("Checkpoint " .. (idCounter + 1))
		addCheckpoint(cpName, root.Position)
		nameInput.Text = ""
	end
end)

listLayout:GetPropertyChangedSignal("AbsoluteContentSize"):Connect(updateScrollCanvas)

print("[CheckpointSystem] Loaded! Drag the header to move. X = self destruct.")

Features & Information

some cool cp script (checkpoint capiche) - open sourced (i mean its ai) - create checkpoints - name checkpoints - speed changer cuz i wanted - idk theres like minus and destroy yk
#universal#teleport#checkpoint#speed#speedchanger

Community Comments (0)

No comments yet for this script.

More Scripts for Universal Scripts