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


-- // BoatHelper | Premium Script
-- // Создано для Roblox

local Players = game:GetService("Players")
local Player = Players.LocalPlayer
local UserInputService = game:GetService("UserInputService")
local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")
local Workspace = game:GetService("Workspace")

-- // Функции, которые будут отключаться при уничтожении GUI
local ActiveFunctions = {
    TestFunction = {
        Enabled = false,
        Connection = nil,
        Name = "Тестовая Функция",
        Description = "Включает/выключает тестовый вывод в консоль каждую секунду."
    },
    ESP = {
        Enabled = false,
        Connection = nil,
        PlayersData = {}, -- Хранит данные для каждого игрока
        Name = "ESP Игроков",
        Description = "Подсвечивает игроков через стены и показывает их ник, расстояние и здоровье."
    }
}

-- // Очистка ESP для конкретного игрока
local function CleanupPlayerESP(player)
    local data = ActiveFunctions.ESP.PlayersData[player]
    if not data then return end
    
    if data.Highlight then
        data.Highlight:Destroy()
        data.Highlight = nil
    end
    
    if data.Billboard then
        data.Billboard:Destroy()
        data.Billboard = nil
    end
    
    if data.UpdateConnection then
        data.UpdateConnection:Disconnect()
        data.UpdateConnection = nil
    end
    
    if data.CharacterConnection then
        data.CharacterConnection:Disconnect()
        data.CharacterConnection = nil
    end
    
    ActiveFunctions.ESP.PlayersData[player] = nil
end

-- // Создание ESP для игрока
local function SetupPlayerESP(player)
    if player == Player then return end
    
    -- Очищаем старые данные если есть
    CleanupPlayerESP(player)
    
    -- Инициализируем данные игрока
    ActiveFunctions.ESP.PlayersData[player] = {
        Highlight = nil,
        Billboard = nil,
        UpdateConnection = nil,
        CharacterConnection = nil
    }
    
    local function CreateESPVisuals(character)
        if not character or not ActiveFunctions.ESP.Enabled then return end
        
        local data = ActiveFunctions.ESP.PlayersData[player]
        if not data then return end
        
        -- Удаляем старые визуалы если есть
        if data.Highlight then
            data.Highlight:Destroy()
            data.Highlight = nil
        end
        if data.Billboard then
            data.Billboard:Destroy()
            data.Billboard = nil
        end
        if data.UpdateConnection then
            data.UpdateConnection:Disconnect()
            data.UpdateConnection = nil
        end
        
        -- Ждем загрузки персонажа
        local humanoidRootPart = character:WaitForChild("HumanoidRootPart", 5)
        local humanoid = character:WaitForChild("Humanoid", 5)
        
        if not humanoidRootPart or not humanoid then return end
        
        -- Создаем Highlight
        local highlight = Instance.new("Highlight")
        highlight.Name = "ESP_Highlight"
        highlight.FillColor = Color3.fromRGB(255, 255, 255)
        highlight.FillTransparency = 0.5
        highlight.OutlineColor = Color3.fromRGB(255, 255, 255)
        highlight.OutlineTransparency = 0
        highlight.Adornee = character
        highlight.Parent = character
        data.Highlight = highlight
        
        -- Создаем BillboardGui
        local billboard = Instance.new("BillboardGui")
        billboard.Name = "ESP_Billboard"
        billboard.Adornee = humanoidRootPart
        billboard.Parent = character
        billboard.Size = UDim2.new(0, 300, 0, 30)
        billboard.StudsOffset = Vector3.new(0, 3, 0)
        billboard.AlwaysOnTop = true
        billboard.MaxDistance = 1000
        
        local textLabel = Instance.new("TextLabel")
        textLabel.Parent = billboard
        textLabel.Size = UDim2.new(1, 0, 1, 0)
        textLabel.BackgroundTransparency = 1
        textLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
        textLabel.Font = Enum.Font.GothamBold
        textLabel.TextSize = 14
        textLabel.TextStrokeTransparency = 0.3
        textLabel.TextStrokeColor3 = Color3.fromRGB(0, 0, 0)
        textLabel.Text = "Загрузка..."
        data.Billboard = billboard
        
        -- Функция обновления информации
        local function UpdateInfo()
            if not ActiveFunctions.ESP.Enabled then return end
            if not player.Parent then return end -- Игрок вышел
            
            local localPlayer = Player
            local localCharacter = localPlayer.Character
            if not localCharacter then return end
            
            local localRoot = localCharacter:FindFirstChild("HumanoidRootPart")
            if not localRoot then return end
            
            local targetCharacter = player.Character
            if not targetCharacter then return end
            
            local targetRoot = targetCharacter:FindFirstChild("HumanoidRootPart")
            local targetHumanoid = targetCharacter:FindFirstChild("Humanoid")
            
            if not targetRoot or not targetHumanoid then
                textLabel.Text = player.DisplayName or player.Name
                return
            end
            
            local distance = (targetRoot.Position - localRoot.Position).Magnitude
            local health = math.floor(targetHumanoid.Health)
            
            textLabel.Text = string.format("%s | %.0fstuds | %dHP", 
                player.DisplayName or player.Name, 
                distance, 
                health
            )
        end
        
        -- Запускаем обновление
        data.UpdateConnection = RunService.Heartbeat:Connect(function()
            if not ActiveFunctions.ESP.Enabled then
                if data.UpdateConnection then
                    data.UpdateConnection:Disconnect()
                    data.UpdateConnection = nil
                end
                return
            end
            UpdateInfo()
        end)
    end
    
    -- Отслеживаем появление персонажа
    local function OnCharacterAdded(character)
        if ActiveFunctions.ESP.Enabled then
            CreateESPVisuals(character)
        end
    end
    
    -- Если персонаж уже есть - создаем ESP
    if player.Character then
        CreateESPVisuals(player.Character)
    end
    
    -- Подписываемся на появление нового персонажа
    local data = ActiveFunctions.ESP.PlayersData[player]
    if data then
        data.CharacterConnection = player.CharacterAdded:Connect(OnCharacterAdded)
    end
