--[[ Drone ESP + GUI for ПАНЦИР Toggle panel: ON/OFF highlights for Workspace.Drones BOT (red) vs PLAYER (blue) via IsPlayerDrone / OwnerUserId ]] local Players = game:GetService("Players") local RunService = game:GetService("RunService") local UserInputService = game:GetService("UserInputService") -- tear down previous full session (ESP + GUI) if type(_G.UAI_DestroyDroneESP) == "function" then pcall(_G.UAI_DestroyDroneESP) elseif type(_G.UAI_StopDroneESP) == "function" then pcall(_G.UAI_StopDroneESP) end local LOCAL = Players.LocalPlayer local PLAYER_GUI = LOCAL:WaitForChild("PlayerGui") local FOLDER_MAIN = workspace:WaitForChild("Drones"):WaitForChild("SpawnedDrones") local FOLDER_SCOUT = workspace.Drones:FindFirstChild("Scout") and workspace.Drones.Scout:FindFirstChild("Spawned") local COLOR_BOT = Color3.fromRGB(255, 70, 70) local COLOR_PLAYER = Color3.fromRGB(60, 180, 255) local OUTLINE = Color3.fromRGB(255, 255, 255) local TEXT_BOT = Color3.fromRGB(255, 180, 180) local TEXT_PLAYER = Color3.fromRGB(160, 230, 255) local MAX_DIST = 20000 local tracked = {} local folderConns = {} local updateConn: RBXScriptConnection? = nil local espEnabled = false local guiConns = {} local screenGui: ScreenGui? = nil local function getDroneType(drone: Model): string local named = drone:GetAttribute("DroneName") if typeof(named) == "string" and named ~= "" then return named end for _, child in ipairs(drone:GetChildren()) do if child:IsA("Model") and child.Name ~= "UAI_DroneESP" then return child.Name end end return "Drone" end local function getAnchor(drone: Model): BasePart? if drone.PrimaryPart then return drone.PrimaryPart end local body = drone:FindFirstChild("Body", true) if body and body:IsA("BasePart") then return body end return drone:FindFirstChildWhichIsA("BasePart", true) end local function getRootPos(): Vector3? local char = LOCAL.Character if not char then return nil end local hrp = char:FindFirstChild("HumanoidRootPart") return hrp and hrp.Position end local function resolvePilotName(userId: number?): string? if not userId or userId <= 0 then return nil end local plr = Players:GetPlayerByUserId(userId) if plr then return plr.DisplayName ~= "" and plr.DisplayName or plr.Name end local ok, name = pcall(function() return Players:GetNameFromUserIdAsync(userId) end) if ok and typeof(name) == "string" then return name end return tostring(userId) end local function readControl(drone: Model) local isPlayer = drone:GetAttribute("IsPlayerDrone") == true local ownerId = drone:GetAttribute("OwnerUserId") if typeof(ownerId) ~= "number" then ownerId = nil end if ownerId and ownerId > 0 then isPlayer = true end local pilot = isPlayer and resolvePilotName(ownerId) or nil return isPlayer, ownerId, pilot end local function applyVisual(data, isPlayer: boolean) local fill = isPlayer and COLOR_PLAYER or COLOR_BOT local text = isPlayer and TEXT_PLAYER or TEXT_BOT data.highlight.FillColor = fill data.highlight.OutlineColor = OUTLINE data.label.TextColor3 = text data.isPlayer = isPlayer end local function countTracked(): (number, number, number) local bots, players, total = 0, 0, 0 for _, data in pairs(tracked) do total += 1 if data.isPlayer then players += 1 else bots += 1 end end return total, bots, players end local statusLabel: TextLabel? = nil local toggleBtn: TextButton? = nil local function refreshGui() local total, bots, players = countTracked() if statusLabel then if espEnabled then statusLabel.Text = string.format("ON | %d (BOT %d / PLAYER %d)", total, bots, players) statusLabel.TextColor3 = Color3.fromRGB(120, 255, 160) else statusLabel.Text = "OFF | ESP выключен" statusLabel.TextColor3 = Color3.fromRGB(200, 200, 200) end end if toggleBtn then if espEnabled then toggleBtn.Text = "ВЫКЛЮЧИТЬ" toggleBtn.BackgroundColor3 = Color3.fromRGB(180, 50, 50) else toggleBtn.Text = "ВКЛЮЧИТЬ" toggleBtn.BackgroundColor3 = Color3.fromRGB(40, 140, 70) end end end local function untrack(drone: Model) local data = tracked[drone] if not data then return end for _, c in ipairs(data.conns or {}) do c:Disconnect() end if data.highlight then data.highlight:Destroy() end if data.billboard then data.billboard:Destroy() end tracked[drone] = nil end local function clearAllTracked() for drone in pairs(tracked) do untrack(drone) end end local function track(drone: Model) if not espEnabled then return end if tracked[drone] then return end if not drone:IsA("Model") or drone.Name ~= "Drone" then return end local oldHl = drone:FindFirstChild("UAI_DroneESP") if oldHl then oldHl:Destroy() end local oldBb = drone:FindFirstChild("UAI_DroneESP_BB") if oldBb then oldBb:Destroy() end local anchor = getAnchor(drone) if not anchor then return end local isPlayer, ownerId, pilot = readControl(drone) local typeName = getDroneType(drone) local hl = Instance.new("Highlight") hl.Name = "UAI_DroneESP" hl.Adornee = drone hl.FillTransparency = 0.55 hl.OutlineTransparency = 0 hl.DepthMode = Enum.HighlightDepthMode.AlwaysOnTop hl.Parent = drone local bb = Instance.new("BillboardGui") bb.Name = "UAI_DroneESP_BB" bb.Adornee = anchor bb.AlwaysOnTop = true bb.Size = UDim2.fromOffset(200, 48) bb.StudsOffset = Vector3.new(0, 3, 0) bb.MaxDistance = MAX_DIST or 100000 bb.Parent = drone local label = Instance.new("TextLabel") label.Name = "Label" label.BackgroundTransparency = 1 label.Size = UDim2.fromScale(1, 1) label.Font = Enum.Font.GothamBold label.TextSize = 14 label.TextStrokeTransparency = 0.3 label.TextWrapped = true label.Parent = bb local conns = {} table.insert(conns, drone.AncestryChanged:Connect(function(_, parent) if parent == nil then untrack(drone) refreshGui() end end)) local data = { highlight = hl, billboard = bb, label = label, typeName = typeName, isPlayer = isPlayer, ownerId = ownerId, pilot = pilot, conns = conns, } applyVisual(data, isPlayer) tracked[drone] = data end local function scanFolder(folder: Instance?) if not folder then return end for _, child in ipairs(folder:GetChildren()) do if child:IsA("Model") and child.Name == "Drone" then track(child) end end end local function disconnectFolderHooks() for _, c in ipairs(folderConns) do c:Disconnect() end table.clear(folderConns) end local function hookFolder(folder: Instance?) if not folder then return end scanFolder(folder) table.insert(folderConns, folder.ChildAdded:Connect(function(child) task.defer(function() if espEnabled and child.Parent and child:IsA("Model") and child.Name == "Drone" then track(child) refreshGui() end end) end)) table.insert(folderConns, folder.ChildRemoved:Connect(function(child) if tracked[child] then untrack(child) refreshGui() end end)) end local function stopUpdate() if updateConn then updateConn:Disconnect() updateConn = nil end end local function startUpdate() stopUpdate() updateConn = RunService.Heartbeat:Connect(function() if not espEnabled then return end local root = getRootPos() if not root then return end for drone, data in pairs(tracked) do if drone.Parent and data.label then local isPlayer, ownerId, pilot = readControl(drone) data.typeName = getDroneType(drone) if isPlayer ~= data.isPlayer or ownerId ~= data.ownerId or pilot ~= data.pilot then data.ownerId = ownerId data.pilot = pilot applyVisual(data, isPlayer) end local anchor = getAnchor(drone) if anchor then local dist = (anchor.Position - root).Magnitude if MAX_DIST and dist > MAX_DIST then data.highlight.Enabled = false data.billboard.Enabled = false else data.highlight.Enabled = true data.billboard.Enabled = true local who if isPlayer then who = pilot and ("PLAYER:" .. pilot) or "PLAYER" else who = "BOT" end data.label.Text = string.format("%s\n%s [%.0fm]", data.typeName, who, dist) end end else untrack(drone) end end end) end local function setEspEnabled(on: boolean) if on == espEnabled then refreshGui() return end espEnabled = on if on then disconnectFolderHooks() hookFolder(FOLDER_MAIN) hookFolder(FOLDER_SCOUT) startUpdate() else stopUpdate() disconnectFolderHooks() clearAllTracked() end refreshGui() end local function destroyGui() for _, c in ipairs(guiConns) do c:Disconnect() end table.clear(guiConns) if screenGui then screenGui:Destroy() screenGui = nil end statusLabel = nil toggleBtn = nil end local function makeCorner(parent: Instance, radius: number) local c = Instance.new("UICorner") c.CornerRadius = UDim.new(0, radius) c.Parent = parent return c end local function makeStroke(parent: Instance, color: Color3, thickness: number) local s = Instance.new("UIStroke") s.Color = color s.Thickness = thickness s.ApplyStrokeMode = Enum.ApplyStrokeMode.Border s.Parent = parent return s end local function createGui() destroyGui() local old = PLAYER_GUI:FindFirstChild("UAI_DroneESP_Gui") if old then old:Destroy() end local gui = Instance.new("ScreenGui") gui.Name = "UAI_DroneESP_Gui" gui.ResetOnSpawn = false gui.ZIndexBehavior = Enum.ZIndexBehavior.Sibling gui.DisplayOrder = 100 gui.Parent = PLAYER_GUI screenGui = gui local panel = Instance.new("Frame") panel.Name = "Panel" panel.Size = UDim2.fromOffset(220, 128) panel.Position = UDim2.new(0, 16, 0.35, 0) panel.BackgroundColor3 = Color3.fromRGB(22, 24, 30) panel.BackgroundTransparency = 0.12 panel.BorderSizePixel = 0 panel.Active = true panel.Parent = gui makeCorner(panel, 10) makeStroke(panel, Color3.fromRGB(70, 80, 100), 1) local title = Instance.new("TextLabel") title.Name = "Title" title.BackgroundTransparency = 1 title.Position = UDim2.fromOffset(12, 8) title.Size = UDim2.new(1, -48, 0, 22) title.Font = Enum.Font.GothamBold title.TextSize = 16 title.TextXAlignment = Enum.TextXAlignment.Left title.TextColor3 = Color3.fromRGB(240, 240, 245) title.Text = "Drone ESP" title.Parent = panel local hideBtn = Instance.new("TextButton") hideBtn.Name = "Hide" hideBtn.Size = UDim2.fromOffset(28, 28) hideBtn.Position = UDim2.new(1, -36, 0, 6) hideBtn.BackgroundColor3 = Color3.fromRGB(45, 48, 58) hideBtn.Text = "–" hideBtn.Font = Enum.Font.GothamBold hideBtn.TextSize = 18 hideBtn.TextColor3 = Color3.fromRGB(220, 220, 230) hideBtn.AutoButtonColor = true hideBtn.Parent = panel makeCorner(hideBtn, 6) statusLabel = Instance.new("TextLabel") statusLabel.Name = "Status" statusLabel.BackgroundTransparency = 1 statusLabel.Position = UDim2.fromOffset(12, 34) statusLabel.Size = UDim2.new(1, -24, 0, 18) statusLabel.Font = Enum.Font.Gotham statusLabel.TextSize = 13 statusLabel.TextXAlignment = Enum.TextXAlignment.Left statusLabel.Text = "OFF" statusLabel.Parent = panel toggleBtn = Instance.new("TextButton") toggleBtn.Name = "Toggle" toggleBtn.Size = UDim2.new(1, -24, 0, 34) toggleBtn.Position = UDim2.fromOffset(12, 58) toggleBtn.Font = Enum.Font.GothamBold toggleBtn.TextSize = 15 toggleBtn.TextColor3 = Color3.fromRGB(255, 255, 255) toggleBtn.AutoButtonColor = true toggleBtn.Parent = panel makeCorner(toggleBtn, 8) local hint = Instance.new("TextLabel") hint.Name = "Hint" hint.BackgroundTransparency = 1 hint.Position = UDim2.fromOffset(12, 98) hint.Size = UDim2.new(1, -24, 0, 18) hint.Font = Enum.Font.Gotham hint.TextSize = 11 hint.TextXAlignment = Enum.TextXAlignment.Left hint.TextColor3 = Color3.fromRGB(140, 145, 160) hint.Text = "Красный=BOT Синий=PLAYER" hint.Parent = panel -- collapsed open chip local openBtn = Instance.new("TextButton") openBtn.Name = "OpenChip" openBtn.Visible = false openBtn.Size = UDim2.fromOffset(110, 32) openBtn.Position = UDim2.new(0, 16, 0.35, 0) openBtn.BackgroundColor3 = Color3.fromRGB(22, 24, 30) openBtn.BackgroundTransparency = 0.12 openBtn.Font = Enum.Font.GothamBold openBtn.TextSize = 13 openBtn.TextColor3 = Color3.fromRGB(240, 240, 245) openBtn.Text = "Drone ESP" openBtn.AutoButtonColor = true openBtn.Parent = gui makeCorner(openBtn, 8) makeStroke(openBtn, Color3.fromRGB(70, 80, 100), 1) table.insert(guiConns, toggleBtn.MouseButton1Click:Connect(function() setEspEnabled(not espEnabled) end)) table.insert(guiConns, hideBtn.MouseButton1Click:Connect(function() panel.Visible = false openBtn.Visible = true end)) table.insert(guiConns, openBtn.MouseButton1Click:Connect(function() openBtn.Visible = false panel.Visible = true end)) -- drag panel local dragging = false local dragStart: Vector2? = nil local startPos: UDim2? = nil table.insert(guiConns, panel.InputBegan:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then dragging = true dragStart = input.Position startPos = panel.Position end end)) table.insert(guiConns, UserInputService.InputChanged:Connect(function(input) if not dragging or not dragStart or not startPos then return end if input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch then local delta = input.Position - dragStart panel.Position = UDim2.new( startPos.X.Scale, startPos.X.Offset + delta.X, startPos.Y.Scale, startPos.Y.Offset + delta.Y ) openBtn.Position = panel.Position end end)) table.insert(guiConns, UserInputService.InputEnded:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then dragging = false end end)) refreshGui() end local function destroyAll() setEspEnabled(false) stopUpdate() disconnectFolderHooks() clearAllTracked() destroyGui() _G.UAI_StopDroneESP = nil _G.UAI_DestroyDroneESP = nil _G.UAI_SetDroneESP = nil print("[UAI] Drone ESP + GUI destroyed") end _G.UAI_StopDroneESP = function() setEspEnabled(false) print("[UAI] Drone ESP stopped (GUI remains)") end _G.UAI_SetDroneESP = setEspEnabled _G.UAI_DestroyDroneESP = destroyAll createGui() setEspEnabled(true) local total, bots, players = countTracked() print(string.format( "[UAI] Drone ESP GUI ready — ON, %d (%d BOT / %d PLAYER). Destroy: _G.UAI_DestroyDroneESP()", total, bots, players )) return string.format("GUI ready, ESP ON: %d (%d bot / %d player)", total, bots, players)