Загрузка данных


local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UIS = game:GetService("UserInputService")
local Camera = workspace.CurrentCamera
local LP = Players.LocalPlayer

local Drawing = Drawing or (syn and syn.Drawing) or (getgenv and getgenv().Drawing)
if not Drawing then warn("No Drawing") end

local aimEnabled = false
local espEnabled = false
local espObjects = {}
local currentTarget = nil  -- {player, head}

local function createESP(p)
    if not Drawing then return end
    local b = Drawing.new("Square")
    b.Thickness = 2
    b.Color = Color3.fromRGB(255,0,0)
    b.Transparency = 0.5
    b.Filled = false
    b.Visible = false
    local l = Drawing.new("Text")
    l.Color = Color3.fromRGB(255,0,0)
    l.Size = 14
    l.Center = true
    l.Outline = true
    l.OutlineColor = Color3.fromRGB(0,0,0)
    l.Visible = false
    espObjects[p] = {box = b, label = l}
end

local function removeESP(p)
    local o = espObjects[p]
    if o then
        o.box:Remove()
        o.label:Remove()
        espObjects[p] = nil
    end
end

local function updateESP()
    if not espEnabled then
        for _,o in pairs(espObjects) do
            o.box.Visible = false
            o.label.Visible = false
        end
        return
    end
    for _,p in pairs(Players:GetPlayers()) do
        if p == LP then continue end
        local c = p.Character
        if not c or not c.PrimaryPart then
            local o = espObjects[p]
            if o then
                o.box.Visible = false
                o.label.Visible = false
            end
            continue
        end
        local o = espObjects[p]
        if not o then createESP(p) o = espObjects[p] end
        local root = c.PrimaryPart
        local pos, on = Camera:WorldToScreenPoint(root.Position)
        if not on then
            o.box.Visible = false
            o.label.Visible = false
            continue
        end
        local dist = (Camera.CFrame.Position - root.Position).Magnitude
        local size = math.clamp(200/dist*3, 20, 150)
        local half = size/2
        local x,y = pos.X, pos.Y - size*0.8
        o.box.Position = Vector2.new(x-half, y-half)
        o.box.Size = Vector2.new(size, size*1.5)
        o.box.Visible = true
        local hp = 100
        local hum = c:FindFirstChild("Humanoid")
        if hum then hp = math.floor(hum.Health) end
        o.label.Text = p.Name .. " [" .. hp .. " HP]"
        o.label.Position = Vector2.new(x, y - size*0.9 - 20)
        o.label.Visible = true
    end
    for p,_ in pairs(espObjects) do
        if not p.Parent then removeESP(p) end
    end
end

-- Проверка видимости (не через стены)
local function isVisible(head)
    local origin = Camera.CFrame.Position
    local direction = (head.Position - origin).Unit
    local ray = Ray.new(origin, direction * (head.Position - origin).Magnitude)
    local hit, pos = workspace:FindPartOnRayWithIgnoreList(ray, {LP.Character, Camera})
    if hit then
        local distToHit = (pos - origin).Magnitude
        local distToHead = (head.Position - origin).Magnitude
        if distToHit < distToHead - 0.5 then
            return false
        end
    end
    return true
end

-- Поиск ближайшей цели в поле зрения (FOV 90 градусов от направления камеры)
local function findTarget()
    local closestDist = math.huge
    local closestHead = nil
    local closestPlayer = nil
    local camDir = Camera.CFrame.LookVector
    for _,p in pairs(Players:GetPlayers()) do
        if p == LP then continue end
        local c = p.Character
        if not c then continue end
        local head = c:FindFirstChild("Head")
        if not head then continue end
        -- Проверка угла
        local toTarget = (head.Position - Camera.CFrame.Position).Unit
        local dot = camDir:Dot(toTarget)
        if dot < 0.5 then continue end -- угол больше 60 градусов, не в центре
        -- Проверка стены
        if not isVisible(head) then continue end
        local dist = (head.Position - Camera.CFrame.Position).Magnitude
        if dist < closestDist then
            closestDist = dist
            closestHead = head
            closestPlayer = p
        end
    end
    return closestPlayer, closestHead
end

-- Поворот персонажа к голове цели
local function aimAtHead(head)
    local character = LP.Character
    if not character then return end
    local root = character:FindFirstChild("HumanoidRootPart")
    if not root then return end
    local currentPos = root.Position
    local targetPos = head.Position
    -- Вычисляем направление только по Y (горизонтальный поворот), игнорируем вертикаль
    local direction = Vector3.new(targetPos.X - currentPos.X, 0, targetPos.Z - currentPos.Z)
    if direction.Magnitude < 0.1 then return end
    direction = direction.Unit
    -- Угол поворота
    local angle = math.atan2(direction.X, direction.Z)
    local newCFrame = CFrame.new(currentPos) * CFrame.Angles(0, angle, 0)
    root.CFrame = newCFrame
end

-- Обработка клавиш
UIS.InputBegan:Connect(function(input, gp)
    if gp then return end
    if input.KeyCode == Enum.KeyCode.B then
        aimEnabled = not aimEnabled
        if aimEnabled then
            print("AIM ON")
            local player, head = findTarget()
            if head then
                currentTarget = {player = player, head = head}
                aimAtHead(head)
            else
                currentTarget = nil
            end
        else
            print("AIM OFF")
            currentTarget = nil
        end
    end
    if input.KeyCode == Enum.KeyCode.N then
        espEnabled = not espEnabled
        if espEnabled then
            print("ESP ON")
            for _,p in pairs(Players:GetPlayers()) do
                if p ~= LP then createESP(p) end
            end
        else
            print("ESP OFF")
            for p,_ in pairs(espObjects) do removeESP(p) end
        end
    end
end)

-- Обновление каждый кадр
RunService.RenderStepped:Connect(function()
    if aimEnabled then
        if currentTarget and currentTarget.head and currentTarget.head.Parent then
            -- Проверяем, видна ли цель и жива ли
            if not isVisible(currentTarget.head) or not currentTarget.head.Parent:FindFirstChild("Humanoid") or currentTarget.head.Parent.Humanoid.Health <= 0 then
                currentTarget = nil
            else
                aimAtHead(currentTarget.head)
            end
        end
        if not currentTarget then
            local player, head = findTarget()
            if head then
                currentTarget = {player = player, head = head}
                aimAtHead(head)
            end
        end
    end
    updateESP()
end)

Players.PlayerAdded:Connect(function(p)
    if espEnabled and p ~= LP then createESP(p) end
end)
Players.PlayerRemoving:Connect(removeESP)

print("Loaded. B - aim, N - esp")