end

-- // Сканирование всех игроков
local function ScanAllPlayers()
    for _, player in pairs(Players:GetPlayers()) do
        if player ~= Player then
            SetupPlayerESP(player)
        end
    end
end

-- // Очистка всего ESP
local function ClearAllESP()
    for player, _ in pairs(ActiveFunctions.ESP.PlayersData) do
        CleanupPlayerESP(player)
    end
    ActiveFunctions.ESP.PlayersData = {}
end

-- // Создание GUI
local function CreateBoatHelper()
    -- // Основной контейнер ScreenGui
    local ScreenGui = Instance.new("ScreenGui")
    ScreenGui.Name = "BoatHelper"
    ScreenGui.Parent = Player:WaitForChild("PlayerGui")
    ScreenGui.ResetOnSpawn = false
    ScreenGui.ZIndexBehavior = Enum.ZIndexBehavior.Sibling

    -- // Главное окно
    local MainFrame = Instance.new("Frame")
    MainFrame.Name = "MainFrame"
    MainFrame.Parent = ScreenGui
    MainFrame.Size = UDim2.new(0, 320, 0, 295)
    MainFrame.Position = UDim2.new(0.5, -160, 0.5, -147)
    MainFrame.BackgroundColor3 = Color3.fromRGB(30, 30, 30)
    MainFrame.BorderSizePixel = 1
    MainFrame.BorderColor3 = Color3.fromRGB(60, 60, 60)
    MainFrame.Active = true

    -- // Заголовок (верхняя панель для перетаскивания)
    local TitleBar = Instance.new("Frame")
    TitleBar.Name = "TitleBar"
    TitleBar.Parent = MainFrame
    TitleBar.Size = UDim2.new(1, 0, 0, 30)
    TitleBar.BackgroundColor3 = Color3.fromRGB(20, 20, 20)
    TitleBar.BorderSizePixel = 1
    TitleBar.BorderColor3 = Color3.fromRGB(60, 60, 60)

    local TitleText = Instance.new("TextLabel")
    TitleText.Parent = TitleBar
    TitleText.Size = UDim2.new(1, -10, 1, 0)
    TitleText.Position = UDim2.new(0, 10, 0, 0)
    TitleText.BackgroundTransparency = 1
    TitleText.Text = "BoatHelper"
    TitleText.TextColor3 = Color3.fromRGB(200, 200, 200)
    TitleText.Font = Enum.Font.GothamBold
    TitleText.TextSize = 14
    TitleText.TextXAlignment = Enum.TextXAlignment.Left

    -- // Разделитель под заголовком
    local Divider1 = Instance.new("Frame")
    Divider1.Parent = MainFrame
    Divider1.Size = UDim2.new(1, 0, 0, 1)
    Divider1.Position = UDim2.new(0, 0, 0, 30)
    Divider1.BackgroundColor3 = Color3.fromRGB(60, 60, 60)
    Divider1.BorderSizePixel = 0

    -- // Функция создания строки с функцией
    local function CreateFunctionRow(yPos, funcData, toggleCallback)
        local Container = Instance.new("Frame")
        Container.Parent = MainFrame
        Container.Size = UDim2.new(1, -20, 0, 40)
        Container.Position = UDim2.new(0, 10, 0, yPos)
        Container.BackgroundColor3 = Color3.fromRGB(40, 40, 40)
        Container.BorderSizePixel = 1
        Container.BorderColor3 = Color3.fromRGB(60, 60, 60)

        local FuncInfo = Instance.new("TextLabel")
        FuncInfo.Parent = Container
        FuncInfo.Size = UDim2.new(1, -60, 1, 0)
        FuncInfo.Position = UDim2.new(0, 10, 0, 0)
        FuncInfo.BackgroundTransparency = 1
        FuncInfo.Text = funcData.Name .. "\n" .. funcData.Description
        FuncInfo.TextColor3 = Color3.fromRGB(180, 180, 180)
        FuncInfo.Font = Enum.Font.Gotham
        FuncInfo.TextSize = 11
        FuncInfo.TextXAlignment = Enum.TextXAlignment.Left
        FuncInfo.TextYAlignment = Enum.TextYAlignment.Center
        FuncInfo.TextWrapped = true

        local ToggleButton = Instance.new("TextButton")
        ToggleButton.Name = "ToggleButton"
        ToggleButton.Parent = Container
        ToggleButton.Size = UDim2.new(0, 40, 0, 20)
        ToggleButton.Position = UDim2.new(1, -50, 0.5, -10)
        ToggleButton.BackgroundColor3 = Color3.fromRGB(150, 30, 30)
        ToggleButton.BorderSizePixel = 1
        ToggleButton.BorderColor3 = Color3.fromRGB(100, 100, 100)
        ToggleButton.Text = "OFF"
        ToggleButton.TextColor3 = Color3.fromRGB(255, 255, 255)
        ToggleButton.Font = Enum.Font.GothamBold
        ToggleButton.TextSize = 11
        ToggleButton.AutoButtonColor = false

        -- Обновление цвета кнопки
        local function UpdateButtonState()
            if funcData.Enabled then
                ToggleButton.BackgroundColor3 = Color3.fromRGB(30, 150, 30)
                ToggleButton.Text = "ON"
            else
                ToggleButton.BackgroundColor3 = Color3.fromRGB(150, 30, 30)
                ToggleButton.Text = "OFF"
            end
        end

        ToggleButton.MouseButton1Click:Connect(function()
            funcData.Enabled = not funcData.Enabled
            UpdateButtonState()
            if toggleCallback then
                toggleCallback(funcData.Enabled)
            end
        end)

        return Container, ToggleButton, UpdateButtonState
    end

    -- // Создаем строку для Тестовой Функции
    local testContainer, testToggle, testUpdate = CreateFunctionRow(45, ActiveFunctions.TestFunction, function(enabled)
        if enabled then
            ActiveFunctions.TestFunction.Connection = RunService.Heartbeat:Connect(function()
                if not ActiveFunctions.TestFunction.Enabled then return end
                print("BoatHelper: Тестовая функция активна - " .. os.time())
                task.wait(1)
            end)
            print("BoatHelper: Тестовая функция ВКЛЮЧЕНА")
        else
            if ActiveFunctions.TestFunction.Connection then
                ActiveFunctions.TestFunction.Connection:Disconnect()
                ActiveFunctions.TestFunction.Connection = nil
            end
            print("BoatHelper: Тестовая функция ВЫКЛЮЧЕНА")
        end
    end)

    -- // Разделитель между функциями
    local DividerBetween = Instance.new("Frame")
    DividerBetween.Parent = MainFrame
    DividerBetween.Size = UDim2.new(1, 0, 0, 1)
    DividerBetween.Position = UDim2.new(0, 0, 0, 95)
    DividerBetween.BackgroundColor3 = Color3.fromRGB(60, 60, 60)
    DividerBetween.BorderSizePixel = 0

    -- // Создаем строку для ESP
    local espContainer, espToggle, espUpdate = CreateFunctionRow(105, ActiveFunctions.ESP, function(enabled)
        if enabled then
            print("BoatHelper: ESP ВКЛЮЧЕН")
            ScanAllPlayers()
            
            -- Отслеживание новых игроков
            ActiveFunctions.ESP.Connection = Players.PlayerAdded:Connect(function(newPlayer)
                if ActiveFunctions.ESP.Enabled and newPlayer ~= Player then
                    SetupPlayerESP(newPlayer)
                end
            end)
            
            -- Отслеживание выхода игроков
            Players.PlayerRemoving:Connect(function(leavingPlayer)
                if ActiveFunctions.ESP.PlayersData[leavingPlayer] then
                    CleanupPlayerESP(leavingPlayer)
                end
            end)
        else
            print("BoatHelper: ESP ВЫКЛЮЧЕН")
            if ActiveFunctions.ESP.Connection then
                ActiveFunctions.ESP.Connection:Disconnect()
                ActiveFunctions.ESP.Connection = nil
            end
            ClearAllESP()
        end
    end)

    -- // Разделитель перед кнопкой Destroy
    local Divider2 = Instance.new("Frame")
    Divider2.Parent = MainFrame
    Divider2.Size = UDim2.new(1, 0, 0, 1)
    Divider2.Position = UDim2.new(0, 0, 0, 155)
    Divider2.BackgroundColor3 = Color3.fromRGB(60, 60, 60)
    Divider2.BorderSizePixel = 0

    -- // Кнопка DestroyGUI
    local DestroyButton = Instance.new("TextButton")
    DestroyButton.Name = "DestroyButton"
    DestroyButton.Parent = MainFrame
    DestroyButton.Size = UDim2.new(1, -20, 0, 30)
    DestroyButton.Position = UDim2.new(0, 10, 1, -40)
    DestroyButton.BackgroundColor3 = Color3.fromRGB(120, 20, 20)
    DestroyButton.BorderSizePixel = 1
    DestroyButton.BorderColor3 = Color3.fromRGB(60, 60, 60)
    DestroyButton.Text = "DestroyGUI"
    DestroyButton.TextColor3 = Color3.fromRGB(255, 255, 255)
    DestroyButton.Font = Enum.Font.GothamBold
    DestroyButton.TextSize = 13
    DestroyButton.AutoButtonColor = false

    -- // Эффект наведения на DestroyButton
    DestroyButton.MouseEnter:Connect(function()
        DestroyButton.BackgroundColor3 = Color3.fromRGB(160, 30, 30)
    end)
    DestroyButton.MouseLeave:Connect(function()
        DestroyButton.BackgroundColor3 = Color3.fromRGB(120, 20, 20)
    end)

    -- // Логика перетаскивания
    local dragging = false
    local dragInput, dragStart, startPos

    TitleBar.InputBegan:Connect(function(input)
        if input.UserInputType == Enum.UserInputType.MouseButton1 then
            dragging = true
            dragStart = input.Position
            startPos = MainFrame.Position
            input.Changed:Connect(function()
                if input.UserInputState == Enum.UserInputState.End then
                    dragging = false
                end
            end)
        end
    end)

    TitleBar.InputChanged:Connect(function(input)
        if input.UserInputType == Enum.UserInputType.MouseMovement and dragging 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)

    -- // Открытие/закрытие по Insert
    local function ToggleVisibility()
        MainFrame.Visible = not MainFrame.Visible
    end

    UserInputService.InputBegan:Connect(function(input, gameProcessed)
        if gameProcessed then return end
        if input.KeyCode == Enum.KeyCode.Insert then
            ToggleVisibility()
        end
    end)

    -- // Логика уничтожения GUI и всех функций
    DestroyButton.MouseButton1Click:Connect(function()
        -- Отключаем все активные функции
        for funcName, funcData in pairs(ActiveFunctions) do
            if funcData.Connection then
                funcData.Connection:Disconnect()
                funcData.Connection = nil
            end
            if funcName == "ESP" then
                ClearAllESP()
            end
            funcData.Enabled = false
            print("BoatHelper: Функция '" .. funcName .. "' отключена при уничтожении GUI.")
        end

        -- Уничтожаем GUI
        ScreenGui:Destroy()
        print("BoatHelper: GUI успешно уничтожен.")
    end)

    -- Инициализация состояний
    testUpdate()
    espUpdate()
    
    print("BoatHelper: Меню загружено и готово к работе.")
    print("BoatHelper: Используйте Insert для открытия/закрытия меню.")
end

-- Запуск
CreateBoatHelper()