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)
Comments
shi fire dude