-- Services local Players = game:GetService("Players") local RunService = game:GetService("RunService") local UserInputService = game:GetService("UserInputService") local Workspace = game:GetService("Workspace") local CoreGui = game:GetService("CoreGui") local HttpService = game:GetService("HttpService") -- Safe service cloning local function GetService(serviceName) local success, service = pcall(function() return cloneref(game:GetService(serviceName)) end) return success and service or game:GetService(serviceName) end local LocalPlayer = Players.LocalPlayer local Camera = Workspace.CurrentCamera local Mouse = LocalPlayer:GetMouse() -- Connection tracking for cleanup local Connections = {} local function Track(connection) table.insert(Connections, connection) return connection end -- Configuration with default values local Config = { UI = { ToggleKey = Enum.KeyCode.Insert, Visible = true }, ESP = { Enabled = false, Box = false, Name = false, HealthBar = false, Distance = false, Chams = false, Skeleton = false, TeamCheck = true, MaxDistance = 1000, EnemyColor = Color3.fromRGB(255, 0, 0), AllyColor = Color3.fromRGB(0, 255, 0), BehindWall = false, BehindWallColor = Color3.fromRGB(128, 128, 128), IgnoreList = {} } } -- Config path local CONFIG_PATH = "CustomUI_Config.json" -- Load config if exists local function LoadConfig() if readfile and isfile and isfile(CONFIG_PATH) then local success, data = pcall(function() return HttpService:JSONDecode(readfile(CONFIG_PATH)) end) if success and data then for category, values in pairs(data) do if Config[category] then for key, value in pairs(values) do if typeof(value) == "string" and string.find(value, "Enum") then local enumType, enumValue = string.match(value, "Enum%.([^.]+)%.(.+)") if enumType and enumValue then local enum = Enum[enumType] if enum then Config[category][key] = enum[enumValue] end end else Config[category][key] = value end end end end print("Config loaded successfully") end end end -- Save config local function SaveConfig() if writefile then local configToSave = {} for category, values in pairs(Config) do configToSave[category] = {} for key, value in pairs(values) do if typeof(value) == "EnumItem" then configToSave[category][key] = tostring(value) else configToSave[category][key] = value end end end local success, err = pcall(function() writefile(CONFIG_PATH, HttpService:JSONEncode(configToSave)) end) if success then print("Config saved successfully") else warn("Failed to save config:", err) end end end -- Ignore list helpers local function IsIgnored(player) for _, name in ipairs(Config.ESP.IgnoreList) do if name == player.Name then return true end end return false end local function SetIgnored(player, state) local found = false for i, name in ipairs(Config.ESP.IgnoreList) do if name == player.Name then found = true if not state then table.remove(Config.ESP.IgnoreList, i) end break end end if state and not found then table.insert(Config.ESP.IgnoreList, player.Name) end end -- UI Creation local ScreenGui = Instance.new("ScreenGui") ScreenGui.Name = "CustomUI_" .. tostring(math.random(100000, 999999)) ScreenGui.ZIndexBehavior = Enum.ZIndexBehavior.Sibling ScreenGui.ResetOnSpawn = false ScreenGui.DisplayOrder = 999999 if syn and syn.protect_gui then syn.protect_gui(ScreenGui) ScreenGui.Parent = CoreGui elseif gethui then ScreenGui.Parent = gethui() elseif get_hidden_gui then ScreenGui.Parent = get_hidden_gui() else ScreenGui.Parent = CoreGui end -- Main Frame local MainFrame = Instance.new("Frame") MainFrame.Size = UDim2.new(0, 600, 0, 400) MainFrame.Position = UDim2.new(0.5, -300, 0.5, -200) MainFrame.BackgroundColor3 = Color3.fromRGB(25, 25, 25) MainFrame.BorderSizePixel = 0 MainFrame.Visible = Config.UI.Visible MainFrame.Parent = ScreenGui local Corner = Instance.new("UICorner") Corner.CornerRadius = UDim.new(0, 8) Corner.Parent = MainFrame -- Title Bar local TitleBar = Instance.new("Frame") TitleBar.Size = UDim2.new(1, 0, 0, 35) TitleBar.BackgroundColor3 = Color3.fromRGB(35, 35, 35) TitleBar.BorderSizePixel = 0 TitleBar.Parent = MainFrame local TitleCorner = Instance.new("UICorner") TitleCorner.CornerRadius = UDim.new(0, 8) TitleCorner.Parent = TitleBar local TitleFix = Instance.new("Frame") TitleFix.Size = UDim2.new(1, 0, 0.5, 0) TitleFix.Position = UDim2.new(0, 0, 0.5, 0) TitleFix.BackgroundColor3 = Color3.fromRGB(35, 35, 35) TitleFix.BorderSizePixel = 0 TitleFix.Parent = TitleBar local TitleText = Instance.new("TextLabel") TitleText.Size = UDim2.new(1, -10, 1, 0) TitleText.Position = UDim2.new(0, 10, 0, 0) TitleText.BackgroundTransparency = 1 TitleText.Text = "Custom ESP UI" TitleText.TextColor3 = Color3.fromRGB(255, 255, 255) TitleText.TextSize = 16 TitleText.Font = Enum.Font.GothamBold TitleText.TextXAlignment = Enum.TextXAlignment.Left TitleText.Parent = TitleBar -- Tab Container local TabContainer = Instance.new("Frame") TabContainer.Size = UDim2.new(0, 120, 1, -35) TabContainer.Position = UDim2.new(0, 0, 0, 35) TabContainer.BackgroundColor3 = Color3.fromRGB(30, 30, 30) TabContainer.BorderSizePixel = 0 TabContainer.Parent = MainFrame -- Content Container local ContentContainer = Instance.new("Frame") ContentContainer.Size = UDim2.new(1, -120, 1, -35) ContentContainer.Position = UDim2.new(0, 120, 0, 35) ContentContainer.BackgroundTransparency = 1 ContentContainer.Parent = MainFrame -- Tab System local Tabs = {} local CurrentTab = nil local function CreateTab(name) local TabButton = Instance.new("TextButton") TabButton.Size = UDim2.new(1, -10, 0, 30) TabButton.Position = UDim2.new(0, 5, 0, #Tabs * 35 + 10) TabButton.BackgroundColor3 = Color3.fromRGB(45, 45, 45) TabButton.Text = name TabButton.TextColor3 = Color3.fromRGB(200, 200, 200) TabButton.TextSize = 14 TabButton.Font = Enum.Font.Gotham TabButton.Parent = TabContainer local TabCorner = Instance.new("UICorner") TabCorner.CornerRadius = UDim.new(0, 6) TabCorner.Parent = TabButton local TabContent = Instance.new("ScrollingFrame") TabContent.Size = UDim2.new(1, -20, 1, -20) TabContent.Position = UDim2.new(0, 10, 0, 10) TabContent.BackgroundTransparency = 1 TabContent.ScrollBarThickness = 4 TabContent.Visible = false TabContent.Parent = ContentContainer local UIList = Instance.new("UIListLayout") UIList.Padding = UDim.new(0, 10) UIList.Parent = TabContent local tab = { Button = TabButton, Content = TabContent, Name = name } table.insert(Tabs, tab) Track(TabButton.MouseButton1Click:Connect(function() if CurrentTab then CurrentTab.Content.Visible = false CurrentTab.Button.BackgroundColor3 = Color3.fromRGB(45, 45, 45) end CurrentTab = tab tab.Content.Visible = true tab.Button.BackgroundColor3 = Color3.fromRGB(60, 120, 180) end)) return tab end -- UI Element Creators local function CreateToggle(parent, text, default, callback) local Toggle = Instance.new("Frame") Toggle.Size = UDim2.new(1, 0, 0, 35) Toggle.BackgroundTransparency = 1 Toggle.Parent = parent local Label = Instance.new("TextLabel") Label.Size = UDim2.new(1, -60, 1, 0) Label.BackgroundTransparency = 1 Label.Text = text Label.TextColor3 = Color3.fromRGB(255, 255, 255) Label.TextSize = 14 Label.Font = Enum.Font.Gotham Label.TextXAlignment = Enum.TextXAlignment.Left Label.Parent = Toggle local Button = Instance.new("TextButton") Button.Size = UDim2.new(0, 50, 0, 25) Button.Position = UDim2.new(1, -55, 0.5, -12.5) Button.BackgroundColor3 = default and Color3.fromRGB(60, 180, 60) or Color3.fromRGB(60, 60, 60) Button.Text = default and "ON" or "OFF" Button.TextColor3 = Color3.fromRGB(255, 255, 255) Button.TextSize = 12 Button.Font = Enum.Font.GothamBold Button.Parent = Toggle local ButtonCorner = Instance.new("UICorner") ButtonCorner.CornerRadius = UDim.new(0, 4) ButtonCorner.Parent = Button Track(Button.MouseButton1Click:Connect(function() default = not default Button.Text = default and "ON" or "OFF" Button.BackgroundColor3 = default and Color3.fromRGB(60, 180, 60) or Color3.fromRGB(60, 60, 60) callback(default) end)) return Toggle end local function CreateSlider(parent, text, min, max, default, callback) local SliderFrame = Instance.new("Frame") SliderFrame.Size = UDim2.new(1, 0, 0, 50) SliderFrame.BackgroundTransparency = 1 SliderFrame.Parent = parent local Label = Instance.new("TextLabel") Label.Size = UDim2.new(1, 0, 0, 20) Label.BackgroundTransparency = 1 Label.Text = text .. ": " .. default Label.TextColor3 = Color3.fromRGB(255, 255, 255) Label.TextSize = 14 Label.Font = Enum.Font.Gotham Label.TextXAlignment = Enum.TextXAlignment.Left Label.Parent = SliderFrame local SliderBG = Instance.new("Frame") SliderBG.Size = UDim2.new(1, 0, 0, 8) SliderBG.Position = UDim2.new(0, 0, 0, 30) SliderBG.BackgroundColor3 = Color3.fromRGB(60, 60, 60) SliderBG.BorderSizePixel = 0 SliderBG.Parent = SliderFrame local SliderCorner = Instance.new("UICorner") SliderCorner.CornerRadius = UDim.new(0, 4) SliderCorner.Parent = SliderBG local SliderFill = Instance.new("Frame") SliderFill.Size = UDim2.new((default - min) / (max - min), 0, 1, 0) SliderFill.BackgroundColor3 = Color3.fromRGB(60, 120, 180) SliderFill.BorderSizePixel = 0 SliderFill.Parent = SliderBG local SliderFillCorner = Instance.new("UICorner") SliderFillCorner.CornerRadius = UDim.new(0, 4) SliderFillCorner.Parent = SliderFill local dragging = false local function update(input) local pos = math.clamp((input.Position.X - SliderBG.AbsolutePosition.X) / SliderBG.AbsoluteSize.X, 0, 1) local value = math.floor(min + (max - min) * pos) SliderFill.Size = UDim2.new(pos, 0, 1, 0) Label.Text = text .. ": " .. value callback(value) end Track(SliderBG.InputBegan:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 then dragging = true update(input) end end)) Track(UserInputService.InputChanged:Connect(function(input) if dragging and input.UserInputType == Enum.UserInputType.MouseMovement then update(input) end end)) Track(UserInputService.InputEnded:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 then dragging = false end end)) return SliderFrame end local function CreateColorPicker(parent, text, defaultColor, callback) local Picker = Instance.new("Frame") Picker.Size = UDim2.new(1, 0, 0, 35) Picker.BackgroundTransparency = 1 Picker.Parent = parent local Label = Instance.new("TextLabel") Label.Size = UDim2.new(1, -60, 1, 0) Label.BackgroundTransparency = 1 Label.Text = text Label.TextColor3 = Color3.fromRGB(255, 255, 255) Label.TextSize = 14 Label.Font = Enum.Font.Gotham Label.TextXAlignment = Enum.TextXAlignment.Left Label.Parent = Picker local ColorButton = Instance.new("TextButton") ColorButton.Size = UDim2.new(0, 50, 0, 25) ColorButton.Position = UDim2.new(1, -55, 0.5, -12.5) ColorButton.BackgroundColor3 = defaultColor ColorButton.Text = "" ColorButton.Parent = Picker local ColorCorner = Instance.new("UICorner") ColorCorner.CornerRadius = UDim.new(0, 4) ColorCorner.Parent = ColorButton local colors = { Color3.fromRGB(255, 0, 0), Color3.fromRGB(0, 255, 0), Color3.fromRGB(0, 0, 255), Color3.fromRGB(255, 255, 0), Color3.fromRGB(255, 0, 255), Color3.fromRGB(0, 255, 255), Color3.fromRGB(255, 255, 255), Color3.fromRGB(128, 128, 128), Color3.fromRGB(255, 128, 0), Color3.fromRGB(128, 0, 255) } local current = 1 for i, c in ipairs(colors) do if c == defaultColor then current = i break end end Track(ColorButton.MouseButton1Click:Connect(function() current = current % #colors + 1 ColorButton.BackgroundColor3 = colors[current] callback(colors[current]) end)) return Picker end local function CreateKeybind(parent, text, defaultKey, callback) local Keybind = Instance.new("Frame") Keybind.Size = UDim2.new(1, 0, 0, 35) Keybind.BackgroundTransparency = 1 Keybind.Parent = parent local Label = Instance.new("TextLabel") Label.Size = UDim2.new(1, -110, 1, 0) Label.BackgroundTransparency = 1 Label.Text = text Label.TextColor3 = Color3.fromRGB(255, 255, 255) Label.TextSize = 14 Label.Font = Enum.Font.Gotham Label.TextXAlignment = Enum.TextXAlignment.Left Label.Parent = Keybind local Button = Instance.new("TextButton") Button.Size = UDim2.new(0, 100, 0, 25) Button.Position = UDim2.new(1, -105, 0.5, -12.5) Button.BackgroundColor3 = Color3.fromRGB(45, 45, 45) Button.Text = defaultKey and defaultKey.Name or "NONE" Button.TextColor3 = Color3.fromRGB(255, 255, 255) Button.TextSize = 12 Button.Font = Enum.Font.Gotham Button.Parent = Keybind local ButtonCorner = Instance.new("UICorner") ButtonCorner.CornerRadius = UDim.new(0, 4) ButtonCorner.Parent = Button local listening = false Track(Button.MouseButton1Click:Connect(function() listening = true Button.Text = "..." Button.BackgroundColor3 = Color3.fromRGB(80, 60, 60) end)) Track(UserInputService.InputBegan:Connect(function(input) if listening and input.UserInputType == Enum.UserInputType.Keyboard then listening = false Button.Text = input.KeyCode.Name Button.BackgroundColor3 = Color3.fromRGB(45, 45, 45) callback(input.KeyCode) end end)) return Keybind end local function CreateButton(parent, text, color, callback) local ButtonFrame = Instance.new("Frame") ButtonFrame.Size = UDim2.new(1, 0, 0, 35) ButtonFrame.BackgroundTransparency = 1 ButtonFrame.Parent = parent local Button = Instance.new("TextButton") Button.Size = UDim2.new(1, 0, 0, 30) Button.Position = UDim2.new(0, 0, 0.5, -15) Button.BackgroundColor3 = color or Color3.fromRGB(60, 120, 180) Button.Text = text Button.TextColor3 = Color3.fromRGB(255, 255, 255) Button.TextSize = 14 Button.Font = Enum.Font.GothamBold Button.Parent = ButtonFrame local ButtonCorner = Instance.new("UICorner") ButtonCorner.CornerRadius = UDim.new(0, 6) ButtonCorner.Parent = Button Track(Button.MouseButton1Click:Connect(callback)) return ButtonFrame end -- Initialize Tabs local VisualsTab = CreateTab("Visuals") local PlayersTab = CreateTab("Players") local SettingsTab = CreateTab("Settings") -- Populate Visuals Tab CreateToggle(VisualsTab.Content, "Enable ESP", Config.ESP.Enabled, function(v) Config.ESP.Enabled = v end) CreateToggle(VisualsTab.Content, "Box ESP", Config.ESP.Box, function(v) Config.ESP.Box = v end) CreateToggle(VisualsTab.Content, "Name ESP", Config.ESP.Name, function(v) Config.ESP.Name = v end) CreateToggle(VisualsTab.Content, "Health Bar", Config.ESP.HealthBar, function(v) Config.ESP.HealthBar = v end) CreateToggle(VisualsTab.Content, "Distance", Config.ESP.Distance, function(v) Config.ESP.Distance = v end) CreateToggle(VisualsTab.Content, "Chams", Config.ESP.Chams, function(v) Config.ESP.Chams = v end) CreateToggle(VisualsTab.Content, "Skeleton", Config.ESP.Skeleton, function(v) Config.ESP.Skeleton = v end) CreateToggle(VisualsTab.Content, "Team Check", Config.ESP.TeamCheck, function(v) Config.ESP.TeamCheck = v end) CreateToggle(VisualsTab.Content, "Behind Wall Color", Config.ESP.BehindWall, function(v) Config.ESP.BehindWall = v end) CreateSlider(VisualsTab.Content, "Max Distance", 100, 2000, Config.ESP.MaxDistance, function(v) Config.ESP.MaxDistance = v end) CreateColorPicker(VisualsTab.Content, "Enemy Color", Config.ESP.EnemyColor, function(v) Config.ESP.EnemyColor = v end) CreateColorPicker(VisualsTab.Content, "Ally Color", Config.ESP.AllyColor, function(v) Config.ESP.AllyColor = v end) CreateColorPicker(VisualsTab.Content, "Behind Wall Color", Config.ESP.BehindWallColor, function(v) Config.ESP.BehindWallColor = v end) -- Populate Settings Tab CreateKeybind(SettingsTab.Content, "Toggle UI Key", Config.UI.ToggleKey, function(v) Config.UI.ToggleKey = v end) CreateButton(SettingsTab.Content, "Save Configuration", Color3.fromRGB(60, 120, 180), function() SaveConfig() end) CreateButton(SettingsTab.Content, "Load Configuration", Color3.fromRGB(60, 120, 180), function() LoadConfig() end) CreateButton(SettingsTab.Content, "Unload Script", Color3.fromRGB(180, 60, 60), function() Unload() end) -- ============================================================ -- PLAYERS TAB (manual whitelist / ignore list) -- ============================================================ local PlayerListHolder = Instance.new("Frame") PlayerListHolder.Size = UDim2.new(1, 0, 0, 0) PlayerListHolder.AutomaticSize = Enum.AutomaticSize.Y PlayerListHolder.BackgroundTransparency = 1 PlayerListHolder.Parent = PlayersTab.Content local PlayerListLayout = Instance.new("UIListLayout") PlayerListLayout.Padding = UDim.new(0, 5) PlayerListLayout.Parent = PlayerListHolder local PlayerRows = {} local function RefreshPlayerList() for player, row in pairs(PlayerRows) do if not player.Parent then row:Destroy() PlayerRows[player] = nil end end for _, player in ipairs(Players:GetPlayers()) do if player ~= LocalPlayer and not PlayerRows[player] then local Row = Instance.new("Frame") Row.Size = UDim2.new(1, 0, 0, 30) Row.BackgroundTransparency = 1 Row.Parent = PlayerListHolder local NameLabel = Instance.new("TextLabel") NameLabel.Size = UDim2.new(1, -80, 1, 0) NameLabel.BackgroundTransparency = 1 NameLabel.Text = player.Name NameLabel.TextColor3 = Color3.fromRGB(255, 255, 255) NameLabel.TextSize = 14 NameLabel.Font = Enum.Font.Gotham NameLabel.TextXAlignment = Enum.TextXAlignment.Left NameLabel.Parent = Row local ignored = IsIgnored(player) local Btn = Instance.new("TextButton") Btn.Size = UDim2.new(0, 70, 0, 22) Btn.Position = UDim2.new(1, -75, 0.5, -11) Btn.BackgroundColor3 = ignored and Color3.fromRGB(120, 60, 60) or Color3.fromRGB(60, 120, 60) Btn.Text = ignored and "SKIP" or "SHOW" Btn.TextColor3 = Color3.fromRGB(255, 255, 255) Btn.TextSize = 12 Btn.Font = Enum.Font.GothamBold Btn.Parent = Row local BtnCorner = Instance.new("UICorner") BtnCorner.CornerRadius = UDim.new(0, 4) BtnCorner.Parent = Btn Track(Btn.MouseButton1Click:Connect(function() local nowIgnored = not IsIgnored(player) SetIgnored(player, nowIgnored) Btn.Text = nowIgnored and "SKIP" or "SHOW" Btn.BackgroundColor3 = nowIgnored and Color3.fromRGB(120, 60, 60) or Color3.fromRGB(60, 120, 60) end)) PlayerRows[player] = Row end end end RefreshPlayerList() Track(Players.PlayerAdded:Connect(function() task.wait(0.1) RefreshPlayerList() end)) Track(Players.PlayerRemoving:Connect(function() task.wait(0.1) RefreshPlayerList() end)) -- Select first tab Tabs[1].Button.BackgroundColor3 = Color3.fromRGB(60, 120, 180) CurrentTab = Tabs[1] CurrentTab.Content.Visible = true -- Dragging local dragging = false local dragInput = nil local dragStart = nil local startPos = nil Track(TitleBar.InputBegan:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 then dragging = true dragStart = input.Position startPos = MainFrame.Position end end)) Track(TitleBar.InputChanged:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseMovement then dragInput = input end end)) Track(UserInputService.InputChanged:Connect(function(input) if dragging and input == dragInput then local delta = input.Position - dragStart MainFrame.Position = UDim2.new(startPos.X.Scale, startPos.X.Offset + delta.X, startPos.Y.Scale, startPos.Y.Offset + delta.Y) end end)) Track(UserInputService.InputEnded:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 then dragging = false end end)) -- UI Toggle with Mouse handling Track(UserInputService.InputBegan:Connect(function(input) if input.UserInputType == Enum.UserInputType.Keyboard and input.KeyCode == Config.UI.ToggleKey then Config.UI.Visible = not Config.UI.Visible MainFrame.Visible = Config.UI.Visible if Config.UI.Visible then UserInputService.MouseBehavior = Enum.MouseBehavior.Default UserInputService.MouseIconEnabled = true end end end)) -- Utility Functions local function GetCharacter(player) return player.Character end local function GetHumanoid(character) return character:FindFirstChildOfClass("Humanoid") end local function IsAlive(character) local humanoid = GetHumanoid(character) return humanoid and humanoid.Health > 0 end local function IsTeammate(player) if not LocalPlayer.Team then return false end return player.Team == LocalPlayer.Team end local function GetDistance(pos1, pos2) return (pos1 - pos2).Magnitude end local function WorldToScreen(position) local screenPos, onScreen = Camera:WorldToViewportPoint(position) return Vector2.new(screenPos.X, screenPos.Y), onScreen, screenPos.Z end local function IsPlayerValid(player) if player == LocalPlayer then return false end if IsIgnored(player) then return false end local character = GetCharacter(player) if not character then return false end if not IsAlive(character) then return false end return true end -- ============================================================ -- VISIBILITY CHECK (behind wall detection) -- ============================================================ local raycastParams = RaycastParams.new() pcall(function() raycastParams.FilterType = Enum.RaycastFilterType.Exclude end) pcall(function() raycastParams.FilterType = Enum.RaycastFilterType.Blacklist end) raycastParams.IgnoreWater = true local function IsVisible(character) local targetPart = character:FindFirstChild("HumanoidRootPart") or character:FindFirstChild("Head") if not targetPart then return false end local filter = {} if LocalPlayer.Character then filter = {LocalPlayer.Character} end raycastParams.FilterDescendantsInstances = filter local origin = Camera.CFrame.Position local direction = targetPart.Position - origin local result = Workspace:Raycast(origin, direction, raycastParams) if result then if result.Instance and result.Instance:IsDescendantOf(character) then return true end return false end return true end -- ============================================================ -- SKELETON ESP JOINT MAPS -- ============================================================ local SKELETON_R15 = { {"Head", "UpperTorso"}, {"UpperTorso", "LowerTorso"}, {"UpperTorso", "LeftUpperArm"}, {"LeftUpperArm", "LeftLowerArm"}, {"LeftLowerArm", "LeftHand"}, {"UpperTorso", "RightUpperArm"}, {"RightUpperArm", "RightLowerArm"}, {"RightLowerArm", "RightHand"}, {"LowerTorso", "LeftUpperLeg"}, {"LeftUpperLeg", "LeftLowerLeg"}, {"LeftLowerLeg", "LeftFoot"}, {"LowerTorso", "RightUpperLeg"}, {"RightUpperLeg", "RightLowerLeg"}, {"RightLowerLeg", "RightFoot"}, } local SKELETON_R6 = { {"Head", "Torso"}, {"Torso", "Left Arm"}, {"Torso", "Right Arm"}, {"Torso", "Left Leg"}, {"Torso", "Right Leg"}, } local function GetJointList(character) local humanoid = GetHumanoid(character) if humanoid and humanoid.RigType == Enum.HumanoidRigType.R15 then return SKELETON_R15 end return SKELETON_R6 end -- Drawing API Setup local function CreateDrawing(type, properties) local drawing = Drawing.new(type) for prop, value in pairs(properties) do pcall(function() drawing[prop] = value end) end return drawing end -- ESP System local ESPObjects = {} local function GetESPObject(player) if not ESPObjects[player] then ESPObjects[player] = { Box = CreateDrawing("Square", {Thickness = 1, Filled = false, Visible = false}), Name = CreateDrawing("Text", {Size = 13, Center = true, Outline = true, Visible = false}), HealthBar = CreateDrawing("Square", {Thickness = 1, Filled = true, Visible = false}), HealthBarOutline = CreateDrawing("Square", {Thickness = 1, Filled = false, Visible = false}), Distance = CreateDrawing("Text", {Size = 12, Center = true, Outline = true, Visible = false}), Skeleton = {}, Cham = nil } end return ESPObjects[player] end local function RemoveESPObject(player) if ESPObjects[player] then local obj = ESPObjects[player] pcall(function() obj.Box:Remove() end) pcall(function() obj.Name:Remove() end) pcall(function() obj.HealthBar:Remove() end) pcall(function() obj.HealthBarOutline:Remove() end) pcall(function() obj.Distance:Remove() end) for _, line in ipairs(obj.Skeleton) do pcall(function() line:Remove() end) end if obj.Cham then pcall(function() obj.Cham:Destroy() end) end ESPObjects[player] = nil end end local function UpdateChams(player, character, color) if not Config.ESP.Chams then if ESPObjects[player] and ESPObjects[player].Cham then pcall(function() ESPObjects[player].Cham:Destroy() end) ESPObjects[player].Cham = nil end return end local obj = GetESPObject(player) if not obj.Cham or obj.Cham.Parent ~= character then pcall(function() if obj.Cham then obj.Cham:Destroy() end end) obj.Cham = Instance.new("Highlight") obj.Cham.DepthMode = Enum.HighlightDepthMode.AlwaysOnTop end if obj.Cham and obj.Cham.Parent ~= character then obj.Cham.Parent = character end if obj.Cham then obj.Cham.FillColor = color obj.Cham.OutlineColor = color obj.Cham.FillTransparency = 0.5 obj.Cham.OutlineTransparency = 0 end end local function UpdateSkeleton(player, character, color) local obj = GetESPObject(player) if not Config.ESP.Skeleton then for _, line in ipairs(obj.Skeleton) do line.Visible = false end return end local joints = GetJointList(character) -- Grow the line pool if needed while #obj.Skeleton < #joints do table.insert(obj.Skeleton, CreateDrawing("Line", {Thickness = 1, Visible = false})) end -- Hide unused lines for i = #joints + 1, #obj.Skeleton do obj.Skeleton[i].Visible = false end -- Draw each joint connection for i, joint in ipairs(joints) do local line = obj.Skeleton[i] local partA = character:FindFirstChild(joint[1]) local partB = character:FindFirstChild(joint[2]) if partA and partB then local posA, onA = WorldToScreen(partA.Position) local posB, onB = WorldToScreen(partB.Position) if onA and onB then line.From = posA line.To = posB line.Color = color line.Thickness = 1 line.Visible = true else line.Visible = false end else line.Visible = false end end end local function UpdateESP() -- Sweep out ESP objects for players who are no longer in the game local stale = {} for player in pairs(ESPObjects) do if not player.Parent or not Players:FindFirstChild(player.Name) or player ~= Players:FindFirstChild(player.Name) then table.insert(stale, player) end end for _, player in ipairs(stale) do RemoveESPObject(player) end for player, obj in pairs(ESPObjects) do if obj.Cham then obj.Cham.Enabled = Config.ESP.Chams end end if not Config.ESP.Enabled then for player, obj in pairs(ESPObjects) do obj.Box.Visible = false obj.Name.Visible = false obj.HealthBar.Visible = false obj.HealthBarOutline.Visible = false obj.Distance.Visible = false for _, line in ipairs(obj.Skeleton) do line.Visible = false end end return end for _, player in ipairs(Players:GetPlayers()) do if IsPlayerValid(player) then local character = GetCharacter(player) local humanoid = GetHumanoid(character) local rootPart = character:FindFirstChild("HumanoidRootPart") if not rootPart then RemoveESPObject(player) continue end local isEnemy = not IsTeammate(player) if Config.ESP.TeamCheck and not isEnemy then RemoveESPObject(player) continue end local pos = rootPart.Position local screenPos, onScreen, depth = WorldToScreen(pos) local distance = GetDistance(Camera.CFrame.Position, pos) if distance > Config.ESP.MaxDistance or not onScreen or depth < 0 then RemoveESPObject(player) continue end local obj = GetESPObject(player) local color = isEnemy and Config.ESP.EnemyColor or Config.ESP.AllyColor if Config.ESP.BehindWall then if not IsVisible(character) then color = Config.ESP.BehindWallColor end end -- Get bounding box local minVec, maxVec = Vector3.new(math.huge, math.huge, math.huge), Vector3.new(-math.huge, -math.huge, -math.huge) for _, part in ipairs(character:GetDescendants()) do if part:IsA("BasePart") then local min, max = part.Position - part.Size/2, part.Position + part.Size/2 minVec = Vector3.new(math.min(minVec.X, min.X), math.min(minVec.Y, min.Y), math.min(minVec.Z, min.Z)) maxVec = Vector3.new(math.max(maxVec.X, max.X), math.max(maxVec.Y, max.Y), math.max(maxVec.Z, max.Z)) end end local corner1 = WorldToScreen(Vector3.new(minVec.X, maxVec.Y, minVec.Z)) local corner2 = WorldToScreen(Vector3.new(maxVec.X, maxVec.Y, minVec.Z)) local corner3 = WorldToScreen(Vector3.new(minVec.X, maxVec.Y, maxVec.Z)) local corner4 = WorldToScreen(Vector3.new(maxVec.X, maxVec.Y, maxVec.Z)) local corner5 = WorldToScreen(Vector3.new(minVec.X, minVec.Y, minVec.Z)) local corner8 = WorldToScreen(Vector3.new(maxVec.X, minVec.Y, maxVec.Z)) local width = math.max(math.abs(corner1.X - corner2.X), math.abs(corner3.X - corner4.X), math.abs(corner5.X - corner8.X)) local height = math.max(math.abs(corner1.Y - corner5.Y), math.abs(corner2.Y - corner8.Y)) local boxX = screenPos.X - width/2 local boxY = screenPos.Y - height/2 -- Box ESP obj.Box.Visible = Config.ESP.Box obj.Box.Size = Vector2.new(width, height) obj.Box.Position = Vector2.new(boxX, boxY) obj.Box.Color = color -- Name ESP obj.Name.Visible = Config.ESP.Name obj.Name.Text = player.Name obj.Name.Position = Vector2.new(screenPos.X, boxY - 15) obj.Name.Color = color -- Health Bar if Config.ESP.HealthBar and humanoid then local healthPercent = math.clamp(humanoid.Health / humanoid.MaxHealth, 0, 1) local barHeight = height * healthPercent local barX = boxX - 6 local barY = boxY + height - barHeight obj.HealthBarOutline.Visible = true obj.HealthBarOutline.Size = Vector2.new(4, height) obj.HealthBarOutline.Position = Vector2.new(barX - 1, boxY) obj.HealthBarOutline.Color = Color3.new(0, 0, 0) obj.HealthBar.Visible = true obj.HealthBar.Size = Vector2.new(2, barHeight) obj.HealthBar.Position = Vector2.new(barX, barY) obj.HealthBar.Color = Color3.new(1 - healthPercent, healthPercent, 0) else obj.HealthBar.Visible = false obj.HealthBarOutline.Visible = false end -- Distance ESP obj.Distance.Visible = Config.ESP.Distance obj.Distance.Text = math.floor(distance) .. " studs" obj.Distance.Position = Vector2.new(screenPos.X, boxY + height + 2) obj.Distance.Color = color -- Skeleton ESP UpdateSkeleton(player, character, color) -- Chams UpdateChams(player, character, color) else RemoveESPObject(player) end end end -- Main Loop Track(RunService.RenderStepped:Connect(UpdateESP)) -- Remove ESP immediately when a player leaves Track(Players.PlayerRemoving:Connect(function(player) RemoveESPObject(player) end)) -- ============================================================ -- UNLOAD FUNCTION -- ============================================================ function Unload() for _, conn in ipairs(Connections) do pcall(function() conn:Disconnect() end) end Connections = {} for player, obj in pairs(ESPObjects) do pcall(function() obj.Box:Remove() end) pcall(function() obj.Name:Remove() end) pcall(function() obj.HealthBar:Remove() end) pcall(function() obj.HealthBarOutline:Remove() end) pcall(function() obj.Distance:Remove() end) for _, line in ipairs(obj.Skeleton) do pcall(function() line:Remove() end) end if obj.Cham then pcall(function() obj.Cham:Destroy() end) end end ESPObjects = {} if ScreenGui then pcall(function() ScreenGui:Destroy() end) end print("Unloaded successfully!") end -- Load config on startup LoadConfig() print("ESP Script loaded! Press " .. Config.UI.ToggleKey.Name .. " to toggle UI")