--[[
Fully Functional ESP + UI
Features:
- Shared live config
- Boxes, Names, Distance, Tracers
- MaxDistance slider
- Draggable UI
- Toggle UI keybind
]]
-- Services
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local Camera = workspace.CurrentCamera
local LocalPlayer = Players.LocalPlayer
local PlayerGui = LocalPlayer:WaitForChild("PlayerGui")
-- Shared Config Table (ESP + UI both use this)
getgenv().ESP_Config = {
Enabled = true,
Boxes = true,
Names = true,
Distance = true,
Tracers = true,
MaxDistance = 2500,
ToggleKey = Enum.KeyCode.RightShift
}
local Config = getgenv().ESP_Config
-- Utility Functions
local function IsAlive(character)
local hum = character:FindFirstChildOfClass("Humanoid")
return hum and hum.Health > 0
end
local function WorldToScreen(pos)
local screenPos, onScreen = Camera:WorldToViewportPoint(pos)
return Vector2.new(screenPos.X, screenPos.Y), onScreen, screenPos.Z
end
local function RayVisible(origin, target, ignore)
local params = RaycastParams.new()
params.FilterDescendantsInstances = ignore
params.FilterType = Enum.RaycastFilterType.Blacklist
local result = workspace:Raycast(origin, target - origin, params)
return result == nil
end
-- ESP Object
local ESPObject = {}
ESPObject.__index = ESPObject
function ESPObject.new(player)
local self = setmetatable({}, ESPObject)
self.Player = player
self.Drawings = {
Box = Drawing.new("Square"),
Name = Drawing.new("Text"),
Distance = Drawing.new("Text"),
Tracer = Drawing.new("Line")
}
for _, d in pairs(self.Drawings) do
d.Visible = false
d.Transparency = 1
end
return self
end
function ESPObject:Destroy()
for _, d in pairs(self.Drawings) do
d:Remove()
end
end
function ESPObject:Update()
if not Config.Enabled then return end
if self.Player == LocalPlayer then return end
local character = self.Player.Character
local root = character and character:FindFirstChild("HumanoidRootPart")
if not (character and root and IsAlive(character)) then
for _, d in pairs(self.Drawings) do d.Visible = false end
return
end
local screenPos, onScreen, depth = WorldToScreen(root.Position)
if not onScreen or depth > Config.MaxDistance then
for _, d in pairs(self.Drawings) do d.Visible = false end
return
end
local visible = RayVisible(
Camera.CFrame.Position,
root.Position,
{LocalPlayer.Character, character}
)
local color = visible and Color3.fromRGB(60, 255, 60) or Color3.fromRGB(255, 60, 60)
-- Box
if Config.Boxes then
local size = Vector2.new(2000 / depth, 3000 / depth)
local box = self.Drawings.Box
box.Size = size
box.Position = screenPos - size / 2
box.Color = color
box.Thickness = 2
box.Visible = true
else
self.Drawings.Box.Visible = false
end
-- Name
if Config.Names then
local name = self.Drawings.Name
name.Text = self.Player.Name
name.Size = 14
name.Center = true
name.Outline = true
name.Color = color
name.Position = screenPos - Vector2.new(0, 25)
name.Visible = true
else
self.Drawings.Name.Visible = false
end
-- Distance
if Config.Distance then
local dist = (Camera.CFrame.Position - root.Position).Magnitude
local text = self.Drawings.Distance
text.Text = string.format("[%.0f]", dist)
text.Size = 13
text.Center = true
text.Outline = true
text.Color = color
text.Position = screenPos + Vector2.new(0, 20)
text.Visible = true
else
self.Drawings.Distance.Visible = false
end
-- Tracer
if Config.Tracers then
local tracer = self.Drawings.Tracer
tracer.From = Vector2.new(Camera.ViewportSize.X / 2, Camera.ViewportSize.Y)
tracer.To = screenPos
tracer.Color = color
tracer.Thickness = 1
tracer.Visible = true
else
self.Drawings.Tracer.Visible = false
end
end
-- ESP Manager
local ESPManager = { Objects = {} }
function ESPManager:Add(player)
self.Objects[player] = ESPObject.new(player)
end
function ESPManager:Remove(player)
if self.Objects[player] then
self.Objects[player]:Destroy()
self.Objects[player] = nil
end
end
-- Initialize ESP objects for current players
for _, p in ipairs(Players:GetPlayers()) do
if p ~= LocalPlayer then ESPManager:Add(p) end
end
-- Player added/removed
Players.PlayerAdded:Connect(function(p) ESPManager:Add(p) end)
Players.PlayerRemoving:Connect(function(p) ESPManager:Remove(p) end)
-- Render loop
RunService.RenderStepped:Connect(function()
for _, esp in pairs(ESPManager.Objects) do
esp:Update()
end
end)
-- ==============================
-- UI
-- ==============================
local TweenService = game:GetService("TweenService")
local Gui = Instance.new("ScreenGui")
Gui.Name = "ESP_UI"
Gui.ResetOnSpawn = false
Gui.Parent = PlayerGui
local Main = Instance.new("Frame")
Main.Size = UDim2.fromOffset(260, 300)
Main.Position = UDim2.fromScale(0.05, 0.2)
Main.BackgroundColor3 = Color3.fromRGB(20, 20, 20)
Main.BorderSizePixel = 0
Main.Parent = Gui
Main.Active = true
Main.Draggable = true
local Title = Instance.new("TextLabel")
Title.Size = UDim2.new(1, 0, 0, 32)
Title.BackgroundColor3 = Color3.fromRGB(30, 30, 30)
Title.Text = "ESP CONTROL PANEL"
Title.TextColor3 = Color3.fromRGB(220, 220, 220)
Title.Font = Enum.Font.Code
Title.TextSize = 14
Title.Parent = Main
local Layout = Instance.new("UIListLayout")
Layout.Padding = UDim.new(0, 6)
Layout.Parent = Main
Layout.HorizontalAlignment = Enum.HorizontalAlignment.Center
Layout.VerticalAlignment = Enum.VerticalAlignment.Top
local Padding = Instance.new("UIPadding")
Padding.PaddingTop = UDim.new(0, 40)
Padding.Parent = Main
-- Toggle Factory
local function CreateToggle(text, flag)
local Button = Instance.new("TextButton")
Button.Size = UDim2.fromOffset(220, 30)
Button.BackgroundColor3 = Color3.fromRGB(40, 40, 40)
Button.TextColor3 = Color3.fromRGB(200, 200, 200)
Button.Font = Enum.Font.Code
Button.TextSize = 13
Button.Text = text .. ": " .. (Config[flag] and "ON" or "OFF")
Button.Parent = Main
local function Refresh()
Button.Text = text .. ": " .. (Config[flag] and "ON" or "OFF")
TweenService:Create(
Button,
TweenInfo.new(0.15),
{BackgroundColor3 = Config[flag] and Color3.fromRGB(60, 120, 60) or Color3.fromRGB(80, 40, 40)}
):Play()
end
Button.MouseButton1Click:Connect(function()
Config[flag] = not Config[flag]
Refresh()
end)
Refresh()
end
CreateToggle("ESP", "Enabled")
CreateToggle("Boxes", "Boxes")
CreateToggle("Names", "Names")
CreateToggle("Distance", "Distance")
CreateToggle("Tracers", "Tracers")
-- Distance Slider
local SliderFrame = Instance.new("Frame")
SliderFrame.Size = UDim2.fromOffset(220, 40)
SliderFrame.BackgroundTransparency = 1
SliderFrame.Parent = Main
local SliderLabel = Instance.new("TextLabel")
SliderLabel.Size = UDim2.new(1, 0, 0, 20)
SliderLabel.BackgroundTransparency = 1
SliderLabel.Text = "Max Distance"
SliderLabel.TextColor3 = Color3.fromRGB(200, 200, 200)
SliderLabel.Font = Enum.Font.Code
SliderLabel.TextSize = 13
SliderLabel.Parent = SliderFrame
local Bar = Instance.new("Frame")
Bar.Size = UDim2.fromOffset(220, 6)
Bar.Position = UDim2.fromOffset(0, 26)
Bar.BackgroundColor3 = Color3.fromRGB(50, 50, 50)
Bar.BorderSizePixel = 0
Bar.Parent = SliderFrame
local Fill = Instance.new("Frame")
Fill.Size = UDim2.fromScale(Config.MaxDistance / 5000, 1)
Fill.BackgroundColor3 = Color3.fromRGB(100, 180, 100)
Fill.BorderSizePixel = 0
Fill.Parent = Bar
Bar.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1 then
local move
move = UserInputService.InputChanged:Connect(function(i)
if i.UserInputType == Enum.UserInputType.MouseMovement then
local percent = math.clamp(
(i.Position.X - Bar.AbsolutePosition.X) / Bar.AbsoluteSize.X,
0, 1
)
Config.MaxDistance = math.floor(percent * 5000)
Fill.Size = UDim2.fromScale(percent, 1)
end
end)
UserInputService.InputEnded:Once(function(e)
if e.UserInputType == Enum.UserInputType.MouseButton1 then
move:Disconnect()
end
end)
end
end)
-- UI Toggle Keybind
UserInputService.InputBegan:Connect(function(input, gp)
if not gp and input.KeyCode == Config.ToggleKey then
Gui.Enabled = not Gui.Enabled
end
end)
Comments
No comments yet
Be the first to share your thoughts!