local Players = game:GetService("Players") local RunService = game:GetService("RunService") local UserInputService = game:GetService("UserInputService") local CoreGui = game:GetService("CoreGui") local TweenService = game:GetService("TweenService") local LocalPlayer = Players.LocalPlayer local DEFAULT_COLOR = Color3.fromRGB(50, 205, 50) local KNIFE_COLOR = Color3.fromRGB(220, 40, 40) local GUN_COLOR = Color3.fromRGB(40, 120, 255) local FILL_ALPHA = 1 local OUTLINE_ALPHA = 0 local HL_TAG = "_WH" local BB_TAG = "_WBB" local trackedData = {} local espEnabled = true local weaponKeywords = { { pattern = "gun", priority = 2, color = GUN_COLOR }, { pattern = "knife", priority = 1, color = KNIFE_COLOR }, } -- --- UI Creation --- local screenGui = Instance.new("ScreenGui") screenGui.Name = "ESPToggleGui" screenGui.ResetOnSpawn = false pcall(function() screenGui.Parent = CoreGui end) if not screenGui.Parent then screenGui.Parent = LocalPlayer:WaitForChild("PlayerGui") end local toggleButton = Instance.new("TextButton") toggleButton.Name = "ToggleButton" toggleButton.Size = UDim2.new(0, 120, 0, 40) toggleButton.Position = UDim2.new(0, 20, 1, -60) toggleButton.BackgroundColor3 = Color3.fromRGB(30, 30, 30) toggleButton.BorderSizePixel = 0 toggleButton.Font = Enum.Font.GothamBold toggleButton.Text = espEnabled and "ESP: ON" or "ESP: OFF" toggleButton.TextColor3 = espEnabled and Color3.fromRGB(50, 255, 50) or Color3.fromRGB(255, 50, 50) toggleButton.TextSize = 16 toggleButton.Active = true -- Necessary for dragging registration toggleButton.Parent = screenGui local uiCorner = Instance.new("UICorner") uiCorner.CornerRadius = UDim.new(0, 8) uiCorner.Parent = toggleButton -- --- Draggable Logic --- local dragging, dragInput, dragStart, startPos local function update(input) local delta = input.Position - dragStart local targetPos = UDim2.new(startPos.X.Scale, startPos.X.Offset + delta.X, startPos.Y.Scale, startPos.Y.Offset + delta.Y) -- Tweens the movement slightly so the drag feels smooth instead of rigid TweenService:Create(toggleButton, TweenInfo.new(0.1, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {Position = targetPos}):Play() end toggleButton.InputBegan:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then dragging = true dragStart = input.Position startPos = toggleButton.Position input.Changed:Connect(function() if input.UserInputState == Enum.UserInputState.End then dragging = false end end) end end) toggleButton.InputChanged:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch then dragInput = input end end) UserInputService.InputChanged:Connect(function(input) if input == dragInput and dragging then update(input) end end) -- --- ESP Cleanup Helper --- local function clearESP(player, character) local hl = character:FindFirstChild(HL_TAG) if hl then hl:Destroy() end local head = character:FindFirstChild("Head") if head then local bb = head:FindFirstChild(BB_TAG) if bb then bb:Destroy() end end end local function detectWeaponColor(character, player) local best, bestPrio = nil, 0 local function checkTool(tool) if not tool:IsA("Tool") then return end local lower = tool.Name:lower() for _, entry in ipairs(weaponKeywords) do if lower:find(entry.pattern) and entry.priority > bestPrio then bestPrio = entry.priority best = entry.color end end end for _, obj in ipairs(character:GetChildren()) do checkTool(obj) end local bp = player:FindFirstChildOfClass("Backpack") if bp then for _, obj in ipairs(bp:GetChildren()) do checkTool(obj) end end return best or DEFAULT_COLOR end local function getOrMakeHighlight(character) local h = character:FindFirstChild(HL_TAG) if h and h:IsA("Highlight") then return h end if h then h:Destroy() end local hl = Instance.new("Highlight") hl.Name = HL_TAG hl.Adornee = character hl.DepthMode = Enum.HighlightDepthMode.AlwaysOnTop hl.FillTransparency = FILL_ALPHA hl.OutlineTransparency = OUTLINE_ALPHA hl.FillColor = DEFAULT_COLOR hl.OutlineColor = DEFAULT_COLOR hl.Parent = character return hl end local function getOrMakeBillboard(character, playerName) local head = character:FindFirstChild("Head") if not head then return nil end local bb = head:FindFirstChild(BB_TAG) if bb and bb:IsA("BillboardGui") then return bb:FindFirstChild("NameLabel") end if bb then bb:Destroy() end local billboard = Instance.new("BillboardGui") billboard.Name = BB_TAG billboard.Adornee = head billboard.AlwaysOnTop = true billboard.Size = UDim2.new(0, 140, 0, 26) billboard.StudsOffset = Vector3.new(0, 2.6, 0) billboard.ResetOnSpawn = false billboard.Parent = head local label = Instance.new("TextLabel") label.Name = "NameLabel" label.Size = UDim2.new(1, 0, 1, 0) label.BackgroundTransparency = 1 label.Text = playerName label.Font = Enum.Font.GothamBold label.TextSize = 13 label.TextColor3 = DEFAULT_COLOR label.TextStrokeTransparency = 1 label.TextScaled = false label.Parent = billboard return label end local function updatePlayer(player) if player == LocalPlayer then return end local character = player.Character if not character or not character:FindFirstChild("HumanoidRootPart") then return end if not espEnabled then clearESP(player, character) return end local color = detectWeaponColor(character, player) local hl = getOrMakeHighlight(character) hl.OutlineColor = color hl.FillColor = color local label = getOrMakeBillboard(character, player.DisplayName) if label then label.TextColor3 = color end end local function hookCharacter(player, character) character:WaitForChild("HumanoidRootPart", 10) local conn = RunService.Heartbeat:Connect(function() if not character.Parent then return end updatePlayer(player) end) local prev = trackedData[player] if prev then if prev.conn then prev.conn:Disconnect() end if prev.character then clearESP(player, prev.character) end end trackedData[player] = { conn = conn, character = character } character.AncestryChanged:Connect(function(_, parent) if not parent and trackedData[player] and trackedData[player].character == character then conn:Disconnect() end end) end local function hookPlayer(player) if player == LocalPlayer then return end if player.Character then task.spawn(hookCharacter, player, player.Character) end player.CharacterAdded:Connect(function(character) task.spawn(hookCharacter, player, character) end) end -- --- Toggle Logic --- local function toggleESP() espEnabled = not espEnabled if espEnabled then toggleButton.Text = "ESP: ON" toggleButton.TextColor3 = Color3.fromRGB(50, 255, 50) else toggleButton.Text = "ESP: OFF" toggleButton.TextColor3 = Color3.fromRGB(255, 50, 50) for p, data in pairs(trackedData) do if data.character then clearESP(p, data.character) end end end end toggleButton.MouseButton1Click:Connect(toggleESP) UserInputService.InputBegan:Connect(function(input, gameProcessed) if gameProcessed then return end if input.KeyCode == Enum.KeyCode.V then toggleESP() end end) -- --- Initialize --- for _, player in ipairs(Players:GetPlayers()) do task.spawn(hookPlayer, player) end Players.PlayerAdded:Connect(hookPlayer) Players.PlayerRemoving:Connect(function(player) local data = trackedData[player] if not data then return end if data.conn then data.conn:Disconnect() end if data.character then clearESP(player, data.character) end trackedData[player] = nil end)